跳到主要内容
Deno 2.4 现已发布,包含 deno bundle、字节/文本导入、OTel 稳定版等功能
了解更多
Terraform

使用 Terraform 管理你的 Deno Deploy 和 Deno Subhosting 项目

我们最近推出了Deno Subhosting(基于Deno Deploy基础设施),它是运行和托管用户代码最简便、最安全的方式。公司可以使用 Subhosting 通过开发者平台或第三方应用市场来扩展其产品功能。Deno Subhosting 简洁的 API 使其易于集成到你的平台,从而可以编程方式管理部署、项目等。

然而,许多开发者更喜欢使用 Terraform 等基础设施即代码模式来管理云中的关键业务基础设施,因为这是一种安全、可靠且可预测的方式来配置和管理云服务。现在,我们很高兴地宣布,你可以通过我们官方的Deno Terraform Provider 来使用 Deno Subhosting 和 Deno Deploy。

该 Provider 将允许你使用 Terraform 管理大量的项目、自定义域名、部署等。我们将维护此 Provider 并使其与新的Subhosting API保持同步。

尽管我们仍在完善文档,但你可以在这里找到自动生成的 Provider 文档,以及在 GitHub 中找到许多可运行的示例

请继续阅读以了解更多信息

如何将本地代码目录发布到 Deno Deploy

为了给你一个 Deno Terraform Provider 如何工作的例子,我们来演示一个将本地代码目录发布到 Deno Deploy 的示例。

给定以下项目结构(本示例已简化)

.
├── deno.json
├── src
│   └── main.ts
├── static
│   └── cat.png
└── terraform
    └── main.tf

我们希望部署 `src/main.ts`,它访问 `static/cat.png` 和一个环境变量 `FOO`

Deno.serve(async (req) => {
  const url = new URL(req.url);

  // Respond with `cat.png` if requested to `/cat.png`.
  // Otherwise respond with the value of env var `FOO`.
  switch (url.pathname) {
    case "/cat.png": {
      const file = await Deno.open("./static/cat.png");
      return new Response(file.readable, {
        headers: {
          "content-type": "image/png",
        },
      });
    }
    default: {
      return new Response(`FOO is ${Deno.env.get("FOO")}`);
    }
  }
});

定义 Terraform 文件

接下来,我们来定义 `.tf` 文件。请注意,有两个必需参数:你的组织 ID 和一个访问令牌,你可以在部署仪表板上生成。在下面的示例中,我们将这些硬编码到 terraform 文件中;或者,你可以通过环境变量 `DENO_DEPLOY_ORGANIZATION_ID` 和 `DENO_DEPLOY_TOKEN` 分别传递它们。

terraform {
  required_providers {
    deno = {
      source = "denoland/deno"
    }
  }
}

provider "deno" {
  // As an alternative to specifying your organization ID in the terraform code
  // itself, you can also use the `DENO_DEPLOY_ORGANIZATION_ID` environment
  // variable.
  organization_id = "e1ae3bcc-923e-4930-a6a7-5841e69849ed"

    // Similarly, you may omit the token here and use the `DENO_DEPLOY_TOKEN`
  // environment variable.
  token = "ddo_3JfdN41GxH0PufmzcoahcJtQXcbde144Z7l9"
}

接下来,让我们使用 `deno_project` 资源创建一个项目。请注意,`name` 是可选的(如果省略,将自动生成一个随机名称),但它必须是全局唯一的。

resource "deno_project" "sample_project" {
  name = "awesome-deno-40"
}

然后,让我们使用 `deno_assets` 数据源定义“资产”。你可以将其视为一组要上传的文件。第一个必需参数 `path` 用作 Terraform 查找资产的根目录路径。第二个参数 `pattern` 是一个 glob 字符串,其匹配项决定要包含哪些资产。

在此示例中,将包含 `src/main.ts` 和 `static/cat.png`

data "deno_assets" "sample_assets" {
  path    = "../"
  pattern = "{src,static}/**/*.{ts,png}"
}

我们现在准备好使用 `deno_deployment` 资源创建部署。此资源接受到目前为止已创建的 `project_id` 和 `assets` 数据参数。还可以提供其他参数,例如 `env_vars`。(有关更多详细信息,请查看此使用示例。)

