github.com/argoproj/argo-cd@v1.8.7/util/ksonnet/ksonnet.go (about) 1 package ksonnet 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "strings" 11 12 "github.com/argoproj/gitops-engine/pkg/utils/kube" 13 "github.com/ghodss/yaml" 14 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 15 16 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1" 17 executil "github.com/argoproj/argo-cd/util/exec" 18 ) 19 20 // Destination returns the deployment destination for an environment in app spec data 21 func Destination(data []byte, environment string) (*v1alpha1.ApplicationDestination, error) { 22 var appSpec struct { 23 Environments map[string]struct { 24 Destination v1alpha1.ApplicationDestination 25 } 26 } 27 err := yaml.Unmarshal(data, &appSpec) 28 if err != nil { 29 return nil, fmt.Errorf("could not unmarshal ksonnet spec app.yaml: %v", err) 30 } 31 32 envSpec, ok := appSpec.Environments[environment] 33 if !ok { 34 return nil, fmt.Errorf("environment '%s' does not exist in ksonnet app", environment) 35 } 36 37 return &envSpec.Destination, nil 38 } 39 40 // KsonnetApp represents a ksonnet application directory and provides wrapper functionality around 41 // the `ks` command. 42 type KsonnetApp interface { 43 // Root is the root path ksonnet application directory 44 Root() string 45 46 // Show returns a list of unstructured objects that would be applied to an environment 47 Show(environment string) ([]*unstructured.Unstructured, error) 48 49 // Destination returns the deployment destination for an environment 50 Destination(environment string) (*v1alpha1.ApplicationDestination, error) 51 52 // ListParams returns list of ksonnet parameters 53 ListParams(environment string) ([]*v1alpha1.KsonnetParameter, error) 54 55 // SetComponentParams updates component parameter in specified environment. 56 SetComponentParams(environment string, component string, param string, value string) error 57 } 58 59 // Version returns the version of ksonnet used when running ksonnet commands 60 func Version() (string, error) { 61 ksApp := ksonnetApp{} 62 out, err := ksApp.ksCmd("", "version") 63 if err != nil { 64 return "", fmt.Errorf("unable to determine ksonnet version: %v", err) 65 } 66 ksonnetVersionStr := strings.Split(out, "\n")[0] 67 parts := strings.SplitN(ksonnetVersionStr, ":", 2) 68 if len(parts) != 2 { 69 return "", fmt.Errorf("unexpected version string format: %s", ksonnetVersionStr) 70 } 71 version := strings.TrimSpace(parts[1]) 72 if version[0] != 'v' { 73 version = "v" + version 74 } 75 return version, nil 76 } 77 78 type ksonnetApp struct { 79 rootDir string 80 } 81 82 // NewKsonnetApp tries to create a new wrapper to run commands on the `ks` command-line tool. 83 func NewKsonnetApp(path string) (KsonnetApp, error) { 84 ksApp := ksonnetApp{rootDir: path} 85 // ensure that the file exists 86 if _, err := ksApp.appYamlPath(); err != nil { 87 return nil, err 88 } 89 return &ksApp, nil 90 } 91 92 func (k *ksonnetApp) appYamlPath() (string, error) { 93 const appYamlName = "app.yaml" 94 p := filepath.Join(k.Root(), appYamlName) 95 if _, err := os.Stat(p); err != nil { 96 return "", err 97 } 98 return p, nil 99 } 100 101 func (k *ksonnetApp) ksCmd(args ...string) (string, error) { 102 cmd := exec.Command("ks", args...) 103 cmd.Dir = k.Root() 104 105 return executil.Run(cmd) 106 } 107 108 func (k *ksonnetApp) Root() string { 109 return k.rootDir 110 } 111 112 // Show generates a concatenated list of Kubernetes manifests in the given environment. 113 func (k *ksonnetApp) Show(environment string) ([]*unstructured.Unstructured, error) { 114 out, err := k.ksCmd("show", environment) 115 if err != nil { 116 return nil, fmt.Errorf("`ks show` failed: %v", err) 117 } 118 return kube.SplitYAML([]byte(out)) 119 } 120 121 // Destination returns the deployment destination for an environment 122 func (k *ksonnetApp) Destination(environment string) (*v1alpha1.ApplicationDestination, error) { 123 p, err := k.appYamlPath() 124 if err != nil { 125 return nil, err 126 } 127 data, err := ioutil.ReadFile(p) 128 if err != nil { 129 return nil, err 130 } 131 return Destination(data, environment) 132 } 133 134 // ListParams returns list of ksonnet parameters 135 func (k *ksonnetApp) ListParams(environment string) ([]*v1alpha1.KsonnetParameter, error) { 136 args := []string{"param", "list", "--output", "json"} 137 if environment != "" { 138 args = append(args, "--env", environment) 139 } 140 out, err := k.ksCmd(args...) 141 if err != nil { 142 return nil, err 143 } 144 // Auxiliary data to hold unmarshaled JSON output, which may use different field names 145 var ksParams struct { 146 Data []struct { 147 Component string `json:"component"` 148 Key string `json:"param"` 149 Value string `json:"value"` 150 } `json:"data"` 151 } 152 if err := json.Unmarshal([]byte(out), &ksParams); err != nil { 153 return nil, err 154 } 155 var params []*v1alpha1.KsonnetParameter 156 for _, ksParam := range ksParams.Data { 157 value := strings.Trim(ksParam.Value, `'"`) 158 params = append(params, &v1alpha1.KsonnetParameter{ 159 Component: ksParam.Component, 160 Name: ksParam.Key, 161 Value: value, 162 }) 163 } 164 return params, nil 165 } 166 167 // SetComponentParams updates component parameter in specified environment. 168 func (k *ksonnetApp) SetComponentParams(environment string, component string, param string, value string) error { 169 _, err := k.ksCmd("param", "set", component, param, value, "--env", environment) 170 return err 171 }