Skip to content

Commit 8a94b72

Browse files
feat: Allow hide resources (#3977)
1 parent f6aa025 commit 8a94b72

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+458
-335
lines changed

coderd/database/databasefake/databasefake.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,6 +1767,7 @@ func (q *fakeQuerier) InsertWorkspaceResource(_ context.Context, arg database.In
17671767
Transition: arg.Transition,
17681768
Type: arg.Type,
17691769
Name: arg.Name,
1770+
Hide: arg.Hide,
17701771
}
17711772
q.provisionerJobResources = append(q.provisionerJobResources, resource)
17721773
return resource, nil

coderd/database/dump.sql

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE workspace_resources
2+
DROP COLUMN hide;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
ALTER TABLE workspace_resources
2+
ADD COLUMN hide boolean DEFAULT false NOT NULL;

coderd/database/models.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

Lines changed: 11 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries/workspaceresources.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ SELECT * FROM workspace_resources WHERE created_at > $1;
1919

2020
-- name: InsertWorkspaceResource :one
2121
INSERT INTO
22-
workspace_resources (id, created_at, job_id, transition, type, name)
22+
workspace_resources (id, created_at, job_id, transition, type, name, hide)
2323
VALUES
24-
($1, $2, $3, $4, $5, $6) RETURNING *;
24+
($1, $2, $3, $4, $5, $6, $7) RETURNING *;
2525

2626
-- name: GetWorkspaceResourceMetadataByResourceID :many
2727
SELECT

coderd/provisionerdaemons.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ func insertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
752752
Transition: transition,
753753
Type: protoResource.Type,
754754
Name: protoResource.Name,
755+
Hide: protoResource.Hide,
755756
})
756757
if err != nil {
757758
return xerrors.Errorf("insert provisioner job resource %q: %w", protoResource.Name, err)

coderd/workspacebuilds.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,7 @@ func convertWorkspaceResource(resource database.WorkspaceResource, agents []code
698698
Transition: codersdk.WorkspaceTransition(resource.Transition),
699699
Type: resource.Type,
700700
Name: resource.Name,
701+
Hide: resource.Hide,
701702
Agents: agents,
702703
Metadata: convertedMetadata,
703704
}

codersdk/workspaceresources.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type WorkspaceResource struct {
2525
Transition WorkspaceTransition `json:"workspace_transition"`
2626
Type string `json:"type"`
2727
Name string `json:"name"`
28+
Hide bool `json:"hide"`
2829
Agents []WorkspaceAgent `json:"agents,omitempty"`
2930
Metadata []WorkspaceResourceMetadata `json:"metadata,omitempty"`
3031
}

provisioner/terraform/provision_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ func TestProvision_Cancel(t *testing.T) {
6868

6969
cwd, err := os.Getwd()
7070
require.NoError(t, err)
71-
fakeBin := filepath.Join(cwd, "testdata", "bin", "terraform_fake_cancel.sh")
71+
fakeBin := filepath.Join(cwd, "testdata", "fake_cancel.sh")
7272

7373
tests := []struct {
7474
name string

provisioner/terraform/resources.go

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ type agentAppAttributes struct {
3636
// A mapping of attributes on the "coder_metadata" resource.
3737
type metadataAttributes struct {
3838
ResourceID string `mapstructure:"resource_id"`
39+
Hide bool `mapstructure:"hide"`
3940
Items []metadataItem `mapstructure:"item"`
4041
}
4142

@@ -48,6 +49,7 @@ type metadataItem struct {
4849

4950
// ConvertResources consumes Terraform state and a GraphViz representation produced by
5051
// `terraform graph` to produce resources consumable by Coder.
52+
// nolint:gocyclo
5153
func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Resource, error) {
5254
parsedGraph, err := gographviz.ParseString(rawGraph)
5355
if err != nil {
@@ -137,7 +139,7 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
137139
}
138140

139141
var agentResource *graphResource
140-
for _, resource := range findResourcesUpGraph(graph, tfResourceByLabel, agentNode.Name, 0) {
142+
for _, resource := range findResourcesInGraph(graph, tfResourceByLabel, agentNode.Name, 0, true) {
141143
if agentResource == nil {
142144
// Default to the first resource because we have nothing to compare!
143145
agentResource = resource
@@ -234,7 +236,8 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
234236

235237
// Associate metadata blocks with resources.
236238
resourceMetadata := map[string][]*proto.Resource_Metadata{}
237-
for label, resource := range tfResourceByLabel {
239+
resourceHidden := map[string]bool{}
240+
for _, resource := range tfResourceByLabel {
238241
if resource.Type != "coder_metadata" {
239242
continue
240243
}
@@ -244,17 +247,54 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
244247
return nil, xerrors.Errorf("decode metadata attributes: %w", err)
245248
}
246249

250+
var targetLabel string
251+
// This occurs in a plan, because there is no resource ID.
252+
// We attempt to find the closest node, just so we can hide it from the UI.
247253
if attrs.ResourceID == "" {
248-
// TODO: detect this as an error
249-
// At plan time, change.after_unknown.resource_id should be "true".
250-
// At provision time, values.resource_id should be set.
251-
continue
254+
resourceLabel := convertAddressToLabel(resource.Address)
255+
256+
var attachedNode *gographviz.Node
257+
for _, node := range graph.Nodes.Lookup {
258+
// The node attributes surround the label with quotes.
259+
if strings.Trim(node.Attrs["label"], `"`) != resourceLabel {
260+
continue
261+
}
262+
attachedNode = node
263+
break
264+
}
265+
if attachedNode == nil {
266+
continue
267+
}
268+
var attachedResource *graphResource
269+
for _, resource := range findResourcesInGraph(graph, tfResourceByLabel, attachedNode.Name, 0, false) {
270+
if attachedResource == nil {
271+
// Default to the first resource because we have nothing to compare!
272+
attachedResource = resource
273+
continue
274+
}
275+
if resource.Depth < attachedResource.Depth {
276+
// There's a closer resource!
277+
attachedResource = resource
278+
continue
279+
}
280+
if resource.Depth == attachedResource.Depth && resource.Label < attachedResource.Label {
281+
attachedResource = resource
282+
continue
283+
}
284+
}
285+
if attachedResource == nil {
286+
continue
287+
}
288+
targetLabel = attachedResource.Label
252289
}
253-
targetLabel, ok := resourceLabelByID[attrs.ResourceID]
254-
if !ok {
255-
return nil, xerrors.Errorf("attribute %s.resource_id = %q does not refer to a valid resource", label, attrs.ResourceID)
290+
if targetLabel == "" {
291+
targetLabel = resourceLabelByID[attrs.ResourceID]
292+
}
293+
if targetLabel == "" {
294+
continue
256295
}
257296

297+
resourceHidden[targetLabel] = attrs.Hide
258298
for _, item := range attrs.Items {
259299
resourceMetadata[targetLabel] = append(resourceMetadata[targetLabel],
260300
&proto.Resource_Metadata{
@@ -284,6 +324,7 @@ func ConvertResources(module *tfjson.StateModule, rawGraph string) ([]*proto.Res
284324
Name: resource.Name,
285325
Type: resource.Type,
286326
Agents: agents,
327+
Hide: resourceHidden[label],
287328
Metadata: resourceMetadata[label],
288329
})
289330
}
@@ -344,14 +385,19 @@ func applyAutomaticInstanceID(resource *tfjson.StateResource, agents []*proto.Ag
344385
}
345386
}
346387

347-
// findResourcesUpGraph traverses upwards in a graph until a resource is found,
388+
// findResourcesInGraph traverses directionally in a graph until a resource is found,
348389
// then it stores the depth it was found at, and continues working up the tree.
349-
func findResourcesUpGraph(graph *gographviz.Graph, tfResourceByLabel map[string]*tfjson.StateResource, nodeName string, currentDepth uint) []*graphResource {
390+
// nolint:revive
391+
func findResourcesInGraph(graph *gographviz.Graph, tfResourceByLabel map[string]*tfjson.StateResource, nodeName string, currentDepth uint, up bool) []*graphResource {
350392
graphResources := make([]*graphResource, 0)
351-
for destination := range graph.Edges.DstToSrcs[nodeName] {
393+
mapping := graph.Edges.DstToSrcs
394+
if !up {
395+
mapping = graph.Edges.SrcToDsts
396+
}
397+
for destination := range mapping[nodeName] {
352398
destinationNode := graph.Nodes.Lookup[destination]
353399
// Work our way up the tree!
354-
graphResources = append(graphResources, findResourcesUpGraph(graph, tfResourceByLabel, destinationNode.Name, currentDepth+1)...)
400+
graphResources = append(graphResources, findResourcesInGraph(graph, tfResourceByLabel, destinationNode.Name, currentDepth+1, up)...)
355401

356402
destinationLabel, exists := destinationNode.Attrs["label"]
357403
if !exists {

provisioner/terraform/resources_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ func TestConvertResources(t *testing.T) {
120120
"resource-metadata": {{
121121
Name: "about",
122122
Type: "null_resource",
123+
Hide: true,
123124
Metadata: []*proto.Resource_Metadata{{
124125
Key: "hello",
125126
Value: "world",
@@ -155,11 +156,13 @@ func TestConvertResources(t *testing.T) {
155156
require.NoError(t, err)
156157
sortResources(resources)
157158

158-
// plan does not contain metadata, so clone expected and remove it
159159
var expectedNoMetadata []*proto.Resource
160160
for _, resource := range expected {
161161
resourceCopy, _ := protobuf.Clone(resource).(*proto.Resource)
162-
resourceCopy.Metadata = nil
162+
// plan cannot know whether values are null or not
163+
for _, metadata := range resourceCopy.Metadata {
164+
metadata.IsNull = false
165+
}
163166
expectedNoMetadata = append(expectedNoMetadata, resourceCopy)
164167
}
165168

provisioner/terraform/testdata/calling-module/calling-module.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ terraform {
22
required_providers {
33
coder = {
44
source = "coder/coder"
5-
version = "0.4.2"
5+
version = "0.4.10"
66
}
77
}
88
}

provisioner/terraform/testdata/calling-module/calling-module.tfplan.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

provisioner/terraform/testdata/calling-module/calling-module.tfstate.json

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

provisioner/terraform/testdata/chaining-resources/chaining-resources.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ terraform {
22
required_providers {
33
coder = {
44
source = "coder/coder"
5-
version = "0.4.2"
5+
version = "0.4.10"
66
}
77
}
88
}

0 commit comments

Comments
 (0)