Terraform integration
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
調査の方向性
The issue describes a new Terraform hosting integration with environment and CLI resource types, configuration helpers, and deployment pipeline steps, but names no source files or tests. Start by locating the hosting integrations and their pipeline step patterns, then read the targeted Aspire version’s ATS exports and adapters. Done means implementing and validating the described resources, helpers, execution behavior, and pipeline support across the listed scenarios.
索引モデルが issue の本文から書いたものです。
説明
Aspire issue link
No response
Overview
Applications often need Terraform-managed configuration or infrastructure alongside their Aspire resources: identity provider configuration, external services, or infrastructure required before deployment.
Today, integrating an existing Terraform module requires manually composing executable resources, propagating input variables and backend settings, ordering commands, and implementing deployment pipeline steps. The local development workflow and CI deployment workflow can easily diverge, particularly when applying a previously reviewed plan.
There is no dedicated Terraform hosting resource that:
- Models a module with shared variables, backend configuration, and workspace selection
- Executes Terraform commands as observable Aspire resources with completion dependencies
- Uses Aspire parameters and reference expressions as Terraform inputs
- Exposes init, plan, apply, and destroy as Aspire deployment pipeline steps
- Applies the same saved plan across separate planning and approval stages
A CommunityToolkit.Aspire.Hosting.Terraform integration with the following resource types:
| Resource | Type | Description |
|---|---|---|
TerraformEnvironmentResource |
Resource |
Logical Terraform module with shared configuration and declared operations; starts no process |
TerraformCliResource |
ExecutableResource |
Runs one Terraform command from a configured module directory |
AddTerraformEnvironment creates the logical module. WithInit, WithPlan, WithApply, and WithDestroy declare its operations, creating child TerraformCliResource instances through AddTerraformCli and registering corresponding pipeline steps.
AddTerraformCli is also available directly for standalone commands and explicitly composed workflows.
Usage example
Terraform environment
var serviceUrl = builder.AddParameter("service-url");
var serviceToken = builder.AddParameter("service-token", secret: true);
var infrastructure = builder.AddTerraformEnvironment("infrastructure", "./terraform")
.WithTfVar("service_url", serviceUrl)
.WithTfVar("service_token", serviceToken)
.WithTfVarsFile("./configuration/production.tfvars")
.WithBackendConfigFile("./configuration/backend.hcl")
.WithWorkspace("production")
.WithInit()
.WithPlan(outputPath: "./artifacts/infrastructure.tfplan")
.WithApply(apply => apply.WithExplicitStart())
.WithDestroy();
Each operation accepts a callback receiving its IResourceBuilder<TerraformCliResource>:
infrastructure.WithPlan(configure: plan => plan
.WithArgs("-lock-timeout=60s")
.WithTfVar("validation_mode", "strict"));
Additional arguments and operation-specific environment values are used by both the local resource and its pipeline step. Repeating an operation declaration reuses its existing resource.
Standalone CLI resources
var init = builder.AddTerraformCli("module-init", "./terraform")
.WithBackendConfigFile("./configuration/backend.hcl")
.WithInit();
var plan = builder.AddTerraformCli("module-plan", "./terraform")
.WithTfVar("service_token", serviceToken)
.WithPlan("-out=review.tfplan")
.WaitForCompletion(init);
builder.AddTerraformCli("module-apply", "./terraform")
.WithApply(args: ["review.tfplan"])
.WaitForCompletion(plan)
.WithExplicitStart();
builder.AddTerraformCli("module-validate", "./terraform")
.WithArgs("validate", "-no-color")
.WaitForCompletion(init);
Standalone operation helpers select the command on the existing resource. They do not create sibling resources, infer dependencies, or register Terraform pipeline steps.
WithApply(bool autoApprove = false, params string[] args) and WithDestroy(bool autoApprove = false, bool explicitStart = true, params string[] args) support explicitly requested auto-approval. WithExplicitStart controls process startup, not Terraform's interactive approval prompt.
Variables and state backend
Configuration helpers target ITerraformConfigurableResource, implemented by both resource types:
var stateConnection = builder.AddParameter("terraform-state-connection", secret: true);
var stateSchema = builder.AddParameter("terraform-state-schema");
infrastructure
.WithPostgresBackend(ReferenceExpression.Create($"{stateConnection}"))
.WithBackendConfig("schema_name", stateSchema)
.WithTfVar("service_url", serviceUrl)
.WithTfVar("service_token", serviceToken)
.WithTfVar("deployment_name", "production");
WithTfVaraccepts strings, parameter builders, and Aspire values implementingIValueProviderandIManifestExpressionProvider, including endpoint references and reference expressions. It setsTF_VAR_<name>.WithTfVarsFile(path)adds a variable file for plan, apply without a saved plan, and destroy. Multiple calls accumulate in call order.WithBackendConfig(key, value)accepts strings, parameters, or reference expressions;WithBackendConfigFile(path)supplies a backend configuration file. Both apply only to init.WithPostgresBackend(connectionString, schema: null)setsPG_CONN_STRand optionallyPG_SCHEMA_NAME. The module must already declarebackend "pg" {}.- Other backends and provider credential chains use backend configuration and standard
WithEnvironmentcalls.
Deployment pipeline
Every declared environment operation registers a pipeline step:
| Declaration | Local child resource | Pipeline step |
|---|---|---|
WithInit() |
<name>-init |
terraform-init-<name> |
WithPlan() |
<name>-plan |
terraform-plan-<name> |
WithApply() |
<name>-apply |
terraform-apply-<name> |
WithDestroy() |
<name>-destroy |
terraform-destroy-<name> |
Pipeline attachment and chaining are configurable:
infrastructure.WithPipelineOptions(options =>
{
options.ChainSteps = false;
options.RequiredByDeploy = true;
options.RequiredByDestroy = true;
});
These are the defaults. Operation steps are independent unless ChainSteps is enabled; declared apply and destroy steps participate in aspire deploy and aspire destroy, respectively.
A CI workflow with a separate approval stage can:
- Run
aspire do terraform-init-infrastructure, thenaspire do terraform-plan-infrastructure. - Publish the saved plan as a restricted-access artifact and obtain approval.
- Restore the module, provider lock file, and saved plan at the configured path on the apply runner.
- Run init on that runner, then
aspire deployoraspire do terraform-apply-infrastructure.
With ChainSteps = true, plan depends on init, apply on plan (or init without a declared plan), and destroy on init. Applying with chaining creates a fresh plan rather than consuming only the previously approved artifact.
Additional context
- CLI resources as the execution primitive - the environment creates actual
TerraformCliResourcechildren. Their command, arguments, and environment configuration are also the source for pipeline execution, avoiding separate configuration paths. - Shared configuration evaluated at execution time - environment settings apply to all declared operations regardless of configuration order. Operation-specific environment values override shared values; parameters and expressions resolve when the command executes.
- Local completion dependencies - plan waits for declared init; apply waits for declared plan, or init without a plan; destroy waits for declared init. These local dependencies are separate from optional pipeline chaining.
- Saved-plan apply - environment
WithPlansaves a binary plan, defaulting to<module>/<name>.tfplan. Environment apply consumes that exact artifact and fails if it is missing; it never silently replans. Variable-file arguments are omitted for saved-plan apply, while unrelated apply settings are preserved. Terraform rejects stale plans. - Explicit destructive behavior - environment apply starts automatically after its prerequisites unless configured with
WithExplicitStart; without a declared plan it uses-auto-approve. Environment destroy uses-auto-approvebut always requires explicit local start. No destroy runs on AppHost shutdown. - Pipeline invocation is explicit execution, not dashboard startup - local
WithExplicitStartis not a CI approval gate. A declared operation can still execute through its pipeline step or enabled deploy/destroy hook. With default independent steps, CI must initialize the runner and supply the saved plan before invoking apply. - Automation and failures - pipeline execution uses
-input=false,-no-color,TF_INPUT=false, andTF_IN_AUTOMATION=true. Plan additionally uses-detailed-exitcode, treating 0 and 2 as success. Other nonzero exit codes fail the step; output is reported and cancellation terminates the process tree. - AppHost-relative paths - module directories, configuration files, and explicit environment plan paths resolve relative to the AppHost directory. Absolute paths are supported. The plan output directory is created before planning.
- Local tooling - Terraform must be installed on the AppHost or pipeline runner.
WithTerraformExecutablePathselects the environment executable and propagates it to every operation; standalone resources use standardWithCommand. - Execution-only resources - the environment and generated CLI children are excluded from deployment manifests. Deployment runs Terraform on the pipeline runner, not as a published application service. Local endpoints are not automatically translated into production endpoints.
- State and credential ownership - existing modules, workspaces, backends, and provider authentication remain under Terraform's control. The integration does not generate HCL, install Terraform, migrate state, or provision backend storage. State and plan artifacts can contain secrets; backend configuration may be persisted in
.terraform. Concurrent operations require isolated working copies and backend state locking. - Polyglot AppHosts - compatible resources and methods are exported through Aspire ATS, with adapters for variable unions and optional settings. Operation callbacks and pipeline option exports must be validated against the targeted Aspire version.
Help us help you
Yes, I'd like to be assigned to work on this item
- 主要言語
- C#
- スター
- 632
- フォーク
- 204
- 平均マージ
- 2日 18時間
- マージ済み PR(30日)
- 99
環境構築
このプロジェクトの開発コンテナを、あなたの GitHub アカウントでブラウザ上に起動します。
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
CommunityToolkit/Aspire のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
CommunityToolkit/Aspire#1622 · コメント 6 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 70/100
CommunityToolkit/Aspire#1620 · コメント 6 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 3/5 1〜2日 初心者へのやさしさ 66/100
CommunityToolkit/Aspire#2420 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
RavenDB Cloud hosting integration for aspire deploy対応中かも @poissoncorp が 3 日前に担当しました。 オープン
難易度 5/5 1週間以上 初心者へのやさしさ 20/100
CommunityToolkit/Aspire#2412 ·
メンテナーはふだん 1 日以内に返信
-
feature request :mailbox_with_mail:
難易度 5/5 1週間以上 初心者へのやさしさ 30/100
CommunityToolkit/Aspire#2342 · コメント 5 件 ·
メンテナーはふだん 1 日以内に返信
CommunityToolkit/Aspire の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
dotnet/wpf#12108 · リアクション 3 件 ·
メンテナーはふだん 1 日以内に返信
-
:watch: Not Triaged dotnet/svc
難易度 1/5 1時間未満 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
area:build type:chore
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
csharp good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
area-System.Collections untriaged
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
dotnet/runtime#137167 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信