github.com/argoproj/argo-cd/v3@v3.2.1/cmd/argocd/commands/admin/generatespec_utils.go (about) 1 package admin 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "io" 8 "os" 9 10 "github.com/argoproj/gitops-engine/pkg/utils/kube" 11 corev1 "k8s.io/api/core/v1" 12 "sigs.k8s.io/yaml" 13 14 utilio "github.com/argoproj/argo-cd/v3/util/io" 15 ) 16 17 func getOutWriter(inline bool, filePath string) (io.Writer, io.Closer, error) { 18 if !inline { 19 return os.Stdout, utilio.NopCloser, nil 20 } 21 22 if filePath == "" { 23 return nil, nil, errors.New("the file path must be specified using flag '--file'") 24 } 25 26 err := os.Rename(filePath, filePath+".back") 27 if err != nil { 28 return nil, nil, err 29 } 30 31 fileOut, err := os.Create(filePath) 32 if err != nil { 33 return nil, nil, err 34 } 35 return fileOut, fileOut, nil 36 } 37 38 // PrintResources prints a single resource in YAML or JSON format to stdout according to the output format 39 func PrintResources(output string, out io.Writer, resources ...any) error { 40 for i, resource := range resources { 41 if secret, ok := resource.(*corev1.Secret); ok { 42 convertSecretData(secret) 43 } 44 filteredResource, err := omitFields(resource) 45 if err != nil { 46 return fmt.Errorf("error omitting filtered fields from the resource: %w", err) 47 } 48 resources[i] = filteredResource 49 } 50 var obj any = resources 51 if len(resources) == 1 { 52 obj = resources[0] 53 } 54 55 switch output { 56 case "json": 57 jsonBytes, err := json.MarshalIndent(obj, "", " ") 58 if err != nil { 59 return fmt.Errorf("error marshaling json: %w", err) 60 } 61 62 _, _ = fmt.Fprintln(out, string(jsonBytes)) 63 case "yaml": 64 yamlBytes, err := yaml.Marshal(obj) 65 if err != nil { 66 return fmt.Errorf("error marshaling yaml: %w", err) 67 } 68 // marshaled YAML already ends with the new line character 69 _, _ = fmt.Fprint(out, string(yamlBytes)) 70 default: 71 return fmt.Errorf("unknown output format: %s", output) 72 } 73 return nil 74 } 75 76 // omit fields such as status, creationTimestamp and metadata.namespace in k8s objects 77 func omitFields(resource any) (any, error) { 78 jsonBytes, err := json.Marshal(resource) 79 if err != nil { 80 return nil, err 81 } 82 83 toMap := make(map[string]any) 84 err = json.Unmarshal(jsonBytes, &toMap) 85 if err != nil { 86 return nil, err 87 } 88 89 delete(toMap, "status") 90 if v, ok := toMap["metadata"]; ok { 91 if metadata, ok := v.(map[string]any); ok { 92 delete(metadata, "creationTimestamp") 93 delete(metadata, "namespace") 94 } 95 } 96 return toMap, nil 97 } 98 99 // convertSecretData converts kubernetes secret's data to stringData 100 func convertSecretData(secret *corev1.Secret) { 101 secret.Kind = kube.SecretKind 102 secret.APIVersion = "v1" 103 secret.StringData = map[string]string{} 104 for k, v := range secret.Data { 105 secret.StringData[k] = string(v) 106 } 107 secret.Data = map[string][]byte{} 108 }