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  }