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 }