Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions docs/resources/script_order.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "coder_script_order Resource - terraform-provider-coder"
subcategory: ""
description: |-
Use this resource to declare ordering constraints between coder_script resources on an agent. Multiple coder_script_order resources are additive; each rule block adds edges to the startup dependency graph. Reference scripts by their id, e.g. coder_script.install.id.
---

# coder_script_order (Resource)

Use this resource to declare ordering constraints between `coder_script` resources on an agent. Multiple `coder_script_order` resources are additive; each `rule` block adds edges to the startup dependency graph. Reference scripts by their id, e.g. `coder_script.install.id`.

## Example Usage

```terraform
resource "coder_agent" "dev" {
os = "linux"
arch = "amd64"
}

resource "coder_script" "clone" {
agent_id = coder_agent.dev.id
display_name = "clone"
script = "git clone ..."
run_on_start = true
}

resource "coder_script" "install" {
agent_id = coder_agent.dev.id
display_name = "install"
script = "make install"
run_on_start = true
}

# install waits until clone completes.
resource "coder_script_order" "startup" {
rule {
run = [coder_script.install.id]
after = [coder_script.clone.id]
state = "completes"
}
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- `rule` (Block List) Each `rule` block declares that the scripts in `run` must wait for the scripts in `after` to reach `state`. (see [below for nested schema](#nestedblock--rule))

### Read-Only

- `id` (String) The ID of this resource.

<a id="nestedblock--rule"></a>
### Nested Schema for `rule`

Required:

- `run` (List of String) The ids of the `coder_script` resources this rule applies to (e.g. `coder_script.install.id`).

Optional:

- `after` (List of String) The ids of the `coder_script` resources that must reach `state` before the `run` scripts start.
- `state` (String) The lifecycle state the `after` scripts must reach before the `run` scripts may start. One of `completes` or `starts`.
27 changes: 27 additions & 0 deletions examples/resources/coder_script_order/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
resource "coder_agent" "dev" {
os = "linux"
arch = "amd64"
}

resource "coder_script" "clone" {
agent_id = coder_agent.dev.id
display_name = "clone"
script = "git clone ..."
run_on_start = true
}

resource "coder_script" "install" {
agent_id = coder_agent.dev.id
display_name = "install"
script = "make install"
run_on_start = true
}

# install waits until clone completes.
resource "coder_script_order" "startup" {
rule {
run = [coder_script.install.id]
after = [coder_script.clone.id]
state = "completes"
}
}
1 change: 1 addition & 0 deletions provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func New() *schema.Provider {
"coder_app": appResource(),
"coder_metadata": metadataResource(),
"coder_script": scriptResource(),
"coder_script_order": scriptOrderResource(),
"coder_env": envResource(),
"coder_devcontainer": devcontainerResource(),
"coder_external_agent": externalAgentResource(),
Expand Down
64 changes: 64 additions & 0 deletions provider/script_order.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package provider

import (
"context"

"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func scriptOrderResource() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,

Description: "Use this resource to declare ordering constraints between `coder_script` resources on an agent. Multiple `coder_script_order` resources are additive; each `rule` block adds edges to the startup dependency graph. Reference scripts by their id, e.g. `coder_script.install.id`.",
CreateContext: func(_ context.Context, rd *schema.ResourceData, _ interface{}) diag.Diagnostics {
rd.SetId(uuid.NewString())
// Validate that every rule declares at least one script to run.
rules, _ := rd.Get("rule").([]interface{})
for i, raw := range rules {
m, _ := raw.(map[string]interface{})
run, _ := m["run"].([]interface{})
if len(run) == 0 {
return diag.Errorf("rule[%d]: \"run\" must contain at least one coder_script id", i)
}
}
return nil
},
ReadContext: schema.NoopContext,
DeleteContext: schema.NoopContext,
Schema: map[string]*schema.Schema{
"rule": {
Type: schema.TypeList,
Description: "Each `rule` block declares that the scripts in `run` must wait for the scripts in `after` to reach `state`.",
ForceNew: true,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"run": {
Type: schema.TypeList,
Description: "The ids of the `coder_script` resources this rule applies to (e.g. `coder_script.install.id`).",
Required: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"after": {
Type: schema.TypeList,
Description: "The ids of the `coder_script` resources that must reach `state` before the `run` scripts start.",
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"state": {
Type: schema.TypeString,
Description: "The lifecycle state the `after` scripts must reach before the `run` scripts may start. One of `completes` or `starts`.",
Optional: true,
Default: "completes",
ValidateFunc: validation.StringInSlice([]string{"completes", "starts"}, false),
},
},
},
},
},
}
}
69 changes: 69 additions & 0 deletions provider/script_order_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package provider_test

import (
"regexp"
"testing"

"github.com/stretchr/testify/require"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestScriptOrder(t *testing.T) {
t.Parallel()

resource.Test(t, resource.TestCase{
ProviderFactories: coderFactory(),
IsUnitTest: true,
Steps: []resource.TestStep{{
Config: `
provider "coder" {
}
resource "coder_script_order" "startup" {
rule {
run = ["coder_script.install.id"]
after = ["coder_script.clone.id"]
state = "completes"
}
}
`,
Check: func(state *terraform.State) error {
require.Len(t, state.Modules, 1)
require.Len(t, state.Modules[0].Resources, 1)
order := state.Modules[0].Resources["coder_script_order.startup"]
require.NotNil(t, order)
t.Logf("script_order attributes: %#v", order.Primary.Attributes)
for key, expected := range map[string]string{
"rule.#": "1",
"rule.0.run.0": "coder_script.install.id",
"rule.0.state": "completes",
} {
require.Equal(t, expected, order.Primary.Attributes[key])
}
return nil
},
}},
})
}

func TestScriptOrderEmptyRun(t *testing.T) {
t.Parallel()

resource.Test(t, resource.TestCase{
ProviderFactories: coderFactory(),
IsUnitTest: true,
Steps: []resource.TestStep{{
Config: `
provider "coder" {
}
resource "coder_script_order" "startup" {
rule {
run = []
}
}
`,
ExpectError: regexp.MustCompile(`"run" must contain at least one coder_script id`),
}},
})
}
Loading