k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/def/configmap/main.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 // configmap will write a configmap to --output from --data=name=/path/to/source 18 package main 19 20 import ( 21 "bytes" 22 "flag" 23 "fmt" 24 "log" 25 "os" 26 "strings" 27 28 v1 "k8s.io/api/core/v1" 29 "sigs.k8s.io/yaml" 30 ) 31 32 type options struct { 33 data multiKeyValue 34 labels multiKeyValue 35 name string 36 namespace string 37 output string 38 } 39 40 // multiKeyValue allows --key=value --key=value2 41 type multiKeyValue map[string]string 42 43 func (mkv *multiKeyValue) String() string { 44 var b bytes.Buffer 45 if mkv == nil { 46 return "" 47 } 48 for k, v := range *mkv { 49 if b.Len() > 0 { 50 b.WriteString(",") 51 } 52 fmt.Fprintf(&b, "%s=%s", k, v) 53 } 54 return b.String() 55 } 56 57 func (mkv *multiKeyValue) Set(v string) error { 58 p := strings.SplitN(v, "=", 2) 59 if len(p) != 2 { 60 return fmt.Errorf("%s does not match label=value", v) 61 } 62 if mkv != nil { 63 (*mkv)[p[0]] = p[1] 64 } 65 return nil 66 } 67 68 func flags() *options { 69 opt := options{ 70 data: multiKeyValue{}, 71 labels: multiKeyValue{}, 72 } 73 flag.StringVar(&opt.output, "output", "", "Write configmap here instead of stdout") 74 flag.StringVar(&opt.name, "name", "", "Name of resource") 75 flag.StringVar(&opt.namespace, "namespace", "", "Namespace for resource") 76 flag.Var(&opt.labels, "label", "Add a key=value label (repeat flag)") 77 flag.Var(&opt.data, "data", "Add a key=/path/to/file configmap source (repeat flag)") 78 flag.Parse() 79 return &opt 80 } 81 82 func buildConfigMap(name, namespace string, labels map[string]string, data map[string]string) (*v1.ConfigMap, error) { 83 84 var cm v1.ConfigMap 85 cm.TypeMeta.Kind = "ConfigMap" 86 cm.TypeMeta.APIVersion = "v1" 87 cm.ObjectMeta.Name = name 88 cm.ObjectMeta.Namespace = namespace 89 cm.ObjectMeta.Labels = labels 90 if len(data) > 0 { 91 cm.Data = map[string]string{} 92 for key, value := range data { 93 buf, err := os.ReadFile(value) 94 if err != nil { 95 wd, _ := os.Getwd() 96 return nil, fmt.Errorf("could not read %s/%s: %w", wd, value, err) 97 } 98 cm.Data[key] = string(buf) 99 } 100 } 101 return &cm, nil 102 } 103 104 func main() { 105 opt := flags() 106 if opt.name == "" { 107 log.Fatal("Non-empty --name required") 108 } 109 cm, err := buildConfigMap(opt.name, opt.namespace, opt.labels, opt.data) 110 if err != nil { 111 log.Fatalf("Failed to create %s: %v", opt.name, err) 112 } 113 buf, err := yaml.Marshal(cm) 114 if err != nil { 115 log.Fatalf("Failed to serialize %s: %v", opt.name, err) 116 } 117 if opt.output == "" { 118 fmt.Print(string(buf)) 119 return 120 } 121 err = os.WriteFile(opt.output, buf, 0644) 122 if err != nil { 123 log.Fatalf("Failed to write %s: %v", opt.output, err) 124 } 125 }