resource "deno_deployment" "sample_deployment" {
  project_id      = deno_project.sample_project.id
  entry_point_url = "src/main.ts"
  assets          = data.deno_assets.sample_assets.output
  env_vars = {
    FOO = "42"
  }
}

就是这样!

运行 Terraform

我们运行 `terraform plan` 来查看是否配置正确

$ cd terraform
$ terraform plan
data.deno_assets.sample_assets: Reading...
data.deno_assets.sample_assets: Read complete after 0s

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # deno_deployment.sample_deployment will be created
  + resource "deno_deployment" "sample_deployment" {
      + assets          = {
          + "src/main.ts" = {
              + content_source_path = "../src/main.ts"
              + kind                = "file"
            },
          + "static/cat.png" = {
              + content_source_path = "../static/cat.png"
              + kind                = "file"
            },
        }
      + created_at      = (known after apply)
      + deployment_id   = (known after apply)
      + domains         = (known after apply)
      + entry_point_url = "src/main.ts"
      + env_vars        = {
          + "FOO" = "42"
        }
      + project_id      = (known after apply)
      + status          = (known after apply)
      + updated_at      = (known after apply)
      + uploaded_assets = (known after apply)
    }

  # deno_project.sample_project will be created
  + resource "deno_project" "sample_project" {
      + created_at = (known after apply)
      + id         = (known after apply)
      + name       = "awesome-deno-40"
      + updated_at = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.

看起来不错!现在我们运行 `terraform apply`。

$ terraform apply
data.deno_assets.sample_assets: Reading...
data.deno_assets.sample_assets: Read complete after 0s

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # deno_deployment.sample_deployment will be created
  + resource "deno_deployment" "sample_deployment" {
      + assets          = {
          + "src/main.ts" = {
              + content_source_path = "../src/main.ts"
              + kind                = "file"
            },
          + "static/cat.png" = {
              + content_source_path = "../static/cat.png"
              + kind                = "file"
            },
        }
      + created_at      = (known after apply)
      + deployment_id   = (known after apply)
      + domains         = (known after apply)
      + entry_point_url = "src/main.ts"
      + env_vars        = {
          + "FOO" = "42"
        }
      + project_id      = (known after apply)
      + status          = (known after apply)
      + updated_at      = (known after apply)
      + uploaded_assets = (known after apply)
    }

  # deno_project.sample_project will be created
  + resource "deno_project" "sample_project" {
      + created_at = (known after apply)
      + id         = (known after apply)
      + name       = "awesome-deno-40"
      + updated_at = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

deno_project.sample_project: Creating...
deno_project.sample_project: Creation complete after 0s [id=82672716-5aee-4279-a7da-3a3554ec9f74]
deno_deployment.sample_deployment: Creating...
deno_deployment.sample_deployment: Creation complete after 4s

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

完成!让我们查看 Terraform 状态以获取访问部署的 URL

$ terraform state show deno_deployment.sample_deployment
# deno_deployment.sample_deployment:
resource "deno_deployment" "sample_deployment" {
    // ...
    deployment_id   = "rpxayrskrhzt"
    domains         = [
        "awesome-deno-40-rpxayrskrhzt.deno.dev",
    ]
    entry_point_url = "src/main.ts"
    // ...
}

为了检查我们的代码是否成功部署到 Deno Deploy 并正常工作,让我们访问https://awesome-deno-40-rpxayrskrhzt.deno.dev/,它应该显示已配置的环境变量。此外,访问https://awesome-deno-40-rpxayrskrhzt.deno.dev/cat.png应该显示你可爱的猫图片。

Cute cat picture

下一步

尽管 Deno Subhosting 提供了简单的 API 来管理 Deno Deploy 上的项目、部署等,但对于熟悉基础设施即代码模式的人来说,使用 Deno Terraform Provider 会更简单,尤其是在协调数百个项目时。

我们希望能添加更多文档和示例,但如果你需要技术帮助,请加入我们活跃的 Discord 群组在此处创建问题

💡️ 了解如何通过 Deno Subhosting 释放平台最后 10% 的价值,在我们的直播中,Kevin 和 Bert 将分享创新公司的 Subhosting 示例并演示 Subhosting API。

Linkedin Event