mirror of
https://github.com/coder/coder.git
synced 2025-07-13 21:36:50 +00:00
fix: properly apply metadata when multiple resources share the same id (#5443)
This commit is contained in:
@ -1069,12 +1069,12 @@ func (api *API) postTemplateVersionsByOrganization(rw http.ResponseWriter, r *ht
|
|||||||
|
|
||||||
// templateVersionResources returns the workspace agent resources associated
|
// templateVersionResources returns the workspace agent resources associated
|
||||||
// with a template version. A template can specify more than one resource to be
|
// with a template version. A template can specify more than one resource to be
|
||||||
// provisioned, each resource can have an agent that dials back to coderd.
|
// provisioned, each resource can have an agent that dials back to coderd. The
|
||||||
// The agents returned are informative of the template version, and do not
|
// agents returned are informative of the template version, and do not return
|
||||||
// return agents associated with any particular workspace.
|
// agents associated with any particular workspace.
|
||||||
func (api *API) templateVersionResources(rw http.ResponseWriter, r *http.Request) {
|
func (api *API) templateVersionResources(rw http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
|
||||||
var (
|
var (
|
||||||
|
ctx = r.Context()
|
||||||
templateVersion = httpmw.TemplateVersionParam(r)
|
templateVersion = httpmw.TemplateVersionParam(r)
|
||||||
template = httpmw.TemplateParam(r)
|
template = httpmw.TemplateParam(r)
|
||||||
)
|
)
|
||||||
@ -1100,8 +1100,8 @@ func (api *API) templateVersionResources(rw http.ResponseWriter, r *http.Request
|
|||||||
// and not any build logs for a workspace.
|
// and not any build logs for a workspace.
|
||||||
// Eg: Logs returned from 'terraform plan' when uploading a new terraform file.
|
// Eg: Logs returned from 'terraform plan' when uploading a new terraform file.
|
||||||
func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) {
|
func (api *API) templateVersionLogs(rw http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
|
||||||
var (
|
var (
|
||||||
|
ctx = r.Context()
|
||||||
templateVersion = httpmw.TemplateVersionParam(r)
|
templateVersion = httpmw.TemplateVersionParam(r)
|
||||||
template = httpmw.TemplateParam(r)
|
template = httpmw.TemplateParam(r)
|
||||||
)
|
)
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -270,7 +269,7 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) {
|
|||||||
return "", ctx.Err()
|
return "", ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
var out bytes.Buffer
|
var out strings.Builder
|
||||||
cmd := exec.CommandContext(killCtx, e.binaryPath, "graph") // #nosec
|
cmd := exec.CommandContext(killCtx, e.binaryPath, "graph") // #nosec
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
cmd.Dir = e.workdir
|
cmd.Dir = e.workdir
|
||||||
@ -289,14 +288,13 @@ func (e *executor) graph(ctx, killCtx context.Context) (string, error) {
|
|||||||
return out.String(), nil
|
return out.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// revive:disable-next-line:flag-parameter
|
|
||||||
func (e *executor) apply(
|
func (e *executor) apply(
|
||||||
ctx, killCtx context.Context, plan []byte, env []string, logr logSink,
|
ctx, killCtx context.Context, plan []byte, env []string, logr logSink,
|
||||||
) (*proto.Provision_Response, error) {
|
) (*proto.Provision_Response, error) {
|
||||||
e.mut.Lock()
|
e.mut.Lock()
|
||||||
defer e.mut.Unlock()
|
defer e.mut.Unlock()
|
||||||
|
|
||||||
planFile, err := ioutil.TempFile("", "coder-terrafrom-plan")
|
planFile, err := os.CreateTemp("", "coder-terrafrom-plan")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("create plan file: %w", err)
|
return nil, xerrors.Errorf("create plan file: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -68,8 +68,8 @@ type metadataItem struct {
|
|||||||
IsNull bool `mapstructure:"is_null"`
|
IsNull bool `mapstructure:"is_null"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConvertResources consumes Terraform state and a GraphViz representation produced by
|
// ConvertResources consumes Terraform state and a GraphViz representation
|
||||||
// `terraform graph` to produce resources consumable by Coder.
|
// produced by `terraform graph` to produce resources consumable by Coder.
|
||||||
// nolint:gocyclo
|
// nolint:gocyclo
|
||||||
func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Resource, error) {
|
func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Resource, error) {
|
||||||
parsedGraph, err := gographviz.ParseString(rawGraph)
|
parsedGraph, err := gographviz.ParseString(rawGraph)
|
||||||
@ -84,13 +84,9 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
|
|||||||
resources := make([]*proto.Resource, 0)
|
resources := make([]*proto.Resource, 0)
|
||||||
resourceAgents := map[string][]*proto.Agent{}
|
resourceAgents := map[string][]*proto.Agent{}
|
||||||
|
|
||||||
// Indexes Terraform resources by their label and ID.
|
// Indexes Terraform resources by their label.
|
||||||
// The label is what "terraform graph" uses to reference nodes, and the ID
|
// The label is what "terraform graph" uses to reference nodes.
|
||||||
// is used by "coder_metadata" resources to refer to their targets. (The ID
|
|
||||||
// field is only available when reading a state file, and not when reading a
|
|
||||||
// plan file.)
|
|
||||||
tfResourceByLabel := map[string]*tfjson.StateResource{}
|
tfResourceByLabel := map[string]*tfjson.StateResource{}
|
||||||
resourceLabelByID := map[string]string{}
|
|
||||||
var findTerraformResources func(mod *tfjson.StateModule)
|
var findTerraformResources func(mod *tfjson.StateModule)
|
||||||
findTerraformResources = func(mod *tfjson.StateModule) {
|
findTerraformResources = func(mod *tfjson.StateModule) {
|
||||||
for _, module := range mod.ChildModules {
|
for _, module := range mod.ChildModules {
|
||||||
@ -100,14 +96,6 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
|
|||||||
label := convertAddressToLabel(resource.Address)
|
label := convertAddressToLabel(resource.Address)
|
||||||
// index by label
|
// index by label
|
||||||
tfResourceByLabel[label] = resource
|
tfResourceByLabel[label] = resource
|
||||||
// index by ID, if it exists
|
|
||||||
id, ok := resource.AttributeValues["id"]
|
|
||||||
if ok {
|
|
||||||
idString, ok := id.(string)
|
|
||||||
if ok {
|
|
||||||
resourceLabelByID[idString] = label
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
findTerraformResources(module)
|
findTerraformResources(module)
|
||||||
@ -319,16 +307,13 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
|
|||||||
if resource.Type != "coder_metadata" {
|
if resource.Type != "coder_metadata" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var attrs metadataAttributes
|
var attrs metadataAttributes
|
||||||
err = mapstructure.Decode(resource.AttributeValues, &attrs)
|
err = mapstructure.Decode(resource.AttributeValues, &attrs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("decode metadata attributes: %w", err)
|
return nil, xerrors.Errorf("decode metadata attributes: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetLabel string
|
|
||||||
// This occurs in a plan, because there is no resource ID.
|
|
||||||
// We attempt to find the closest node, just so we can hide it from the UI.
|
|
||||||
if attrs.ResourceID == "" {
|
|
||||||
resourceLabel := convertAddressToLabel(resource.Address)
|
resourceLabel := convertAddressToLabel(resource.Address)
|
||||||
|
|
||||||
var attachedNode *gographviz.Node
|
var attachedNode *gographviz.Node
|
||||||
@ -363,14 +348,7 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
|
|||||||
if attachedResource == nil {
|
if attachedResource == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
targetLabel = attachedResource.Label
|
targetLabel := attachedResource.Label
|
||||||
}
|
|
||||||
if targetLabel == "" {
|
|
||||||
targetLabel = resourceLabelByID[attrs.ResourceID]
|
|
||||||
}
|
|
||||||
if targetLabel == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
resourceHidden[targetLabel] = attrs.Hide
|
resourceHidden[targetLabel] = attrs.Hide
|
||||||
resourceIcon[targetLabel] = attrs.Icon
|
resourceIcon[targetLabel] = attrs.Icon
|
||||||
@ -416,9 +394,11 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
// convertAddressToLabel returns the Terraform address without the count
|
// convertAddressToLabel returns the Terraform address without the count
|
||||||
// specifier. eg. "module.ec2_dev.ec2_instance.dev[0]" becomes "module.ec2_dev.ec2_instance.dev"
|
// specifier.
|
||||||
|
// eg. "module.ec2_dev.ec2_instance.dev[0]" becomes "module.ec2_dev.ec2_instance.dev"
|
||||||
func convertAddressToLabel(address string) string {
|
func convertAddressToLabel(address string) string {
|
||||||
return strings.Split(address, "[")[0]
|
cut, _, _ := strings.Cut(address, "[")
|
||||||
|
return cut
|
||||||
}
|
}
|
||||||
|
|
||||||
type graphResource struct {
|
type graphResource struct {
|
||||||
|
@ -8,14 +8,14 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
protobuf "github.com/golang/protobuf/proto"
|
||||||
tfjson "github.com/hashicorp/terraform-json"
|
tfjson "github.com/hashicorp/terraform-json"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
|
|
||||||
"github.com/coder/coder/cryptorand"
|
"github.com/coder/coder/cryptorand"
|
||||||
"github.com/coder/coder/provisioner/terraform"
|
"github.com/coder/coder/provisioner/terraform"
|
||||||
"github.com/coder/coder/provisionersdk/proto"
|
"github.com/coder/coder/provisionersdk/proto"
|
||||||
|
|
||||||
protobuf "github.com/golang/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestConvertResources(t *testing.T) {
|
func TestConvertResources(t *testing.T) {
|
||||||
@ -165,6 +165,53 @@ func TestConvertResources(t *testing.T) {
|
|||||||
Sensitive: true,
|
Sensitive: true,
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
|
// Tests that resources with the same id correctly get metadata applied
|
||||||
|
// to them.
|
||||||
|
"kubernetes-metadata": {{
|
||||||
|
Name: "coder_workspace",
|
||||||
|
Type: "kubernetes_service_account",
|
||||||
|
}, {
|
||||||
|
Name: "coder_workspace",
|
||||||
|
Type: "kubernetes_config_map",
|
||||||
|
}, {
|
||||||
|
Name: "coder_workspace",
|
||||||
|
Type: "kubernetes_role",
|
||||||
|
}, {
|
||||||
|
Name: "coder_workspace",
|
||||||
|
Type: "kubernetes_role_binding",
|
||||||
|
}, {
|
||||||
|
Name: "coder_workspace",
|
||||||
|
Type: "kubernetes_secret",
|
||||||
|
}, {
|
||||||
|
Name: "main",
|
||||||
|
Type: "kubernetes_pod",
|
||||||
|
Metadata: []*proto.Resource_Metadata{{
|
||||||
|
Key: "cpu",
|
||||||
|
Value: "1",
|
||||||
|
}, {
|
||||||
|
Key: "memory",
|
||||||
|
Value: "1Gi",
|
||||||
|
}, {
|
||||||
|
Key: "gpu",
|
||||||
|
Value: "1",
|
||||||
|
}},
|
||||||
|
Agents: []*proto.Agent{{
|
||||||
|
Name: "main",
|
||||||
|
OperatingSystem: "linux",
|
||||||
|
Architecture: "amd64",
|
||||||
|
StartupScript: " #!/bin/bash\n # home folder can be empty, so copying default bash settings\n if [ ! -f ~/.profile ]; then\n cp /etc/skel/.profile $HOME\n fi\n if [ ! -f ~/.bashrc ]; then\n cp /etc/skel/.bashrc $HOME\n fi\n # install and start code-server\n curl -fsSL https://code-server.dev/install.sh | sh | tee code-server-install.log\n code-server --auth none --port 13337 | tee code-server-install.log &\n",
|
||||||
|
Apps: []*proto.App{
|
||||||
|
{
|
||||||
|
Icon: "/icon/code.svg",
|
||||||
|
Slug: "code-server",
|
||||||
|
DisplayName: "code-server",
|
||||||
|
Url: "http://localhost:13337?folder=/home/coder",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Auth: &proto.Agent_Token{},
|
||||||
|
ConnectionTimeoutSeconds: 120,
|
||||||
|
}},
|
||||||
|
}},
|
||||||
} {
|
} {
|
||||||
folderName := folderName
|
folderName := folderName
|
||||||
expected := expected
|
expected := expected
|
||||||
@ -210,6 +257,17 @@ func TestConvertResources(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &resourcesMap)
|
err = json.Unmarshal(data, &resourcesMap)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
slices.SortFunc(expectedNoMetadataMap, func(a, b map[string]interface{}) bool {
|
||||||
|
//nolint:forcetypeassert
|
||||||
|
return a["name"].(string)+a["type"].(string) <
|
||||||
|
b["name"].(string)+b["type"].(string)
|
||||||
|
})
|
||||||
|
slices.SortFunc(resourcesMap, func(a, b map[string]interface{}) bool {
|
||||||
|
//nolint:forcetypeassert
|
||||||
|
return a["name"].(string)+a["type"].(string) <
|
||||||
|
b["name"].(string)+b["type"].(string)
|
||||||
|
})
|
||||||
|
|
||||||
require.Equal(t, expectedNoMetadataMap, resourcesMap)
|
require.Equal(t, expectedNoMetadataMap, resourcesMap)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -251,6 +309,17 @@ func TestConvertResources(t *testing.T) {
|
|||||||
err = json.Unmarshal(data, &resourcesMap)
|
err = json.Unmarshal(data, &resourcesMap)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
slices.SortFunc(expectedMap, func(a, b map[string]interface{}) bool {
|
||||||
|
//nolint:forcetypeassert
|
||||||
|
return a["name"].(string)+a["type"].(string) <
|
||||||
|
b["name"].(string)+b["type"].(string)
|
||||||
|
})
|
||||||
|
slices.SortFunc(resourcesMap, func(a, b map[string]interface{}) bool {
|
||||||
|
//nolint:forcetypeassert
|
||||||
|
return a["name"].(string)+a["type"].(string) <
|
||||||
|
b["name"].(string)+b["type"].(string)
|
||||||
|
})
|
||||||
|
|
||||||
require.Equal(t, expectedMap, resourcesMap)
|
require.Equal(t, expectedMap, resourcesMap)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
2
provisioner/terraform/testdata/calling-module/calling-module.tfplan.json
generated
vendored
2
provisioner/terraform/testdata/calling-module/calling-module.tfplan.json
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"format_version": "1.1",
|
"format_version": "1.1",
|
||||||
"terraform_version": "1.3.3",
|
"terraform_version": "1.3.6",
|
||||||
"planned_values": {
|
"planned_values": {
|
||||||
"root_module": {
|
"root_module": {
|
||||||
"resources": [
|
"resources": [
|
||||||
|
10
provisioner/terraform/testdata/calling-module/calling-module.tfstate.json
generated
vendored
10
provisioner/terraform/testdata/calling-module/calling-module.tfstate.json
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"format_version": "1.0",
|
"format_version": "1.0",
|
||||||
"terraform_version": "1.3.3",
|
"terraform_version": "1.3.6",
|
||||||
"values": {
|
"values": {
|
||||||
"root_module": {
|
"root_module": {
|
||||||
"resources": [
|
"resources": [
|
||||||
@ -17,11 +17,11 @@
|
|||||||
"connection_timeout": 120,
|
"connection_timeout": 120,
|
||||||
"dir": null,
|
"dir": null,
|
||||||
"env": null,
|
"env": null,
|
||||||
"id": "5c92d003-112d-4eb1-8e5f-d3009aa52fcb",
|
"id": "411bdd93-0ea4-4376-a032-52b1fbf44ca5",
|
||||||
"init_script": "",
|
"init_script": "",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
"startup_script": null,
|
"startup_script": null,
|
||||||
"token": "fedbf404-c42d-4360-815b-5ffc34198df3",
|
"token": "eeac85aa-19f9-4a50-8002-dfd11556081b",
|
||||||
"troubleshooting_url": null
|
"troubleshooting_url": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {}
|
"sensitive_values": {}
|
||||||
@ -46,7 +46,7 @@
|
|||||||
"outputs": {
|
"outputs": {
|
||||||
"script": ""
|
"script": ""
|
||||||
},
|
},
|
||||||
"random": "5577006791947779410"
|
"random": "5816533441722838433"
|
||||||
},
|
},
|
||||||
"sensitive_values": {
|
"sensitive_values": {
|
||||||
"inputs": {},
|
"inputs": {},
|
||||||
@ -61,7 +61,7 @@
|
|||||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"values": {
|
"values": {
|
||||||
"id": "8674665223082153551",
|
"id": "5594550025354402054",
|
||||||
"triggers": null
|
"triggers": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {},
|
"sensitive_values": {},
|
||||||
|
2
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json
generated
vendored
2
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfplan.json
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"format_version": "1.1",
|
"format_version": "1.1",
|
||||||
"terraform_version": "1.3.3",
|
"terraform_version": "1.3.6",
|
||||||
"planned_values": {
|
"planned_values": {
|
||||||
"root_module": {
|
"root_module": {
|
||||||
"resources": [
|
"resources": [
|
||||||
|
10
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json
generated
vendored
10
provisioner/terraform/testdata/chaining-resources/chaining-resources.tfstate.json
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"format_version": "1.0",
|
"format_version": "1.0",
|
||||||
"terraform_version": "1.3.3",
|
"terraform_version": "1.3.6",
|
||||||
"values": {
|
"values": {
|
||||||
"root_module": {
|
"root_module": {
|
||||||
"resources": [
|
"resources": [
|
||||||
@ -17,11 +17,11 @@
|
|||||||
"connection_timeout": 120,
|
"connection_timeout": 120,
|
||||||
"dir": null,
|
"dir": null,
|
||||||
"env": null,
|
"env": null,
|
||||||
"id": "6cc2be0d-fe90-4256-944f-482787433587",
|
"id": "4dc52ff5-b270-47a2-8b6a-695b4872f07b",
|
||||||
"init_script": "",
|
"init_script": "",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
"startup_script": null,
|
"startup_script": null,
|
||||||
"token": "1927809c-5fcf-4fdd-94d7-9a619fb86d13",
|
"token": "c5c8378e-66df-4f3f-94a2-84bff1dc6fc9",
|
||||||
"troubleshooting_url": null
|
"troubleshooting_url": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {}
|
"sensitive_values": {}
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"values": {
|
"values": {
|
||||||
"id": "8674665223082153551",
|
"id": "7372487656283423086",
|
||||||
"triggers": null
|
"triggers": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {},
|
"sensitive_values": {},
|
||||||
@ -51,7 +51,7 @@
|
|||||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"values": {
|
"values": {
|
||||||
"id": "5577006791947779410",
|
"id": "2553224683756509362",
|
||||||
"triggers": null
|
"triggers": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {},
|
"sensitive_values": {},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"format_version": "1.1",
|
"format_version": "1.1",
|
||||||
"terraform_version": "1.3.3",
|
"terraform_version": "1.3.6",
|
||||||
"planned_values": {
|
"planned_values": {
|
||||||
"root_module": {
|
"root_module": {
|
||||||
"resources": [
|
"resources": [
|
||||||
|
10
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json
generated
vendored
10
provisioner/terraform/testdata/conflicting-resources/conflicting-resources.tfstate.json
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"format_version": "1.0",
|
"format_version": "1.0",
|
||||||
"terraform_version": "1.3.3",
|
"terraform_version": "1.3.6",
|
||||||
"values": {
|
"values": {
|
||||||
"root_module": {
|
"root_module": {
|
||||||
"resources": [
|
"resources": [
|
||||||
@ -17,11 +17,11 @@
|
|||||||
"connection_timeout": 120,
|
"connection_timeout": 120,
|
||||||
"dir": null,
|
"dir": null,
|
||||||
"env": null,
|
"env": null,
|
||||||
"id": "bcaf2577-5dfd-4083-a446-789092a7babe",
|
"id": "3cd9cbba-31f7-482c-a8a0-bf39dfe42dc2",
|
||||||
"init_script": "",
|
"init_script": "",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
"startup_script": null,
|
"startup_script": null,
|
||||||
"token": "862867af-cf08-4aea-a2af-70d0014f848b",
|
"token": "8b063f22-9e66-4dbf-9f13-7b09ac2a470f",
|
||||||
"troubleshooting_url": null
|
"troubleshooting_url": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {}
|
"sensitive_values": {}
|
||||||
@ -34,7 +34,7 @@
|
|||||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"values": {
|
"values": {
|
||||||
"id": "8674665223082153551",
|
"id": "3370347998754925285",
|
||||||
"triggers": null
|
"triggers": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {},
|
"sensitive_values": {},
|
||||||
@ -50,7 +50,7 @@
|
|||||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"values": {
|
"values": {
|
||||||
"id": "5577006791947779410",
|
"id": "4707694957868093590",
|
||||||
"triggers": null
|
"triggers": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {},
|
"sensitive_values": {},
|
||||||
|
6
provisioner/terraform/testdata/generate.sh
vendored
6
provisioner/terraform/testdata/generate.sh
vendored
@ -6,6 +6,12 @@ cd "$(dirname "${BASH_SOURCE[0]}")"
|
|||||||
for d in */; do
|
for d in */; do
|
||||||
pushd "$d"
|
pushd "$d"
|
||||||
name=$(basename "$(pwd)")
|
name=$(basename "$(pwd)")
|
||||||
|
|
||||||
|
# This needs care to update correctly.
|
||||||
|
if [[ $name == "kubernetes-metadata" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
terraform init -upgrade
|
terraform init -upgrade
|
||||||
terraform plan -out terraform.tfplan
|
terraform plan -out terraform.tfplan
|
||||||
terraform show -json ./terraform.tfplan | jq >"$name".tfplan.json
|
terraform show -json ./terraform.tfplan | jq >"$name".tfplan.json
|
||||||
|
2
provisioner/terraform/testdata/instance-id/instance-id.tfplan.json
generated
vendored
2
provisioner/terraform/testdata/instance-id/instance-id.tfplan.json
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"format_version": "1.1",
|
"format_version": "1.1",
|
||||||
"terraform_version": "1.3.3",
|
"terraform_version": "1.3.6",
|
||||||
"planned_values": {
|
"planned_values": {
|
||||||
"root_module": {
|
"root_module": {
|
||||||
"resources": [
|
"resources": [
|
||||||
|
12
provisioner/terraform/testdata/instance-id/instance-id.tfstate.json
generated
vendored
12
provisioner/terraform/testdata/instance-id/instance-id.tfstate.json
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"format_version": "1.0",
|
"format_version": "1.0",
|
||||||
"terraform_version": "1.3.3",
|
"terraform_version": "1.3.6",
|
||||||
"values": {
|
"values": {
|
||||||
"root_module": {
|
"root_module": {
|
||||||
"resources": [
|
"resources": [
|
||||||
@ -17,11 +17,11 @@
|
|||||||
"connection_timeout": 120,
|
"connection_timeout": 120,
|
||||||
"dir": null,
|
"dir": null,
|
||||||
"env": null,
|
"env": null,
|
||||||
"id": "30431432-7afb-4d73-8eeb-ee464a28e157",
|
"id": "36189f12-6eed-4094-9179-6584a8659219",
|
||||||
"init_script": "",
|
"init_script": "",
|
||||||
"os": "linux",
|
"os": "linux",
|
||||||
"startup_script": null,
|
"startup_script": null,
|
||||||
"token": "3ce9bbd8-0f31-4460-842b-8e9c1de9a567",
|
"token": "907fa482-fd3b-44be-8cfb-4515e3122e78",
|
||||||
"troubleshooting_url": null
|
"troubleshooting_url": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {}
|
"sensitive_values": {}
|
||||||
@ -34,8 +34,8 @@
|
|||||||
"provider_name": "registry.terraform.io/coder/coder",
|
"provider_name": "registry.terraform.io/coder/coder",
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"values": {
|
"values": {
|
||||||
"agent_id": "30431432-7afb-4d73-8eeb-ee464a28e157",
|
"agent_id": "36189f12-6eed-4094-9179-6584a8659219",
|
||||||
"id": "679f9bf2-8887-4201-a5cd-e53913e8d361",
|
"id": "c9bd849e-ac37-440b-9c5b-a288344be41c",
|
||||||
"instance_id": "example"
|
"instance_id": "example"
|
||||||
},
|
},
|
||||||
"sensitive_values": {},
|
"sensitive_values": {},
|
||||||
@ -51,7 +51,7 @@
|
|||||||
"provider_name": "registry.terraform.io/hashicorp/null",
|
"provider_name": "registry.terraform.io/hashicorp/null",
|
||||||
"schema_version": 0,
|
"schema_version": 0,
|
||||||
"values": {
|
"values": {
|
||||||
"id": "5577006791947779410",
|
"id": "4399071137990404376",
|
||||||
"triggers": null
|
"triggers": null
|
||||||
},
|
},
|
||||||
"sensitive_values": {},
|
"sensitive_values": {},
|
||||||
|
183
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tf
vendored
Normal file
183
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tf
vendored
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
terraform {
|
||||||
|
required_providers {
|
||||||
|
coder = {
|
||||||
|
source = "coder/coder"
|
||||||
|
version = "0.6.5"
|
||||||
|
}
|
||||||
|
kubernetes = {
|
||||||
|
source = "hashicorp/kubernetes"
|
||||||
|
version = "~> 2.13.1"
|
||||||
|
}
|
||||||
|
google = {
|
||||||
|
source = "hashicorp/google"
|
||||||
|
version = "4.46.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data "google_client_config" "provider" {}
|
||||||
|
|
||||||
|
data "google_container_cluster" "dev-4-2" {
|
||||||
|
project = "coder-dev-1"
|
||||||
|
name = "dev-4-2"
|
||||||
|
location = "us-central1-a"
|
||||||
|
}
|
||||||
|
|
||||||
|
locals {
|
||||||
|
namespace = "colin-coder"
|
||||||
|
workspace_name = lower("coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}")
|
||||||
|
cpu = 1
|
||||||
|
memory = "1Gi"
|
||||||
|
gpu = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "kubernetes" {
|
||||||
|
host = "https://${data.google_container_cluster.dev-4-2.endpoint}"
|
||||||
|
token = data.google_client_config.provider.access_token
|
||||||
|
cluster_ca_certificate = base64decode(
|
||||||
|
data.google_container_cluster.dev-4-2.master_auth[0].cluster_ca_certificate,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data "coder_workspace" "me" {}
|
||||||
|
|
||||||
|
resource "coder_agent" "main" {
|
||||||
|
os = "linux"
|
||||||
|
arch = "amd64"
|
||||||
|
startup_script = <<EOT
|
||||||
|
#!/bin/bash
|
||||||
|
# home folder can be empty, so copying default bash settings
|
||||||
|
if [ ! -f ~/.profile ]; then
|
||||||
|
cp /etc/skel/.profile $HOME
|
||||||
|
fi
|
||||||
|
if [ ! -f ~/.bashrc ]; then
|
||||||
|
cp /etc/skel/.bashrc $HOME
|
||||||
|
fi
|
||||||
|
# install and start code-server
|
||||||
|
curl -fsSL https://code-server.dev/install.sh | sh | tee code-server-install.log
|
||||||
|
code-server --auth none --port 13337 | tee code-server-install.log &
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "coder_app" "code-server" {
|
||||||
|
agent_id = coder_agent.main.id
|
||||||
|
slug = "code-server"
|
||||||
|
icon = "/icon/code.svg"
|
||||||
|
url = "http://localhost:13337?folder=/home/coder"
|
||||||
|
subdomain = false
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_config_map" "coder_workspace" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
metadata {
|
||||||
|
name = local.workspace_name
|
||||||
|
namespace = local.namespace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_service_account" "coder_workspace" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
metadata {
|
||||||
|
name = local.workspace_name
|
||||||
|
namespace = local.namespace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resource "kubernetes_secret" "coder_workspace" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
metadata {
|
||||||
|
name = local.workspace_name
|
||||||
|
namespace = local.namespace
|
||||||
|
annotations = {
|
||||||
|
"kubernetes.io/service-account.name" = local.workspace_name
|
||||||
|
"kubernetes.io/service-account.namespace" = local.namespace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type = "kubernetes.io/service-account-token"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_role" "coder_workspace" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
metadata {
|
||||||
|
name = local.workspace_name
|
||||||
|
namespace = local.namespace
|
||||||
|
}
|
||||||
|
|
||||||
|
rule {
|
||||||
|
api_groups = ["*"]
|
||||||
|
resources = ["configmaps"]
|
||||||
|
resource_names = [local.workspace_name]
|
||||||
|
verbs = ["*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_role_binding" "coder_workspace" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
metadata {
|
||||||
|
name = local.workspace_name
|
||||||
|
namespace = local.namespace
|
||||||
|
}
|
||||||
|
role_ref {
|
||||||
|
api_group = "rbac.authorization.k8s.io"
|
||||||
|
kind = "Role"
|
||||||
|
name = local.workspace_name
|
||||||
|
}
|
||||||
|
subject {
|
||||||
|
kind = "ServiceAccount"
|
||||||
|
name = local.workspace_name
|
||||||
|
namespace = local.namespace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "kubernetes_pod" "main" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
depends_on = [
|
||||||
|
kubernetes_role.coder_workspace,
|
||||||
|
kubernetes_role_binding.coder_workspace,
|
||||||
|
kubernetes_service_account.coder_workspace,
|
||||||
|
kubernetes_secret.coder_workspace,
|
||||||
|
kubernetes_config_map.coder_workspace
|
||||||
|
]
|
||||||
|
metadata {
|
||||||
|
name = local.workspace_name
|
||||||
|
namespace = local.namespace
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
service_account_name = local.workspace_name
|
||||||
|
|
||||||
|
container {
|
||||||
|
name = "dev"
|
||||||
|
image = "codercom/enterprise-base:ubuntu"
|
||||||
|
command = ["sh", "-c", coder_agent.main.init_script]
|
||||||
|
security_context {
|
||||||
|
run_as_user = "1000"
|
||||||
|
}
|
||||||
|
env {
|
||||||
|
name = "CODER_AGENT_TOKEN"
|
||||||
|
value = coder_agent.main.token
|
||||||
|
}
|
||||||
|
resources {
|
||||||
|
limits = {
|
||||||
|
cpu = local.cpu
|
||||||
|
memory = local.memory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "coder_metadata" "kubernetes_pod_main" {
|
||||||
|
count = data.coder_workspace.me.start_count
|
||||||
|
resource_id = kubernetes_pod.main[0].id
|
||||||
|
item {
|
||||||
|
key = "cpu"
|
||||||
|
value = local.cpu
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
key = "memory"
|
||||||
|
value = local.memory
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
key = "gpu"
|
||||||
|
value = local.gpu
|
||||||
|
}
|
||||||
|
}
|
63
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tfplan.dot
generated
vendored
Normal file
63
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tfplan.dot
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
digraph {
|
||||||
|
compound = "true"
|
||||||
|
newrank = "true"
|
||||||
|
subgraph "root" {
|
||||||
|
"[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"]
|
||||||
|
"[root] coder_app.code-server (expand)" [label = "coder_app.code-server", shape = "box"]
|
||||||
|
"[root] coder_metadata.kubernetes_pod_main (expand)" [label = "coder_metadata.kubernetes_pod_main", shape = "box"]
|
||||||
|
"[root] data.coder_workspace.me (expand)" [label = "data.coder_workspace.me", shape = "box"]
|
||||||
|
"[root] data.google_client_config.provider (expand)" [label = "data.google_client_config.provider", shape = "box"]
|
||||||
|
"[root] data.google_container_cluster.dev-4-2 (expand)" [label = "data.google_container_cluster.dev-4-2", shape = "box"]
|
||||||
|
"[root] kubernetes_config_map.coder_workspace (expand)" [label = "kubernetes_config_map.coder_workspace", shape = "box"]
|
||||||
|
"[root] kubernetes_pod.main (expand)" [label = "kubernetes_pod.main", shape = "box"]
|
||||||
|
"[root] kubernetes_role.coder_workspace (expand)" [label = "kubernetes_role.coder_workspace", shape = "box"]
|
||||||
|
"[root] kubernetes_role_binding.coder_workspace (expand)" [label = "kubernetes_role_binding.coder_workspace", shape = "box"]
|
||||||
|
"[root] kubernetes_secret.coder_workspace (expand)" [label = "kubernetes_secret.coder_workspace", shape = "box"]
|
||||||
|
"[root] kubernetes_service_account.coder_workspace (expand)" [label = "kubernetes_service_account.coder_workspace", shape = "box"]
|
||||||
|
"[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"]
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/google\"]" [label = "provider[\"registry.terraform.io/hashicorp/google\"]", shape = "diamond"]
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]" [label = "provider[\"registry.terraform.io/hashicorp/kubernetes\"]", shape = "diamond"]
|
||||||
|
"[root] coder_agent.main (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
|
||||||
|
"[root] coder_app.code-server (expand)" -> "[root] coder_agent.main (expand)"
|
||||||
|
"[root] coder_metadata.kubernetes_pod_main (expand)" -> "[root] kubernetes_pod.main (expand)"
|
||||||
|
"[root] coder_metadata.kubernetes_pod_main (expand)" -> "[root] local.gpu (expand)"
|
||||||
|
"[root] data.coder_workspace.me (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
|
||||||
|
"[root] data.google_client_config.provider (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/google\"]"
|
||||||
|
"[root] data.google_container_cluster.dev-4-2 (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/google\"]"
|
||||||
|
"[root] kubernetes_config_map.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_config_map.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_config_map.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] coder_agent.main (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_config_map.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_role.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_role_binding.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_secret.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_service_account.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] local.cpu (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] local.memory (expand)"
|
||||||
|
"[root] kubernetes_role.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_role.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_role.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] kubernetes_role_binding.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_role_binding.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_role_binding.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] kubernetes_secret.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_secret.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_secret.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] kubernetes_service_account.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_service_account.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_service_account.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] local.workspace_name (expand)" -> "[root] data.coder_workspace.me (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_app.code-server (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_metadata.kubernetes_pod_main (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/google\"] (close)" -> "[root] data.google_client_config.provider (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/google\"] (close)" -> "[root] data.google_container_cluster.dev-4-2 (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"] (close)" -> "[root] kubernetes_pod.main (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]" -> "[root] data.google_client_config.provider (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]" -> "[root] data.google_container_cluster.dev-4-2 (expand)"
|
||||||
|
"[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)"
|
||||||
|
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/google\"] (close)"
|
||||||
|
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"] (close)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2179
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tfplan.json
generated
vendored
Normal file
2179
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tfplan.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
63
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tfstate.dot
generated
vendored
Normal file
63
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tfstate.dot
generated
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
digraph {
|
||||||
|
compound = "true"
|
||||||
|
newrank = "true"
|
||||||
|
subgraph "root" {
|
||||||
|
"[root] coder_agent.main (expand)" [label = "coder_agent.main", shape = "box"]
|
||||||
|
"[root] coder_app.code-server (expand)" [label = "coder_app.code-server", shape = "box"]
|
||||||
|
"[root] coder_metadata.kubernetes_pod_main (expand)" [label = "coder_metadata.kubernetes_pod_main", shape = "box"]
|
||||||
|
"[root] data.coder_workspace.me (expand)" [label = "data.coder_workspace.me", shape = "box"]
|
||||||
|
"[root] data.google_client_config.provider (expand)" [label = "data.google_client_config.provider", shape = "box"]
|
||||||
|
"[root] data.google_container_cluster.dev-4-2 (expand)" [label = "data.google_container_cluster.dev-4-2", shape = "box"]
|
||||||
|
"[root] kubernetes_config_map.coder_workspace (expand)" [label = "kubernetes_config_map.coder_workspace", shape = "box"]
|
||||||
|
"[root] kubernetes_pod.main (expand)" [label = "kubernetes_pod.main", shape = "box"]
|
||||||
|
"[root] kubernetes_role.coder_workspace (expand)" [label = "kubernetes_role.coder_workspace", shape = "box"]
|
||||||
|
"[root] kubernetes_role_binding.coder_workspace (expand)" [label = "kubernetes_role_binding.coder_workspace", shape = "box"]
|
||||||
|
"[root] kubernetes_secret.coder_workspace (expand)" [label = "kubernetes_secret.coder_workspace", shape = "box"]
|
||||||
|
"[root] kubernetes_service_account.coder_workspace (expand)" [label = "kubernetes_service_account.coder_workspace", shape = "box"]
|
||||||
|
"[root] provider[\"registry.terraform.io/coder/coder\"]" [label = "provider[\"registry.terraform.io/coder/coder\"]", shape = "diamond"]
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/google\"]" [label = "provider[\"registry.terraform.io/hashicorp/google\"]", shape = "diamond"]
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]" [label = "provider[\"registry.terraform.io/hashicorp/kubernetes\"]", shape = "diamond"]
|
||||||
|
"[root] coder_agent.main (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
|
||||||
|
"[root] coder_app.code-server (expand)" -> "[root] coder_agent.main (expand)"
|
||||||
|
"[root] coder_metadata.kubernetes_pod_main (expand)" -> "[root] kubernetes_pod.main (expand)"
|
||||||
|
"[root] coder_metadata.kubernetes_pod_main (expand)" -> "[root] local.gpu (expand)"
|
||||||
|
"[root] data.coder_workspace.me (expand)" -> "[root] provider[\"registry.terraform.io/coder/coder\"]"
|
||||||
|
"[root] data.google_client_config.provider (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/google\"]"
|
||||||
|
"[root] data.google_container_cluster.dev-4-2 (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/google\"]"
|
||||||
|
"[root] kubernetes_config_map.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_config_map.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_config_map.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] coder_agent.main (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_config_map.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_role.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_role_binding.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_secret.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] kubernetes_service_account.coder_workspace (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] local.cpu (expand)"
|
||||||
|
"[root] kubernetes_pod.main (expand)" -> "[root] local.memory (expand)"
|
||||||
|
"[root] kubernetes_role.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_role.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_role.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] kubernetes_role_binding.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_role_binding.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_role_binding.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] kubernetes_secret.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_secret.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_secret.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] kubernetes_service_account.coder_workspace (expand)" -> "[root] local.namespace (expand)"
|
||||||
|
"[root] kubernetes_service_account.coder_workspace (expand)" -> "[root] local.workspace_name (expand)"
|
||||||
|
"[root] kubernetes_service_account.coder_workspace (expand)" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]"
|
||||||
|
"[root] local.workspace_name (expand)" -> "[root] data.coder_workspace.me (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_app.code-server (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/coder/coder\"] (close)" -> "[root] coder_metadata.kubernetes_pod_main (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/google\"] (close)" -> "[root] data.google_client_config.provider (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/google\"] (close)" -> "[root] data.google_container_cluster.dev-4-2 (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"] (close)" -> "[root] kubernetes_pod.main (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]" -> "[root] data.google_client_config.provider (expand)"
|
||||||
|
"[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"]" -> "[root] data.google_container_cluster.dev-4-2 (expand)"
|
||||||
|
"[root] root" -> "[root] provider[\"registry.terraform.io/coder/coder\"] (close)"
|
||||||
|
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/google\"] (close)"
|
||||||
|
"[root] root" -> "[root] provider[\"registry.terraform.io/hashicorp/kubernetes\"] (close)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
1116
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tfstate.json
generated
vendored
Normal file
1116
provisioner/terraform/testdata/kubernetes-metadata/kubernetes-metadata.tfstate.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user