github.com/argoproj/argo-cd@v1.8.7/util/config/reader.go (about) 1 package config 2 3 import ( 4 "encoding/json" 5 "io" 6 "io/ioutil" 7 "net/http" 8 9 "github.com/ghodss/yaml" 10 ) 11 12 // UnmarshalReader is used to read manifests from stdin 13 func UnmarshalReader(reader io.Reader, obj interface{}) error { 14 data, err := ioutil.ReadAll(reader) 15 if err != nil { 16 return err 17 } 18 return unmarshalObject(data, obj) 19 } 20 21 // unmarshalObject tries to convert a YAML or JSON byte array into the provided type. 22 func unmarshalObject(data []byte, obj interface{}) error { 23 // first, try unmarshaling as JSON 24 // Based on technique from Kubectl, which supports both YAML and JSON: 25 // https://mlafeldt.github.io/blog/teaching-go-programs-to-love-json-and-yaml/ 26 // http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/ 27 // Short version: JSON unmarshaling won't zero out null fields; YAML unmarshaling will. 28 // This may have unintended effects or hard-to-catch issues when populating our application object. 29 jsonData, err := yaml.YAMLToJSON(data) 30 if err != nil { 31 return err 32 } 33 34 err = json.Unmarshal(jsonData, &obj) 35 if err != nil { 36 return err 37 } 38 39 return err 40 } 41 42 // MarshalLocalYAMLFile writes JSON or YAML to a file on disk. 43 // The caller is responsible for checking error return values. 44 func MarshalLocalYAMLFile(path string, obj interface{}) error { 45 yamlData, err := yaml.Marshal(obj) 46 if err == nil { 47 err = ioutil.WriteFile(path, yamlData, 0600) 48 } 49 return err 50 } 51 52 // UnmarshalLocalFile retrieves JSON or YAML from a file on disk. 53 // The caller is responsible for checking error return values. 54 func UnmarshalLocalFile(path string, obj interface{}) error { 55 data, err := ioutil.ReadFile(path) 56 if err == nil { 57 err = unmarshalObject(data, obj) 58 } 59 return err 60 } 61 62 // UnmarshalRemoteFile retrieves JSON or YAML through a GET request. 63 // The caller is responsible for checking error return values. 64 func UnmarshalRemoteFile(url string, obj interface{}) error { 65 data, err := ReadRemoteFile(url) 66 if err == nil { 67 err = unmarshalObject(data, obj) 68 } 69 return err 70 } 71 72 // ReadRemoteFile issues a GET request to retrieve the contents of the specified URL as a byte array. 73 // The caller is responsible for checking error return values. 74 func ReadRemoteFile(url string) ([]byte, error) { 75 var data []byte 76 resp, err := http.Get(url) 77 if err == nil { 78 defer func() { 79 _ = resp.Body.Close() 80 }() 81 data, err = ioutil.ReadAll(resp.Body) 82 } 83 return data, err 84 }