Skip to main content

Workspace

Coming soon

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.

apiVersiontofu.stackngo.io/v1alpha1
kindWorkspace
Applied bysng apply (upcoming)
Related commandssng 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.tag and module.digest are mutually exclusive; digest follows ^sha256:[a-f0-9]{64}$.
  • In varsFrom, exactly one source: secretRef or workspaceOutputRef; varName requires secretRef.key; default only exists with workspaceOutputRef.
  • In imports, exactly one identifier: id or idFrom.
  • refresh.interval is at least 1m.

Workspace​

Workspace applique un module OpenTofu publié en OCI, dans des exécutions propres à votre tenant.

ChampDescriptionDéfautValidation
apiVersion stringtofu.stackngo.io/v1alpha1
kind stringWorkspace
metadata ObjectMetaSeul metadata.name est à renseigner (nom de la ressource dans votre tenant).
spec WorkspaceSpec
status WorkspaceStatus

WorkspaceSpec​

WorkspaceSpec : module OCI à appliquer et ses entrées.

ChampDescriptionDéfautValidation
module ModuleSourceModule OpenTofu à appliquer : adresse OCI, version (tag) ou empreinte (digest).
providers LocalRef arrayProviders : Provider de votre tenant câblés dans le run (bloc provider généré).Optional: {}
dependsOn LocalRef arrayDependsOn : Workspace de votre tenant qui doivent être Ready avant tout run (ordre seul).Optional: {}
vars JSONVars : valeurs JSON libres, écrites dans terraform.tfvars.json.Type: object
Optional: {}
varsFrom VarsFromSource arrayVarsFrom : variables secrètes, injectées en TF_VAR_<nom>. Prioritaires sur Vars.Optional: {}
imports ImportSpec arrayImports : ressources existantes adoptées par des blocs import (no-op une fois dans le state).Optional: {}
backend BackendSpecOù conserver le state. Absent : la plateforme le conserve pour vous.Optional: {}
outputs OutputsSpecOù publier les outputs du module.Optional: {}
refresh RefreshSpecExécution périodique pour détecter la dérive. Absent : aucun run hors changement de manifeste ou de secret.Optional: {}
approval Approvalauto (défaut) applique le plan sans intervention ; manual attend votre approbation du plan.autoEnum: [auto manual]
Optional: {}
deletionPolicy DeletionPolicySort de l'infrastructure à la suppression du Workspace : Orphan (défaut) la laisse en place, Destroy la détruit d'abord.OrphanEnum: [Orphan Destroy]
Optional: {}
suspend booleanSuspend : aucun nouveau run tant que vrai.Optional: {}
resources ResourceRequirementsResources : ressources du conteneur tofu. Absent = valeurs par défaut de la plateforme.Optional: {}

WorkspaceStatus​

WorkspaceStatus : état observé.

ChampDescriptionDéfautValidation
observedGeneration integerDernière version du manifeste prise en compte par la plateforme.Optional: {}
conditions Condition arrayConditions : Ready, Drifted, Planning, Applying, AwaitingApproval, Failed.Optional: {}
lastPlan PlanSummaryRésumé du dernier plan : identifiant, date et nombre de changements.Optional: {}
lastApply ApplySummaryRésumé du dernier apply : date, résultat et message.Optional: {}
activeJob stringActiveJob : exécution en cours (une seule à la fois par Workspace).Optional: {}
nextRunAt TimeNextRunAt : prochain run périodique.Optional: {}
inputsHash stringInputsHash : empreinte des entrées (spec, secrets, Providers, outputs des parents)
du dernier run réussi.
Optional: {}
lastRunJob stringLastRunJob : dernière exécution dont le résultat a été pris en compte.Optional: {}
lastRunAt TimeLastRunAt : fin du dernier run.Optional: {}
consecutiveFailures integerConsecutiveFailures : échecs consécutifs (backoff des reprises), remis à zéro par un succès.Optional: {}
dependencies DependencyStatus arrayDependencies : état des Workspace parents.Optional: {}
lock LockStatusLock : 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).

ChampDescriptionDéfautValidation
source stringSource : adresse oci://<registry>/<repository>, sans tag ni digest.Pattern: ^oci://[^?@]+$
tag stringTag de l'artefact. Absent avec digest absent = "latest".Optional: {}
digest stringDigest du manifest (sha256:…), prioritaire sur tout tag.Pattern: ^sha256:[a-f0-9]\{64\}$
Optional: {}
pullSecretRef LocalObjectReferencePullSecretRef : 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.

ChampDescriptionDéfautValidation
name stringNom 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.

ChampDescriptionDéfautValidation
secretRef SecretVarsRefSecret de votre tenant et clé qui contiennent la valeur de la variable.Optional: {}
workspaceOutputRef WorkspaceOutputRefWorkspaceOutputRef : 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 stringVarName : nom de la variable. Absent = nom de la clé ou de l'output.Pattern: ^[A-Za-z_][A-Za-z0-9_-]*$
Optional: {}
default stringDefault : 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.

ChampDescriptionDéfautValidation
to stringTo : 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 stringID : identifiant de la ressource chez le fournisseur.MinLength: 1
Optional: {}
idFrom ImportIDSourceIdentifiant 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.

