| 
									
										
										
										
											2021-03-26 15:24:19 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | Copyright 2021 The KubeVela Authors. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  | you may not use this file except in compliance with the License. | 
					
						
							|  |  |  | You may obtain a copy of the License at | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  | distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  | See the License for the specific language governing permissions and | 
					
						
							|  |  |  | limitations under the License. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-16 18:55:01 +08:00
										 |  |  | package common | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-12-18 10:18:16 +08:00
										 |  |  | 	"bytes" | 
					
						
							| 
									
										
										
										
											2020-11-18 16:08:16 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2020-12-18 10:18:16 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-01-28 18:36:52 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2020-11-18 16:08:16 +08:00
										 |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2021-01-28 18:36:52 +08:00
										 |  |  | 	"os/exec" | 
					
						
							| 
									
										
										
										
											2020-12-18 10:18:16 +08:00
										 |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-18 10:18:16 +08:00
										 |  |  | 	"cuelang.org/go/cue" | 
					
						
							|  |  |  | 	"cuelang.org/go/encoding/openapi" | 
					
						
							| 
									
										
										
										
											2021-02-20 04:11:26 +08:00
										 |  |  | 	"github.com/AlecAivazis/survey/v2" | 
					
						
							| 
									
										
										
										
											2021-03-20 12:08:15 +08:00
										 |  |  | 	"github.com/ghodss/yaml" | 
					
						
							| 
									
										
										
										
											2021-05-13 21:46:45 +08:00
										 |  |  | 	terraformv1beta1 "github.com/oam-dev/terraform-controller/api/v1beta1" | 
					
						
							| 
									
										
										
										
											2021-03-24 08:01:24 +08:00
										 |  |  | 	kruise "github.com/openkruise/kruise-api/apps/v1alpha1" | 
					
						
							| 
									
										
										
										
											2020-10-15 11:51:41 +08:00
										 |  |  | 	certmanager "github.com/wonderflow/cert-manager-api/pkg/apis/certmanager/v1" | 
					
						
							| 
									
										
										
										
											2021-03-24 08:01:24 +08:00
										 |  |  | 	istioclientv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1" | 
					
						
							|  |  |  | 	crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" | 
					
						
							| 
									
										
										
										
											2020-11-17 14:25:58 +08:00
										 |  |  | 	k8sruntime "k8s.io/apimachinery/pkg/runtime" | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 	clientgoscheme "k8s.io/client-go/kubernetes/scheme" | 
					
						
							| 
									
										
										
										
											2020-11-17 14:25:58 +08:00
										 |  |  | 	"sigs.k8s.io/controller-runtime/pkg/client/config" | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-24 08:01:24 +08:00
										 |  |  | 	oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev" | 
					
						
							|  |  |  | 	oamstandard "github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1" | 
					
						
							| 
									
										
										
										
											2020-12-18 10:18:16 +08:00
										 |  |  | 	mycue "github.com/oam-dev/kubevela/pkg/cue" | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2020-11-17 17:46:56 +08:00
										 |  |  | 	// Scheme defines the default KubeVela schema
 | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 	Scheme = k8sruntime.NewScheme() | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	_ = clientgoscheme.AddToScheme(Scheme) | 
					
						
							| 
									
										
										
										
											2021-03-24 08:01:24 +08:00
										 |  |  | 	_ = crdv1.AddToScheme(Scheme) | 
					
						
							|  |  |  | 	_ = oamcore.AddToScheme(Scheme) | 
					
						
							|  |  |  | 	_ = oamstandard.AddToScheme(Scheme) | 
					
						
							|  |  |  | 	_ = istioclientv1beta1.AddToScheme(Scheme) | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 	_ = certmanager.AddToScheme(Scheme) | 
					
						
							| 
									
										
										
										
											2021-03-24 08:01:24 +08:00
										 |  |  | 	_ = kruise.AddToScheme(Scheme) | 
					
						
							| 
									
										
										
										
											2021-05-13 21:46:45 +08:00
										 |  |  | 	_ = terraformv1beta1.AddToScheme(Scheme) | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 	// +kubebuilder:scaffold:scheme
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 17:46:56 +08:00
										 |  |  | // InitBaseRestConfig will return reset config for create controller runtime client
 | 
					
						
							| 
									
										
										
										
											2021-03-23 16:30:49 +08:00
										 |  |  | func InitBaseRestConfig() (Args, error) { | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 	restConf, err := config.GetConfig() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Println("get kubeConfig err", err) | 
					
						
							|  |  |  | 		os.Exit(1) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-23 16:30:49 +08:00
										 |  |  | 	return Args{ | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | 		Config: restConf, | 
					
						
							|  |  |  | 		Schema: Scheme, | 
					
						
							| 
									
										
										
										
											2020-11-12 13:25:06 +08:00
										 |  |  | 	}, nil | 
					
						
							| 
									
										
										
										
											2020-09-24 16:30:12 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-18 16:08:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // HTTPGet will send GET http request with context
 | 
					
						
							|  |  |  | func HTTPGet(ctx context.Context, url string) ([]byte, error) { | 
					
						
							|  |  |  | 	// Change NewRequest to NewRequestWithContext and pass context it
 | 
					
						
							|  |  |  | 	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	resp, err := http.DefaultClient.Do(req) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	//nolint:errcheck
 | 
					
						
							|  |  |  | 	defer resp.Body.Close() | 
					
						
							|  |  |  | 	return ioutil.ReadAll(resp.Body) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-12-18 10:18:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // GetCUEParameterValue converts definitions to cue format
 | 
					
						
							|  |  |  | func GetCUEParameterValue(cueStr string) (cue.Value, error) { | 
					
						
							|  |  |  | 	r := cue.Runtime{} | 
					
						
							|  |  |  | 	template, err := r.Compile("", cueStr+mycue.BaseTemplate) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return cue.Value{}, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	tempStruct, err := template.Value().Struct() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return cue.Value{}, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// find the parameter definition
 | 
					
						
							|  |  |  | 	var paraDef cue.FieldInfo | 
					
						
							|  |  |  | 	var found bool | 
					
						
							|  |  |  | 	for i := 0; i < tempStruct.Len(); i++ { | 
					
						
							|  |  |  | 		paraDef = tempStruct.Field(i) | 
					
						
							| 
									
										
										
										
											2021-03-29 17:20:33 +08:00
										 |  |  | 		if paraDef.Name == mycue.ParameterTag { | 
					
						
							| 
									
										
										
										
											2020-12-18 10:18:16 +08:00
										 |  |  | 			found = true | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !found { | 
					
						
							|  |  |  | 		return cue.Value{}, errors.New("parameter not exist") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	arguments := paraDef.Value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return arguments, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GenOpenAPI generates OpenAPI json schema from cue.Instance
 | 
					
						
							|  |  |  | func GenOpenAPI(inst *cue.Instance) ([]byte, error) { | 
					
						
							|  |  |  | 	if inst.Err != nil { | 
					
						
							|  |  |  | 		return nil, inst.Err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	defaultConfig := &openapi.Config{} | 
					
						
							|  |  |  | 	b, err := openapi.Gen(inst, defaultConfig) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var out = &bytes.Buffer{} | 
					
						
							|  |  |  | 	_ = json.Indent(out, b, "", "   ") | 
					
						
							|  |  |  | 	return out.Bytes(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-28 18:36:52 +08:00
										 |  |  | // RealtimePrintCommandOutput prints command output in real time
 | 
					
						
							|  |  |  | // If logFile is "", it will prints the stdout, or it will write to local file
 | 
					
						
							|  |  |  | func RealtimePrintCommandOutput(cmd *exec.Cmd, logFile string) error { | 
					
						
							|  |  |  | 	var writer io.Writer | 
					
						
							|  |  |  | 	if logFile == "" { | 
					
						
							|  |  |  | 		writer = io.MultiWriter(os.Stdout) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if _, err := os.Stat(filepath.Dir(logFile)); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		f, err := os.Create(filepath.Clean(logFile)) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		writer = io.MultiWriter(f) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cmd.Stdout = writer | 
					
						
							|  |  |  | 	cmd.Stderr = writer | 
					
						
							|  |  |  | 	if err := cmd.Run(); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-02-20 04:11:26 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // AskToChooseOneService will ask users to select one service of the application if more than one exidi
 | 
					
						
							|  |  |  | func AskToChooseOneService(svcNames []string) (string, error) { | 
					
						
							|  |  |  | 	if len(svcNames) == 0 { | 
					
						
							|  |  |  | 		return "", fmt.Errorf("no service exist in the application") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(svcNames) == 1 { | 
					
						
							|  |  |  | 		return svcNames[0], nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	prompt := &survey.Select{ | 
					
						
							|  |  |  | 		Message: "You have multiple services in your app. Please choose one service: ", | 
					
						
							|  |  |  | 		Options: svcNames, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var svcName string | 
					
						
							|  |  |  | 	err := survey.AskOne(prompt, &svcName) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", fmt.Errorf("choosing service err %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return svcName, nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-03-20 12:08:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ReadYamlToObject will read a yaml K8s object to runtime.Object
 | 
					
						
							|  |  |  | func ReadYamlToObject(path string, object k8sruntime.Object) error { | 
					
						
							|  |  |  | 	data, err := ioutil.ReadFile(filepath.Clean(path)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return yaml.Unmarshal(data, object) | 
					
						
							|  |  |  | } |