Workspace
In preparation. This page describes the target interface to gather your feedback; nothing is usable yet.
OpenTofu workspaces are in preparation: this manifest is not accepted by sng apply yet. The schema below is that of the target version.
apiVersion | tofu.stackngo.io/v1alpha1 |
kind | Workspace |
| Applied by | sng apply (upcoming) |
| Related commands | sng kind get Workspace, sng kind delete Workspace |
What it is for
A Workspace applies an OpenTofu module published as OCI in your tenant: the platform runs
init, plan, apply in an ephemeral container, keeps the state and its lock, publishes
the outputs to a secret, and detects drift. Guide: Workspaces.
Minimal example
apiVersion: tofu.stackngo.io/v1alpha1
kind: Workspace
metadata:
name: pet
spec:
module:
source: oci://ovh-gra-0.registry.dev.stackngo.fr/acme/random-pet
tag: 1.0.0
Complete annotated example
apiVersion: tofu.stackngo.io/v1alpha1
kind: Workspace
metadata:
name: app
spec:
module:
source: oci://ovh-gra-0.registry.dev.stackngo.fr/acme/ovh-instance # oci:// required
digest: sha256:9f1c… # or tag; never both
pullSecretRef: {name: registry-creds} # if the registry requires authentication
providers:
- {name: ovh-gra} # Provider of the tenant
dependsOn:
- {name: network} # execution order
vars: # written as terraform.tfvars.json
size: s1-2
varsFrom:
- workspaceOutputRef: {name: network, output: subnet_id}
default: subnet-mock # plan possible before the parent publishes, never apply
- secretRef: {name: app-secrets, key: ssh-key}
varName: ssh_public_key # renames the variable
imports:
- {to: ovh_cloud_project_instance.this, id: "i-123"}
outputs:
secretName: app-outputs # default: <nom>-outputs
refresh:
interval: 30m # ≥ 1m
mode: plan # plan (drift) | apply
approval: manual # auto | manual
deletionPolicy: Orphan # Orphan | Destroy
suspend: false
Fields
Cross-field validation rules
module.tagandmodule.digestare mutually exclusive;digestfollows^sha256:[a-f0-9]{64}$.- In
varsFrom, exactly one source:secretReforworkspaceOutputRef;varNamerequiressecretRef.key;defaultonly exists withworkspaceOutputRef. - In
imports, exactly one identifier:idoridFrom. refresh.intervalis at least1m.
Workspace
Workspace applique un module OpenTofu publié en OCI, dans des exécutions propres à votre tenant.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
apiVersion string | tofu.stackngo.io/v1alpha1 | ||
kind string | Workspace | ||
metadata ObjectMeta | Seul metadata.name est à renseigner (nom de la ressource dans votre tenant). | ||
spec WorkspaceSpec | |||
status WorkspaceStatus |
WorkspaceSpec
WorkspaceSpec : module OCI à appliquer et ses entrées.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
module ModuleSource | Module OpenTofu à appliquer : adresse OCI, version (tag) ou empreinte (digest). | ||
providers LocalRef array | Providers : Provider de votre tenant câblés dans le run (bloc provider généré). | Optional: {} | |
dependsOn LocalRef array | DependsOn : Workspace de votre tenant qui doivent être Ready avant tout run (ordre seul). | Optional: {} | |
vars JSON | Vars : valeurs JSON libres, écrites dans terraform.tfvars.json. | Type: object Optional: {} | |
varsFrom VarsFromSource array | VarsFrom : variables secrètes, injectées en TF_VAR_<nom>. Prioritaires sur Vars. | Optional: {} | |
imports ImportSpec array | Imports : ressources existantes adoptées par des blocs import (no-op une fois dans le state). | Optional: {} | |
backend BackendSpec | Où conserver le state. Absent : la plateforme le conserve pour vous. | Optional: {} | |
outputs OutputsSpec | Où publier les outputs du module. | Optional: {} | |
refresh RefreshSpec | Exécution périodique pour détecter la dérive. Absent : aucun run hors changement de manifeste ou de secret. | Optional: {} | |
approval Approval | auto (défaut) applique le plan sans intervention ; manual attend votre approbation du plan. | auto | Enum: [auto manual] Optional: {} |
deletionPolicy DeletionPolicy | Sort de l'infrastructure à la suppression du Workspace : Orphan (défaut) la laisse en place, Destroy la détruit d'abord. | Orphan | Enum: [Orphan Destroy] Optional: {} |
suspend boolean | Suspend : aucun nouveau run tant que vrai. | Optional: {} | |
resources ResourceRequirements | Resources : ressources du conteneur tofu. Absent = valeurs par défaut de la plateforme. | Optional: {} |
WorkspaceStatus
WorkspaceStatus : état observé.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
observedGeneration integer | Dernière version du manifeste prise en compte par la plateforme. | Optional: {} | |
conditions Condition array | Conditions : Ready, Drifted, Planning, Applying, AwaitingApproval, Failed. | Optional: {} | |
lastPlan PlanSummary | Résumé du dernier plan : identifiant, date et nombre de changements. | Optional: {} | |
lastApply ApplySummary | Résumé du dernier apply : date, résultat et message. | Optional: {} | |
activeJob string | ActiveJob : exécution en cours (une seule à la fois par Workspace). | Optional: {} | |
nextRunAt Time | NextRunAt : prochain run périodique. | Optional: {} | |
inputsHash string | InputsHash : empreinte des entrées (spec, secrets, Providers, outputs des parents) du dernier run réussi. | Optional: {} | |
lastRunJob string | LastRunJob : dernière exécution dont le résultat a été pris en compte. | Optional: {} | |
lastRunAt Time | LastRunAt : fin du dernier run. | Optional: {} | |
consecutiveFailures integer | ConsecutiveFailures : échecs consécutifs (backoff des reprises), remis à zéro par un succès. | Optional: {} | |
dependencies DependencyStatus array | Dependencies : état des Workspace parents. | Optional: {} | |
lock LockStatus | Lock : lock de state tenu par un tiers, qui bloque les runs. | Optional: {} |
ModuleSource
ModuleSource : module OpenTofu publié en OCI au format natif (artifactType application/vnd.opentofu.modulepkg, une couche archive/zip).
| Champ | Description | Défaut | Validation |
|---|---|---|---|
source string | Source : adresse oci://<registry>/<repository>, sans tag ni digest. | Pattern: ^oci://[^?@]+$ | |
tag string | Tag de l'artefact. Absent avec digest absent = "latest". | Optional: {} | |
digest string | Digest du manifest (sha256:…), prioritaire sur tout tag. | Pattern: ^sha256:[a-f0-9]\{64\}$ Optional: {} | |
pullSecretRef LocalObjectReference | PullSecretRef : secret d'accès au registre (format dockerconfigjson) de votre tenant. Absent = accès par défaut de la plateforme, en lecture seule, au dépôt des modules partagés. | Optional: {} |
LocalRef
LocalRef : référence par nom à un objet de votre tenant.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Nom de l'objet dans votre tenant. | MinLength: 1 |
VarsFromSource
VarsFromSource : variables lues dans un secret de votre tenant ou dans les outputs d'un autre de vos Workspace (dépendance façon terragrunt). Exactement une source.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
secretRef SecretVarsRef | Secret de votre tenant et clé qui contiennent la valeur de la variable. | Optional: {} | |
workspaceOutputRef WorkspaceOutputRef | WorkspaceOutputRef : un output d'un autre de vos Workspace. Le Workspace attend que ce parent soit Ready et se relance quand ses outputs changent. | Optional: {} | |
varName string | VarName : nom de la variable. Absent = nom de la clé ou de l'output. | Pattern: ^[A-Za-z_][A-Za-z0-9_-]*$ Optional: {} | |
default string | Default : valeur utilisée tant que le parent n'a pas publié l'output (terragrunt mock_outputs). Elle ne permet qu'un plan, jamais un apply. | Optional: {} |
ImportSpec
ImportSpec : adoption d'une ressource existante par un bloc import déclaratif.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
to string | To : adresse de la ressource dans le module (ex. aws_s3_bucket.assets["logs"]). | Pattern: ^[a-zA-Z_][a-zA-Z0-9_-]*(\[[0-9]+\]|\["[^"\\$%]*"\])?(\.[a-zA-Z_][a-zA-Z0-9_-]*(\[[0-9]+\]|\["[^"\\$%]*"\])?)+$ | |
id string | ID : identifiant de la ressource chez le fournisseur. | MinLength: 1 Optional: {} | |
idFrom ImportIDSource | Identifiant lu dans un Secret ou dans l'output d'un autre Workspace, au lieu de id. | Optional: {} |
BackendSpec
BackendSpec : backend de state. Absent = state conservé par la plateforme.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
s3 S3Backend | Stockage objet propre à votre tenant, joint directement pendant l'exécution avec vos identifiants. | Optional: {} |
OutputsSpec
OutputsSpec : publication des outputs du module.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
secretName string | SecretName : secret de votre tenant, une clé par output (JSON si l'output n'est pas une chaîne). Absent = <name>-outputs. | MinLength: 1 Optional: {} |
RefreshSpec
RefreshSpec : run périodique. Absent = aucun run hors changement de spec ou de secret.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
interval Duration | Interval entre deux runs (Go duration, minimum 1m). | ||
mode RunMode | Mode du run périodique. | plan | Enum: [plan apply] Optional: {} |
Approval
Type sous-jacent : string
Approval : apply automatique ou après approbation du plan.
Règles de validation :
Enum: [auto manual]
| Valeur | Description |
|---|---|
auto | ApprovalAuto : l'apply suit le plan sans intervention. |
manual | ApprovalManual : l'apply attend l'approbation explicite du plan dont l'id figure dans status.lastPlan.id. |
DeletionPolicy
Type sous-jacent : string
DeletionPolicy : sort de l'infrastructure quand le Workspace est supprimé.
Règles de validation :
Enum: [Orphan Destroy]
| Valeur | Description |
|---|---|
Orphan | DeletionOrphan : l'infrastructure et le state restent en place. |
Destroy | DeletionDestroy : un tofu destroy est exécuté avant la suppression, qui attend sa fin. |
PlanSummary
PlanSummary : résultat du dernier plan.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
id string | ID du plan, à fournir pour l'approuver (approval: manual). | ||
at Time | Date du plan. | ||
add integer | Nombre de ressources à créer. | Optional: {} | |
change integer | Nombre de ressources à modifier. | Optional: {} | |
destroy integer | Nombre de ressources à détruire. | Optional: {} | |
import integer | Nombre de ressources à importer. | Optional: {} | |
hash string | Hash des resource_changes : l'apply approuvé est refusé s'il diffère. |
ApplySummary
ApplySummary : résultat du dernier apply.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
at Time | Date de l'apply. | ||
result string | Résultat : Succeeded, Failed, Rejected, Interrupted ou StateLocked. | Enum: [Succeeded Failed Rejected Interrupted StateLocked] | |
message string | Détail du résultat, notamment l'erreur en cas d'échec. | Optional: {} |
DependencyStatus
DependencyStatus : état d'un parent.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Nom du Workspace parent. | ||
ready boolean | Vrai quand le parent est Ready. | ||
outputsHash string | OutputsHash : empreinte du secret d'outputs du parent pris en compte. | Optional: {} |
LockStatus
LockStatus : lock de state tenu par un tiers, que la plateforme n'a pas levé (détenteur inconnu ou encore actif).
| Champ | Description | Défaut | Validation |
|---|---|---|---|
id string | Identifiant du verrou de state. | ||
who string | Qui tient le verrou. |
SecretVarsRef
SecretVarsRef : secret source de variables.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Nom du Secret de votre tenant. | MinLength: 1 | |
key string | Key : une seule clé. Absent = chaque clé du secret devient une variable. | Optional: {} |
WorkspaceOutputRef
WorkspaceOutputRef : un output publié par un autre Workspace de votre tenant.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Name du Workspace parent. | MinLength: 1 | |
output string | Output : nom de l'output du module parent. | Pattern: ^[A-Za-z_][A-Za-z0-9_-]*$ |
ImportIDSource
ImportIDSource : identifiant d'import lu hors de la spec.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
secretRef SecretKeyRef | Secret et clé qui contiennent l'identifiant à importer. | Optional: {} | |
workspaceOutputRef WorkspaceOutputRef | Output d'un autre de vos Workspace qui fournit l'identifiant à importer. | Optional: {} |
S3Backend
S3Backend : bucket de stockage objet de votre tenant (AWS ou compatible).
| Champ | Description | Défaut | Validation |
|---|---|---|---|
endpoint string | Endpoint d'un stockage objet compatible (ex. https://s3.gra.io.cloud.ovh.net). Absent = AWS. | Optional: {} | |
region string | Région du bucket. | MinLength: 1 | |
bucket string | Nom du bucket qui conserve le state. | MinLength: 1 | |
key string | Key de l'objet de state. Absent = une clé propre à votre tenant, terminée par <name>.tfstate. | Optional: {} | |
credentialsSecretRef LocalObjectReference | CredentialsSecretRef : secret aux clés AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY. | ||
lockfile boolean | Lockfile : lock natif par fichier (use_lockfile). Le bucket doit gérer les écritures conditionnelles (AWS oui, OVH Object Storage non). Sans lock, la plateforme exécute quand même les runs d'un Workspace un par un. | Optional: {} |
RunMode
Type sous-jacent : string
RunMode : ce que fait un run périodique.
Règles de validation :
Enum: [plan apply]
| Valeur | Description |
|---|---|
plan | ModePlan : plan seul, détection de dérive (condition Drifted). |
apply | ModeApply : plan puis apply. |
SecretKeyRef
SecretKeyRef : une clé d'un secret de votre tenant.
| Champ | Description | Défaut | Validation |
|---|---|---|---|
name string | Nom du Secret de votre tenant. | MinLength: 1 | |
key string | Clé du Secret qui contient la valeur. | MinLength: 1 |
Status and conditions
| Condition | True when |
|---|---|
Ready | The last apply succeeded and no input has changed since |
Drifted | The last plan shows unapplied changes |
Planning / Applying | A run is in progress |
AwaitingApproval | A plan is waiting for your approval (approval: manual) |
Failed | The last run failed; consecutiveFailures counts |
reason | Meaning | Action |
|---|---|---|
ProviderMismatch | The referenced Provider does not match the module's required_providers | Fix the Provider's type/source |
DependencyCycle | Loop in dependsOn or workspaceOutputRef | Break the cycle |
BlockedByDependents | Destroy deletion blocked by children | Delete the children first |
ImportTargetMissing | The to address of an import does not exist in the module | Fix the address |
PlanChangedSinceApproval | The approved plan no longer matches the real state | Approve the new plan again |
StateLocked | Lock held by a third party | Contact support |
SecretNotFound | Secret of varsFrom, imports, or backend missing | Create the secret |
status.lastPlan: id, at, add, change, destroy, import, hash.
status.lastApply: at, result (Succeeded, Failed, Rejected, Interrupted,
StateLocked), message. Also: nextRunAt, activeJob, lastRunJob, inputsHash,
dependencies[], lock{id, who}.
What happens on apply and deletion
- Creation: a run starts as soon as the parents are
Readyand the secrets are present. - Update: any input change triggers a new run;
suspend: truesuspends them. - Deletion: with
Orphan, the manifest and its state disappear, the infrastructure created stays in place; withDestroy, the infrastructure is destroyed first, in reverse dependency order.
Common errors
tag et digest sont exclusifs: choose one of the two.- Plan that never progresses: a parent is not
Ready, or adefaultis missing to plan before publication. Interrupted: the run was stopped cleanly; the next one re-plans against the real state, nothing to do.