github.com/terraform-linters/tflint@v0.51.2-0.20240520175844-3750771571b6/terraform/module_mgr.go (about)

     1  package terraform
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io"
     7  	"log"
     8  	"os"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	"github.com/hashicorp/go-version"
    13  	"github.com/spf13/afero"
    14  	"github.com/terraform-linters/tflint/terraform/addrs"
    15  )
    16  
    17  func moduleManifestPath() string {
    18  	return filepath.Join(dataDir(), "modules", "modules.json")
    19  }
    20  
    21  // moduleMgr is a fork of configload.moduleMgr. It manages the installation
    22  // state for modules. Unlike Terraform, it does not install from the registry
    23  // and is read-only.
    24  type moduleMgr struct {
    25  	fs       afero.Afero
    26  	manifest moduleManifest
    27  }
    28  
    29  // moduleRecord is a fork of modsdir.Record. This describes the structure of
    30  // the manifest file which is usually placed in .terraform/modules/modules.json.
    31  type moduleRecord struct {
    32  	Key        string           `json:"Key"`
    33  	Source     string           `json:"Source"`
    34  	Version    *version.Version `json:"-"`
    35  	VersionStr string           `json:"Version,omitempty"`
    36  	Dir        string           `json:"Dir"`
    37  }
    38  
    39  type moduleManifestFile struct {
    40  	Records []*moduleRecord `json:"Modules"`
    41  }
    42  
    43  type moduleManifest map[string]*moduleRecord
    44  
    45  func (m moduleManifest) moduleKey(path addrs.Module) string {
    46  	if len(path) == 0 {
    47  		return ""
    48  	}
    49  	return strings.Join([]string(path), ".")
    50  }
    51  
    52  func (l *moduleMgr) readModuleManifest() error {
    53  	r, err := l.fs.Open(moduleManifestPath())
    54  	if err != nil {
    55  		if os.IsNotExist(err) {
    56  			// We'll treat a missing file as an empty manifest
    57  			l.manifest = make(moduleManifest)
    58  			return nil
    59  		}
    60  		return err
    61  	}
    62  
    63  	log.Print("[INFO] Module manifest file found. Initializing...")
    64  
    65  	src, err := io.ReadAll(r)
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	var read moduleManifestFile
    71  	err = json.Unmarshal(src, &read)
    72  	if err != nil {
    73  		return fmt.Errorf("error unmarshalling module manifest file: %v", err)
    74  	}
    75  
    76  	for _, record := range read.Records {
    77  		l.manifest[record.Key] = record
    78  	}
    79  
    80  	return nil
    81  }