package piperenv import ( "bytes" "encoding/json" "fmt" "io/ioutil" "os" "path" "path/filepath" "strings" "github.com/SAP/jenkins-library/pkg/log" ) // CPEMap represents the common pipeline environment map type CPEMap map[string]interface{} // LoadFromDisk reads the given path from disk and populates it to the CPEMap. func (c *CPEMap) LoadFromDisk(path string) error { if *c == nil { *c = CPEMap{} } err := dirToMap(*c, path, "") if err != nil { return err } return nil } // WriteToDisk writes the CPEMap to a disk and uses rootDirectory as the starting point func (c CPEMap) WriteToDisk(rootDirectory string) error { err := os.MkdirAll(rootDirectory, 0777) if err != nil { return err } for k, v := range c { entryPath := path.Join(rootDirectory, k) err := os.MkdirAll(filepath.Dir(entryPath), 0777) if err != nil { return err } // if v is a string no json marshalling is needed if vString, ok := v.(string); ok { err := ioutil.WriteFile(entryPath, []byte(vString), 0666) if err != nil { return err } continue } // v is not a string. serialise v to json and add '.json' suffix jsonVal, err := json.Marshal(v) if err != nil { return err } err = ioutil.WriteFile(fmt.Sprintf("%s.json", entryPath), jsonVal, 0666) if err != nil { return err } } return nil } func dirToMap(m map[string]interface{}, dirPath, prefix string) error { if stat, err := os.Stat(dirPath); err != nil || !stat.IsDir() { log.Entry().Debugf("stat on %s failed. Path does not exist", dirPath) return nil } items, err := ioutil.ReadDir(dirPath) if err != nil { return err } for _, dirItem := range items { if dirItem.IsDir() { err := dirToMap(m, path.Join(dirPath, dirItem.Name()), dirItem.Name()) if err != nil { return err } continue } // load file content and unmarshal it if needed mapKey, value, toBeEmptied, err := readFileContent(path.Join(dirPath, dirItem.Name())) if err != nil { return err } if toBeEmptied { err := addEmptyValueToFile(path.Join(dirPath, dirItem.Name())) if err != nil { return err } log.Entry().Debugf("Writing empty contents to file on disk: %v", path.Join(dirPath, dirItem.Name())) m[path.Join(prefix, mapKey)] = "" } else { m[path.Join(prefix, mapKey)] = value } } return nil } func addEmptyValueToFile(fullPath string) error { err := ioutil.WriteFile(fullPath, []byte(""), 0666) if err != nil { return err } return nil } func readFileContent(fullPath string) (string, interface{}, bool, error) { toBeEmptied := false fileContent, err := ioutil.ReadFile(fullPath) if err != nil { return "", nil, toBeEmptied, err } fileName := filepath.Base(fullPath) if strings.HasSuffix(fullPath, ".json") { // value is json encoded var value interface{} decoder := json.NewDecoder(bytes.NewReader(fileContent)) decoder.UseNumber() err = decoder.Decode(&value) if err != nil { return "", nil, toBeEmptied, err } return strings.TrimSuffix(fileName, ".json"), value, toBeEmptied, nil } if string(fileContent) == "toBeEmptied" { toBeEmptied = true } return fileName, string(fileContent), toBeEmptied, nil }