ChampDescriptionDéfautValidation
s3 S3BackendStockage objet propre à votre tenant, joint directement pendant l'exécution avec vos identifiants.Optional: {}

OutputsSpec​

OutputsSpec : publication des outputs du module.

ChampDescriptionDéfautValidation
secretName stringSecretName : 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.

ChampDescriptionDéfautValidation
interval DurationInterval entre deux runs (Go duration, minimum 1m).
mode RunModeMode du run périodique.planEnum: [plan apply]
Optional: {}

Approval​

Type sous-jacent : string

Approval : apply automatique ou après approbation du plan.

Règles de validation :

  • Enum: [auto manual]
ValeurDescription
autoApprovalAuto : l'apply suit le plan sans intervention.
manualApprovalManual : 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]
ValeurDescription
OrphanDeletionOrphan : l'infrastructure et le state restent en place.
DestroyDeletionDestroy : un tofu destroy est exécuté avant la suppression, qui attend sa fin.

PlanSummary​

PlanSummary : résultat du dernier plan.

ChampDescriptionDéfautValidation
id stringID du plan, à fournir pour l'approuver (approval: manual).
at TimeDate du plan.
add integerNombre de ressources à créer.Optional: {}
change integerNombre de ressources à modifier.Optional: {}
destroy integerNombre de ressources à détruire.Optional: {}
import integerNombre de ressources à importer.Optional: {}
hash stringHash des resource_changes : l'apply approuvé est refusé s'il diffère.

ApplySummary​

ApplySummary : résultat du dernier apply.

ChampDescriptionDéfautValidation
at TimeDate de l'apply.
result stringRésultat : Succeeded, Failed, Rejected, Interrupted ou StateLocked.Enum: [Succeeded Failed Rejected Interrupted StateLocked]
message stringDétail du résultat, notamment l'erreur en cas d'échec.Optional: {}

DependencyStatus​

DependencyStatus : état d'un parent.

ChampDescriptionDéfautValidation
name stringNom du Workspace parent.
ready booleanVrai quand le parent est Ready.
outputsHash stringOutputsHash : 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).

ChampDescriptionDéfautValidation
id stringIdentifiant du verrou de state.
who stringQui tient le verrou.

SecretVarsRef​

SecretVarsRef : secret source de variables.

ChampDescriptionDéfautValidation
name stringNom du Secret de votre tenant.MinLength: 1
key stringKey : une seule clé. Absent = chaque clé du secret devient une variable.Optional: {}

WorkspaceOutputRef​

WorkspaceOutputRef : un output publié par un autre Workspace de votre tenant.

ChampDescriptionDéfautValidation
name stringName du Workspace parent.MinLength: 1
output stringOutput : 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.

ChampDescriptionDéfautValidation
secretRef SecretKeyRefSecret et clé qui contiennent l'identifiant à importer.Optional: {}
workspaceOutputRef WorkspaceOutputRefOutput d'un autre de vos Workspace qui fournit l'identifiant à importer.Optional: {}

S3Backend​

S3Backend : bucket de stockage objet de votre tenant (AWS ou compatible).

ChampDescriptionDéfautValidation
endpoint stringEndpoint d'un stockage objet compatible (ex. https://s3.gra.io.cloud.ovh.net). Absent = AWS.Optional: {}
region stringRégion du bucket.MinLength: 1
bucket stringNom du bucket qui conserve le state.MinLength: 1
key stringKey de l'objet de state. Absent = une clé propre à votre tenant, terminée par <name>.tfstate.Optional: {}
credentialsSecretRef LocalObjectReferenceCredentialsSecretRef : secret aux clés AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY.
lockfile booleanLockfile : 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]
ValeurDescription
planModePlan : plan seul, détection de dérive (condition Drifted).
applyModeApply : plan puis apply.

SecretKeyRef​

SecretKeyRef : une clé d'un secret de votre tenant.

ChampDescriptionDéfautValidation
name stringNom du Secret de votre tenant.MinLength: 1
key stringClé du Secret qui contient la valeur.MinLength: 1

Status and conditions​

ConditionTrue when
ReadyThe last apply succeeded and no input has changed since
DriftedThe last plan shows unapplied changes
Planning / ApplyingA run is in progress
AwaitingApprovalA plan is waiting for your approval (approval: manual)
FailedThe last run failed; consecutiveFailures counts
reasonMeaningAction
ProviderMismatchThe referenced Provider does not match the module's required_providersFix the Provider's type/source
DependencyCycleLoop in dependsOn or workspaceOutputRefBreak the cycle
BlockedByDependentsDestroy deletion blocked by childrenDelete the children first
ImportTargetMissingThe to address of an import does not exist in the moduleFix the address
PlanChangedSinceApprovalThe approved plan no longer matches the real stateApprove the new plan again
StateLockedLock held by a third partyContact support
SecretNotFoundSecret of varsFrom, imports, or backend missingCreate 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 Ready and the secrets are present.
  • Update: any input change triggers a new run; suspend: true suspends them.
  • Deletion: with Orphan, the manifest and its state disappear, the infrastructure created stays in place; with Destroy, 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 a default is missing to plan before publication.
  • Interrupted: the run was stopped cleanly; the next one re-plans against the real state, nothing to do.

See also​