github.com/argoproj/argo-cd/v3@v3.2.1/util/config/reader.go (about) 1 package config 2 3 import ( 4 "encoding/json" 5 "io" 6 "net/http" 7 "os" 8 9 "sigs.k8s.io/yaml" 10 ) 11 12 // UnmarshalReader is used to read manifests from stdin 13 func UnmarshalReader(reader io.Reader, obj any) error { 14 data, err := io.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 any) 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 return json.Unmarshal(jsonData, &obj) 34 } 35 36 // MarshalLocalYAMLFile writes JSON or YAML to a file on disk. 37 // The caller is responsible for checking error return values. 38 func MarshalLocalYAMLFile(path string, obj any) error { 39 yamlData, err := yaml.Marshal(obj) 40 if err == nil { 41 err = os.WriteFile(path, yamlData, 0o600) 42 } 43 return err 44 } 45 46 // UnmarshalLocalFile retrieves JSON or YAML from a file on disk. 47 // The caller is responsible for checking error return values. 48 func UnmarshalLocalFile(path string, obj any) error { 49 data, err := os.ReadFile(path) 50 if err == nil { 51 err = unmarshalObject(data, obj) 52 } 53 return err 54 } 55 56 func Unmarshal(data []byte, obj any) error { 57 return unmarshalObject(data, obj) 58 } 59 60 // UnmarshalRemoteFile retrieves JSON or YAML through a GET request. 61 // The caller is responsible for checking error return values. 62 func UnmarshalRemoteFile(url string, obj any) error { 63 data, err := ReadRemoteFile(url) 64 if err == nil { 65 err = unmarshalObject(data, obj) 66 } 67 return err 68 } 69 70 // ReadRemoteFile issues a GET request to retrieve the contents of the specified URL as a byte array. 71 // The caller is responsible for checking error return values. 72 func ReadRemoteFile(url string) ([]byte, error) { 73 var data []byte 74 resp, err := http.Get(url) 75 if err == nil { 76 defer func() { 77 _ = resp.Body.Close() 78 }() 79 data, err = io.ReadAll(resp.Body) 80 } 81 return data, err 82 }