Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit558c1eb

Browse files
committed
fix: respect resource_id for coder_metadata
1 parentbe4f5ef commit558c1eb

File tree

2 files changed

+238
-26
lines changed

2 files changed

+238
-26
lines changed

‎provisioner/terraform/resources.go

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -646,41 +646,77 @@ func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph s
646646
iferr!=nil {
647647
returnnil,xerrors.Errorf("decode metadata attributes: %w",err)
648648
}
649-
resourceLabel:=convertAddressToLabel(resource.Address)
650649

651-
varattachedNode*gographviz.Node
652-
for_,node:=rangegraph.Nodes.Lookup {
653-
// The node attributes surround the label with quotes.
654-
ifstrings.Trim(node.Attrs["label"],`"`)!=resourceLabel {
655-
continue
650+
vartargetLabelstring
651+
652+
// First, check if ResourceID is provided and try to find the resource by ID
653+
ifattrs.ResourceID!="" {
654+
// Look for a resource with matching ID
655+
foundByID:=false
656+
forlabel,tfResources:=rangetfResourcesByLabel {
657+
for_,tfResource:=rangetfResources {
658+
// Check if this resource's ID matches the ResourceID
659+
idAttr,hasID:=tfResource.AttributeValues["id"]
660+
ifhasID {
661+
idStr,ok:=idAttr.(string)
662+
ifok&&idStr==attrs.ResourceID {
663+
targetLabel=label
664+
foundByID=true
665+
break
666+
}
667+
}
668+
}
669+
iffoundByID {
670+
break
671+
}
672+
}
673+
674+
// If we couldn't find by ID, fall back to graph traversal
675+
if!foundByID {
676+
logger.Warn(ctx,"coder_metadata resource_id not found, falling back to graph traversal",
677+
slog.F("resource_id",attrs.ResourceID),
678+
slog.F("metadata_address",resource.Address))
656679
}
657-
attachedNode=node
658-
break
659-
}
660-
ifattachedNode==nil {
661-
continue
662680
}
663-
varattachedResource*graphResource
664-
for_,resource:=rangefindResourcesInGraph(graph,tfResourcesByLabel,attachedNode.Name,0,false) {
665-
ifattachedResource==nil {
666-
// Default to the first resource because we have nothing to compare!
667-
attachedResource=resource
668-
continue
681+
682+
// If ResourceID wasn't provided or wasn't found, use graph traversal
683+
iftargetLabel=="" {
684+
resourceLabel:=convertAddressToLabel(resource.Address)
685+
686+
varattachedNode*gographviz.Node
687+
for_,node:=rangegraph.Nodes.Lookup {
688+
// The node attributes surround the label with quotes.
689+
ifstrings.Trim(node.Attrs["label"],`"`)!=resourceLabel {
690+
continue
691+
}
692+
attachedNode=node
693+
break
669694
}
670-
ifresource.Depth<attachedResource.Depth {
671-
// There's a closer resource!
672-
attachedResource=resource
695+
ifattachedNode==nil {
673696
continue
674697
}
675-
ifresource.Depth==attachedResource.Depth&&resource.Label<attachedResource.Label {
676-
attachedResource=resource
698+
varattachedResource*graphResource
699+
for_,resource:=rangefindResourcesInGraph(graph,tfResourcesByLabel,attachedNode.Name,0,false) {
700+
ifattachedResource==nil {
701+
// Default to the first resource because we have nothing to compare!
702+
attachedResource=resource
703+
continue
704+
}
705+
ifresource.Depth<attachedResource.Depth {
706+
// There's a closer resource!
707+
attachedResource=resource
708+
continue
709+
}
710+
ifresource.Depth==attachedResource.Depth&&resource.Label<attachedResource.Label {
711+
attachedResource=resource
712+
continue
713+
}
714+
}
715+
ifattachedResource==nil {
677716
continue
678717
}
718+
targetLabel=attachedResource.Label
679719
}
680-
ifattachedResource==nil {
681-
continue
682-
}
683-
targetLabel:=attachedResource.Label
684720

685721
ifmetadataTargetLabels[targetLabel] {
686722
returnnil,xerrors.Errorf("duplicate metadata resource: %s",targetLabel)

‎provisioner/terraform/resources_test.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,3 +1469,179 @@ func sortExternalAuthProviders(providers []*proto.ExternalAuthProviderResource)
14691469
returnstrings.Compare(providers[i].Id,providers[j].Id)==-1
14701470
})
14711471
}
1472+
1473+
funcTestMetadataResourceID(t*testing.T) {
1474+
t.Parallel()
1475+
1476+
t.Run("UsesResourceIDWhenProvided",func(t*testing.T) {
1477+
t.Parallel()
1478+
ctx,logger:=ctxAndLogger(t)
1479+
1480+
// Create a state with two resources and metadata that references the second one via resource_id
1481+
state,err:=terraform.ConvertState(ctx, []*tfjson.StateModule{{
1482+
Resources: []*tfjson.StateResource{{
1483+
Address:"null_resource.first",
1484+
Type:"null_resource",
1485+
Name:"first",
1486+
Mode:tfjson.ManagedResourceMode,
1487+
AttributeValues:map[string]interface{}{
1488+
"id":"first-resource-id",
1489+
},
1490+
}, {
1491+
Address:"null_resource.second",
1492+
Type:"null_resource",
1493+
Name:"second",
1494+
Mode:tfjson.ManagedResourceMode,
1495+
AttributeValues:map[string]interface{}{
1496+
"id":"second-resource-id",
1497+
},
1498+
}, {
1499+
Address:"coder_metadata.example",
1500+
Type:"coder_metadata",
1501+
Name:"example",
1502+
Mode:tfjson.ManagedResourceMode,
1503+
DependsOn: []string{"null_resource.first"},
1504+
AttributeValues:map[string]interface{}{
1505+
"resource_id":"second-resource-id",
1506+
"item": []interface{}{
1507+
map[string]interface{}{
1508+
"key":"test",
1509+
"value":"value",
1510+
},
1511+
},
1512+
},
1513+
}},
1514+
}},`digraph {
1515+
compound = "true"
1516+
newrank = "true"
1517+
subgraph "root" {
1518+
"[root] null_resource.first" [label = "null_resource.first", shape = "box"]
1519+
"[root] null_resource.second" [label = "null_resource.second", shape = "box"]
1520+
"[root] coder_metadata.example" [label = "coder_metadata.example", shape = "box"]
1521+
"[root] coder_metadata.example" -> "[root] null_resource.first"
1522+
}
1523+
}`,logger)
1524+
require.NoError(t,err)
1525+
require.Len(t,state.Resources,2)
1526+
1527+
// Find the resources
1528+
varfirstResource,secondResource*proto.Resource
1529+
for_,res:=rangestate.Resources {
1530+
ifres.Name=="first"&&res.Type=="null_resource" {
1531+
firstResource=res
1532+
}elseifres.Name=="second"&&res.Type=="null_resource" {
1533+
secondResource=res
1534+
}
1535+
}
1536+
1537+
require.NotNil(t,firstResource)
1538+
require.NotNil(t,secondResource)
1539+
1540+
// The metadata should be on the second resource (as specified by resource_id),
1541+
// not the first one (which is the closest in the graph)
1542+
require.Len(t,firstResource.Metadata,0,"first resource should have no metadata")
1543+
require.Len(t,secondResource.Metadata,1,"second resource should have metadata")
1544+
require.Equal(t,"test",secondResource.Metadata[0].Key)
1545+
require.Equal(t,"value",secondResource.Metadata[0].Value)
1546+
})
1547+
1548+
t.Run("FallsBackToGraphWhenResourceIDNotFound",func(t*testing.T) {
1549+
t.Parallel()
1550+
ctx,logger:=ctxAndLogger(t)
1551+
1552+
// Create a state where resource_id references a non-existent ID
1553+
state,err:=terraform.ConvertState(ctx, []*tfjson.StateModule{{
1554+
Resources: []*tfjson.StateResource{{
1555+
Address:"null_resource.example",
1556+
Type:"null_resource",
1557+
Name:"example",
1558+
Mode:tfjson.ManagedResourceMode,
1559+
AttributeValues:map[string]interface{}{
1560+
"id":"example-resource-id",
1561+
},
1562+
}, {
1563+
Address:"coder_metadata.example",
1564+
Type:"coder_metadata",
1565+
Name:"example",
1566+
Mode:tfjson.ManagedResourceMode,
1567+
DependsOn: []string{"null_resource.example"},
1568+
AttributeValues:map[string]interface{}{
1569+
"resource_id":"non-existent-id",
1570+
"item": []interface{}{
1571+
map[string]interface{}{
1572+
"key":"test",
1573+
"value":"value",
1574+
},
1575+
},
1576+
},
1577+
}},
1578+
}},`digraph {
1579+
compound = "true"
1580+
newrank = "true"
1581+
subgraph "root" {
1582+
"[root] null_resource.example" [label = "null_resource.example", shape = "box"]
1583+
"[root] coder_metadata.example" [label = "coder_metadata.example", shape = "box"]
1584+
"[root] coder_metadata.example" -> "[root] null_resource.example"
1585+
}
1586+
}`,logger)
1587+
require.NoError(t,err)
1588+
require.Len(t,state.Resources,1)
1589+
1590+
// The metadata should still be applied via graph traversal
1591+
require.Equal(t,"example",state.Resources[0].Name)
1592+
require.Len(t,state.Resources[0].Metadata,1)
1593+
require.Equal(t,"test",state.Resources[0].Metadata[0].Key)
1594+
require.Equal(t,"value",state.Resources[0].Metadata[0].Value)
1595+
1596+
// When resource_id is not found, it falls back to graph traversal
1597+
// We can't easily verify the warning was logged without access to the log capture API
1598+
})
1599+
1600+
t.Run("UsesGraphWhenResourceIDNotProvided",func(t*testing.T) {
1601+
t.Parallel()
1602+
ctx,logger:=ctxAndLogger(t)
1603+
1604+
// Create a state without resource_id
1605+
state,err:=terraform.ConvertState(ctx, []*tfjson.StateModule{{
1606+
Resources: []*tfjson.StateResource{{
1607+
Address:"null_resource.example",
1608+
Type:"null_resource",
1609+
Name:"example",
1610+
Mode:tfjson.ManagedResourceMode,
1611+
AttributeValues:map[string]interface{}{
1612+
"id":"example-resource-id",
1613+
},
1614+
}, {
1615+
Address:"coder_metadata.example",
1616+
Type:"coder_metadata",
1617+
Name:"example",
1618+
Mode:tfjson.ManagedResourceMode,
1619+
DependsOn: []string{"null_resource.example"},
1620+
AttributeValues:map[string]interface{}{
1621+
"item": []interface{}{
1622+
map[string]interface{}{
1623+
"key":"test",
1624+
"value":"value",
1625+
},
1626+
},
1627+
},
1628+
}},
1629+
}},`digraph {
1630+
compound = "true"
1631+
newrank = "true"
1632+
subgraph "root" {
1633+
"[root] null_resource.example" [label = "null_resource.example", shape = "box"]
1634+
"[root] coder_metadata.example" [label = "coder_metadata.example", shape = "box"]
1635+
"[root] coder_metadata.example" -> "[root] null_resource.example"
1636+
}
1637+
}`,logger)
1638+
require.NoError(t,err)
1639+
require.Len(t,state.Resources,1)
1640+
1641+
// The metadata should be applied via graph traversal
1642+
require.Equal(t,"example",state.Resources[0].Name)
1643+
require.Len(t,state.Resources[0].Metadata,1)
1644+
require.Equal(t,"test",state.Resources[0].Metadata[0].Key)
1645+
require.Equal(t,"value",state.Resources[0].Metadata[0].Value)
1646+
})
1647+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp