From 66cdc97e9d3b94d158052d306acf6f711f936094 Mon Sep 17 00:00:00 2001 From: Ansgar Mertens Date: Fri, 17 Jan 2025 16:39:36 +0100 Subject: [PATCH] feat: Collect write only attributes via PathDecoder (#442) --- decoder/write_only_attributes.go | 76 ++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 decoder/write_only_attributes.go diff --git a/decoder/write_only_attributes.go b/decoder/write_only_attributes.go new file mode 100644 index 00000000..672c0ae9 --- /dev/null +++ b/decoder/write_only_attributes.go @@ -0,0 +1,76 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package decoder + +import ( + "github.com/hashicorp/hcl-lang/decoder/internal/ast" + "github.com/hashicorp/hcl-lang/decoder/internal/schemahelper" + "github.com/hashicorp/hcl-lang/schema" + "github.com/hashicorp/hcl/v2" +) + +type WriteOnlyAttribute struct { + Name string + Resource string +} + +type WriteOnlyAttributes []WriteOnlyAttribute + +func (d *PathDecoder) CollectWriteOnlyAttributes() (WriteOnlyAttributes, error) { + if d.pathCtx.Schema == nil { + // unable to collect write-only attributes without schema + return nil, &NoSchemaError{} + } + + attrs := make(WriteOnlyAttributes, 0) + files := d.filenames() + for _, filename := range files { + f, err := d.fileByName(filename) + if err != nil { + // skip unparseable file + continue + } + attrs = append(attrs, d.decodeWriteOnlyAttributesForBody(f.Body, d.pathCtx.Schema)...) + } + + return attrs, nil +} + +func (d *PathDecoder) decodeWriteOnlyAttributesForBody(body hcl.Body, bodySchema *schema.BodySchema) WriteOnlyAttributes { + woAttrs := make(WriteOnlyAttributes, 0) + + if bodySchema == nil { + return WriteOnlyAttributes{} + } + + content := ast.DecodeBody(body, bodySchema) + + for _, block := range content.Blocks { + if block.Type == "resource" { + blockSchema, ok := bodySchema.Blocks[block.Type] + if !ok { + // unknown block (no schema) + continue + } + + mergedSchema, _ := schemahelper.MergeBlockBodySchemas(block.Block, blockSchema) + + blockContent := ast.DecodeBody(block.Body, blockSchema.Body) + + for _, attr := range blockContent.Attributes { + attrSchema, ok := mergedSchema.Attributes[attr.Name] + if ok && attrSchema.IsWriteOnly { + + woAttrs = append(woAttrs, WriteOnlyAttribute{ + Name: attr.Name, + Resource: block.Labels[0], + }) + + } + } + } + } + + return woAttrs +}