github.com/mineiros-io/terradoc@v0.0.9-0.20220711062319-018bd4ae81f5/internal/parsers/docparser/attributes.go (about)

     1  package docparser
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/hashicorp/hcl/v2"
     7  	"github.com/mineiros-io/terradoc/internal/entities"
     8  	"github.com/mineiros-io/terradoc/internal/parsers/hclparser"
     9  	"github.com/mineiros-io/terradoc/internal/schemas/docschema"
    10  )
    11  
    12  func parseVariableAttributes(attributeBlocks hcl.Blocks) (attributes []entities.Attribute, err error) {
    13  	const variableAttributeLevel = 1
    14  
    15  	for _, attrBlk := range attributeBlocks {
    16  		attribute, err := parseAttribute(attrBlk, variableAttributeLevel)
    17  		if err != nil {
    18  			return nil, fmt.Errorf("parsing attributes: %s", err)
    19  		}
    20  
    21  		attributes = append(attributes, attribute)
    22  	}
    23  
    24  	return attributes, nil
    25  }
    26  
    27  func parseAttribute(attrBlock *hcl.Block, level int) (entities.Attribute, error) {
    28  	attrContent, diags := attrBlock.Body.Content(docschema.AttributeSchema())
    29  	if diags.HasErrors() {
    30  		return entities.Attribute{}, fmt.Errorf("parsing attribute block: %v", diags.Errs())
    31  	}
    32  
    33  	if len(attrBlock.Labels) != 1 {
    34  		return entities.Attribute{}, fmt.Errorf("expected single 'name' label, got %v", attrBlock.Labels)
    35  	}
    36  
    37  	// variable blocks are required to have a label as defined in the schema
    38  	name := attrBlock.Labels[0]
    39  
    40  	attr, err := createAttributeFromHCLAttributes(attrContent.Attributes, name, level)
    41  	if err != nil {
    42  		return entities.Attribute{}, fmt.Errorf("parsing attribute: %s", err)
    43  	}
    44  
    45  	nestedAttributeLevel := level + 1
    46  	// attribute blocks have only `attribute` blocks
    47  	for _, blk := range attrContent.Blocks.OfType(attributeBlockName) {
    48  		nestedAttr, err := parseAttribute(blk, nestedAttributeLevel)
    49  		if err != nil {
    50  			return entities.Attribute{}, fmt.Errorf("parsing nested attribute: %s", err)
    51  		}
    52  
    53  		attr.Attributes = append(attr.Attributes, nestedAttr)
    54  	}
    55  
    56  	return attr, nil
    57  }
    58  
    59  func createAttributeFromHCLAttributes(attrs hcl.Attributes, name string, level int) (entities.Attribute, error) {
    60  	var err error
    61  
    62  	attr := entities.Attribute{Name: name, Level: level}
    63  
    64  	attr.Description, err = hclparser.GetAttribute(attrs, descriptionAttributeName).String()
    65  	if err != nil {
    66  		return entities.Attribute{}, err
    67  	}
    68  
    69  	attr.Required, err = hclparser.GetAttribute(attrs, requiredAttributeName).Bool()
    70  	if err != nil {
    71  		return entities.Attribute{}, err
    72  	}
    73  
    74  	attr.ForcesRecreation, err = hclparser.GetAttribute(attrs, forcesRecreationAttributeName).Bool()
    75  	if err != nil {
    76  		return entities.Attribute{}, err
    77  	}
    78  
    79  	attr.ReadmeExample, err = hclparser.GetAttribute(attrs, readmeExampleAttributeName).String()
    80  	if err != nil {
    81  		return entities.Attribute{}, err
    82  	}
    83  
    84  	// type definition
    85  	readmeType := hclparser.GetAttribute(attrs, readmeTypeAttributeName)
    86  	if readmeType == nil {
    87  		attr.Type, err = hclparser.GetAttribute(attrs, typeAttributeName).VarType()
    88  	} else {
    89  		attr.Type, err = readmeType.VarTypeFromString()
    90  	}
    91  
    92  	if err != nil {
    93  		return entities.Attribute{}, err
    94  	}
    95  
    96  	attr.Default, err = hclparser.GetAttribute(attrs, defaultAttributeName).RawJSON()
    97  	if err != nil {
    98  		return entities.Attribute{}, err
    99  	}
   100  
   101  	return attr, nil
   102  }