github.com/jpreese/tflint@v0.19.2-0.20200908152133-b01686250fb6/tflint/provider.go (about)

     1  package tflint
     2  
     3  import (
     4  	"log"
     5  
     6  	hcl "github.com/hashicorp/hcl/v2"
     7  	"github.com/hashicorp/terraform/configs"
     8  	"github.com/hashicorp/terraform/configs/configschema"
     9  )
    10  
    11  // ProviderConfig represents a provider block with an eval context (runner)
    12  type ProviderConfig struct {
    13  	tfProvider *configs.Provider
    14  	runner     *Runner
    15  	attributes hcl.Attributes
    16  	blocks     hcl.Blocks
    17  }
    18  
    19  // NewProviderConfig returns a provider config from the given `configs.Provider` and runner
    20  func NewProviderConfig(tfProvider *configs.Provider, runner *Runner, schema *hcl.BodySchema) (*ProviderConfig, error) {
    21  	providerConfig := &ProviderConfig{
    22  		tfProvider: tfProvider,
    23  		runner:     runner,
    24  		attributes: map[string]*hcl.Attribute{},
    25  		blocks:     []*hcl.Block{},
    26  	}
    27  
    28  	if tfProvider != nil {
    29  		content, _, diags := tfProvider.Config.PartialContent(schema)
    30  		if diags.HasErrors() {
    31  			return nil, diags
    32  		}
    33  
    34  		providerConfig.attributes = content.Attributes
    35  		providerConfig.blocks = content.Blocks
    36  	}
    37  
    38  	return providerConfig, nil
    39  }
    40  
    41  // Get returns a value corresponding to the given key
    42  // It should be noted that the value is evaluated if it is evaluable
    43  // The second return value is a flag that determines whether a value exists
    44  // We assume the provider has only simple attributes, so it just returns string
    45  func (p *ProviderConfig) Get(key string) (string, bool, error) {
    46  	attribute, exists := p.attributes[key]
    47  	if !exists {
    48  		log.Printf("[INFO] `%s` is not found in the provider block.", key)
    49  		return "", false, nil
    50  	}
    51  
    52  	var val string
    53  	err := p.runner.EvaluateExpr(attribute.Expr, &val)
    54  
    55  	err = p.runner.EnsureNoError(err, func() error { return nil })
    56  	if err != nil {
    57  		return "", true, err
    58  	}
    59  	return val, true, nil
    60  }
    61  
    62  // GetBlock is Get for blocks. Obviously from the return type,
    63  // nested blocks and blocks with complex types are not supported.
    64  // Also note that all attributes are lost if the given block
    65  // contains unevalable expressions because the entire block is evaluated.
    66  func (p *ProviderConfig) GetBlock(key string, schema *configschema.Block) (map[string]string, bool, error) {
    67  	val := map[string]string{}
    68  
    69  	var ret *hcl.Block
    70  	for _, block := range p.blocks {
    71  		if block.Type == key {
    72  			ret = block
    73  		}
    74  	}
    75  	if ret == nil {
    76  		log.Printf("[INFO] `%s` is not found in the provider block.", key)
    77  		return val, false, nil
    78  	}
    79  
    80  	err := p.runner.EvaluateBlock(ret, schema, &val)
    81  
    82  	err = p.runner.EnsureNoError(err, func() error { return nil })
    83  	if err != nil {
    84  		return val, true, err
    85  	}
    86  	return val, true, nil
    87  }