github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/piperenv/CPEMap.go (about) 1 package piperenv 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "os" 8 "path" 9 "path/filepath" 10 "strings" 11 12 "github.com/SAP/jenkins-library/pkg/log" 13 ) 14 15 // CPEMap represents the common pipeline environment map 16 type CPEMap map[string]interface{} 17 18 // LoadFromDisk reads the given path from disk and populates it to the CPEMap. 19 func (c *CPEMap) LoadFromDisk(path string) error { 20 if *c == nil { 21 *c = CPEMap{} 22 } 23 err := dirToMap(*c, path, "") 24 if err != nil { 25 return err 26 } 27 return nil 28 } 29 30 // WriteToDisk writes the CPEMap to a disk and uses rootDirectory as the starting point 31 func (c CPEMap) WriteToDisk(rootDirectory string) error { 32 err := os.MkdirAll(rootDirectory, 0777) 33 if err != nil { 34 return err 35 } 36 37 for k, v := range c { 38 entryPath := path.Join(rootDirectory, k) 39 err := os.MkdirAll(filepath.Dir(entryPath), 0777) 40 if err != nil { 41 return err 42 } 43 // if v is a string no json marshalling is needed 44 if vString, ok := v.(string); ok { 45 err := os.WriteFile(entryPath, []byte(vString), 0666) 46 if err != nil { 47 return err 48 } 49 continue 50 } 51 // v is not a string. serialise v to json and add '.json' suffix 52 jsonVal, err := json.Marshal(v) 53 if err != nil { 54 return err 55 } 56 57 err = os.WriteFile(fmt.Sprintf("%s.json", entryPath), jsonVal, 0666) 58 if err != nil { 59 return err 60 } 61 } 62 return nil 63 } 64 65 func dirToMap(m map[string]interface{}, dirPath, prefix string) error { 66 if stat, err := os.Stat(dirPath); err != nil || !stat.IsDir() { 67 log.Entry().Debugf("stat on %s failed. Path does not exist", dirPath) 68 return nil 69 } 70 71 items, err := os.ReadDir(dirPath) 72 if err != nil { 73 return err 74 } 75 76 for _, dirItem := range items { 77 if dirItem.IsDir() { 78 err := dirToMap(m, path.Join(dirPath, dirItem.Name()), dirItem.Name()) 79 if err != nil { 80 return err 81 } 82 continue 83 } 84 // load file content and unmarshal it if needed 85 mapKey, value, toBeEmptied, err := readFileContent(path.Join(dirPath, dirItem.Name())) 86 if err != nil { 87 return err 88 } 89 if toBeEmptied { 90 err := addEmptyValueToFile(path.Join(dirPath, dirItem.Name())) 91 if err != nil { 92 return err 93 } 94 log.Entry().Debugf("Writing empty contents to file on disk: %v", path.Join(dirPath, dirItem.Name())) 95 96 m[path.Join(prefix, mapKey)] = "" 97 98 } else { 99 m[path.Join(prefix, mapKey)] = value 100 } 101 } 102 return nil 103 } 104 105 func addEmptyValueToFile(fullPath string) error { 106 err := os.WriteFile(fullPath, []byte(""), 0666) 107 if err != nil { 108 return err 109 } 110 return nil 111 } 112 113 func readFileContent(fullPath string) (string, interface{}, bool, error) { 114 toBeEmptied := false 115 116 fileContent, err := os.ReadFile(fullPath) 117 if err != nil { 118 return "", nil, toBeEmptied, err 119 } 120 fileName := filepath.Base(fullPath) 121 122 if strings.HasSuffix(fullPath, ".json") { 123 // value is json encoded 124 var value interface{} 125 decoder := json.NewDecoder(bytes.NewReader(fileContent)) 126 decoder.UseNumber() 127 err = decoder.Decode(&value) 128 if err != nil { 129 return "", nil, toBeEmptied, err 130 } 131 return strings.TrimSuffix(fileName, ".json"), value, toBeEmptied, nil 132 } 133 if string(fileContent) == "toBeEmptied" { 134 toBeEmptied = true 135 } 136 return fileName, string(fileContent), toBeEmptied, nil 137 }