mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
fix: Use explicit resource order when assocating agents (#2219)
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.
This commit is contained in:
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -63,6 +63,7 @@
|
||||
"sdktrace",
|
||||
"Signup",
|
||||
"sourcemapped",
|
||||
"Srcs",
|
||||
"stretchr",
|
||||
"TCGETS",
|
||||
"tcpip",
|
||||
|
@ -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)
|
||||
findTerraformResources(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"`
|
||||
}
|
||||
|
||||
// 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{}
|
||||
}
|
||||
// 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)...)
|
||||
continue
|
||||
}
|
||||
// An agent must be deleted after being assigned so it isn't referenced twice.
|
||||
delete(agents, dep)
|
||||
resourceAgents = append(resourceAgents, agent)
|
||||
}
|
||||
return resourceAgents
|
||||
type graphResource struct {
|
||||
Label string
|
||||
Depth uint
|
||||
}
|
||||
|
||||
// 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]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
label, exists := dependencyNode.Attrs["label"]
|
||||
if !exists {
|
||||
dependencies = append(dependencies, findDependenciesWithLabels(graph, dependencyNode.Name)...)
|
||||
continue
|
||||
}
|
||||
label = strings.Trim(label, `"`)
|
||||
dependencies = append(dependencies, label)
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
if agent.GetInstanceId() != "" {
|
||||
// If an instance ID is manually specified, do not override!
|
||||
continue
|
||||
}
|
||||
|
||||
agent.Auth = &proto.Agent_InstanceId{
|
||||
InstanceId: instanceID,
|
||||
}
|
||||
}
|
||||
return dependencies
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
destinationLabel = strings.Trim(destinationLabel, `"`)
|
||||
resource, exists := tfResourceByLabel[destinationLabel]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
// 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 graphResources
|
||||
}
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
|
6
provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot
generated
vendored
6
provisioner/terraform/testdata/calling-module/calling-module.tfplan.dot
generated
vendored
@ -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)"
|
||||
|
74
provisioner/terraform/testdata/calling-module/calling-module.tfplan.json
generated
vendored
74
provisioner/terraform/testdata/calling-module/calling-module.tfplan.json
generated
vendored
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
6
provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot
generated
vendored
6
provisioner/terraform/testdata/calling-module/calling-module.tfstate.dot
generated
vendored
@ -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)"
|
||||
|
32
provisioner/terraform/testdata/calling-module/calling-module.tfstate.json
generated
vendored
32
provisioner/terraform/testdata/calling-module/calling-module.tfstate.json
generated
vendored
@ -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"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
@ -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
|
||||
]
|
||||
}
|
||||
|
@ -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
|
||||
]
|
||||
}
|
||||
|
18
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot
generated
vendored
18
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.dot
generated
vendored
@ -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)"
|
||||
}
|
||||
|
40
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json
generated
vendored
40
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json
generated
vendored
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
18
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot
generated
vendored
18
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.dot
generated
vendored
@ -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)"
|
||||
}
|
||||
|
26
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json
generated
vendored
26
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json
generated
vendored
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
25
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf
vendored
Normal file
25
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tf
vendored
Normal file
@ -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
|
||||
]
|
||||
}
|
22
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot
generated
vendored
Normal file
22
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.dot
generated
vendored
Normal file
@ -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)"
|
||||
}
|
||||
}
|
||||
|
178
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json
generated
vendored
Normal file
178
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfplan.json
generated
vendored
Normal file
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
22
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot
generated
vendored
Normal file
22
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.dot
generated
vendored
Normal file
@ -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)"
|
||||
}
|
||||
}
|
||||
|
62
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json
generated
vendored
Normal file
62
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json
generated
vendored
Normal file
@ -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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
10
provisioner/terraform/testdata/instance-id/instance-id.tfstate.json
generated
vendored
10
provisioner/terraform/testdata/instance-id/instance-id.tfstate.json
generated
vendored
@ -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": {},
|
||||
|
14
provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json
generated
vendored
14
provisioner/terraform/testdata/multiple-agents/multiple-agents.tfstate.json
generated
vendored
@ -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": {},
|
||||
|
14
provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json
generated
vendored
14
provisioner/terraform/testdata/multiple-apps/multiple-apps.tfstate.json
generated
vendored
@ -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": {},
|
||||
|
Reference in New Issue
Block a user