MCPcopy Create free account
hub / github.com/coder/coder / ConvertState

Function ConvertState

provisioner/terraform/resources.go:193–1076  ·  view source on GitHub ↗

ConvertState consumes Terraform state and a GraphViz representation produced by `terraform graph` to produce resources consumable by Coder. nolint:gocognit // This function makes more sense being large for now, until refactored.

(ctx context.Context, modules []*tfjson.StateModule, rawGraph string, logger slog.Logger)

Source from the content-addressed store, hash-verified

191// produced by `terraform graph` to produce resources consumable by Coder.
192// nolint:gocognit // This function makes more sense being large for now, until refactored.
193func ConvertState(ctx context.Context, modules []*tfjson.StateModule, rawGraph string, logger slog.Logger) (*State, error) {
194 parsedGraph, err := gographviz.ParseString(rawGraph)
195 if err != nil {
196 return nil, xerrors.Errorf("parse graph: %w", err)
197 }
198 graph, err := gographviz.NewAnalysedGraph(parsedGraph)
199 if err != nil {
200 return nil, xerrors.Errorf("analyze graph: %w", err)
201 }
202
203 resources := make([]*proto.Resource, 0)
204 resourceAgents := map[string][]*proto.Agent{}
205
206 // Indexes Terraform resources by their label.
207 // The label is what "terraform graph" uses to reference nodes.
208 tfResourcesByLabel := map[string]map[string]*tfjson.StateResource{}
209
210 // Extra array to preserve the order of rich parameters.
211 tfResourcesRichParameters := make([]*tfjson.StateResource, 0)
212 tfResourcesPresets := make([]*tfjson.StateResource, 0)
213 tfResourcesAITasks := make([]*tfjson.StateResource, 0)
214 var findTerraformResources func(mod *tfjson.StateModule)
215 findTerraformResources = func(mod *tfjson.StateModule) {
216 for _, module := range mod.ChildModules {
217 findTerraformResources(module)
218 }
219 for _, resource := range mod.Resources {
220 if resource.Type == "coder_parameter" {
221 tfResourcesRichParameters = append(tfResourcesRichParameters, resource)
222 }
223 if resource.Type == "coder_workspace_preset" {
224 tfResourcesPresets = append(tfResourcesPresets, resource)
225 }
226 if resource.Type == "coder_ai_task" {
227 tfResourcesAITasks = append(tfResourcesAITasks, resource)
228 }
229
230 label := convertAddressToLabel(resource.Address)
231 if tfResourcesByLabel[label] == nil {
232 tfResourcesByLabel[label] = map[string]*tfjson.StateResource{}
233 }
234 tfResourcesByLabel[label][resource.Address] = resource
235 }
236 }
237 for _, module := range modules {
238 findTerraformResources(module)
239 }
240
241 // Group all resources by type in a single pass so that
242 // subsequent lookups are O(1) instead of scanning the
243 // full map each time.
244 sortedResources := sortResourcesByType(tfResourcesByLabel)
245
246 // Find all agents!
247 agentNames := map[string]struct{}{}
248 for _, tfResource := range sortedResources["coder_agent"] {
249 var attrs agentAttributes
250 err = mapstructure.Decode(tfResource.AttributeValues, &attrs)

Callers 15

TestConvertResourcesFunction · 0.92
TestAppSlugValidationFunction · 0.92
TestAppSlugDuplicateFunction · 0.92
TestAgentNameInvalidFunction · 0.92
TestAgentNameDuplicateFunction · 0.92
TestParameterValidationFunction · 0.92
TestDefaultPresetsFunction · 0.92
TestAITasksFunction · 0.92

Calls 15

GetDevcontainersMethod · 0.95
DefaultDisplayAppsFunction · 0.92
FormTypeFunction · 0.92
RefFunction · 0.92
ContainsFunction · 0.92
ContainsCompareFunction · 0.92
convertAddressToLabelFunction · 0.85
sortResourcesByTypeFunction · 0.85
findResourcesInGraphFunction · 0.85
dependsOnAgentFunction · 0.85
dependsOnDevcontainerFunction · 0.85
managedNonCoderResourcesFunction · 0.85

Tested by 15

TestConvertResourcesFunction · 0.74
TestAppSlugValidationFunction · 0.74
TestAppSlugDuplicateFunction · 0.74
TestAgentNameInvalidFunction · 0.74
TestAgentNameDuplicateFunction · 0.74
TestParameterValidationFunction · 0.74
TestDefaultPresetsFunction · 0.74
TestAITasksFunction · 0.74