From 6f4047fc8bfb9e0021475c1466dba19e04762146 Mon Sep 17 00:00:00 2001 From: kylecarbs Date: Thu, 9 Jun 2022 21:26:25 +0000 Subject: [PATCH] fix: Use explicit resource order when assocating agents This cleans up agent association code to explicitly map a single agent to a single resource. This will fix #1884, and unblock a prospect from beginning a POC. --- .vscode/settings.json | 1 + provisioner/terraform/resources.go | 297 +++++++++++------- provisioner/terraform/resources_test.go | 56 +++- .../calling-module/calling-module.tfplan.dot | 6 +- .../calling-module/calling-module.tfplan.json | 74 ++++- .../calling-module/calling-module.tfstate.dot | 6 +- .../calling-module.tfstate.json | 32 +- .../testdata/calling-module/module/module.tf | 8 +- .../chaining-resources/chaining-resources.tf | 10 +- .../chaining-resources.tfplan.dot | 18 +- .../chaining-resources.tfplan.json | 40 +-- .../chaining-resources.tfstate.dot | 18 +- .../chaining-resources.tfstate.json | 26 +- .../conflicting-resources.tf | 25 ++ .../conflicting-resources.tfplan.dot | 22 ++ .../conflicting-resources.tfplan.json | 178 +++++++++++ .../conflicting-resources.tfstate.dot | 22 ++ .../conflicting-resources.tfstate.json | 62 ++++ .../instance-id/instance-id.tfstate.json | 10 +- .../multiple-agents.tfstate.json | 14 +- .../multiple-apps/multiple-apps.tfstate.json | 14 +- 21 files changed, 723 insertions(+), 216 deletions(-) create mode 100644 provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf create mode 100644 provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot create mode 100644 provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json create mode 100644 provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot create mode 100644 provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 61f0037e8e4b9..0d81d15cc32b5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,6 +63,7 @@ "sdktrace", "Signup", "sourcemapped", + "Srcs", "stretchr", "TCGETS", "tcpip", diff --git a/provisioner/terraform/resources.go b/provisioner/terraform/resources.go index 2e075a5b02a53..044ad9837445a 100644 --- a/provisioner/terraform/resources.go +++ b/provisioner/terraform/resources.go @@ -11,6 +11,28 @@ import ( "github.com/coder/coder/provisionersdk/proto" ) +// A mapping of attributes on the "coder_agent" resource. +type agentAttributes struct { + Auth string `mapstructure:"auth"` + OperatingSystem string `mapstructure:"os"` + Architecture string `mapstructure:"arch"` + Directory string `mapstructure:"dir"` + ID string `mapstructure:"id"` + Token string `mapstructure:"token"` + Env map[string]string `mapstructure:"env"` + StartupScript string `mapstructure:"startup_script"` +} + +// A mapping of attributes on the "coder_app" resource. +type agentAppAttributes struct { + AgentID string `mapstructure:"agent_id"` + Name string `mapstructure:"name"` + Icon string `mapstructure:"icon"` + URL string `mapstructure:"url"` + Command string `mapstructure:"command"` + RelativePath bool `mapstructure:"relative_path"` +} + // ConvertResources consumes Terraform state and a GraphViz representation produced by // `terraform graph` to produce resources consumable by Coder. func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Resource, error) { @@ -22,52 +44,36 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res if err != nil { return nil, xerrors.Errorf("analyze graph: %w", err) } - resourceDependencies := map[string][]string{} - for _, node := range graph.Nodes.Nodes { - label, exists := node.Attrs["label"] - if !exists { - continue - } - label = strings.Trim(label, `"`) - resourceDependencies[label] = findDependenciesWithLabels(graph, node.Name) - } resources := make([]*proto.Resource, 0) - agents := map[string]*proto.Agent{} + resourceAgents := map[string][]*proto.Agent{} - tfResources := make([]*tfjson.StateResource, 0) - var appendResources func(mod *tfjson.StateModule) - appendResources = func(mod *tfjson.StateModule) { + // Indexes Terraform resources by it's label. The label + // is what "terraform graph" uses to reference nodes. + tfResourceByLabel := map[string]*tfjson.StateResource{} + var findTerraformResources func(mod *tfjson.StateModule) + findTerraformResources = func(mod *tfjson.StateModule) { for _, module := range mod.ChildModules { - appendResources(module) + findTerraformResources(module) + } + for _, resource := range mod.Resources { + tfResourceByLabel[convertAddressToLabel(resource.Address)] = resource } - tfResources = append(tfResources, mod.Resources...) - } - appendResources(module) - - type agentAttributes struct { - Auth string `mapstructure:"auth"` - OperatingSystem string `mapstructure:"os"` - Architecture string `mapstructure:"arch"` - Directory string `mapstructure:"dir"` - ID string `mapstructure:"id"` - Token string `mapstructure:"token"` - Env map[string]string `mapstructure:"env"` - StartupScript string `mapstructure:"startup_script"` } + findTerraformResources(module) - // Store all agents inside the maps! - for _, resource := range tfResources { - if resource.Type != "coder_agent" { + // Find all agents! + for _, tfResource := range tfResourceByLabel { + if tfResource.Type != "coder_agent" { continue } var attrs agentAttributes - err = mapstructure.Decode(resource.AttributeValues, &attrs) + err = mapstructure.Decode(tfResource.AttributeValues, &attrs) if err != nil { return nil, xerrors.Errorf("decode agent attributes: %w", err) } agent := &proto.Agent{ - Name: resource.Name, + Name: tfResource.Name, Id: attrs.ID, Env: attrs.Env, StartupScript: attrs.StartupScript, @@ -81,14 +87,56 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res Token: attrs.Token, } default: + // If token authentication isn't specified, + // assume instance auth. It's our only other + // authentication type! agent.Auth = &proto.Agent_InstanceId{} } - agents[convertAddressToLabel(resource.Address)] = agent + // The label is used to find the graph node! + agentLabel := convertAddressToLabel(tfResource.Address) + + var agentNode *gographviz.Node + for _, node := range graph.Nodes.Lookup { + // The node attributes surround the label with quotes. + if strings.Trim(node.Attrs["label"], `"`) != agentLabel { + continue + } + agentNode = node + break + } + if agentNode == nil { + return nil, xerrors.Errorf("couldn't find node on graph: %q", agentLabel) + } + + var agentResource *graphResource + for _, resource := range findResourcesUpGraph(graph, tfResourceByLabel, agentNode.Name, 0) { + if agentResource == nil { + // Default to the first resource because we have nothing to compare! + agentResource = resource + continue + } + if resource.Depth < agentResource.Depth { + // There's a closer resource! + agentResource = resource + continue + } + if resource.Depth == agentResource.Depth && resource.Label < agentResource.Label { + agentResource = resource + continue + } + } + + agents, exists := resourceAgents[agentResource.Label] + if !exists { + agents = make([]*proto.Agent, 0) + } + agents = append(agents, agent) + resourceAgents[agentResource.Label] = agents } // Manually associate agents with instance IDs. - for _, resource := range tfResources { + for _, resource := range tfResourceByLabel { if resource.Type != "coder_agent_instance" { continue } @@ -109,31 +157,25 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res continue } - for _, agent := range agents { - if agent.Id != agentID { - continue + for _, agents := range resourceAgents { + for _, agent := range agents { + if agent.Id != agentID { + continue + } + agent.Auth = &proto.Agent_InstanceId{ + InstanceId: instanceID, + } + break } - agent.Auth = &proto.Agent_InstanceId{ - InstanceId: instanceID, - } - break } } - type appAttributes struct { - AgentID string `mapstructure:"agent_id"` - Name string `mapstructure:"name"` - Icon string `mapstructure:"icon"` - URL string `mapstructure:"url"` - Command string `mapstructure:"command"` - RelativePath bool `mapstructure:"relative_path"` - } // Associate Apps with agents. - for _, resource := range tfResources { + for _, resource := range tfResourceByLabel { if resource.Type != "coder_app" { continue } - var attrs appAttributes + var attrs agentAppAttributes err = mapstructure.Decode(resource.AttributeValues, &attrs) if err != nil { return nil, xerrors.Errorf("decode app attributes: %w", err) @@ -142,58 +184,34 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res // Default to the resource name if none is set! attrs.Name = resource.Name } - for _, agent := range agents { - if agent.Id != attrs.AgentID { - continue + for _, agents := range resourceAgents { + for _, agent := range agents { + // Find agents with the matching ID and associate them! + if agent.Id != attrs.AgentID { + continue + } + agent.Apps = append(agent.Apps, &proto.App{ + Name: attrs.Name, + Command: attrs.Command, + Url: attrs.URL, + Icon: attrs.Icon, + RelativePath: attrs.RelativePath, + }) } - agent.Apps = append(agent.Apps, &proto.App{ - Name: attrs.Name, - Command: attrs.Command, - Url: attrs.URL, - Icon: attrs.Icon, - RelativePath: attrs.RelativePath, - }) } } - for _, resource := range tfResources { + for _, resource := range tfResourceByLabel { if resource.Mode == tfjson.DataResourceMode { continue } if resource.Type == "coder_agent" || resource.Type == "coder_agent_instance" || resource.Type == "coder_app" { continue } - agents := findAgents(resourceDependencies, agents, convertAddressToLabel(resource.Address)) - for _, agent := range agents { - // Didn't use instance identity. - if agent.GetToken() != "" { - continue - } - // These resource types are for automatically associating an instance ID - // with an agent for authentication. - key, isValid := map[string]string{ - "google_compute_instance": "instance_id", - "aws_instance": "id", - "azurerm_linux_virtual_machine": "id", - "azurerm_windows_virtual_machine": "id", - }[resource.Type] - if !isValid { - // The resource type doesn't support - // automatically setting the instance ID. - continue - } - instanceIDRaw, valid := resource.AttributeValues[key] - if !valid { - continue - } - instanceID, valid := instanceIDRaw.(string) - if !valid { - continue - } - agent.Auth = &proto.Agent_InstanceId{ - InstanceId: instanceID, - } + agents, exists := resourceAgents[convertAddressToLabel(resource.Address)] + if exists { + applyAutomaticInstanceID(resource, agents) } resources = append(resources, &proto.Resource{ @@ -212,46 +230,83 @@ func convertAddressToLabel(address string) string { return strings.Split(address, "[")[0] } -// findAgents recursively searches through resource dependencies -// to find associated agents. Nested is required for indirect -// dependency matching. -func findAgents(resourceDependencies map[string][]string, agents map[string]*proto.Agent, resourceLabel string) []*proto.Agent { - resourceNode, exists := resourceDependencies[resourceLabel] - if !exists { - return []*proto.Agent{} +type graphResource struct { + Label string + Depth uint +} + +// applyAutomaticInstanceID checks if the resource is one of a set of *magical* IDs +// that automatically index their identifier for automatic authentication. +func applyAutomaticInstanceID(resource *tfjson.StateResource, agents []*proto.Agent) { + // These resource types are for automatically associating an instance ID + // with an agent for authentication. + key, isValid := map[string]string{ + "google_compute_instance": "instance_id", + "aws_instance": "id", + "azurerm_linux_virtual_machine": "id", + "azurerm_windows_virtual_machine": "id", + }[resource.Type] + if !isValid { + return } - // Associate resources that depend on an agent. - resourceAgents := make([]*proto.Agent, 0) - for _, dep := range resourceNode { - var has bool - agent, has := agents[dep] - if !has { - resourceAgents = append(resourceAgents, findAgents(resourceDependencies, agents, dep)...) + + // The resource type doesn't support + // automatically setting the instance ID. + instanceIDRaw, isValid := resource.AttributeValues[key] + if !isValid { + return + } + instanceID, isValid := instanceIDRaw.(string) + if !isValid { + return + } + for _, agent := range agents { + // Didn't use instance identity. + if agent.GetToken() != "" { continue } - // An agent must be deleted after being assigned so it isn't referenced twice. - delete(agents, dep) - resourceAgents = append(resourceAgents, agent) + if agent.GetInstanceId() != "" { + // If an instance ID is manually specified, do not override! + continue + } + + agent.Auth = &proto.Agent_InstanceId{ + InstanceId: instanceID, + } } - return resourceAgents } -// findDependenciesWithLabels recursively finds nodes with labels (resource and data nodes) -// to build a dependency tree. -func findDependenciesWithLabels(graph *gographviz.Graph, nodeName string) []string { - dependencies := make([]string, 0) - for destination := range graph.Edges.SrcToDsts[nodeName] { - dependencyNode, exists := graph.Nodes.Lookup[destination] +// findResourcesUpGraph traverses upwards in a graph until a resource is found, +// then it stores the depth it was found at, and continues working up the tree. +func findResourcesUpGraph(graph *gographviz.Graph, tfResourceByLabel map[string]*tfjson.StateResource, nodeName string, currentDepth uint) []*graphResource { + graphResources := make([]*graphResource, 0) + for destination := range graph.Edges.DstToSrcs[nodeName] { + destinationNode := graph.Nodes.Lookup[destination] + // Work our way up the tree! + graphResources = append(graphResources, findResourcesUpGraph(graph, tfResourceByLabel, destinationNode.Name, currentDepth+1)...) + + destinationLabel, exists := destinationNode.Attrs["label"] if !exists { continue } - label, exists := dependencyNode.Attrs["label"] + destinationLabel = strings.Trim(destinationLabel, `"`) + resource, exists := tfResourceByLabel[destinationLabel] if !exists { - dependencies = append(dependencies, findDependenciesWithLabels(graph, dependencyNode.Name)...) continue } - label = strings.Trim(label, `"`) - dependencies = append(dependencies, label) + // Data sources cannot be associated with agents for now! + if resource.Mode != tfjson.ManagedResourceMode { + continue + } + // Don't associate Coder resources with other Coder resources! + if strings.HasPrefix(resource.Type, "coder_") { + continue + } + graphResources = append(graphResources, &graphResource{ + Label: destinationLabel, + Depth: currentDepth, + }) } - return dependencies + + return graphResources } diff --git a/provisioner/terraform/resources_test.go b/provisioner/terraform/resources_test.go index 03386557151e6..e7d9517a22120 100644 --- a/provisioner/terraform/resources_test.go +++ b/provisioner/terraform/resources_test.go @@ -22,11 +22,29 @@ func TestConvertResources(t *testing.T) { _, filename, _, _ := runtime.Caller(0) // nolint:paralleltest for folderName, expected := range map[string][]*proto.Resource{ + // When a resource depends on another, the shortest route + // to a resource should always be chosen for the agent. "chaining-resources": {{ + Name: "a", + Type: "null_resource", + }, { + Name: "b", + Type: "null_resource", + Agents: []*proto.Agent{{ + Name: "dev", + OperatingSystem: "linux", + Architecture: "amd64", + Auth: &proto.Agent_Token{}, + }}, + }}, + // This can happen when resources hierarchically conflict. + // When multiple resources exist at the same level, the first + // listed in state will be chosen. + "conflicting-resources": {{ Name: "first", Type: "null_resource", Agents: []*proto.Agent{{ - Name: "dev1", + Name: "dev", OperatingSystem: "linux", Architecture: "amd64", Auth: &proto.Agent_Token{}, @@ -35,6 +53,7 @@ func TestConvertResources(t *testing.T) { Name: "second", Type: "null_resource", }}, + // Ensures the instance ID authentication type surfaces. "instance-id": {{ Name: "dev", Type: "null_resource", @@ -45,6 +64,8 @@ func TestConvertResources(t *testing.T) { Auth: &proto.Agent_InstanceId{}, }}, }}, + // Ensures that calls to resources through modules work + // as expected. "calling-module": {{ Name: "example", Type: "null_resource", @@ -55,6 +76,8 @@ func TestConvertResources(t *testing.T) { Auth: &proto.Agent_Token{}, }}, }}, + // Ensures the attachment of multiple agents to a single + // resource is successful. "multiple-agents": {{ Name: "dev", Type: "null_resource", @@ -75,6 +98,7 @@ func TestConvertResources(t *testing.T) { Auth: &proto.Agent_Token{}, }}, }}, + // Ensures multiple applications can be set for a single agent. "multiple-apps": {{ Name: "dev", Type: "null_resource", @@ -109,11 +133,7 @@ func TestConvertResources(t *testing.T) { resources, err := terraform.ConvertResources(tfPlan.PlannedValues.RootModule, string(tfPlanGraph)) require.NoError(t, err) - for _, resource := range resources { - sort.Slice(resource.Agents, func(i, j int) bool { - return resource.Agents[i].Name < resource.Agents[j].Name - }) - } + sortResources(resources) resourcesWant, err := json.Marshal(expected) require.NoError(t, err) resourcesGot, err := json.Marshal(resources) @@ -132,10 +152,8 @@ func TestConvertResources(t *testing.T) { resources, err := terraform.ConvertResources(tfState.Values.RootModule, string(tfStateGraph)) require.NoError(t, err) + sortResources(resources) for _, resource := range resources { - sort.Slice(resource.Agents, func(i, j int) bool { - return resource.Agents[i].Name < resource.Agents[j].Name - }) for _, agent := range resource.Agents { agent.Id = "" if agent.GetToken() != "" { @@ -191,6 +209,7 @@ func TestInstanceIDAssociation(t *testing.T) { Address: "coder_agent.dev", Type: "coder_agent", Name: "dev", + Mode: tfjson.ManagedResourceMode, AttributeValues: map[string]interface{}{ "arch": "amd64", "auth": tc.Auth, @@ -199,6 +218,7 @@ func TestInstanceIDAssociation(t *testing.T) { Address: tc.ResourceType + ".dev", Type: tc.ResourceType, Name: "dev", + Mode: tfjson.ManagedResourceMode, DependsOn: []string{"coder_agent.dev"}, AttributeValues: map[string]interface{}{ tc.InstanceIDKey: instanceID, @@ -222,3 +242,21 @@ func TestInstanceIDAssociation(t *testing.T) { }) } } + +// sortResource ensures resources appear in a consistent ordering +// to prevent tests from flaking. +func sortResources(resources []*proto.Resource) { + sort.Slice(resources, func(i, j int) bool { + return resources[i].Name < resources[j].Name + }) + for _, resource := range resources { + for _, agent := range resource.Agents { + sort.Slice(agent.Apps, func(i, j int) bool { + return agent.Apps[i].Name < agent.Apps[j].Name + }) + } + sort.Slice(resource.Agents, func(i, j int) bool { + return resource.Agents[i].Name < resource.Agents[j].Name + }) + } +} diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot index 0d5447f4bb153..4cdf10b11a0b4 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot @@ -3,13 +3,15 @@ digraph { newrank = "true" subgraph "root" { "[root] coder_agent.dev (expand)" [label = "coder_agent.dev", shape = "box"] + "[root] module.module.data.null_data_source.script (expand)" [label = "module.module.data.null_data_source.script", shape = "box"] "[root] module.module.null_resource.example (expand)" [label = "module.module.null_resource.example", shape = "box"] "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] "[root] coder_agent.dev (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" "[root] module.module (close)" -> "[root] module.module.null_resource.example (expand)" - "[root] module.module.null_resource.example (expand)" -> "[root] module.module.var.script (expand)" - "[root] module.module.null_resource.example (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] module.module.data.null_data_source.script (expand)" -> "[root] module.module.var.script (expand)" + "[root] module.module.data.null_data_source.script (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] module.module.null_resource.example (expand)" -> "[root] module.module.data.null_data_source.script (expand)" "[root] module.module.var.script (expand)" -> "[root] coder_agent.dev (expand)" "[root] module.module.var.script (expand)" -> "[root] module.module (expand)" "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev (expand)" diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json index 57b0ec2bbdaac..c703e64f5d1d2 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfplan.json @@ -25,6 +25,21 @@ "child_modules": [ { "resources": [ + { + "address": "module.module.data.null_data_source.script", + "mode": "data", + "type": "null_data_source", + "name": "script", + "provider_name": "registry.terraform.io/hashicorp/null", + "schema_version": 0, + "values": { + "inputs": {} + }, + "sensitive_values": { + "inputs": {}, + "outputs": {} + } + }, { "address": "module.module.null_resource.example", "mode": "managed", @@ -72,6 +87,38 @@ "after_sensitive": {} } }, + { + "address": "module.module.data.null_data_source.script", + "module_address": "module.module", + "mode": "data", + "type": "null_data_source", + "name": "script", + "provider_name": "registry.terraform.io/hashicorp/null", + "change": { + "actions": [ + "read" + ], + "before": null, + "after": { + "inputs": {} + }, + "after_unknown": { + "has_computed_default": true, + "id": true, + "inputs": { + "script": true + }, + "outputs": true, + "random": true + }, + "before_sensitive": false, + "after_sensitive": { + "inputs": {}, + "outputs": {} + } + }, + "action_reason": "read_because_config_unknown" + }, { "address": "module.module.null_resource.example", "module_address": "module.module", @@ -148,8 +195,23 @@ "provider_config_key": "module.module:null", "schema_version": 0, "depends_on": [ - "var.script" + "data.null_data_source.script" ] + }, + { + "address": "data.null_data_source.script", + "mode": "data", + "type": "null_data_source", + "name": "script", + "provider_config_key": "module.module:null", + "expressions": { + "inputs": { + "references": [ + "var.script" + ] + } + }, + "schema_version": 0 } ], "variables": { @@ -159,5 +221,13 @@ } } } - } + }, + "relevant_attributes": [ + { + "resource": "coder_agent.dev", + "attribute": [ + "init_script" + ] + } + ] } diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot index 0d5447f4bb153..4cdf10b11a0b4 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot @@ -3,13 +3,15 @@ digraph { newrank = "true" subgraph "root" { "[root] coder_agent.dev (expand)" [label = "coder_agent.dev", shape = "box"] + "[root] module.module.data.null_data_source.script (expand)" [label = "module.module.data.null_data_source.script", shape = "box"] "[root] module.module.null_resource.example (expand)" [label = "module.module.null_resource.example", shape = "box"] "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] "[root] coder_agent.dev (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" "[root] module.module (close)" -> "[root] module.module.null_resource.example (expand)" - "[root] module.module.null_resource.example (expand)" -> "[root] module.module.var.script (expand)" - "[root] module.module.null_resource.example (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] module.module.data.null_data_source.script (expand)" -> "[root] module.module.var.script (expand)" + "[root] module.module.data.null_data_source.script (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] module.module.null_resource.example (expand)" -> "[root] module.module.data.null_data_source.script (expand)" "[root] module.module.var.script (expand)" -> "[root] coder_agent.dev (expand)" "[root] module.module.var.script (expand)" -> "[root] module.module (expand)" "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev (expand)" diff --git a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json index d3c18630106e4..5efed1544f880 100644 --- a/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json +++ b/provisioner/terraform/testdata/calling-module/calling-module.tfstate.json @@ -16,11 +16,11 @@ "auth": "token", "dir": null, "env": null, - "id": "0f0b7be8-9d82-4b01-b5e5-88279ae4f977", + "id": "66fed4b4-2246-4c0f-8e55-74e109ee0603", "init_script": "", "os": "linux", "startup_script": null, - "token": "0144998d-4154-495a-902b-0cece2800d76" + "token": "c7f7d527-3eab-4f77-8c0f-05f543bce5c1" }, "sensitive_values": {} } @@ -28,6 +28,29 @@ "child_modules": [ { "resources": [ + { + "address": "module.module.data.null_data_source.script", + "mode": "data", + "type": "null_data_source", + "name": "script", + "provider_name": "registry.terraform.io/hashicorp/null", + "schema_version": 0, + "values": { + "has_computed_default": "default", + "id": "static", + "inputs": { + "script": "" + }, + "outputs": { + "script": "" + }, + "random": "2465369318401710566" + }, + "sensitive_values": { + "inputs": {}, + "outputs": {} + } + }, { "address": "module.module.null_resource.example", "mode": "managed", @@ -36,12 +59,13 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "4090647596312392999", + "id": "354396519773748320", "triggers": null }, "sensitive_values": {}, "depends_on": [ - "coder_agent.dev" + "coder_agent.dev", + "module.module.data.null_data_source.script" ] } ], diff --git a/provisioner/terraform/testdata/calling-module/module/module.tf b/provisioner/terraform/testdata/calling-module/module/module.tf index deb3f71f5a3cf..483b1511df10b 100644 --- a/provisioner/terraform/testdata/calling-module/module/module.tf +++ b/provisioner/terraform/testdata/calling-module/module/module.tf @@ -2,8 +2,14 @@ variable "script" { type = string } +data "null_data_source" "script" { + inputs = { + script = var.script + } +} + resource "null_resource" "example" { depends_on = [ - var.script + data.null_data_source.script ] } diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tf b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tf index cc5a43218beac..7125d9d89f089 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tf +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tf @@ -7,19 +7,19 @@ terraform { } } -resource "coder_agent" "dev1" { +resource "coder_agent" "dev" { os = "linux" arch = "amd64" } -resource "null_resource" "first" { +resource "null_resource" "b" { depends_on = [ - coder_agent.dev1 + coder_agent.dev ] } -resource "null_resource" "second" { +resource "null_resource" "a" { depends_on = [ - null_resource.first + null_resource.b ] } diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot index b590846e3828e..aa21b626e6a82 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot @@ -2,17 +2,17 @@ digraph { compound = "true" newrank = "true" subgraph "root" { - "[root] coder_agent.dev1 (expand)" [label = "coder_agent.dev1", shape = "box"] - "[root] null_resource.first (expand)" [label = "null_resource.first", shape = "box"] - "[root] null_resource.second (expand)" [label = "null_resource.second", shape = "box"] + "[root] coder_agent.dev (expand)" [label = "coder_agent.dev", shape = "box"] + "[root] null_resource.a (expand)" [label = "null_resource.a", shape = "box"] + "[root] null_resource.b (expand)" [label = "null_resource.b", shape = "box"] "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] - "[root] coder_agent.dev1 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" - "[root] null_resource.first (expand)" -> "[root] coder_agent.dev1 (expand)" - "[root] null_resource.first (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" - "[root] null_resource.second (expand)" -> "[root] null_resource.first (expand)" - "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev1 (expand)" - "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.second (expand)" + "[root] coder_agent.dev (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] null_resource.a (expand)" -> "[root] null_resource.b (expand)" + "[root] null_resource.b (expand)" -> "[root] coder_agent.dev (expand)" + "[root] null_resource.b (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev (expand)" + "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.a (expand)" "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json index 9e338c184cc9f..92e9849f56ccb 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json @@ -5,10 +5,10 @@ "root_module": { "resources": [ { - "address": "coder_agent.dev1", + "address": "coder_agent.dev", "mode": "managed", "type": "coder_agent", - "name": "dev1", + "name": "dev", "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { @@ -22,10 +22,10 @@ "sensitive_values": {} }, { - "address": "null_resource.first", + "address": "null_resource.a", "mode": "managed", "type": "null_resource", - "name": "first", + "name": "a", "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { @@ -34,10 +34,10 @@ "sensitive_values": {} }, { - "address": "null_resource.second", + "address": "null_resource.b", "mode": "managed", "type": "null_resource", - "name": "second", + "name": "b", "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { @@ -50,10 +50,10 @@ }, "resource_changes": [ { - "address": "coder_agent.dev1", + "address": "coder_agent.dev", "mode": "managed", "type": "coder_agent", - "name": "dev1", + "name": "dev", "provider_name": "registry.terraform.io/coder/coder", "change": { "actions": [ @@ -78,10 +78,10 @@ } }, { - "address": "null_resource.first", + "address": "null_resource.a", "mode": "managed", "type": "null_resource", - "name": "first", + "name": "a", "provider_name": "registry.terraform.io/hashicorp/null", "change": { "actions": [ @@ -99,10 +99,10 @@ } }, { - "address": "null_resource.second", + "address": "null_resource.b", "mode": "managed", "type": "null_resource", - "name": "second", + "name": "b", "provider_name": "registry.terraform.io/hashicorp/null", "change": { "actions": [ @@ -135,10 +135,10 @@ "root_module": { "resources": [ { - "address": "coder_agent.dev1", + "address": "coder_agent.dev", "mode": "managed", "type": "coder_agent", - "name": "dev1", + "name": "dev", "provider_config_key": "coder", "expressions": { "arch": { @@ -151,25 +151,25 @@ "schema_version": 0 }, { - "address": "null_resource.first", + "address": "null_resource.a", "mode": "managed", "type": "null_resource", - "name": "first", + "name": "a", "provider_config_key": "null", "schema_version": 0, "depends_on": [ - "coder_agent.dev1" + "null_resource.b" ] }, { - "address": "null_resource.second", + "address": "null_resource.b", "mode": "managed", "type": "null_resource", - "name": "second", + "name": "b", "provider_config_key": "null", "schema_version": 0, "depends_on": [ - "null_resource.first" + "coder_agent.dev" ] } ] diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot index b590846e3828e..aa21b626e6a82 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot @@ -2,17 +2,17 @@ digraph { compound = "true" newrank = "true" subgraph "root" { - "[root] coder_agent.dev1 (expand)" [label = "coder_agent.dev1", shape = "box"] - "[root] null_resource.first (expand)" [label = "null_resource.first", shape = "box"] - "[root] null_resource.second (expand)" [label = "null_resource.second", shape = "box"] + "[root] coder_agent.dev (expand)" [label = "coder_agent.dev", shape = "box"] + "[root] null_resource.a (expand)" [label = "null_resource.a", shape = "box"] + "[root] null_resource.b (expand)" [label = "null_resource.b", shape = "box"] "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] - "[root] coder_agent.dev1 (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" - "[root] null_resource.first (expand)" -> "[root] coder_agent.dev1 (expand)" - "[root] null_resource.first (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" - "[root] null_resource.second (expand)" -> "[root] null_resource.first (expand)" - "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev1 (expand)" - "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.second (expand)" + "[root] coder_agent.dev (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] null_resource.a (expand)" -> "[root] null_resource.b (expand)" + "[root] null_resource.b (expand)" -> "[root] coder_agent.dev (expand)" + "[root] null_resource.b (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev (expand)" + "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.a (expand)" "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" } diff --git a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json index 06e6bd12ab28d..d3d8e99a95e6f 100644 --- a/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json +++ b/provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json @@ -5,10 +5,10 @@ "root_module": { "resources": [ { - "address": "coder_agent.dev1", + "address": "coder_agent.dev", "mode": "managed", "type": "coder_agent", - "name": "dev1", + "name": "dev", "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { @@ -16,45 +16,45 @@ "auth": "token", "dir": null, "env": null, - "id": "299427de-bf0c-45a9-9780-97b5c7ea83e7", + "id": "44e31a74-646f-4f29-a979-ff0da7108ed6", "init_script": "", "os": "linux", "startup_script": null, - "token": "c470ea31-7bb4-49f0-af5a-c1d8ad3f2e1c" + "token": "3c011212-912c-45f5-8cdb-84b7e03a8d44" }, "sensitive_values": {} }, { - "address": "null_resource.first", + "address": "null_resource.a", "mode": "managed", "type": "null_resource", - "name": "first", + "name": "a", "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "743088824302893232", + "id": "5747685929405905376", "triggers": null }, "sensitive_values": {}, "depends_on": [ - "coder_agent.dev1" + "coder_agent.dev", + "null_resource.b" ] }, { - "address": "null_resource.second", + "address": "null_resource.b", "mode": "managed", "type": "null_resource", - "name": "second", + "name": "b", "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "661153862134717768", + "id": "4234681175686342228", "triggers": null }, "sensitive_values": {}, "depends_on": [ - "coder_agent.dev1", - "null_resource.first" + "coder_agent.dev" ] } ] diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf new file mode 100644 index 0000000000000..9da5aa64e6384 --- /dev/null +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf @@ -0,0 +1,25 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + version = "0.4.2" + } + } +} + +resource "coder_agent" "dev" { + os = "linux" + arch = "amd64" +} + +resource "null_resource" "first" { + depends_on = [ + coder_agent.dev + ] +} + +resource "null_resource" "second" { + depends_on = [ + coder_agent.dev + ] +} diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot new file mode 100644 index 0000000000000..4e5efe7551100 --- /dev/null +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot @@ -0,0 +1,22 @@ +digraph { + compound = "true" + newrank = "true" + subgraph "root" { + "[root] coder_agent.dev (expand)" [label = "coder_agent.dev", shape = "box"] + "[root] null_resource.first (expand)" [label = "null_resource.first", shape = "box"] + "[root] null_resource.second (expand)" [label = "null_resource.second", shape = "box"] + "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] + "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] + "[root] coder_agent.dev (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] null_resource.first (expand)" -> "[root] coder_agent.dev (expand)" + "[root] null_resource.first (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] null_resource.second (expand)" -> "[root] coder_agent.dev (expand)" + "[root] null_resource.second (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev (expand)" + "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.first (expand)" + "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.second (expand)" + "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" + "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" + } +} + diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json new file mode 100644 index 0000000000000..20b9740114f34 --- /dev/null +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json @@ -0,0 +1,178 @@ +{ + "format_version": "1.1", + "terraform_version": "1.2.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "coder_agent.dev", + "mode": "managed", + "type": "coder_agent", + "name": "dev", + "provider_name": "registry.terraform.io/coder/coder", + "schema_version": 0, + "values": { + "arch": "amd64", + "auth": "token", + "dir": null, + "env": null, + "os": "linux", + "startup_script": null + }, + "sensitive_values": {} + }, + { + "address": "null_resource.first", + "mode": "managed", + "type": "null_resource", + "name": "first", + "provider_name": "registry.terraform.io/hashicorp/null", + "schema_version": 0, + "values": { + "triggers": null + }, + "sensitive_values": {} + }, + { + "address": "null_resource.second", + "mode": "managed", + "type": "null_resource", + "name": "second", + "provider_name": "registry.terraform.io/hashicorp/null", + "schema_version": 0, + "values": { + "triggers": null + }, + "sensitive_values": {} + } + ] + } + }, + "resource_changes": [ + { + "address": "coder_agent.dev", + "mode": "managed", + "type": "coder_agent", + "name": "dev", + "provider_name": "registry.terraform.io/coder/coder", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "arch": "amd64", + "auth": "token", + "dir": null, + "env": null, + "os": "linux", + "startup_script": null + }, + "after_unknown": { + "id": true, + "init_script": true, + "token": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "null_resource.first", + "mode": "managed", + "type": "null_resource", + "name": "first", + "provider_name": "registry.terraform.io/hashicorp/null", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "triggers": null + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "null_resource.second", + "mode": "managed", + "type": "null_resource", + "name": "second", + "provider_name": "registry.terraform.io/hashicorp/null", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "triggers": null + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "coder": { + "name": "coder", + "full_name": "registry.terraform.io/coder/coder", + "version_constraint": "0.4.2" + }, + "null": { + "name": "null", + "full_name": "registry.terraform.io/hashicorp/null" + } + }, + "root_module": { + "resources": [ + { + "address": "coder_agent.dev", + "mode": "managed", + "type": "coder_agent", + "name": "dev", + "provider_config_key": "coder", + "expressions": { + "arch": { + "constant_value": "amd64" + }, + "os": { + "constant_value": "linux" + } + }, + "schema_version": 0 + }, + { + "address": "null_resource.first", + "mode": "managed", + "type": "null_resource", + "name": "first", + "provider_config_key": "null", + "schema_version": 0, + "depends_on": [ + "coder_agent.dev" + ] + }, + { + "address": "null_resource.second", + "mode": "managed", + "type": "null_resource", + "name": "second", + "provider_config_key": "null", + "schema_version": 0, + "depends_on": [ + "coder_agent.dev" + ] + } + ] + } + } +} diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot new file mode 100644 index 0000000000000..4e5efe7551100 --- /dev/null +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot @@ -0,0 +1,22 @@ +digraph { + compound = "true" + newrank = "true" + subgraph "root" { + "[root] coder_agent.dev (expand)" [label = "coder_agent.dev", shape = "box"] + "[root] null_resource.first (expand)" [label = "null_resource.first", shape = "box"] + "[root] null_resource.second (expand)" [label = "null_resource.second", shape = "box"] + "[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"] + "[root] provider[\"registry.terraform.io/hashicorp/null\"]" [label = "provider[\"registry.terraform.io/hashicorp/null\"]", shape = "diamond"] + "[root] coder_agent.dev (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]" + "[root] null_resource.first (expand)" -> "[root] coder_agent.dev (expand)" + "[root] null_resource.first (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] null_resource.second (expand)" -> "[root] coder_agent.dev (expand)" + "[root] null_resource.second (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"]" + "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_agent.dev (expand)" + "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.first (expand)" + "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" -> "[root] null_resource.second (expand)" + "[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)" + "[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/null\"] (close)" + } +} + diff --git a/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json new file mode 100644 index 0000000000000..4bed6de18d3b5 --- /dev/null +++ b/provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json @@ -0,0 +1,62 @@ +{ + "format_version": "1.0", + "terraform_version": "1.2.2", + "values": { + "root_module": { + "resources": [ + { + "address": "coder_agent.dev", + "mode": "managed", + "type": "coder_agent", + "name": "dev", + "provider_name": "registry.terraform.io/coder/coder", + "schema_version": 0, + "values": { + "arch": "amd64", + "auth": "token", + "dir": null, + "env": null, + "id": "99a85fe5-719f-4d20-8dd9-d02e7d477c45", + "init_script": "", + "os": "linux", + "startup_script": null, + "token": "7bdf3592-b3d0-42f8-8e81-132903f28614" + }, + "sensitive_values": {} + }, + { + "address": "null_resource.first", + "mode": "managed", + "type": "null_resource", + "name": "first", + "provider_name": "registry.terraform.io/hashicorp/null", + "schema_version": 0, + "values": { + "id": "5367760563120181345", + "triggers": null + }, + "sensitive_values": {}, + "depends_on": [ + "coder_agent.dev" + ] + }, + { + "address": "null_resource.second", + "mode": "managed", + "type": "null_resource", + "name": "second", + "provider_name": "registry.terraform.io/hashicorp/null", + "schema_version": 0, + "values": { + "id": "3224902069148001434", + "triggers": null + }, + "sensitive_values": {}, + "depends_on": [ + "coder_agent.dev" + ] + } + ] + } + } +} diff --git a/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json b/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json index bd86ce2abf5d5..811786b6f40dd 100644 --- a/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json +++ b/provisioner/terraform/testdata/instance-id/instance-id.tfstate.json @@ -16,11 +16,11 @@ "auth": "google-instance-identity", "dir": null, "env": null, - "id": "a72e01b2-71e9-4498-943f-d1a117c696a0", + "id": "af919173-b148-4852-9552-453c5665efc4", "init_script": "", "os": "linux", "startup_script": null, - "token": "553aedb8-98b2-4f4d-87aa-428ba11afd5c" + "token": "06bcca4d-b37f-4f82-8fcb-f3c00387748a" }, "sensitive_values": {} }, @@ -32,8 +32,8 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "a72e01b2-71e9-4498-943f-d1a117c696a0", - "id": "c1552a99-782e-4d2b-a5b6-638b3f7297e4", + "agent_id": "af919173-b148-4852-9552-453c5665efc4", + "id": "f90a6c0f-11c1-4737-982f-e54590c46cea", "instance_id": "example" }, "sensitive_values": {}, @@ -49,7 +49,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "2578813038449197470", + "id": "4993832153889617160", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json index 1ccdbafa45afe..4cf226531c76a 100644 --- a/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json +++ b/provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json @@ -16,11 +16,11 @@ "auth": "token", "dir": null, "env": null, - "id": "04cb673b-c7b5-47c9-a445-f0f7e11f2696", + "id": "521a6bee-1193-468f-bbe9-4a25a870a9f0", "init_script": "", "os": "linux", "startup_script": null, - "token": "95e9607b-1ff3-4a35-8ee8-c61248fb5642" + "token": "ee0452e2-7efe-4a84-9407-e871c7c4f4c4" }, "sensitive_values": {} }, @@ -36,11 +36,11 @@ "auth": "token", "dir": null, "env": null, - "id": "d97044e4-ce09-4eaf-904e-cd9575f07122", + "id": "f1c2eb3a-2303-4499-8cfc-5a63f5d57def", "init_script": "", "os": "darwin", "startup_script": null, - "token": "dc49231a-57e1-4a21-bb74-ae34f753d7bf" + "token": "15ea44b7-acd7-41d5-98a3-93ac23bd2b84" }, "sensitive_values": {} }, @@ -56,11 +56,11 @@ "auth": "token", "dir": null, "env": null, - "id": "8b03bbd1-bd6a-4a54-b083-9d773c91de54", + "id": "445a229e-6886-46ba-9947-94d39b90b941", "init_script": "", "os": "windows", "startup_script": null, - "token": "4b91ef3f-cada-4b27-9872-df2c5a47e24a" + "token": "26a999c8-d281-46da-a296-15318d4c0998" }, "sensitive_values": {} }, @@ -72,7 +72,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "8472507680226374958", + "id": "6903043049471472110", "triggers": null }, "sensitive_values": {}, diff --git a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json index 678926d95cd8e..1c290719cac8b 100644 --- a/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json +++ b/provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json @@ -16,11 +16,11 @@ "auth": "token", "dir": null, "env": null, - "id": "0ab1ceca-8ce9-4f02-97bb-9f4087739ce9", + "id": "d613fec9-933b-490f-97c7-7e6527e02a91", "init_script": "", "os": "linux", "startup_script": null, - "token": "3a5de99e-5b10-459c-a3d0-0fb0fdf1f43b" + "token": "564c308a-5d9e-42f9-b2a5-da28d3c04a90" }, "sensitive_values": {} }, @@ -32,10 +32,10 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "0ab1ceca-8ce9-4f02-97bb-9f4087739ce9", + "agent_id": "d613fec9-933b-490f-97c7-7e6527e02a91", "command": null, "icon": null, - "id": "5b6a8a53-0368-4313-89cd-65dc2d9daa2d", + "id": "2b92ebdb-1169-4247-b039-87aeaeaf55b3", "name": null, "relative_path": null, "url": null @@ -53,10 +53,10 @@ "provider_name": "registry.terraform.io/coder/coder", "schema_version": 0, "values": { - "agent_id": "0ab1ceca-8ce9-4f02-97bb-9f4087739ce9", + "agent_id": "d613fec9-933b-490f-97c7-7e6527e02a91", "command": null, "icon": null, - "id": "2b421408-9538-422a-8254-df4b629d0a34", + "id": "80eedec0-8816-4c8d-96b7-3aa3d5b5cef8", "name": null, "relative_path": null, "url": null @@ -74,7 +74,7 @@ "provider_name": "registry.terraform.io/hashicorp/null", "schema_version": 0, "values": { - "id": "2309999552249167252", + "id": "3551148082877575423", "triggers": null }, "sensitive_values": {}, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy