systemlink-cli 1.21.0__tar.gz → 1.22.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/PKG-INFO +1 -1
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/pyproject.toml +1 -1
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/_version.py +1 -1
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/example_click.py +31 -8
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/example_loader.py +31 -2
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/example_provisioner.py +35 -16
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/README.md +42 -4
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/_schema/schema-v1.0.json +37 -3
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/SKILL.md +9 -4
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/commands.md +7 -0
- systemlink_cli-1.22.0/slcli/skills/slcli/references/example-authoring.md +193 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/LICENSE +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/dff-editor/editor.js +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/dff-editor/index.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/__init__.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/__main__.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/alarm_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/asset_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/cli_formatters.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/cli_utils.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/comment_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/completion_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/config.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/config_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/dataframe_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/dff_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/dff_decorators.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-1/README.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-1/config.yaml +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-2/README.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-2/config.yaml +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-3/config.yaml +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-3/leakage-current-results.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-3/overvoltage-results.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-3/product-xyz-compliance-report.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-3/product-xyz-specification.csv +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/demo-data-3/thermal-response-results.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/exercise-5-1-parametric-insights/README.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/exercise-5-1-parametric-insights/config.yaml +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/exercise-7-1-test-plans/README.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/exercise-7-1-test-plans/config.yaml +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/spec-compliance-notebooks/README.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/spec-compliance-notebooks/config.yaml +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/spec-compliance-notebooks/notebooks/SpecAnalysis_ComplianceCalculation.ipynb +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/spec-compliance-notebooks/notebooks/SpecComplianceCalculation.ipynb +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/spec-compliance-notebooks/notebooks/SpecfileExtractionAndIngestion.ipynb +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/examples/spec-compliance-notebooks/spec_template.xlsx +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/feed_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/file_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/function_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/function_templates.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/main.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/mcp_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/mcp_reachability.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/mcp_server.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/notebook_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/platform.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/policy_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/policy_utils.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/profiles.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/response_handlers.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/rich_output.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/routine_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skill_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/analysis-recipes.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/datasheet-workflow.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/filtering.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/import-specs.min.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/job-debugging/overview.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/nipkg/overview.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/notebook/interfaces.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/notebook/notebook-patterns.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/notebook/overview.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/python-test/overview.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/routine-examples.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/troubleshooting.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/webapp/angular-ui-packages.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/webapp/deployment.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/webapp/layout-patterns.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/webapp/nimble-angular.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/webapp/overview.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/webapp/systemlink-services.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/references/webapp/troubleshooting.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/skills/slcli/scripts/spec_import_helper.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/spec_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/ssl_trust.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/state_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/system_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/system_query_utils.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/table_utils.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/tag_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/templates_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/testmonitor_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/universal_handlers.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/user_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/utils.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/web_editor.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_bootstrap.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/.gitignore +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/README.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/angular.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/package.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/app-routing.module.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/app.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/app.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/app.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/app.module.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/core/state/app-view-state.service.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/systemlink-context.service.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/theme-sync.service.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/webapp-home-data.service.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/app/shared/states/view-state.model.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/assets/README.md +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/index.html +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/main.ts +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/src/styles.scss +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/tsconfig.app.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/webapp_templates/angular/blank/tsconfig.json +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/workflow_preview.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/workflows_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/workitem_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/workspace_click.py +0 -0
- {systemlink_cli-1.21.0 → systemlink_cli-1.22.0}/slcli/workspace_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "systemlink-cli"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.22.0"
|
|
4
4
|
description = "SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates."
|
|
5
5
|
authors = ["Fred Visser <fred.visser@emerson.com>"]
|
|
6
6
|
packages = [{ include = "slcli" }]
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import sys
|
|
5
|
+
from pathlib import Path
|
|
5
6
|
from typing import Any, Dict, List, Optional
|
|
6
7
|
|
|
7
8
|
import click
|
|
@@ -281,7 +282,13 @@ def register_example_commands(cli: Any) -> None:
|
|
|
281
282
|
handle_api_error(exc)
|
|
282
283
|
|
|
283
284
|
@example.command(name="install")
|
|
284
|
-
@click.argument("example_name")
|
|
285
|
+
@click.argument("example_name", required=False)
|
|
286
|
+
@click.option(
|
|
287
|
+
"--file",
|
|
288
|
+
"config_file",
|
|
289
|
+
type=click.Path(exists=True, dir_okay=False, readable=True, resolve_path=True),
|
|
290
|
+
help="Path to an example config.yaml; referenced files are relative to its directory.",
|
|
291
|
+
)
|
|
285
292
|
@click.option("--workspace", "-w", required=True, help="Workspace name or ID for resources")
|
|
286
293
|
@click.option(
|
|
287
294
|
"--format",
|
|
@@ -302,7 +309,8 @@ def register_example_commands(cli: Any) -> None:
|
|
|
302
309
|
help="Path to write provisioning results as JSON for auditing.",
|
|
303
310
|
)
|
|
304
311
|
def install_example(
|
|
305
|
-
example_name: str,
|
|
312
|
+
example_name: Optional[str],
|
|
313
|
+
config_file: Optional[str],
|
|
306
314
|
workspace: Optional[str],
|
|
307
315
|
format: str,
|
|
308
316
|
dry_run: bool,
|
|
@@ -311,14 +319,29 @@ def register_example_commands(cli: Any) -> None:
|
|
|
311
319
|
"""Provision all resources defined by an example configuration."""
|
|
312
320
|
try:
|
|
313
321
|
loader = ExampleLoader()
|
|
314
|
-
|
|
322
|
+
example_dir: Optional[Path] = None
|
|
323
|
+
if config_file and example_name:
|
|
324
|
+
raise ValueError("Specify either EXAMPLE_NAME or --file, not both.")
|
|
325
|
+
if not config_file and not example_name:
|
|
326
|
+
raise ValueError("Provide an EXAMPLE_NAME or --file path to config.yaml.")
|
|
327
|
+
|
|
328
|
+
if config_file:
|
|
329
|
+
config_path = Path(config_file)
|
|
330
|
+
config = loader.load_config_file(config_path)
|
|
331
|
+
example_name = str(config["name"])
|
|
332
|
+
example_dir = config_path.parent
|
|
333
|
+
else:
|
|
334
|
+
config = loader.load_config(example_name or "")
|
|
315
335
|
|
|
316
336
|
workspace_id = _resolve_workspace_id(get_effective_workspace(workspace))
|
|
317
|
-
|
|
318
|
-
workspace_id
|
|
319
|
-
example_name
|
|
320
|
-
dry_run
|
|
321
|
-
|
|
337
|
+
provisioner_options: Dict[str, Any] = {
|
|
338
|
+
"workspace_id": workspace_id,
|
|
339
|
+
"example_name": example_name,
|
|
340
|
+
"dry_run": dry_run,
|
|
341
|
+
}
|
|
342
|
+
if example_dir is not None:
|
|
343
|
+
provisioner_options["example_dir"] = example_dir
|
|
344
|
+
provisioner = ExampleProvisioner(**provisioner_options)
|
|
322
345
|
|
|
323
346
|
results, err = provisioner.provision(config)
|
|
324
347
|
if err:
|
|
@@ -105,6 +105,31 @@ class ExampleLoader:
|
|
|
105
105
|
f"Example '{example_name}' not found. " f"Config path: {config_path}"
|
|
106
106
|
)
|
|
107
107
|
|
|
108
|
+
return self._load_config(config_path, example_name)
|
|
109
|
+
|
|
110
|
+
def load_config_file(self, config_file: Path) -> Dict[str, Any]:
|
|
111
|
+
"""Load and validate an example configuration from an arbitrary file.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
config_file: Path to the example's YAML configuration file.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Validated config dictionary.
|
|
118
|
+
|
|
119
|
+
Raises:
|
|
120
|
+
FileNotFoundError: If the config file does not exist.
|
|
121
|
+
ValueError: If config fails validation.
|
|
122
|
+
"""
|
|
123
|
+
config_path = config_file.expanduser().resolve()
|
|
124
|
+
if not config_path.exists():
|
|
125
|
+
raise FileNotFoundError(f"Example config not found: {config_path}")
|
|
126
|
+
if not config_path.is_file():
|
|
127
|
+
raise ValueError(f"Example config is not a file: {config_path}")
|
|
128
|
+
|
|
129
|
+
return self._load_config(config_path, str(config_path))
|
|
130
|
+
|
|
131
|
+
def _load_config(self, config_path: Path, source_name: str) -> Dict[str, Any]:
|
|
132
|
+
"""Load and validate a config at a known path."""
|
|
108
133
|
# Load YAML
|
|
109
134
|
try:
|
|
110
135
|
with open(config_path, "r") as f:
|
|
@@ -118,14 +143,14 @@ class ExampleLoader:
|
|
|
118
143
|
# Validate schema
|
|
119
144
|
errors = self.validate_config(config)
|
|
120
145
|
if errors:
|
|
121
|
-
msg = f"Config validation failed for '{
|
|
146
|
+
msg = f"Config validation failed for '{source_name}':\n"
|
|
122
147
|
msg += "\n".join(f" - {e}" for e in errors)
|
|
123
148
|
raise ValueError(msg)
|
|
124
149
|
|
|
125
150
|
# Validate references
|
|
126
151
|
ref_errors = self._validate_references(config)
|
|
127
152
|
if ref_errors:
|
|
128
|
-
msg = f"Reference validation failed for '{
|
|
153
|
+
msg = f"Reference validation failed for '{source_name}':\n"
|
|
129
154
|
msg += "\n".join(f" - {e}" for e in ref_errors)
|
|
130
155
|
raise ValueError(msg)
|
|
131
156
|
|
|
@@ -148,6 +173,10 @@ class ExampleLoader:
|
|
|
148
173
|
if missing_fields:
|
|
149
174
|
errors.append(f"Missing required fields: {', '.join(sorted(missing_fields))}")
|
|
150
175
|
|
|
176
|
+
name = config.get("name")
|
|
177
|
+
if "name" in config and (not isinstance(name, str) or not name.strip()):
|
|
178
|
+
errors.append("name must be a non-empty string")
|
|
179
|
+
|
|
151
180
|
# Check format_version is supported
|
|
152
181
|
version = config.get("format_version")
|
|
153
182
|
if version and version not in self.SUPPORTED_SCHEMA_VERSIONS:
|
|
@@ -62,6 +62,7 @@ class ExampleProvisioner:
|
|
|
62
62
|
workspace_id: Optional[str] = None,
|
|
63
63
|
example_name: Optional[str] = None,
|
|
64
64
|
dry_run: bool = False,
|
|
65
|
+
example_dir: Optional[Path] = None,
|
|
65
66
|
) -> None:
|
|
66
67
|
"""Initialize the provisioner.
|
|
67
68
|
|
|
@@ -69,10 +70,12 @@ class ExampleProvisioner:
|
|
|
69
70
|
workspace_id: Workspace identifier (ID).
|
|
70
71
|
example_name: Example name for tagging resources.
|
|
71
72
|
dry_run: When True, does not create any resources (SKIPPED).
|
|
73
|
+
example_dir: Directory containing an externally supplied example config.
|
|
72
74
|
"""
|
|
73
75
|
self.workspace_id = workspace_id
|
|
74
76
|
self.example_name = example_name
|
|
75
77
|
self.dry_run = dry_run
|
|
78
|
+
self.example_dir = example_dir
|
|
76
79
|
self.id_map: Dict[str, str] = {}
|
|
77
80
|
self._test_results_deleted: bool = False
|
|
78
81
|
self._files_deleted: bool = False
|
|
@@ -3480,15 +3483,10 @@ class ExampleProvisioner:
|
|
|
3480
3483
|
Returns:
|
|
3481
3484
|
File contents as bytes, or None if not found.
|
|
3482
3485
|
"""
|
|
3483
|
-
from pathlib import Path
|
|
3484
|
-
|
|
3485
3486
|
try:
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
full_path = example_dir / file_path
|
|
3490
|
-
else:
|
|
3491
|
-
full_path = Path(file_path)
|
|
3487
|
+
full_path = self._resolve_example_file(file_path)
|
|
3488
|
+
if full_path is None:
|
|
3489
|
+
return None
|
|
3492
3490
|
|
|
3493
3491
|
if not full_path.exists():
|
|
3494
3492
|
click.echo(
|
|
@@ -3518,6 +3516,31 @@ class ExampleProvisioner:
|
|
|
3518
3516
|
)
|
|
3519
3517
|
return None
|
|
3520
3518
|
|
|
3519
|
+
def _resolve_example_file(self, file_path: str) -> Optional[Path]:
|
|
3520
|
+
"""Resolve a fixture file and contain it when a fixture directory is configured.
|
|
3521
|
+
|
|
3522
|
+
Without a fixture directory, return the path as provided for backwards
|
|
3523
|
+
compatibility with callers that supply their own working-directory context.
|
|
3524
|
+
"""
|
|
3525
|
+
if self.example_dir:
|
|
3526
|
+
example_dir = self.example_dir
|
|
3527
|
+
elif self.example_name:
|
|
3528
|
+
example_dir = Path(__file__).parent / "examples" / self.example_name
|
|
3529
|
+
else:
|
|
3530
|
+
return Path(file_path)
|
|
3531
|
+
|
|
3532
|
+
try:
|
|
3533
|
+
resolved_dir = example_dir.resolve()
|
|
3534
|
+
resolved_path = (resolved_dir / file_path).resolve()
|
|
3535
|
+
resolved_path.relative_to(resolved_dir)
|
|
3536
|
+
return resolved_path
|
|
3537
|
+
except (OSError, ValueError):
|
|
3538
|
+
click.echo(
|
|
3539
|
+
f"Warning: File path must remain inside the example directory: {file_path}",
|
|
3540
|
+
err=True,
|
|
3541
|
+
)
|
|
3542
|
+
return None
|
|
3543
|
+
|
|
3521
3544
|
def _get_notebook_by_name(self, name: str) -> Optional[str]:
|
|
3522
3545
|
"""Look up an example-owned notebook by name and workspace."""
|
|
3523
3546
|
if not name:
|
|
@@ -3566,16 +3589,12 @@ class ExampleProvisioner:
|
|
|
3566
3589
|
|
|
3567
3590
|
if not name or not file_path:
|
|
3568
3591
|
return None
|
|
3569
|
-
from pathlib import Path
|
|
3570
3592
|
|
|
3571
3593
|
try:
|
|
3572
|
-
# Resolve file path relative to example directory
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
notebook_file = example_dir / file_path
|
|
3577
|
-
else:
|
|
3578
|
-
notebook_file = Path(file_path)
|
|
3594
|
+
# Resolve file path relative to the example directory
|
|
3595
|
+
notebook_file = self._resolve_example_file(file_path)
|
|
3596
|
+
if notebook_file is None:
|
|
3597
|
+
return None
|
|
3579
3598
|
|
|
3580
3599
|
if not notebook_file.exists():
|
|
3581
3600
|
return None
|
|
@@ -76,6 +76,12 @@ slcli example install demo-data-2 -w <workspace> --audit-log install-log.json --
|
|
|
76
76
|
slcli example install demo-data-3 \
|
|
77
77
|
-w <workspace> --format json --audit-log nigel-fixture-manifest.json
|
|
78
78
|
|
|
79
|
+
# Install an example from any local directory. Paths in config.yaml are
|
|
80
|
+
# resolved relative to the directory containing config.yaml.
|
|
81
|
+
slcli example install \
|
|
82
|
+
--file ./fixtures/example-resources/config.yaml \
|
|
83
|
+
--workspace <workspace>
|
|
84
|
+
|
|
79
85
|
# Delete example resources from a workspace
|
|
80
86
|
slcli example delete demo-data-2 -w <workspace-id> --dry-run
|
|
81
87
|
slcli example delete demo-data-2 -w <workspace>
|
|
@@ -85,6 +91,10 @@ slcli example delete demo-data-2 -w <workspace> --audit-log delete-log.json --fo
|
|
|
85
91
|
|
|
86
92
|
## Creating New Examples
|
|
87
93
|
|
|
94
|
+
For the complete authoring contract, including external fixture directories,
|
|
95
|
+
resource references, file-backed resources, and validation caveats, see the
|
|
96
|
+
[Example Fixture Authoring Guide](../skills/slcli/references/example-authoring.md).
|
|
97
|
+
|
|
88
98
|
1. Create a new directory in `examples/`:
|
|
89
99
|
|
|
90
100
|
```
|
|
@@ -93,13 +103,37 @@ slcli example delete demo-data-2 -w <workspace> --audit-log delete-log.json --fo
|
|
|
93
103
|
└── README.md # Optional: Setup guide
|
|
94
104
|
```
|
|
95
105
|
|
|
96
|
-
2. Create `config.yaml` following the schema in
|
|
106
|
+
2. Create `config.yaml` following the schema in
|
|
107
|
+
[`_schema/schema-v1.0.json`](_schema/schema-v1.0.json). Use the closest
|
|
108
|
+
bundled example as the reference for resource-specific `properties`.
|
|
97
109
|
|
|
98
110
|
3. Test locally:
|
|
99
|
-
|
|
100
|
-
|
|
111
|
+
```bash
|
|
112
|
+
slcli example install my-example --workspace <workspace> --dry-run
|
|
101
113
|
```
|
|
102
114
|
|
|
115
|
+
External fixtures use the same format and do not need to be copied into the
|
|
116
|
+
package:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
fixtures/example-resources/
|
|
120
|
+
├── config.yaml
|
|
121
|
+
├── README.md
|
|
122
|
+
└── product-xyz-specification.csv
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
slcli example install \
|
|
127
|
+
--file fixtures/example-resources/config.yaml \
|
|
128
|
+
--workspace <workspace> \
|
|
129
|
+
--dry-run
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Paths in `file_path`, `rows_file`, and `data_file` properties are resolved
|
|
133
|
+
relative to the directory containing `config.yaml`. Only files named by a
|
|
134
|
+
resource are uploaded; a sibling README or data file is not uploaded merely
|
|
135
|
+
because it is present.
|
|
136
|
+
|
|
103
137
|
## Configuration Format
|
|
104
138
|
|
|
105
139
|
All examples use YAML format with the following structure:
|
|
@@ -158,9 +192,13 @@ cleanup:
|
|
|
158
192
|
## Notes
|
|
159
193
|
|
|
160
194
|
- Examples are versioned with the `format_version` field (currently 1.0)
|
|
161
|
-
- Resource cleanup
|
|
195
|
+
- Resource cleanup uses example ownership tags and reverse resource order. The
|
|
196
|
+
`cleanup` block is descriptive metadata; `example delete` does not currently
|
|
197
|
+
consume its custom order or confirmation settings.
|
|
162
198
|
- References use `${id_reference}` syntax for interpolation
|
|
199
|
+
- Resources are provisioned in list order, so referenced resources must appear first
|
|
163
200
|
- All resources created by an example are tagged with the example name for safe deletion
|
|
201
|
+
- The JSON Schema is the authoring reference; runtime validation currently checks only a subset of its types and patterns
|
|
164
202
|
- Examples with `install_manifest: true` emit grouped resource actions and a
|
|
165
203
|
`validation.complete` flag when JSON output is requested. Unsupported
|
|
166
204
|
capabilities or failed relationships make the command return a nonzero exit
|
|
@@ -25,6 +25,10 @@
|
|
|
25
25
|
"type": "string",
|
|
26
26
|
"description": "Human-readable example title"
|
|
27
27
|
},
|
|
28
|
+
"example_version": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Fixture data version used in the optional install manifest"
|
|
31
|
+
},
|
|
28
32
|
"description": {
|
|
29
33
|
"type": "string",
|
|
30
34
|
"description": "Detailed description of what example includes"
|
|
@@ -64,6 +68,15 @@
|
|
|
64
68
|
],
|
|
65
69
|
"description": "Target workspace name or null for default"
|
|
66
70
|
},
|
|
71
|
+
"workspace_name": {
|
|
72
|
+
"type": "string",
|
|
73
|
+
"description": "Workspace name recorded in the optional install manifest"
|
|
74
|
+
},
|
|
75
|
+
"install_manifest": {
|
|
76
|
+
"type": "boolean",
|
|
77
|
+
"default": false,
|
|
78
|
+
"description": "Emit the grouped install manifest when JSON output is requested"
|
|
79
|
+
},
|
|
67
80
|
"resources": {
|
|
68
81
|
"type": "array",
|
|
69
82
|
"items": {
|
|
@@ -79,19 +92,19 @@
|
|
|
79
92
|
"items": {
|
|
80
93
|
"type": "string"
|
|
81
94
|
},
|
|
82
|
-
"description": "
|
|
95
|
+
"description": "Descriptive intended deletion order; generic example delete currently reverses the resources list"
|
|
83
96
|
},
|
|
84
97
|
"filter_tags": {
|
|
85
98
|
"type": "array",
|
|
86
99
|
"items": {
|
|
87
100
|
"type": "string"
|
|
88
101
|
},
|
|
89
|
-
"description": "
|
|
102
|
+
"description": "Tags intended for cleanup filtering"
|
|
90
103
|
},
|
|
91
104
|
"require_confirmation": {
|
|
92
105
|
"type": "boolean",
|
|
93
106
|
"default": true,
|
|
94
|
-
"description": "
|
|
107
|
+
"description": "Descriptive confirmation preference; generic example delete does not currently prompt from this field"
|
|
95
108
|
}
|
|
96
109
|
}
|
|
97
110
|
},
|
|
@@ -102,6 +115,27 @@
|
|
|
102
115
|
"type": "boolean",
|
|
103
116
|
"default": true,
|
|
104
117
|
"description": "Workspace must exist before install"
|
|
118
|
+
},
|
|
119
|
+
"required_relationships": {
|
|
120
|
+
"type": "array",
|
|
121
|
+
"items": {
|
|
122
|
+
"type": "string"
|
|
123
|
+
},
|
|
124
|
+
"description": "Relationships the fixture expects to be queryable after install"
|
|
125
|
+
},
|
|
126
|
+
"failed_relationships": {
|
|
127
|
+
"type": "array",
|
|
128
|
+
"items": {
|
|
129
|
+
"type": "string"
|
|
130
|
+
},
|
|
131
|
+
"description": "Relationships that failed validation"
|
|
132
|
+
},
|
|
133
|
+
"unsupported": {
|
|
134
|
+
"type": "array",
|
|
135
|
+
"items": {
|
|
136
|
+
"type": "string"
|
|
137
|
+
},
|
|
138
|
+
"description": "Capabilities intentionally not represented by the fixture"
|
|
105
139
|
}
|
|
106
140
|
}
|
|
107
141
|
},
|
|
@@ -4,7 +4,9 @@ description: >-
|
|
|
4
4
|
Query and manage NI SystemLink resources using the slcli command-line interface.
|
|
5
5
|
Use when the user asks about test results, assets, systems, work items,
|
|
6
6
|
specifications, webapps, notebooks, dataframes, files, feeds, tags,
|
|
7
|
-
authorization, users,
|
|
7
|
+
authorization, users, example fixture authoring, example config.yaml files,
|
|
8
|
+
or other SystemLink resource workflows. Use it when the user asks to create,
|
|
9
|
+
validate, review, install, or troubleshoot a SystemLink example fixture.
|
|
8
10
|
argument-hint: >-
|
|
9
11
|
Describe the SystemLink workflow you want to inspect, automate, scaffold, or
|
|
10
12
|
troubleshoot.
|
|
@@ -20,6 +22,7 @@ SystemLink resource workflow that should be driven from the CLI.
|
|
|
20
22
|
- Querying or managing SystemLink resources through `slcli`
|
|
21
23
|
- Looking up exact command syntax, flags, or JSON output patterns
|
|
22
24
|
- Building command sequences for analysis, provisioning, packaging, or cleanup
|
|
25
|
+
- Creating, validating, or reviewing `slcli example` fixture YAML
|
|
23
26
|
- Troubleshooting CLI behavior, platform gating, or command selection
|
|
24
27
|
|
|
25
28
|
## Reference docs
|
|
@@ -29,6 +32,7 @@ Load only what the current task needs.
|
|
|
29
32
|
| Topic | File | When to load |
|
|
30
33
|
| --- | --- | --- |
|
|
31
34
|
| CLI command reference | [commands.md](./references/commands.md) | Looking up command syntax, options, or examples |
|
|
35
|
+
| Example fixture authoring | [example-authoring.md](./references/example-authoring.md) | Creating or reviewing `config.yaml`, resource references, file-backed fixtures, or validation behavior |
|
|
32
36
|
| Datasheet-to-spec workflow | [datasheet-workflow.md](./references/datasheet-workflow.md) | Importing specifications from PDF, CSV, or structured text |
|
|
33
37
|
| Minimal spec import payload | [import-specs.min.json](./references/import-specs.min.json) | Need a bundled create-compatible starter payload or conditions |
|
|
34
38
|
| Spec import helper | [spec_import_helper.py](./scripts/spec_import_helper.py) | Scaffold or validate a datasheet spec import payload |
|
|
@@ -49,9 +53,10 @@ Load only what the current task needs.
|
|
|
49
53
|
4. Use convenience filters first, then fall back to `--filter` with `--substitution` for complex queries.
|
|
50
54
|
5. Stay scoped to the user’s requested resource or workflow.
|
|
51
55
|
6. Load deeper references only when the command surface alone is not enough.
|
|
52
|
-
7.
|
|
53
|
-
8.
|
|
54
|
-
9.
|
|
56
|
+
7. For example authoring or review, load `example-authoring.md` before proposing YAML.
|
|
57
|
+
8. Prefer workspace IDs over names in scripted workflows when an endpoint is strict about identity.
|
|
58
|
+
9. Use `make_api_request` from `slcli.utils` for helper scripts so auth, SSL, and error handling stay consistent.
|
|
59
|
+
10. For datasheet imports, default to autonomy when the product or workspace can be resolved unambiguously.
|
|
55
60
|
|
|
56
61
|
## Common command groups
|
|
57
62
|
|
|
@@ -932,5 +932,12 @@ for training, testing, or evaluation.
|
|
|
932
932
|
slcli example list [-f json] # List available examples
|
|
933
933
|
slcli example info <EXAMPLE_ID> # Show example details
|
|
934
934
|
slcli example install <EXAMPLE_ID> [--workspace NAME] # Provision example resources
|
|
935
|
+
slcli example install --file PATH [--workspace NAME] # Install a local fixture
|
|
935
936
|
slcli example delete <EXAMPLE_ID> [--workspace NAME] # Remove provisioned resources
|
|
936
937
|
```
|
|
938
|
+
|
|
939
|
+
For a local fixture, `PATH` points to its `config.yaml`; referenced files are
|
|
940
|
+
resolved relative to the directory containing that file.
|
|
941
|
+
|
|
942
|
+
For the YAML contract and authoring workflow, load
|
|
943
|
+
[example-authoring.md](./example-authoring.md).
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Example Fixture Authoring
|
|
2
|
+
|
|
3
|
+
Use this guide when creating a SystemLink example for `slcli example install`.
|
|
4
|
+
The machine-readable contract is [schema-v1.0.json](../../../examples/_schema/schema-v1.0.json).
|
|
5
|
+
The schema defines the common YAML envelope; the bundled examples show the
|
|
6
|
+
SystemLink API properties for each resource type.
|
|
7
|
+
|
|
8
|
+
## Quick Start
|
|
9
|
+
|
|
10
|
+
An example is a directory containing `config.yaml` and any files referenced by
|
|
11
|
+
that configuration:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
fixtures/example-resources/
|
|
15
|
+
├── config.yaml
|
|
16
|
+
├── README.md
|
|
17
|
+
├── product-xyz-specification.csv
|
|
18
|
+
└── notebooks/
|
|
19
|
+
└── analysis.ipynb
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Install a bundled example by name:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
slcli example install demo-data-1 \
|
|
26
|
+
--workspace <workspace> --dry-run
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Install an example from any local directory with `--file`:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
slcli example install \
|
|
33
|
+
--file fixtures/example-resources/config.yaml \
|
|
34
|
+
--workspace <workspace> \
|
|
35
|
+
--dry-run
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
For `--file` installs, all relative file references are resolved from the
|
|
39
|
+
directory containing `config.yaml`. A README or an unreferenced file is not
|
|
40
|
+
uploaded automatically; add a `file` or `notebook` resource when it should be
|
|
41
|
+
published to SystemLink.
|
|
42
|
+
|
|
43
|
+
## Configuration Contract
|
|
44
|
+
|
|
45
|
+
The required top-level fields are:
|
|
46
|
+
|
|
47
|
+
| Field | Meaning |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| `format_version` | Schema version. Use the string `"1.0"`. |
|
|
50
|
+
| `name` | Lowercase example slug using letters, numbers, and hyphens. It is also used for ownership tagging. |
|
|
51
|
+
| `title` | Human-readable title. |
|
|
52
|
+
| `resources` | Ordered list of resources to create. |
|
|
53
|
+
|
|
54
|
+
Common optional fields include `description`, `author`, `created_date`,
|
|
55
|
+
`updated_date`, `example_version`, `tags`, `estimated_setup_time_minutes`,
|
|
56
|
+
`required_systemlink_version`, `target_workspace`, `workspace_name`,
|
|
57
|
+
`install_manifest`, `cleanup`, `validation`, and `post_install`.
|
|
58
|
+
|
|
59
|
+
Each resource has this envelope:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
- type: "location"
|
|
63
|
+
name: "Production Test Lab"
|
|
64
|
+
properties:
|
|
65
|
+
city: "Austin"
|
|
66
|
+
id_reference: "loc_lab"
|
|
67
|
+
tags: ["example-resources"]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
- `type` selects one of the supported resource handlers.
|
|
71
|
+
- `name` is the resource name sent to SystemLink.
|
|
72
|
+
- `properties` contains fields specific to that resource type.
|
|
73
|
+
- `id_reference` is a local identifier using lowercase letters, numbers, and
|
|
74
|
+
underscores. Use it in later properties as `${id_reference}`.
|
|
75
|
+
- `tags` is used for organization and cleanup filtering.
|
|
76
|
+
|
|
77
|
+
Resources are processed in list order. Put a resource before any resource that
|
|
78
|
+
references its ID. References are resolved recursively inside `properties`, but
|
|
79
|
+
only a complete string such as `${loc_lab}` is substituted; embedded text such
|
|
80
|
+
as `location-${loc_lab}` is not substituted.
|
|
81
|
+
|
|
82
|
+
## Resource Types
|
|
83
|
+
|
|
84
|
+
The supported `type` values are:
|
|
85
|
+
|
|
86
|
+
| Type | Typical use | Example |
|
|
87
|
+
| --- | --- | --- |
|
|
88
|
+
| `location` | Physical location hierarchy | [demo-data-1](../../../examples/demo-data-1/config.yaml) |
|
|
89
|
+
| `product` | Product definition and part number | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
90
|
+
| `system` | Test system or virtual system | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
91
|
+
| `asset` | Instrument or equipment asset | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
92
|
+
| `dut` | Device under test | [demo-data-1](../../../examples/demo-data-1/config.yaml) |
|
|
93
|
+
| `testtemplate` | Test plan template | [demo-data-2](../../../examples/demo-data-2/config.yaml) |
|
|
94
|
+
| `workflow` | Work item state machine | [demo-data-1](../../../examples/demo-data-1/config.yaml) |
|
|
95
|
+
| `work_item` | Work item instance | [demo-data-1](../../../examples/demo-data-1/config.yaml) |
|
|
96
|
+
| `work_order` | Work order | [demo-data-1](../../../examples/demo-data-1/config.yaml) |
|
|
97
|
+
| `test_result` | Test Monitor result and optional steps | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
98
|
+
| `data_table` | DataFrame table and optional rows | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
99
|
+
| `file` | Supporting file upload | [spec-compliance-notebooks](../../../examples/spec-compliance-notebooks/config.yaml) |
|
|
100
|
+
| `notebook` | Jupyter notebook upload | [spec-compliance-notebooks](../../../examples/spec-compliance-notebooks/config.yaml) |
|
|
101
|
+
| `feed` | Package feed metadata | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
102
|
+
| `state` | Deployment state metadata | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
103
|
+
| `tag` | Workspace tag and optional history | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
104
|
+
| `specification` | Product specification and conditions | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
105
|
+
| `alarm` | Alarm instance or transition | [demo-data-3](../../../examples/demo-data-3/config.yaml) |
|
|
106
|
+
|
|
107
|
+
The `properties` object is intentionally resource-specific and open-ended in
|
|
108
|
+
the common schema. Start with the closest bundled example and verify the
|
|
109
|
+
property names against the corresponding `slcli` command or API model.
|
|
110
|
+
|
|
111
|
+
## File-Backed Resources
|
|
112
|
+
|
|
113
|
+
These are the file-reference keys consumed by the generic provisioner:
|
|
114
|
+
|
|
115
|
+
| Resource | Property | Value |
|
|
116
|
+
| --- | --- | --- |
|
|
117
|
+
| `file` | `file_path` | Relative path to bytes to upload. `description`, `content_type`, `keywords`, and `tags` are also supported metadata. |
|
|
118
|
+
| `notebook` | `file_path` | Relative path to an `.ipynb` file. `notebook_interface` selects the notebook interface, for example `File Analysis`. |
|
|
119
|
+
| `data_table` | `rows_file` or `data_file` | Relative path to JSON rows. The JSON may be a list of rows or an object containing `frame.columns` and `frame.data`. |
|
|
120
|
+
|
|
121
|
+
A data table may use inline `rows` instead of a rows file, but it must not
|
|
122
|
+
define both. Row values are normalized to strings when appended. The configured
|
|
123
|
+
`columns` must match the columns in the rows payload when both are provided.
|
|
124
|
+
|
|
125
|
+
Example:
|
|
126
|
+
|
|
127
|
+
```yaml
|
|
128
|
+
- type: "file"
|
|
129
|
+
name: "product-xyz-specification.csv"
|
|
130
|
+
properties:
|
|
131
|
+
file_path: "product-xyz-specification.csv"
|
|
132
|
+
content_type: "text/csv"
|
|
133
|
+
id_reference: "file_specification"
|
|
134
|
+
|
|
135
|
+
- type: "data_table"
|
|
136
|
+
name: "Overvoltage Results"
|
|
137
|
+
properties:
|
|
138
|
+
columns:
|
|
139
|
+
- name: "timestamp"
|
|
140
|
+
- name: "value"
|
|
141
|
+
rows_file: "data/overvoltage-results.json"
|
|
142
|
+
id_reference: "table_overvoltage"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Validation And Dry Runs
|
|
146
|
+
|
|
147
|
+
The JSON Schema is the authoring reference, but the current loader performs a
|
|
148
|
+
smaller runtime validation set. It checks required fields, the supported format
|
|
149
|
+
version, supported resource types, basic resource reference identifiers, and
|
|
150
|
+
undefined `${reference}` values. It does not enforce every JSON Schema type or
|
|
151
|
+
pattern, and `properties` remains API-specific.
|
|
152
|
+
|
|
153
|
+
Use a dry run before making API calls:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
slcli example install \
|
|
157
|
+
--file fixtures/example-resources/config.yaml \
|
|
158
|
+
--workspace <workspace> \
|
|
159
|
+
--dry-run \
|
|
160
|
+
--format json
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
For a real install, inspect the JSON result when checking automation:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
slcli example install \
|
|
167
|
+
--file fixtures/example-resources/config.yaml \
|
|
168
|
+
--workspace <workspace> \
|
|
169
|
+
--format json \
|
|
170
|
+
--audit-log install.json
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
A successful resource list does not prove that every intended relationship or
|
|
174
|
+
capability was created. If the configuration uses `install_manifest: true`,
|
|
175
|
+
check `validation.complete` and the `unsupported` and `failed_relationships`
|
|
176
|
+
entries in the JSON manifest.
|
|
177
|
+
|
|
178
|
+
The `cleanup` block is currently descriptive metadata. `slcli example delete`
|
|
179
|
+
uses the example ownership marker and reverses the resource list; it does not
|
|
180
|
+
currently apply a custom cleanup order or confirmation setting from the YAML.
|
|
181
|
+
|
|
182
|
+
## Authoring Checklist
|
|
183
|
+
|
|
184
|
+
Before sharing an example:
|
|
185
|
+
|
|
186
|
+
1. Put `config.yaml` and every referenced file in the fixture directory.
|
|
187
|
+
2. Set a unique lowercase `name` and `format_version: "1.0"`.
|
|
188
|
+
3. Give every resource a unique `id_reference` and place resources in dependency order.
|
|
189
|
+
4. Use the closest bundled fixture as the reference for resource-specific properties.
|
|
190
|
+
5. Add explicit `file` or `notebook` resources for files that should be uploaded.
|
|
191
|
+
6. Run the external-file dry run and inspect JSON output for failed resources.
|
|
192
|
+
7. Add a README with the workspace prerequisites, expected resources, and post-install steps.
|
|
193
|
+
8. Add an `install_manifest` and `validation` section when the fixture has known limitations.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|