github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/control/controldisplay/formatter_fs.go (about)

     1  package controldisplay
     2  
     3  import (
     4  	"embed"
     5  	"encoding/json"
     6  	"io/fs"
     7  	"log"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/turbot/steampipe/pkg/filepaths"
    12  )
    13  
    14  //go:embed templates/*
    15  var builtinTemplateFS embed.FS
    16  
    17  type TemplateVersionFile struct {
    18  	Version string `json:"version"`
    19  }
    20  
    21  // EnsureTemplates scans the '$STEAMPIPE_INSTALL_DIR/check/templates' directory and
    22  // copies over the templates defined in the 'templates' package if needed.
    23  //
    24  // The name of the folder in the 'templates' package is used to identify
    25  // templates in '$STEAMPIPE_INSTALL_DIR/templates' - where it is expected
    26  // that a directory with the same name will exist.
    27  //
    28  // We re-write the templates, when there is a higher template version
    29  // available in the 'templates' package.
    30  func EnsureTemplates() error {
    31  	log.Println("[TRACE] ensuring check export/output templates")
    32  	dirs, err := fs.ReadDir(builtinTemplateFS, "templates")
    33  	if err != nil {
    34  		return err
    35  	}
    36  	for _, d := range dirs {
    37  		targetDirectory := filepath.Join(filepaths.EnsureTemplateDir(), d.Name())
    38  		currentVersionsFilePath := filepath.Join(targetDirectory, "version.json")
    39  		embeddedVersionsFilePath := filepath.Join("templates", d.Name(), "version.json")
    40  
    41  		// check if version in version.json matches with embedded template version
    42  		if getCurrentTemplateVersion(currentVersionsFilePath) != getEmbeddedTemplateVersion(embeddedVersionsFilePath) {
    43  			log.Printf("[TRACE] versions do not match for dir '%s' - copying updated template\n", d)
    44  			if err := writeTemplate(d.Name(), targetDirectory); err != nil {
    45  				log.Println("[TRACE] error copying template", err)
    46  				return err
    47  			}
    48  		}
    49  	}
    50  	return nil
    51  }
    52  
    53  func getCurrentTemplateVersion(path string) string {
    54  	data, err := os.ReadFile(path)
    55  	if err != nil {
    56  		if os.IsNotExist(err) {
    57  			log.Println("[TRACE] template version file does not exist - install the new template")
    58  		} else {
    59  			log.Println("[TRACE] error reading current version file - installing the new template")
    60  		}
    61  		return ""
    62  	}
    63  	var ver TemplateVersionFile
    64  	err = json.Unmarshal(data, &ver)
    65  	if err != nil {
    66  		log.Println("[TRACE] error while unmarshaling current version.json file", err)
    67  		return ""
    68  	}
    69  	return ver.Version
    70  }
    71  
    72  func getEmbeddedTemplateVersion(path string) string {
    73  	data, err := fs.ReadFile(builtinTemplateFS, path)
    74  	if err != nil {
    75  		log.Println("[TRACE] error reading embedded version file - installing the new template")
    76  		return ""
    77  	}
    78  	var ver TemplateVersionFile
    79  	err = json.Unmarshal(data, &ver)
    80  	if err != nil {
    81  		log.Println("[TRACE] error while unmarshaling json", err)
    82  		return ""
    83  	}
    84  	return ver.Version
    85  }
    86  
    87  func writeTemplate(path string, target string) error {
    88  	err := os.MkdirAll(target, 0744)
    89  	if err != nil {
    90  		return err
    91  	}
    92  
    93  	entries, err := fs.ReadDir(builtinTemplateFS, filepath.Join("templates", path))
    94  	if err != nil {
    95  		return err
    96  	}
    97  	for _, entry := range entries {
    98  		if entry.IsDir() {
    99  			continue
   100  		}
   101  		sourceInEmbedFs := filepath.Join("templates", path, entry.Name())
   102  		bytes, err := fs.ReadFile(builtinTemplateFS, sourceInEmbedFs)
   103  		if err != nil {
   104  			return err
   105  		}
   106  
   107  		err = os.WriteFile(filepath.Join(target, entry.Name()), bytes, 0744)
   108  		if err != nil {
   109  			return err
   110  		}
   111  	}
   112  
   113  	return nil
   114  }