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  }