Feat: support query endpoints in status command and speed up CLI response (#3052)

Signed-off-by: barnettZQG <barnett.zqg@gmail.com>
This commit is contained in:
barnettZQG
2022-01-07 15:49:27 +08:00
committed by GitHub
parent 578aae6482
commit d4762e09cd
47 changed files with 707 additions and 464 deletions
+4
View File
@@ -48,6 +48,10 @@ const (
LabelDefinitionDeprecated = "custom.definition.oam.dev/deprecated"
// LabelDefinitionHidden is the label which describe whether the capability is hidden by UI
LabelDefinitionHidden = "custom.definition.oam.dev/ui-hidden"
// LabelNodeRoleGateway gateway role of node
LabelNodeRoleGateway = "node-role.kubernetes.io/gateway"
// LabelNodeRoleWorker worker role of node
LabelNodeRoleWorker = "node-role.kubernetes.io/worker"
// AnnoIngressControllerHTTPSPort define ingress controller listen port for https
AnnoIngressControllerHTTPSPort = "ingress.controller/https-port"
// AnnoIngressControllerHTTPPort define ingress controller listen port for http
@@ -0,0 +1,38 @@
apiVersion: "v1"
kind: "ConfigMap"
metadata:
name: "service-endpoints-view"
namespace: "vela-system"
data:
template: |
import (
"vela/ql"
)
parameter: {
appName: string
appNs: string
cluster?: string
clusterNs?: string
}
resources: ql.#CollectServiceEndpoints & {
app: {
name: parameter.appName
namespace: parameter.appNs
filter: {
if parameter.cluster != _|_ {
cluster: parameter.cluster
}
if parameter.clusterNs != _|_ {
clusterNamespace: parameter.clusterNs
}
}
}
}
if resources.err == _|_ {
endpoints: resources.list
}
if resources.err != _|_ {
status: {
error: resources.err
}
}
+3 -1
View File
@@ -87,7 +87,9 @@ func (t *traceContext) Commit(msg string) {
for _, export := range t.exporters {
export(t, duration.Microseconds())
}
klog.InfoSDepth(1, msg, t.getTagsWith("duration", duration.String())...)
if t.logLevel == 0 {
klog.InfoSDepth(1, msg, t.getTagsWith("duration", duration.String())...)
}
}
func (t *traceContext) getTagsWith(keysAndValues ...interface{}) []interface{} {
+5 -5
View File
@@ -75,11 +75,11 @@
}
list?: [...{
endpoint: {
protocol: string
appProtocol: string
host?: string
port: int
path?: string
protocol: string
appProtocol?: string
host?: string
port: int
path?: string
}
ref: {...}
}]
+2
View File
@@ -11,3 +11,5 @@
#SearchEvents: query.#SearchEvents
#CollectLogsInPod: query.#CollectLogsInPod
#CollectServiceEndpoints: query.#CollectServiceEndpoints
+38 -18
View File
@@ -31,53 +31,73 @@ import (
// Args is args for controller-runtime client
type Args struct {
Config *rest.Config
config *rest.Config
Schema *runtime.Scheme
Client client.Client
client client.Client
dm discoverymapper.DiscoveryMapper
pd *packages.PackageDiscover
}
// SetConfig insert kubeconfig into Args
func (a *Args) SetConfig() error {
func (a *Args) SetConfig(c *rest.Config) error {
if c != nil {
a.config = c
return nil
}
restConf, err := config.GetConfig()
if err != nil {
return err
}
restConf.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(100, 200)
a.Config = restConf
a.config = restConf
return nil
}
// GetConfig get config, if not exist, will create
func (a *Args) GetConfig() (*rest.Config, error) {
if a.config != nil {
return a.config, nil
}
if err := a.SetConfig(nil); err != nil {
return nil, err
}
return a.config, nil
}
// SetClient set custom client
func (a *Args) SetClient(c client.Client) {
a.client = c
}
// GetClient get client if exist
func (a *Args) GetClient() (client.Client, error) {
if a.Config == nil {
if err := a.SetConfig(); err != nil {
if a.client != nil {
return a.client, nil
}
if a.config == nil {
if err := a.SetConfig(nil); err != nil {
return nil, err
}
}
if a.Client != nil {
return a.Client, nil
}
newClient, err := client.New(a.Config, client.Options{Scheme: a.Schema})
newClient, err := client.New(a.config, client.Options{Scheme: a.Schema})
if err != nil {
return nil, err
}
a.Client = newClient
return a.Client, nil
a.client = newClient
return a.client, nil
}
// GetDiscoveryMapper get discoveryMapper client if exist, create if not exist.
func (a *Args) GetDiscoveryMapper() (discoverymapper.DiscoveryMapper, error) {
if a.Config == nil {
if err := a.SetConfig(); err != nil {
if a.config == nil {
if err := a.SetConfig(nil); err != nil {
return nil, err
}
}
if a.dm != nil {
return a.dm, nil
}
dm, err := discoverymapper.New(a.Config)
dm, err := discoverymapper.New(a.config)
if err != nil {
return nil, fmt.Errorf("failed to create CRD discovery client %w", err)
}
@@ -87,15 +107,15 @@ func (a *Args) GetDiscoveryMapper() (discoverymapper.DiscoveryMapper, error) {
// GetPackageDiscover get PackageDiscover client if exist, create if not exist.
func (a *Args) GetPackageDiscover() (*packages.PackageDiscover, error) {
if a.Config == nil {
if err := a.SetConfig(); err != nil {
if a.config == nil {
if err := a.SetConfig(nil); err != nil {
return nil, err
}
}
if a.pd != nil {
return a.pd, nil
}
pd, err := packages.NewPackageDiscover(a.Config)
pd, err := packages.NewPackageDiscover(a.config)
if err != nil {
return nil, fmt.Errorf("failed to create CRD discovery for CUE package client %w", err)
}
+5 -7
View File
@@ -47,7 +47,6 @@ import (
k8sruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/util/flowcontrol"
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
ocmclusterv1 "open-cluster-management.io/api/cluster/v1"
ocmclusterv1alpha1 "open-cluster-management.io/api/cluster/v1alpha1"
@@ -100,18 +99,17 @@ func init() {
// InitBaseRestConfig will return reset config for create controller runtime client
func InitBaseRestConfig() (Args, error) {
restConf, err := config.GetConfig()
args := Args{
Schema: Scheme,
}
_, err := args.GetConfig()
if err != nil && os.Getenv("IGNORE_KUBE_CONFIG") != "true" {
fmt.Println("get kubeConfig err", err)
os.Exit(1)
} else if err != nil {
return Args{}, err
}
restConf.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(100, 200)
return Args{
Config: restConf,
Schema: Scheme,
}, nil
return args, nil
}
// globalClient will be a client for whole command lifecycle
+114 -84
View File
@@ -18,7 +18,7 @@ package query
import (
"bufio"
stdctx "context"
"context"
"fmt"
"io"
"regexp"
@@ -44,6 +44,7 @@ import (
"github.com/oam-dev/kubevela/pkg/cue/model/value"
"github.com/oam-dev/kubevela/pkg/multicluster"
"github.com/oam-dev/kubevela/pkg/utils"
querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types"
wfContext "github.com/oam-dev/kubevela/pkg/workflow/context"
"github.com/oam-dev/kubevela/pkg/workflow/providers"
"github.com/oam-dev/kubevela/pkg/workflow/types"
@@ -85,53 +86,6 @@ type FilterOption struct {
Components []string `json:"components,omitempty"`
}
// ServiceEndpoint record the access endpoints of the application services
type ServiceEndpoint struct {
Endpoint Endpoint `json:"endpoint"`
Ref corev1.ObjectReference `json:"ref"`
}
// String return endpoint URL
func (s *ServiceEndpoint) String() string {
protocol := strings.ToLower(string(s.Endpoint.Protocol))
if s.Endpoint.AppProtocol != nil {
protocol = *s.Endpoint.AppProtocol
}
path := s.Endpoint.Path
if s.Endpoint.Path == "/" {
path = ""
}
if (protocol == "https" && s.Endpoint.Port == 443) || (protocol == "http" && s.Endpoint.Port == 80) {
return fmt.Sprintf("%s://%s%s", protocol, s.Endpoint.Host, path)
}
return fmt.Sprintf("%s://%s:%d%s", protocol, s.Endpoint.Host, s.Endpoint.Port, path)
}
// Endpoint create by ingress or service
type Endpoint struct {
// The protocol for this endpoint. Supports "TCP", "UDP", and "SCTP".
// Default is TCP.
// +default="TCP"
// +optional
Protocol corev1.Protocol `json:"protocol,omitempty"`
// The protocol for this endpoint.
// Un-prefixed names are reserved for IANA standard service names (as per
// RFC-6335 and http://www.iana.org/assignments/service-names).
// +optional
AppProtocol *string `json:"appProtocol,omitempty"`
// the host for the endpoint, it could be IP or domain
Host string `json:"host"`
// the port for the endpoint
// Default is 80.
Port int32 `json:"port"`
// the path for the endpoint
Path string `json:"path,omitempty"`
}
// ListResourcesInApp lists CRs created by Application
func (h *provider) ListResourcesInApp(ctx wfContext.Context, v *value.Value, act types.Action) error {
val, err := v.LookupValue("app")
@@ -195,7 +149,7 @@ func (h *provider) SearchEvents(ctx wfContext.Context, v *value.Value, act types
return err
}
listCtx := multicluster.ContextWithClusterName(stdctx.Background(), cluster)
listCtx := multicluster.ContextWithClusterName(context.Background(), cluster)
fieldSelector := getEventFieldSelector(obj)
eventList := corev1.EventList{}
listOpts := []client.ListOption{
@@ -210,15 +164,15 @@ func (h *provider) SearchEvents(ctx wfContext.Context, v *value.Value, act types
return v.FillObject(eventList.Items, "list")
}
// generatorServiceEndpoints generator service endpoints is available for common component type,
// GeneratorServiceEndpoints generator service endpoints is available for common component type,
// such as webservice or helm
// it can not support the cloud service component currently
func (h *provider) GeneratorServiceEndpoints(wfctx wfContext.Context, v *value.Value, act types.Action) error {
ctx := stdctx.Background()
ctx := context.Background()
findResource := func(obj client.Object, name, namespace, cluster string) error {
obj.SetNamespace(namespace)
obj.SetName(name)
gctx, cancel := stdctx.WithTimeout(ctx, time.Second*10)
gctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
if err := h.cli.Get(multicluster.ContextWithClusterName(gctx, cluster),
client.ObjectKeyFromObject(obj), obj); err != nil {
@@ -242,11 +196,23 @@ func (h *provider) GeneratorServiceEndpoints(wfctx wfContext.Context, v *value.V
if err != nil {
return fmt.Errorf("query app failure %w", err)
}
var serviceEndpoints []ServiceEndpoint
for _, resource := range app.Status.AppliedResources {
var serviceEndpoints []querytypes.ServiceEndpoint
var clusterGatewayNodeIP = make(map[string]string)
for i, resource := range app.Status.AppliedResources {
if !isResourceInTargetCluster(opt.Filter, resource) {
continue
}
cluster := app.Status.AppliedResources[i].Cluster
selectorNodeIP := func() string {
if ip, exist := clusterGatewayNodeIP[cluster]; exist {
return ip
}
ip := selectorNodeIP(ctx, cluster, h.cli)
if ip != "" {
clusterGatewayNodeIP[cluster] = ip
}
return ip
}
switch resource.Kind {
case "Ingress":
if resource.GroupVersionKind().Group == networkv1beta1.GroupName && (resource.GroupVersionKind().Version == "v1beta1" || resource.GroupVersionKind().Version == "v1") {
@@ -267,7 +233,7 @@ func (h *provider) GeneratorServiceEndpoints(wfctx wfContext.Context, v *value.V
klog.Error(err, fmt.Sprintf("find v1 Service %s/%s from cluster %s failure", resource.Name, resource.Namespace, resource.Cluster))
continue
}
serviceEndpoints = append(serviceEndpoints, generatorFromService(service)...)
serviceEndpoints = append(serviceEndpoints, generatorFromService(service, selectorNodeIP)...)
case helmapi.HelmReleaseGVK.Kind:
obj := new(unstructured.Unstructured)
obj.SetNamespace(resource.Namespace)
@@ -278,7 +244,7 @@ func (h *provider) GeneratorServiceEndpoints(wfctx wfContext.Context, v *value.V
klog.Error(err, "collect service by helm release failure", "helmRelease", resource.Name, "namespace", resource.Namespace, "cluster", resource.Cluster)
}
for _, service := range services {
serviceEndpoints = append(serviceEndpoints, generatorFromService(service)...)
serviceEndpoints = append(serviceEndpoints, generatorFromService(service, selectorNodeIP)...)
}
// only support network/v1beta1
@@ -323,7 +289,7 @@ func (h *provider) CollectLogsInPod(ctx wfContext.Context, v *value.Value, act t
if err = val.UnmarshalTo(opts); err != nil {
return errors.Wrapf(err, "invalid log options content")
}
cliCtx := multicluster.ContextWithClusterName(stdctx.Background(), cluster)
cliCtx := multicluster.ContextWithClusterName(context.Background(), cluster)
clientSet, err := kubernetes.NewForConfig(h.cfg)
if err != nil {
return errors.Wrapf(err, "failed to create kubernetes clientset")
@@ -396,21 +362,23 @@ func Install(p providers.Providers, cli client.Client, cfg *rest.Config) {
})
}
func generatorFromService(service corev1.Service) []ServiceEndpoint {
var serviceEndpoints []ServiceEndpoint
func generatorFromService(service corev1.Service, selectorNodeIP func() string) []querytypes.ServiceEndpoint {
var serviceEndpoints []querytypes.ServiceEndpoint
switch service.Spec.Type {
case corev1.ServiceTypeLoadBalancer:
for _, port := range service.Spec.Ports {
judgeAppProtocol := judgeAppProtocol(port.Port)
for _, ingress := range service.Status.LoadBalancer.Ingress {
if ingress.Hostname != "" {
serviceEndpoints = append(serviceEndpoints, ServiceEndpoint{
Endpoint: Endpoint{
Protocol: port.Protocol,
Host: ingress.Hostname,
Port: port.Port,
serviceEndpoints = append(serviceEndpoints, querytypes.ServiceEndpoint{
Endpoint: querytypes.Endpoint{
Protocol: port.Protocol,
AppProtocol: &judgeAppProtocol,
Host: ingress.Hostname,
Port: int(port.Port),
},
Ref: corev1.ObjectReference{
Kind: service.Kind,
Kind: "Service",
Namespace: service.ObjectMeta.Namespace,
Name: service.ObjectMeta.Name,
UID: service.UID,
@@ -420,14 +388,15 @@ func generatorFromService(service corev1.Service) []ServiceEndpoint {
})
}
if ingress.IP != "" {
serviceEndpoints = append(serviceEndpoints, ServiceEndpoint{
Endpoint: Endpoint{
Protocol: port.Protocol,
Host: ingress.IP,
Port: port.Port,
serviceEndpoints = append(serviceEndpoints, querytypes.ServiceEndpoint{
Endpoint: querytypes.Endpoint{
Protocol: port.Protocol,
AppProtocol: &judgeAppProtocol,
Host: ingress.IP,
Port: int(port.Port),
},
Ref: corev1.ObjectReference{
Kind: service.Kind,
Kind: "Service",
Namespace: service.ObjectMeta.Namespace,
Name: service.ObjectMeta.Name,
UID: service.UID,
@@ -440,13 +409,16 @@ func generatorFromService(service corev1.Service) []ServiceEndpoint {
}
case corev1.ServiceTypeNodePort:
for _, port := range service.Spec.Ports {
serviceEndpoints = append(serviceEndpoints, ServiceEndpoint{
Endpoint: Endpoint{
Protocol: port.Protocol,
Port: port.NodePort,
judgeAppProtocol := judgeAppProtocol(port.Port)
serviceEndpoints = append(serviceEndpoints, querytypes.ServiceEndpoint{
Endpoint: querytypes.Endpoint{
Protocol: port.Protocol,
Port: int(port.NodePort),
AppProtocol: &judgeAppProtocol,
Host: selectorNodeIP(),
},
Ref: corev1.ObjectReference{
Kind: service.Kind,
Kind: "Service",
Namespace: service.ObjectMeta.Namespace,
Name: service.ObjectMeta.Name,
UID: service.UID,
@@ -460,15 +432,15 @@ func generatorFromService(service corev1.Service) []ServiceEndpoint {
return serviceEndpoints
}
func generatorFromIngress(ingress networkv1beta1.Ingress) (serviceEndpoints []ServiceEndpoint) {
func generatorFromIngress(ingress networkv1beta1.Ingress) (serviceEndpoints []querytypes.ServiceEndpoint) {
getAppProtocol := func(host string) string {
if len(ingress.Spec.TLS) > 0 {
for _, tls := range ingress.Spec.TLS {
if len(tls.Hosts) > 0 && utils.StringsContain(tls.Hosts, host) {
return "https"
return querytypes.HTTPS
}
if len(tls.Hosts) == 0 {
return "https"
return querytypes.HTTPS
}
}
}
@@ -476,7 +448,7 @@ func generatorFromIngress(ingress networkv1beta1.Ingress) (serviceEndpoints []Se
}
// It depends on the Ingress Controller
getEndpointPort := func(appProtocol string) int {
if appProtocol == "https" {
if appProtocol == querytypes.HTTPS {
if port, err := strconv.Atoi(ingress.Annotations[apis.AnnoIngressControllerHTTPSPort]); port > 0 && err == nil {
return port
}
@@ -492,16 +464,16 @@ func generatorFromIngress(ingress networkv1beta1.Ingress) (serviceEndpoints []Se
var appPort = getEndpointPort(appProtocol)
if rule.HTTP != nil {
for _, path := range rule.HTTP.Paths {
serviceEndpoints = append(serviceEndpoints, ServiceEndpoint{
Endpoint: Endpoint{
serviceEndpoints = append(serviceEndpoints, querytypes.ServiceEndpoint{
Endpoint: querytypes.Endpoint{
Protocol: corev1.ProtocolTCP,
AppProtocol: &appProtocol,
Host: rule.Host,
Path: path.Path,
Port: int32(appPort),
Port: appPort,
},
Ref: corev1.ObjectReference{
Kind: ingress.Kind,
Kind: "Ingress",
Namespace: ingress.ObjectMeta.Namespace,
Name: ingress.ObjectMeta.Name,
UID: ingress.UID,
@@ -514,3 +486,61 @@ func generatorFromIngress(ingress networkv1beta1.Ingress) (serviceEndpoints []Se
}
return serviceEndpoints
}
func selectorNodeIP(ctx context.Context, clusterName string, client client.Client) string {
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
var nodes corev1.NodeList
if err := client.List(multicluster.ContextWithClusterName(ctx, clusterName), &nodes); err != nil {
return ""
}
if len(nodes.Items) == 0 {
return ""
}
var gatewayNode *corev1.Node
var workerNodes []corev1.Node
for i, node := range nodes.Items {
if _, exist := node.Labels[apis.LabelNodeRoleGateway]; exist {
gatewayNode = &nodes.Items[i]
break
} else if _, exist := node.Labels[apis.LabelNodeRoleWorker]; exist {
workerNodes = append(workerNodes, nodes.Items[i])
}
}
if gatewayNode == nil && len(workerNodes) > 0 {
gatewayNode = &workerNodes[0]
}
if gatewayNode == nil {
gatewayNode = &nodes.Items[0]
}
if gatewayNode != nil {
var addressMap = make(map[corev1.NodeAddressType]string)
for _, address := range gatewayNode.Status.Addresses {
addressMap[address.Type] = address.Address
}
// first get external ip
if ip, exist := addressMap[corev1.NodeExternalIP]; exist {
return ip
}
if ip, exist := addressMap[corev1.NodeInternalIP]; exist {
return ip
}
}
return ""
}
// judgeAppProtocol RFC-6335 and http://www.iana.org/assignments/service-names).
func judgeAppProtocol(port int32) string {
switch port {
case 80, 8080:
return querytypes.HTTP
case 443:
return querytypes.HTTPS
case 3306:
return querytypes.Mysql
case 6379:
return querytypes.Redis
default:
return ""
}
}
+18 -5
View File
@@ -39,6 +39,7 @@ import (
"github.com/oam-dev/kubevela/pkg/cue/model/value"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/util"
querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types"
"github.com/oam-dev/kubevela/pkg/workflow/providers"
)
@@ -686,23 +687,35 @@ options: {
}
err = pr.GeneratorServiceEndpoints(nil, v, nil)
Expect(err).Should(BeNil())
var node corev1.NodeList
err = k8sClient.List(context.TODO(), &node)
Expect(err).Should(BeNil())
var gatewayIP string
if len(node.Items) > 0 {
for _, address := range node.Items[0].Status.Addresses {
if address.Type == corev1.NodeInternalIP {
gatewayIP = address.Address
break
}
}
}
urls := []string{
"http://ingress.domain",
"https://ingress.domain.https",
"https://ingress.domain.path/test",
"https://ingress.domain.path/test2",
"tcp://:30229",
"tcp://10.10.10.10:80",
"tcp://text.example.com:80",
fmt.Sprintf("http://%s:30229", gatewayIP),
"http://10.10.10.10",
"http://text.example.com",
"tcp://10.10.10.10:81",
"tcp://text.example.com:81",
// helmRelease
"tcp://:30002",
fmt.Sprintf("http://%s:30002", gatewayIP),
"http://ingress.domain.helm",
}
endValue, err := v.Field("list")
Expect(err).Should(BeNil())
var endpoints []ServiceEndpoint
var endpoints []querytypes.ServiceEndpoint
err = endValue.Decode(&endpoints)
Expect(err).Should(BeNil())
for i, endpoint := range endpoints {
+82
View File
@@ -0,0 +1,82 @@
/*
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.
*/
package types
import (
"fmt"
"strings"
corev1 "k8s.io/api/core/v1"
)
const (
// HTTPS https protocol name
HTTPS = "https"
// HTTP http protocol name
HTTP = "http"
// Mysql mysql protocol name
Mysql = "mysql"
// Redis redis protocol name
Redis = "redis"
)
// ServiceEndpoint record the access endpoints of the application services
type ServiceEndpoint struct {
Endpoint Endpoint `json:"endpoint"`
Ref corev1.ObjectReference `json:"ref"`
}
// String return endpoint URL
func (s *ServiceEndpoint) String() string {
protocol := strings.ToLower(string(s.Endpoint.Protocol))
if s.Endpoint.AppProtocol != nil && *s.Endpoint.AppProtocol != "" {
protocol = *s.Endpoint.AppProtocol
}
path := s.Endpoint.Path
if s.Endpoint.Path == "/" {
path = ""
}
if (protocol == HTTPS && s.Endpoint.Port == 443) || (protocol == HTTP && s.Endpoint.Port == 80) {
return fmt.Sprintf("%s://%s%s", protocol, s.Endpoint.Host, path)
}
return fmt.Sprintf("%s://%s:%d%s", protocol, s.Endpoint.Host, s.Endpoint.Port, path)
}
// Endpoint create by ingress or service
type Endpoint struct {
// The protocol for this endpoint. Supports "TCP", "UDP", and "SCTP".
// Default is TCP.
// +default="TCP"
// +optional
Protocol corev1.Protocol `json:"protocol,omitempty"`
// The protocol for this endpoint.
// Un-prefixed names are reserved for IANA standard service names (as per
// RFC-6335 and http://www.iana.org/assignments/service-names).
// +optional
AppProtocol *string `json:"appProtocol,omitempty"`
// the host for the endpoint, it could be IP or domain
Host string `json:"host"`
// the port for the endpoint
// Default is 80.
Port int `json:"port"`
// the path for the endpoint
Path string `json:"path,omitempty"`
}
+1 -1
View File
@@ -82,7 +82,7 @@ func (handler *ViewHandler) QueryView(ctx context.Context, qv QueryView) (*value
Outputs: queryKey.Outputs,
}
taskDiscover := tasks.NewViewTaskDiscover(handler.pd, handler.cli, handler.cfg, handler.dispatch, handler.delete, handler.namespace)
taskDiscover := tasks.NewViewTaskDiscover(handler.pd, handler.cli, handler.cfg, handler.dispatch, handler.delete, handler.namespace, 3)
genTask, err := taskDiscover.GetTaskGenerator(ctx, handler.viewTask.Type)
if err != nil {
return nil, err
+4 -1
View File
@@ -66,6 +66,7 @@ type TaskLoader struct {
pd *packages.PackageDiscover
handlers providers.Providers
runOptionsProcess func(*wfTypes.TaskRunOptions)
logLevel int
}
// GetTaskGenerator get TaskGenerator by name.
@@ -156,6 +157,7 @@ func (t *TaskLoader) makeTaskGenerator(templ string) (wfTypes.TaskGenerator, err
}
}
tracer := options.GetTracer(exec.wfStatus.ID, wfStep).AddTag("step_name", wfStep.Name, "step_type", wfStep.Type)
tracer.V(t.logLevel)
defer func() {
tracer.Commit(string(exec.status().Phase))
}()
@@ -413,7 +415,7 @@ func getLabel(v *value.Value, label string) string {
}
// NewTaskLoader create a tasks loader.
func NewTaskLoader(lt LoadTaskTemplate, pkgDiscover *packages.PackageDiscover, handlers providers.Providers) *TaskLoader {
func NewTaskLoader(lt LoadTaskTemplate, pkgDiscover *packages.PackageDiscover, handlers providers.Providers, logLevel int) *TaskLoader {
return &TaskLoader{
loadTemplate: lt,
pd: pkgDiscover,
@@ -422,5 +424,6 @@ func NewTaskLoader(lt LoadTaskTemplate, pkgDiscover *packages.PackageDiscover, h
options.PreStartHooks = append(options.PreStartHooks, hooks.Input)
options.PostStopHooks = append(options.PostStopHooks, hooks.Output)
},
logLevel: logLevel,
}
}
+4 -4
View File
@@ -75,7 +75,7 @@ myIP: value: "1.1.1.1"
},
})
tasksLoader := NewTaskLoader(mockLoadTemplate, nil, discover)
tasksLoader := NewTaskLoader(mockLoadTemplate, nil, discover, 0)
steps := []v1beta1.WorkflowStep{
{
@@ -178,7 +178,7 @@ close({
return errors.New("mock error")
},
})
tasksLoader := NewTaskLoader(mockLoadTemplate, nil, discover)
tasksLoader := NewTaskLoader(mockLoadTemplate, nil, discover, 0)
steps := []v1beta1.WorkflowStep{
{
@@ -413,7 +413,7 @@ func TestPendingInputCheck(t *testing.T) {
ParameterKey: "score",
}},
}
tasksLoader := NewTaskLoader(mockLoadTemplate, nil, discover)
tasksLoader := NewTaskLoader(mockLoadTemplate, nil, discover, 0)
gen, err := tasksLoader.GetTaskGenerator(context.Background(), step.Type)
r.NoError(err)
run, err := gen(step, &types.GeneratorOptions{})
@@ -442,7 +442,7 @@ func TestPendingDependsOnCheck(t *testing.T) {
Type: "ok",
DependsOn: []string{"depend"},
}
tasksLoader := NewTaskLoader(mockLoadTemplate, nil, discover)
tasksLoader := NewTaskLoader(mockLoadTemplate, nil, discover, 0)
gen, err := tasksLoader.GetTaskGenerator(context.Background(), step.Type)
r.NoError(err)
run, err := gen(step, &types.GeneratorOptions{})
+3 -3
View File
@@ -84,7 +84,7 @@ func NewTaskDiscover(providerHandlers providers.Providers, pd *packages.PackageD
builtins: map[string]types.TaskGenerator{
"suspend": suspend,
},
remoteTaskDiscover: custom.NewTaskLoader(templateLoader.LoadTaskTemplate, pd, providerHandlers),
remoteTaskDiscover: custom.NewTaskLoader(templateLoader.LoadTaskTemplate, pd, providerHandlers, 0),
templateLoader: templateLoader,
}
}
@@ -115,7 +115,7 @@ func (tr *suspendTaskRunner) Pending(ctx wfContext.Context) bool {
}
// NewViewTaskDiscover will create a client for load task generator.
func NewViewTaskDiscover(pd *packages.PackageDiscover, cli client.Client, cfg *rest.Config, apply kube.Dispatcher, delete kube.Deleter, viewNs string) types.TaskDiscover {
func NewViewTaskDiscover(pd *packages.PackageDiscover, cli client.Client, cfg *rest.Config, apply kube.Dispatcher, delete kube.Deleter, viewNs string, logLevel int) types.TaskDiscover {
handlerProviders := providers.NewProviders()
// install builtin provider
@@ -128,7 +128,7 @@ func NewViewTaskDiscover(pd *packages.PackageDiscover, cli client.Client, cfg *r
templateLoader := template.NewViewTemplateLoader(cli, viewNs)
return &taskDiscover{
remoteTaskDiscover: custom.NewTaskLoader(templateLoader.LoadTaskTemplate, pd, handlerProviders),
remoteTaskDiscover: custom.NewTaskLoader(templateLoader.LoadTaskTemplate, pd, handlerProviders, logLevel),
templateLoader: templateLoader,
}
}
+1 -1
View File
@@ -50,7 +50,7 @@ func TestDiscover(t *testing.T) {
builtins: map[string]types.TaskGenerator{
"suspend": suspend,
},
remoteTaskDiscover: custom.NewTaskLoader(loadTemplate, nil, nil),
remoteTaskDiscover: custom.NewTaskLoader(loadTemplate, nil, nil, 0),
}
_, err := discover.GetTaskGenerator(context.Background(), "suspend")
+6 -1
View File
@@ -42,7 +42,12 @@ var _ = It("Test ApplyTerraform", func() {
}},
}
ioStream := util.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
_, err := ApplyTerraform(app, k8sClient, ioStream, addonNamespace, common.Args{Config: cfg})
arg := common.Args{
Schema: scheme,
}
err := arg.SetConfig(cfg)
Expect(err).Should(BeNil())
_, err = ApplyTerraform(app, k8sClient, ioStream, addonNamespace, arg)
Expect(err).Should(BeNil())
})
+35 -15
View File
@@ -69,7 +69,7 @@ func NewAddAddonRegistryCommand(c common.Args, ioStreams cmdutil.IOStreams) *cob
if err != nil {
return err
}
if err := addAddonRegistry(context.Background(), *registry); err != nil {
if err := addAddonRegistry(context.Background(), c, *registry); err != nil {
return err
}
return nil
@@ -91,7 +91,7 @@ func NewGetAddonRegistryCommand(c common.Args, ioStreams cmdutil.IOStreams) *cob
return errors.New("must specify the registry name")
}
name := args[0]
err := getAddonRegistry(context.Background(), name)
err := getAddonRegistry(context.Background(), c, name)
if err != nil {
return err
}
@@ -108,7 +108,7 @@ func NewListAddonRegistryCommand(c common.Args, ioStreams cmdutil.IOStreams) *co
Long: "List addon registries",
Example: "vela addon registry list",
RunE: func(cmd *cobra.Command, args []string) error {
if err := listAddonRegistry(context.Background()); err != nil {
if err := listAddonRegistry(context.Background(), c); err != nil {
return err
}
return nil
@@ -128,7 +128,7 @@ func NewUpdateAddonRegistryCommand(c common.Args, ioStreams cmdutil.IOStreams) *
if err != nil {
return err
}
if err := updateAddonRegistry(context.Background(), *registry); err != nil {
if err := updateAddonRegistry(context.Background(), c, *registry); err != nil {
return err
}
return nil
@@ -150,7 +150,7 @@ func NewDeleteAddonRegistryCommand(c common.Args, ioStreams cmdutil.IOStreams) *
return errors.New("must specify the registry name")
}
name := args[0]
err := deleteAddonRegistry(context.Background(), name)
err := deleteAddonRegistry(context.Background(), c, name)
if err != nil {
return err
}
@@ -159,8 +159,12 @@ func NewDeleteAddonRegistryCommand(c common.Args, ioStreams cmdutil.IOStreams) *
}
}
func listAddonRegistry(ctx context.Context) error {
ds := pkgaddon.NewRegistryDataStore(clt)
func listAddonRegistry(ctx context.Context, c common.Args) error {
client, err := c.GetClient()
if err != nil {
return err
}
ds := pkgaddon.NewRegistryDataStore(client)
registries, err := ds.ListRegistries(ctx)
if err != nil {
return err
@@ -193,8 +197,12 @@ func listAddonRegistry(ctx context.Context) error {
return nil
}
func getAddonRegistry(ctx context.Context, name string) error {
ds := pkgaddon.NewRegistryDataStore(clt)
func getAddonRegistry(ctx context.Context, c common.Args, name string) error {
client, err := c.GetClient()
if err != nil {
return err
}
ds := pkgaddon.NewRegistryDataStore(client)
registry, err := ds.GetRegistry(ctx, name)
if err != nil {
return err
@@ -211,8 +219,12 @@ func getAddonRegistry(ctx context.Context, name string) error {
return nil
}
func deleteAddonRegistry(ctx context.Context, name string) error {
ds := pkgaddon.NewRegistryDataStore(clt)
func deleteAddonRegistry(ctx context.Context, c common.Args, name string) error {
client, err := c.GetClient()
if err != nil {
return err
}
ds := pkgaddon.NewRegistryDataStore(client)
if err := ds.DeleteRegistry(ctx, name); err != nil {
return err
}
@@ -220,8 +232,12 @@ func deleteAddonRegistry(ctx context.Context, name string) error {
return nil
}
func addAddonRegistry(ctx context.Context, registry pkgaddon.Registry) error {
ds := pkgaddon.NewRegistryDataStore(clt)
func addAddonRegistry(ctx context.Context, c common.Args, registry pkgaddon.Registry) error {
client, err := c.GetClient()
if err != nil {
return err
}
ds := pkgaddon.NewRegistryDataStore(client)
if err := ds.AddRegistry(ctx, registry); err != nil {
return err
}
@@ -229,8 +245,12 @@ func addAddonRegistry(ctx context.Context, registry pkgaddon.Registry) error {
return nil
}
func updateAddonRegistry(ctx context.Context, registry pkgaddon.Registry) error {
ds := pkgaddon.NewRegistryDataStore(clt)
func updateAddonRegistry(ctx context.Context, c common.Args, registry pkgaddon.Registry) error {
client, err := c.GetClient()
if err != nil {
return err
}
ds := pkgaddon.NewRegistryDataStore(client)
if err := ds.UpdateRegistry(ctx, registry); err != nil {
return err
}
+56 -108
View File
@@ -19,18 +19,17 @@ package cli
import (
"context"
"fmt"
"os"
"strings"
"time"
"k8s.io/client-go/rest"
"github.com/gosuri/uitable"
"github.com/olekukonko/tablewriter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
v12 "k8s.io/api/core/v1"
v1 "k8s.io/api/networking/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
types2 "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -61,37 +60,6 @@ const (
statusDisabled = "disabled"
)
var clt client.Client
var clientArgs common.Args
// var legacyAddonNamespace map[string]string
func init() {
clientArgs, _ = common.InitBaseRestConfig()
var err error
clt, err = clientArgs.GetClient()
if err != nil {
panic(fmt.Sprintf("fail to create K8s client %v", err))
}
// assume KubeVela 1.2 needn't consider the compatibility of 1.1
// legacyAddonNamespace = map[string]string{
// "fluxcd": types.DefaultKubeVelaNS,
// "ns-flux-system": types.DefaultKubeVelaNS,
// "kruise": types.DefaultKubeVelaNS,
// "prometheus": types.DefaultKubeVelaNS,
// "observability": "observability",
// "observability-asset": types.DefaultKubeVelaNS,
// "istio": "istio-system",
// "ns-istio-system": types.DefaultKubeVelaNS,
// "keda": types.DefaultKubeVelaNS,
// "ocm-cluster-manager": types.DefaultKubeVelaNS,
// "terraform": types.DefaultKubeVelaNS,
// "terraform-provider/alibaba": "default",
// "terraform-provider/azure": "default",
// }
}
// NewAddonCommand create `addon` command
func NewAddonCommand(c common.Args, order string, ioStreams cmdutil.IOStreams) *cobra.Command {
cmd := &cobra.Command{
@@ -104,9 +72,9 @@ func NewAddonCommand(c common.Args, order string, ioStreams cmdutil.IOStreams) *
},
}
cmd.AddCommand(
NewAddonListCommand(),
NewAddonListCommand(c),
NewAddonEnableCommand(c, ioStreams),
NewAddonDisableCommand(ioStreams),
NewAddonDisableCommand(c, ioStreams),
NewAddonStatusCommand(c, ioStreams),
NewAddonRegistryCommand(c, ioStreams),
NewAddonUpgradeCommand(c, ioStreams),
@@ -115,14 +83,18 @@ func NewAddonCommand(c common.Args, order string, ioStreams cmdutil.IOStreams) *
}
// NewAddonListCommand create addon list command
func NewAddonListCommand() *cobra.Command {
func NewAddonListCommand(c common.Args) *cobra.Command {
return &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List addons",
Long: "List addons in KubeVela",
RunE: func(cmd *cobra.Command, args []string) error {
err := listAddons(context.Background(), "")
client, err := c.GetClient()
if err != nil {
return err
}
err = listAddons(context.Background(), client, "")
if err != nil {
return err
}
@@ -140,10 +112,6 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
Long: "enable an addon in cluster",
Example: "vela addon enable <addon-name>",
RunE: func(cmd *cobra.Command, args []string) error {
k8sClient, err := c.GetClient()
if err != nil {
return err
}
if len(args) < 1 {
return fmt.Errorf("must specify addon name")
@@ -153,28 +121,29 @@ func NewAddonEnableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Com
if err != nil {
return err
}
err = enableAddon(ctx, k8sClient, c.Config, name, addonArgs)
config, err := c.GetConfig()
if err != nil {
return err
}
k8sClient, err := c.GetClient()
if err != nil {
return err
}
err = enableAddon(ctx, k8sClient, config, name, addonArgs)
if err != nil {
return err
}
fmt.Printf("Successfully enable addon:%s\n", name)
if name == "velaux" {
// give k8s 10 second to fill the EIP or nodePort
var message string
var err error
for i := 0; i < 10; i++ {
message, err = fetchVelaUXRequestWay(ctx, k8sClient)
if err != nil {
time.Sleep(time.Second)
fmt.Println("try again to fetch the velaux requestWay")
continue
}
fmt.Println(message)
break
}
if err != nil {
return err
endpoints, _ := GetServiceEndpoints(ctx, k8sClient, pkgaddon.Convert2AppName(name), types.DefaultKubeVelaNS, c)
if len(endpoints) > 0 {
table := tablewriter.NewWriter(os.Stdout)
table.SetColWidth(100)
table.SetHeader([]string{"Ref(Kind/Namespace/Name)", "Endpoint"})
for _, endpoint := range endpoints {
table.Append([]string{fmt.Sprintf("%s/%s/%s", endpoint.Ref.Kind, endpoint.Ref.Namespace, endpoint.Ref.Name), endpoint.String()})
}
fmt.Printf("Please access the %s from the following endpoints:\n", name)
table.Render()
}
return nil
},
@@ -190,15 +159,18 @@ func NewAddonUpgradeCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Co
Long: "upgrade an addon in cluster",
Example: "vela addon upgrade <addon-name>",
RunE: func(cmd *cobra.Command, args []string) error {
k8sClient, err := c.GetClient()
if err != nil {
return err
}
if len(args) < 1 {
return fmt.Errorf("must specify addon name")
}
name := args[0]
config, err := c.GetConfig()
if err != nil {
return err
}
k8sClient, err := c.GetClient()
if err != nil {
return err
}
_, err = pkgaddon.FetchAddonRelatedApp(context.Background(), k8sClient, name)
if err != nil {
return errors.Wrapf(err, "cannot fetch addon related addon %s", name)
@@ -207,7 +179,7 @@ func NewAddonUpgradeCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Co
if err != nil {
return err
}
err = enableAddon(ctx, k8sClient, c.Config, name, addonArgs)
err = enableAddon(ctx, k8sClient, config, name, addonArgs)
if err != nil {
return err
}
@@ -237,7 +209,7 @@ func parseToMap(args []string) (map[string]interface{}, error) {
}
// NewAddonDisableCommand create addon disable command
func NewAddonDisableCommand(ioStream cmdutil.IOStreams) *cobra.Command {
func NewAddonDisableCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.Command {
return &cobra.Command{
Use: "disable",
Short: "disable an addon",
@@ -248,7 +220,11 @@ func NewAddonDisableCommand(ioStream cmdutil.IOStreams) *cobra.Command {
return fmt.Errorf("must specify addon name")
}
name := args[0]
err := disableAddon(name)
k8sClient, err := c.GetClient()
if err != nil {
return err
}
err = disableAddon(k8sClient, name)
if err != nil {
return err
}
@@ -295,7 +271,7 @@ func enableAddon(ctx context.Context, k8sClient client.Client, config *rest.Conf
if err != nil {
return err
}
if err = waitApplicationRunning(name); err != nil {
if err = waitApplicationRunning(k8sClient, name); err != nil {
return err
}
return nil
@@ -303,22 +279,26 @@ func enableAddon(ctx context.Context, k8sClient client.Client, config *rest.Conf
return fmt.Errorf("addon: %s not found in registrys", name)
}
func disableAddon(name string) error {
if err := pkgaddon.DisableAddon(context.Background(), clt, name); err != nil {
func disableAddon(client client.Client, name string) error {
if err := pkgaddon.DisableAddon(context.Background(), client, name); err != nil {
return err
}
return nil
}
func statusAddon(name string, ioStreams cmdutil.IOStreams, cmd *cobra.Command, c common.Args) error {
status, err := pkgaddon.GetAddonStatus(context.Background(), clt, name)
client, err := c.GetClient()
if err != nil {
return err
}
status, err := pkgaddon.GetAddonStatus(context.Background(), client, name)
if err != nil {
return err
}
fmt.Printf("addon %s status is %s \n", name, status.AddonPhase)
if status.AddonPhase != statusEnabled && status.AddonPhase != statusDisabled {
fmt.Printf("diagnose addon info from application %s", pkgaddon.Convert2AppName(name))
err := printAppStatus(context.Background(), clt, ioStreams, pkgaddon.Convert2AppName(name), types.DefaultKubeVelaNS, cmd, c)
err := printAppStatus(context.Background(), client, ioStreams, pkgaddon.Convert2AppName(name), types.DefaultKubeVelaNS, cmd, c)
if err != nil {
return err
}
@@ -326,7 +306,7 @@ func statusAddon(name string, ioStreams cmdutil.IOStreams, cmd *cobra.Command, c
return nil
}
func listAddons(ctx context.Context, registry string) error {
func listAddons(ctx context.Context, clt client.Client, registry string) error {
var addons []*pkgaddon.UIData
var err error
registryDS := pkgaddon.NewRegistryDataStore(clt)
@@ -334,7 +314,6 @@ func listAddons(ctx context.Context, registry string) error {
if err != nil {
return err
}
for _, r := range registries {
if registry != "" && r.Name != registry {
continue
@@ -365,7 +344,7 @@ func listAddons(ctx context.Context, registry string) error {
return nil
}
func waitApplicationRunning(addonName string) error {
func waitApplicationRunning(k8sClient client.Client, addonName string) error {
trackInterval := 5 * time.Second
timeout := 600 * time.Second
start := time.Now()
@@ -376,7 +355,7 @@ func waitApplicationRunning(addonName string) error {
defer spinner.Stop()
for {
err := clt.Get(ctx, types2.NamespacedName{Name: pkgaddon.Convert2AppName(addonName), Namespace: types.DefaultKubeVelaNS}, &app)
err := k8sClient.Get(ctx, types2.NamespacedName{Name: pkgaddon.Convert2AppName(addonName), Namespace: types.DefaultKubeVelaNS}, &app)
if err != nil {
return client.IgnoreNotFound(err)
}
@@ -388,7 +367,7 @@ func waitApplicationRunning(addonName string) error {
applySpinnerNewSuffix(spinner, fmt.Sprintf("Waiting addon application running. It is now in phase: %s (timeout %d/%d seconds)...",
phase, timeConsumed, int(timeout.Seconds())))
if timeConsumed > int(timeout.Seconds()) {
return errors.Errorf("Enabling timeout, please run \"vela status %s -n vela-system\" to check the status of the addon", addonName)
return errors.Errorf("Enabling timeout, please run \"vela status %s -n vela-system\" to check the status of the addon", pkgaddon.Convert2AppName(addonName))
}
time.Sleep(trackInterval)
}
@@ -419,37 +398,6 @@ func hasAddon(addons []*pkgaddon.UIData, name string) bool {
return false
}
func fetchVelaUXRequestWay(ctx context.Context, cli client.Client) (string, error) {
ingress := v1.Ingress{}
if err := cli.Get(ctx, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: "velaux"}, &ingress); err != nil {
if !apierrors.IsNotFound(err) {
return "", err
}
svc := v12.Service{}
if err := cli.Get(ctx, types2.NamespacedName{Namespace: types.DefaultKubeVelaNS, Name: "velaux"}, &svc); err != nil {
return "", err
}
switch svc.Spec.Type {
case v12.ServiceTypeClusterIP:
return `"Please use command: \"vela port-forward -n vela-system addon-velaux 9082:80\" and Select \"Cluster: local | Namespace: vela-system | Component: velaux | Kind: Service" to check the dashboard`, nil
case v12.ServiceTypeLoadBalancer:
if len(svc.Status.LoadBalancer.Ingress) == 0 || len(svc.Status.LoadBalancer.Ingress[0].IP) == 0 {
return "", fmt.Errorf("cannot fetch the EIP from velaux service")
}
return fmt.Sprintf("Please use the ExternalIP: %s to check the dashboard", svc.Status.LoadBalancer.Ingress[0].IP), nil
case v12.ServiceTypeNodePort:
if len(svc.Spec.Ports) == 0 || svc.Spec.Ports[0].NodePort == 0 {
return "", fmt.Errorf("cannot fetch the nodeport from velaux service")
}
return fmt.Sprintf("Please use the nodeIP: {NodeIP}:%d to check the dashboard", svc.Spec.Ports[0].NodePort), nil
default:
return "", fmt.Errorf("not support service type")
}
}
return fmt.Sprintf("Please use the domain: %s to check the dashboard", ingress.Spec.Rules[0].Host), nil
}
// TODO(wangyike) addon can support multi-tenancy, an addon can be enabled multi times and will create many times
// func checkWhetherTerraformProviderExist(ctx context.Context, k8sClient client.Client, addonName string, args map[string]string) (string, bool, error) {
// _, providerName := getTerraformProviderArgumentValue(addonName, args)
-5
View File
@@ -29,7 +29,6 @@ import (
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/system"
"github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/references/a/preimport"
"github.com/oam-dev/kubevela/version"
)
@@ -69,10 +68,6 @@ func NewCommand() *cobra.Command {
os.Exit(1)
}
preimport.SuppressLogging()
_, _ = commandArgs.GetClient()
preimport.ResumeLogging()
cmds.AddCommand(
// Getting Start
NewEnvCommand(commandArgs, "3", ioStream),
+40 -22
View File
@@ -44,7 +44,6 @@ import (
"github.com/oam-dev/kubevela/pkg/utils"
"github.com/oam-dev/kubevela/pkg/utils/common"
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/references/a/preimport"
)
const (
@@ -78,16 +77,12 @@ func ClusterCommandGroup(c common.Args, ioStreams cmdutil.IOStreams) *cobra.Comm
},
// check if cluster-gateway is ready
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if c.Config == nil {
if err := c.SetConfig(); err != nil {
return errors.Wrapf(err, "failed to set config for k8s client")
}
config, err := c.GetConfig()
if err != nil {
return err
}
c.Config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper)
c.Client = nil
preimport.SuppressLogging()
config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper)
k8sClient, err := c.GetClient()
preimport.ResumeLogging()
if err != nil {
return errors.Wrapf(err, "failed to get k8s client")
}
@@ -119,7 +114,11 @@ func NewClusterListCommand(c *common.Args) *cobra.Command {
Args: cobra.ExactValidArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
table := newUITable().AddRow("CLUSTER", "TYPE", "ENDPOINT")
clusters, err := clustermanager.GetRegisteredClusters(c.Client)
client, err := c.GetClient()
if err != nil {
return err
}
clusters, err := clustermanager.GetRegisteredClusters(client)
if err != nil {
return errors.Wrap(err, "fail to get registered cluster")
}
@@ -210,7 +209,14 @@ func NewClusterJoinCommand(c *common.Args, ioStreams cmdutil.IOStreams) *cobra.C
if createNamespace == "" {
createNamespace = types.DefaultKubeVelaNS
}
client, err := c.GetClient()
if err != nil {
return err
}
restConfig, err := c.GetConfig()
if err != nil {
return err
}
switch clusterManagementType {
case ClusterGateWayClusterManagement:
if endpoint, err := utils.ParseAPIServerEndpoint(cluster.Server); err == nil {
@@ -218,7 +224,7 @@ func NewClusterJoinCommand(c *common.Args, ioStreams cmdutil.IOStreams) *cobra.C
} else {
ioStreams.Infof("failed to parse server endpoint: %v", err)
}
if err = registerClusterManagedByVela(c.Client, cluster, authInfo, clusterName, createNamespace); err != nil {
if err = registerClusterManagedByVela(client, cluster, authInfo, clusterName, createNamespace); err != nil {
return err
}
case OCMClusterManagement:
@@ -227,7 +233,7 @@ func NewClusterJoinCommand(c *common.Args, ioStreams cmdutil.IOStreams) *cobra.C
return errors.Wrapf(err, "failed to determine the registration endpoint for the hub cluster "+
"when parsing --in-cluster-bootstrap flag")
}
if err = registerClusterManagedByOCM(ioStreams, c.Config, config, clusterName, inClusterBootstrap); err != nil {
if err = registerClusterManagedByOCM(ioStreams, restConfig, config, clusterName, inClusterBootstrap); err != nil {
return err
}
}
@@ -392,14 +398,18 @@ func NewClusterRenameCommand(c *common.Args) *cobra.Command {
if newClusterName == multicluster.ClusterLocalName {
return fmt.Errorf("cannot use `%s` as cluster name, it is reserved as the local cluster", multicluster.ClusterLocalName)
}
clusterSecret, err := multicluster.GetMutableClusterSecret(context.Background(), c.Client, oldClusterName)
client, err := c.GetClient()
if err != nil {
return err
}
clusterSecret, err := multicluster.GetMutableClusterSecret(context.Background(), client, oldClusterName)
if err != nil {
return errors.Wrapf(err, "cluster %s is not mutable now", oldClusterName)
}
if err := clustermanager.EnsureClusterNotExists(c.Client, newClusterName); err != nil {
if err := clustermanager.EnsureClusterNotExists(client, newClusterName); err != nil {
return errors.Wrapf(err, "cannot set cluster name to %s", newClusterName)
}
if err := c.Client.Delete(context.Background(), clusterSecret); err != nil {
if err := client.Delete(context.Background(), clusterSecret); err != nil {
return errors.Wrapf(err, "failed to rename cluster from %s to %s", oldClusterName, newClusterName)
}
clusterSecret.ObjectMeta = metav1.ObjectMeta{
@@ -408,7 +418,7 @@ func NewClusterRenameCommand(c *common.Args) *cobra.Command {
Labels: clusterSecret.Labels,
Annotations: clusterSecret.Annotations,
}
if err := c.Client.Create(context.Background(), clusterSecret); err != nil {
if err := client.Create(context.Background(), clusterSecret); err != nil {
return errors.Wrapf(err, "failed to rename cluster from %s to %s", oldClusterName, newClusterName)
}
cmd.Printf("Rename cluster %s to %s successfully.\n", oldClusterName, newClusterName)
@@ -429,7 +439,11 @@ func NewClusterDetachCommand(c *common.Args) *cobra.Command {
if clusterName == multicluster.ClusterLocalName {
return fmt.Errorf("cannot delete `%s` cluster, it is reserved as the local cluster", multicluster.ClusterLocalName)
}
clusters, err := clustermanager.GetRegisteredClusters(c.Client)
client, err := c.GetClient()
if err != nil {
return err
}
clusters, err := clustermanager.GetRegisteredClusters(client)
if err != nil {
return err
}
@@ -445,11 +459,11 @@ func NewClusterDetachCommand(c *common.Args) *cobra.Command {
switch clusterType {
case string(clusterv1alpha1.CredentialTypeX509Certificate), string(clusterv1alpha1.CredentialTypeServiceAccountToken):
clusterSecret, err := multicluster.GetMutableClusterSecret(context.Background(), c.Client, clusterName)
clusterSecret, err := multicluster.GetMutableClusterSecret(context.Background(), client, clusterName)
if err != nil {
return errors.Wrapf(err, "cluster %s is not mutable now", clusterName)
}
if err := c.Client.Delete(context.Background(), clusterSecret); err != nil {
if err := client.Delete(context.Background(), clusterSecret); err != nil {
return errors.Wrapf(err, "failed to detach cluster %s", clusterName)
}
case "ManagedCluster":
@@ -478,7 +492,7 @@ func NewClusterDetachCommand(c *common.Args) *cobra.Command {
Name: clusterName,
},
}
if err = c.Client.Delete(context.Background(), &managedCluster); err != nil {
if err = client.Delete(context.Background(), &managedCluster); err != nil {
if !apierrors.IsNotFound(err) {
return err
}
@@ -503,7 +517,11 @@ func NewClusterProbeCommand(c *common.Args) *cobra.Command {
if clusterName == multicluster.ClusterLocalName {
return errors.New("you must specify a remote cluster name")
}
content, err := versioned.NewForConfigOrDie(c.Config).ClusterV1alpha1().ClusterGateways().RESTClient(clusterName).Get().AbsPath("healthz").DoRaw(context.TODO())
config, err := c.GetConfig()
if err != nil {
return err
}
content, err := versioned.NewForConfigOrDie(config).ClusterV1alpha1().ClusterGateways().RESTClient(clusterName).Get().AbsPath("healthz").DoRaw(context.TODO())
if err != nil {
return errors.Wrapf(err, "failed connect cluster %s", clusterName)
}
+7 -6
View File
@@ -45,9 +45,6 @@ func NewComponentsCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Co
Short: "List/get components",
Long: "List components & get components in registry",
Example: `vela comp`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
// parse label filter
if label != "" {
@@ -76,7 +73,7 @@ func NewComponentsCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Co
}
return PrintComponentListFromRegistry(registry, ioStreams, filter)
}
return PrintInstalledCompDef(ioStreams, filter)
return PrintInstalledCompDef(c, ioStreams, filter)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeExtension,
@@ -213,9 +210,13 @@ func InstallCompByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStreams
}
// PrintInstalledCompDef will print all ComponentDefinition in cluster
func PrintInstalledCompDef(io cmdutil.IOStreams, filter filterFunc) error {
func PrintInstalledCompDef(c common2.Args, io cmdutil.IOStreams, filter filterFunc) error {
var list v1beta1.ComponentDefinitionList
err := clt.List(context.Background(), &list)
clt, err := c.GetClient()
if err != nil {
return err
}
err = clt.List(context.Background(), &list)
if err != nil {
return errors.Wrap(err, "get component definition list error")
}
-3
View File
@@ -39,9 +39,6 @@ func NewCUEPackageCommand(c common.Args, ioStreams cmdutil.IOStreams) *cobra.Com
Annotations: map[string]string{
types.TagCommandType: types.TypeSystem,
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
return printCUEPackageList(c, ioStreams)
},
+22 -6
View File
@@ -64,7 +64,6 @@ func DefinitionCommandGroup(c common.Args, order string) *cobra.Command {
types.TagCommandType: types.TypeExtension,
},
}
_ = c.SetConfig() // set kubeConfig if possible, otherwise ignore it
cmd.AddCommand(
NewDefinitionGetCommand(c),
NewDefinitionListCommand(c),
@@ -396,6 +395,10 @@ func NewDefinitionEditCommand(c common.Args) *cobra.Command {
if err != nil {
return errors.Wrapf(err, "failed to get `%s`", Namespace)
}
config, err := c.GetConfig()
if err != nil {
return err
}
k8sClient, err := c.GetClient()
if err != nil {
return errors.Wrapf(err, "failed to get k8s client")
@@ -444,7 +447,7 @@ func NewDefinitionEditCommand(c common.Args) *cobra.Command {
cmd.Printf("definition unchanged\n")
return nil
}
if err := def.FromCUEString(string(newBuf), c.Config); err != nil {
if err := def.FromCUEString(string(newBuf), config); err != nil {
return errors.Wrapf(err, "failed to load edited cue string")
}
if err := k8sClient.Update(context.Background(), def); err != nil {
@@ -492,13 +495,18 @@ func NewDefinitionRenderCommand(c common.Args) *cobra.Command {
if err != nil {
return errors.Wrapf(err, "failed to get `%s`", FlagMessage)
}
render := func(inputFilename, outputFilename string) error {
cueBytes, err := loadYAMLBytesFromFileOrHTTP(inputFilename)
if err != nil {
return errors.Wrapf(err, "failed to get %s", args[0])
}
config, err := c.GetConfig()
if err != nil {
return err
}
def := pkgdef.Definition{Unstructured: unstructured.Unstructured{}}
if err := def.FromCUEString(string(cueBytes), c.Config); err != nil {
if err := def.FromCUEString(string(cueBytes), config); err != nil {
return errors.Wrapf(err, "failed to parse CUE")
}
@@ -594,6 +602,10 @@ func NewDefinitionApplyCommand(c common.Args) *cobra.Command {
if err != nil {
return errors.Wrapf(err, "failed to get `%s`", Namespace)
}
config, err := c.GetConfig()
if err != nil {
return err
}
k8sClient, err := c.GetClient()
if err != nil {
return errors.Wrapf(err, "failed to get k8s client")
@@ -604,7 +616,7 @@ func NewDefinitionApplyCommand(c common.Args) *cobra.Command {
return errors.Wrapf(err, "failed to get %s", args[0])
}
def := pkgdef.Definition{Unstructured: unstructured.Unstructured{}}
if err := def.FromCUEString(string(cueBytes), c.Config); err != nil {
if err := def.FromCUEString(string(cueBytes), config); err != nil {
return errors.Wrapf(err, "failed to parse CUE")
}
def.SetNamespace(namespace)
@@ -635,7 +647,7 @@ func NewDefinitionApplyCommand(c common.Args) *cobra.Command {
}
return errors.Wrapf(err, "failed to check existence of target definition in kubernetes")
}
if err := oldDef.FromCUEString(string(cueBytes), c.Config); err != nil {
if err := oldDef.FromCUEString(string(cueBytes), config); err != nil {
return errors.Wrapf(err, "failed to merge with existing definition")
}
if err = k8sClient.Update(ctx, &oldDef); err != nil {
@@ -731,7 +743,11 @@ func NewDefinitionValidateCommand(c common.Args) *cobra.Command {
return errors.Wrapf(err, "failed to read %s", args[0])
}
def := pkgdef.Definition{Unstructured: unstructured.Unstructured{}}
if err := def.FromCUEString(string(cueBytes), c.Config); err != nil {
config, err := c.GetConfig()
if err != nil {
return err
}
if err := def.FromCUEString(string(cueBytes), config); err != nil {
return errors.Wrapf(err, "failed to parse CUE")
}
cmd.Println("Validation succeed.")
+13 -5
View File
@@ -45,9 +45,9 @@ const (
)
func initArgs() common2.Args {
return common2.Args{
Client: fake.NewClientBuilder().WithScheme(common2.Scheme).Build(),
}
arg := common2.Args{}
arg.SetClient(fake.NewClientBuilder().WithScheme(common2.Scheme).Build())
return arg
}
func initCommand(cmd *cobra.Command) {
@@ -66,7 +66,11 @@ func createTrait(c common2.Args, t *testing.T) string {
func createNamespacedTrait(c common2.Args, name string, ns string, t *testing.T) {
traitName := fmt.Sprintf("my-trait-%d", time.Now().UnixNano())
if err := c.Client.Create(context.Background(), &v1beta1.TraitDefinition{
client, err := c.GetClient()
if err != nil {
t.Fatalf("failed to get client: %v", err)
}
if err := client.Create(context.Background(), &v1beta1.TraitDefinition{
ObjectMeta: v1.ObjectMeta{
Name: name,
Namespace: ns,
@@ -343,7 +347,11 @@ func TestNewDefinitionDelCommand(t *testing.T) {
t.Fatalf("unexpeced error when executing del command: %v", err)
}
obj := &v1beta1.TraitDefinition{}
if err := c.Client.Get(context.Background(), types.NamespacedName{
client, err := c.GetClient()
if err != nil {
t.Fatalf("failed to get client: %v", err)
}
if err := client.Get(context.Background(), types.NamespacedName{
Namespace: VelaTestNamespace,
Name: traitName,
}, obj); !errors.IsNotFound(err) {
-3
View File
@@ -35,9 +35,6 @@ func NewDeleteCommand(c common2.Args, order string, ioStreams cmdutil.IOStreams)
DisableFlagsInUseLine: true,
Short: "Delete an application",
Long: "Delete an application",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
Annotations: map[string]string{
types.TagCommandOrder: order,
types.TagCommandType: types.TypeApp,
+5 -5
View File
@@ -58,9 +58,6 @@ func NewDryRunCommand(c common.Args, ioStreams cmdutil.IOStreams) *cobra.Command
Annotations: map[string]string{
types.TagCommandType: types.TypeApp,
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
namespace, err := GetFlagNamespaceOrEnv(cmd, c)
if err != nil {
@@ -101,8 +98,11 @@ func DryRunApplication(cmdOption *DryRunCmdOptions, c common.Args, namespace str
if err != nil {
return buff, err
}
dm, err := discoverymapper.New(c.Config)
config, err := c.GetConfig()
if err != nil {
return buff, err
}
dm, err := discoverymapper.New(config)
if err != nil {
return buff, err
}
-3
View File
@@ -35,9 +35,6 @@ func NewEnvCommand(c common.Args, order string, ioStream cmdutil.IOStreams) *cob
DisableFlagsInUseLine: true,
Short: "Manage environments",
Long: "Manage environments",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
Annotations: map[string]string{
types.TagCommandOrder: order,
types.TagCommandType: types.TypeStart,
+6 -8
View File
@@ -20,7 +20,6 @@ import (
"context"
"time"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/kubernetes"
@@ -82,11 +81,6 @@ func NewExecCommand(c common.Args, order string, ioStreams util.IOStreams) *cobr
Short: "Execute command in a container",
Long: "Execute command in a container",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if c.Config == nil {
if err := c.SetConfig(); err != nil {
return errors.Wrapf(err, "failed to set config for k8s client")
}
}
o.VelaC = c
return nil
},
@@ -169,8 +163,12 @@ func (o *VelaExecOptions) Init(ctx context.Context, c *cobra.Command, argsIn []s
o.resourceName = targetResource.Name
o.Ctx = multicluster.ContextWithClusterName(ctx, targetResource.Cluster)
o.resourceNamespace = targetResource.Namespace
o.VelaC.Config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper)
k8sClient, err := kubernetes.NewForConfig(o.VelaC.Config)
config, err := o.VelaC.GetConfig()
if err != nil {
return err
}
config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper)
k8sClient, err := kubernetes.NewForConfig(config)
if err != nil {
return err
}
-3
View File
@@ -64,9 +64,6 @@ func NewInitCommand(c common2.Args, order string, ioStreams cmdutil.IOStreams) *
Short: "Create scaffold for an application",
Long: "Create scaffold for an application",
Example: "vela init",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
var err error
o.Namespace, err = GetFlagNamespaceOrEnv(cmd, c)
+5 -5
View File
@@ -57,9 +57,6 @@ func NewLiveDiffCommand(c common.Args, order string, ioStreams cmdutil.IOStreams
types.TagCommandOrder: order,
types.TagCommandType: types.TypeApp,
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
namespace, err := GetFlagNamespaceOrEnv(cmd, c)
if err != nil {
@@ -102,8 +99,11 @@ func LiveDiffApplication(cmdOption *LiveDiffCmdOptions, c common.Args, namespace
if err != nil {
return buff, err
}
dm, err := discoverymapper.New(c.Config)
config, err := c.GetConfig()
if err != nil {
return buff, err
}
dm, err := discoverymapper.New(config)
if err != nil {
return buff, err
}
+8 -3
View File
@@ -49,11 +49,12 @@ func NewLogsCommand(c common.Args, order string, ioStreams util.IOStreams) *cobr
Long: "Tail logs for application in multicluster",
Args: cobra.ExactArgs(1),
PreRunE: func(cmd *cobra.Command, args []string) error {
if err := c.SetConfig(); err != nil {
config, err := c.GetConfig()
if err != nil {
return err
}
largs.Args = c
largs.Args.Config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper)
config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper)
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
@@ -95,7 +96,11 @@ type Args struct {
func (l *Args) Run(ctx context.Context, ioStreams util.IOStreams) error {
// TODO(wonderflow): we could get labels from service to narrow the pods scope selected
labelSelector := labels.Everything()
clientSet, err := kubernetes.NewForConfig(l.Args.Config)
config, err := l.Args.GetConfig()
if err != nil {
return err
}
clientSet, err := kubernetes.NewForConfig(config)
if err != nil {
return err
}
-3
View File
@@ -40,9 +40,6 @@ func NewListCommand(c common.Args, order string, ioStreams cmdutil.IOStreams) *c
Short: "List applications",
Long: "List all applications in cluster",
Example: `vela ls`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
newClient, err := c.GetClient()
if err != nil {
+15 -9
View File
@@ -88,9 +88,6 @@ func NewPortForwardCommand(c common.Args, order string, ioStreams util.IOStreams
Long: "Forward local ports to services in an application",
Example: "port-forward APP_NAME [options] [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if err := c.SetConfig(); err != nil {
return err
}
o.VelaC = c
return nil
},
@@ -164,13 +161,18 @@ func (o *VelaPortForwardOptions) Init(ctx context.Context, cmd *cobra.Command, a
o.f = k8scmdutil.NewFactory(k8scmdutil.NewMatchVersionFlags(cf))
o.targetResource = targetResource
o.Ctx = multicluster.ContextWithClusterName(ctx, targetResource.Cluster)
o.VelaC.Config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper)
o.VelaC.Client, err = client.New(o.VelaC.Config, client.Options{Scheme: common.Scheme})
config, err := o.VelaC.GetConfig()
if err != nil {
return err
}
config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper)
client, err := client.New(config, client.Options{Scheme: common.Scheme})
if err != nil {
return err
}
o.VelaC.SetClient(client)
if o.ClientSet == nil {
c, err := kubernetes.NewForConfig(o.VelaC.Config)
c, err := kubernetes.NewForConfig(config)
if err != nil {
return err
}
@@ -217,7 +219,11 @@ func getSvcNameAndPortFromHelmRelease(ctx context.Context, cli client.Client, o
// Complete will complete the config of port-forward
func (o *VelaPortForwardOptions) Complete() error {
compName, err := getCompNameFromClusterObjectReference(o.Ctx, o.VelaC.Client, o.targetResource)
client, err := o.VelaC.GetClient()
if err != nil {
return err
}
compName, err := getCompNameFromClusterObjectReference(o.Ctx, client, o.targetResource)
if err != nil {
return err
}
@@ -225,7 +231,7 @@ func (o *VelaPortForwardOptions) Complete() error {
return fmt.Errorf("failed to get component name")
}
if o.routeTrait {
appconfig, err := appfile.GetAppConfig(o.Ctx, o.VelaC.Client, o.App, o.Env)
appconfig, err := appfile.GetAppConfig(o.Ctx, client, o.App, o.Env)
if err != nil {
return err
}
@@ -234,7 +240,7 @@ func (o *VelaPortForwardOptions) Complete() error {
return fmt.Errorf("no route trait found in %s %s", o.App.Name, compName)
}
var svc = corev1.Service{}
err = o.VelaC.Client.Get(o.Ctx, types2.NamespacedName{Name: routeSvc, Namespace: o.Env.Namespace}, &svc)
err = client.Get(o.Ctx, types2.NamespacedName{Name: routeSvc, Namespace: o.Env.Namespace}, &svc)
if err != nil {
return err
}
-3
View File
@@ -65,9 +65,6 @@ func NewCapabilityShowCommand(c common.Args, ioStreams cmdutil.IOStreams) *cobra
Short: "Show the reference doc for a component type or trait",
Long: "Show the reference doc for a component type or trait",
Example: `show webservice`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return fmt.Errorf("please specify a component type or trait")
+44 -23
View File
@@ -18,11 +18,13 @@ package cli
import (
"context"
"fmt"
"os"
"strings"
"time"
"github.com/fatih/color"
"github.com/olekukonko/tablewriter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -88,24 +90,26 @@ func NewAppStatusCommand(c common.Args, order string, ioStreams cmdutil.IOStream
Short: "Show status of an application",
Long: "Show status of an application, including workloads and traits of each service.",
Example: `vela status APP_NAME`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
// check args
argsLength := len(args)
if argsLength == 0 {
return fmt.Errorf("please specify an application")
}
appName := args[0]
// get namespace
namespace, err := GetFlagNamespaceOrEnv(cmd, c)
if err != nil {
return err
}
argsLength := len(args)
if argsLength == 0 {
ioStreams.Errorf("Hint: please specify an application")
os.Exit(1)
}
appName := args[0]
newClient, err := c.GetClient()
if err != nil {
return err
}
showEndpoints, err := cmd.Flags().GetBool("endpoint")
if showEndpoints && err == nil {
return printAppEndpoints(ctx, newClient, appName, namespace, c)
}
return printAppStatus(ctx, newClient, ioStreams, appName, namespace, cmd, c)
},
Annotations: map[string]string{
@@ -114,7 +118,7 @@ func NewAppStatusCommand(c common.Args, order string, ioStreams cmdutil.IOStream
},
}
cmd.Flags().StringP("svc", "s", "", "service name")
cmd.Flags().BoolP("endpoint", "p", false, "show all service endpoints of the application")
addNamespaceAndEnvArg(cmd)
cmd.SetOut(ioStreams.Out)
return cmd
@@ -140,6 +144,21 @@ func printAppStatus(_ context.Context, c client.Client, ioStreams cmdutil.IOStre
return loopCheckStatus(c, ioStreams, appName, namespace)
}
func printAppEndpoints(ctx context.Context, client client.Client, appName string, namespace string, velaC common.Args) error {
endpoints, err := GetServiceEndpoints(ctx, client, appName, namespace, velaC)
if err != nil {
return err
}
table := tablewriter.NewWriter(os.Stdout)
table.SetColWidth(100)
table.SetHeader([]string{"Ref(Kind/Namespace/Name)", "Endpoint"})
for _, endpoint := range endpoints {
table.Append([]string{fmt.Sprintf("%s/%s/%s", endpoint.Ref.Kind, endpoint.Ref.Namespace, endpoint.Ref.Name), endpoint.String()})
}
table.Render()
return nil
}
func loadRemoteApplication(c client.Client, ns string, name string) (*v1beta1.Application, error) {
app := new(v1beta1.Application)
err := c.Get(context.Background(), client.ObjectKey{
@@ -164,20 +183,22 @@ func printWorkflowStatus(c client.Client, ioStreams cmdutil.IOStreams, appName s
return err
}
workflowStatus := remoteApp.Status.Workflow
ioStreams.Info("Workflow:\n")
ioStreams.Infof(" mode: %s\n", workflowStatus.Mode)
ioStreams.Infof(" finished: %t\n", workflowStatus.Finished)
ioStreams.Infof(" Suspend: %t\n", workflowStatus.Suspend)
ioStreams.Infof(" Terminated: %t\n", workflowStatus.Terminated)
ioStreams.Info(" Steps")
for _, step := range workflowStatus.Steps {
ioStreams.Infof(" - id:%s\n", step.ID)
ioStreams.Infof(" name:%s\n", step.Name)
ioStreams.Infof(" type:%s\n", step.Type)
ioStreams.Infof(" phase:%s \n", getWfStepColor(step.Phase).Sprint(step.Phase))
ioStreams.Infof(" message:%s\n", step.Message)
if workflowStatus != nil {
ioStreams.Info("Workflow:\n")
ioStreams.Infof(" mode: %s\n", workflowStatus.Mode)
ioStreams.Infof(" finished: %t\n", workflowStatus.Finished)
ioStreams.Infof(" Suspend: %t\n", workflowStatus.Suspend)
ioStreams.Infof(" Terminated: %t\n", workflowStatus.Terminated)
ioStreams.Info(" Steps")
for _, step := range workflowStatus.Steps {
ioStreams.Infof(" - id:%s\n", step.ID)
ioStreams.Infof(" name:%s\n", step.Name)
ioStreams.Infof(" type:%s\n", step.Type)
ioStreams.Infof(" phase:%s \n", getWfStepColor(step.Phase).Sprint(step.Phase))
ioStreams.Infof(" message:%s\n", step.Message)
}
ioStreams.Infof("\n")
}
ioStreams.Infof("\n")
return nil
}
+7 -6
View File
@@ -53,9 +53,6 @@ func NewTraitCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Command
Short: "List/get traits",
Long: "List traits & get trait in registry",
Example: `vela trait`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
// parse label filter
if label != "" {
@@ -85,7 +82,7 @@ func NewTraitCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Command
return PrintTraitListFromRegistry(registry, ioStreams, filter)
}
return PrintInstalledTraitDef(ioStreams, filter)
return PrintInstalledTraitDef(c, ioStreams, filter)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeExtension,
@@ -214,9 +211,13 @@ func InstallTraitByNameFromRegistry(args common2.Args, ioStream cmdutil.IOStream
}
// PrintInstalledTraitDef will print all TraitDefinition in cluster
func PrintInstalledTraitDef(io cmdutil.IOStreams, filter filterFunc) error {
func PrintInstalledTraitDef(c common2.Args, io cmdutil.IOStreams, filter filterFunc) error {
var list v1beta1.TraitDefinitionList
err := clt.List(context.Background(), &list)
clt, err := c.GetClient()
if err != nil {
return err
}
err = clt.List(context.Background(), &list)
if err != nil {
return errors.Wrap(err, "get trait definition list error")
}
+1 -13
View File
@@ -17,26 +17,14 @@ limitations under the License.
package cli
import (
"os"
"testing"
"github.com/oam-dev/kubevela/apis/types"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
common2 "github.com/oam-dev/kubevela/pkg/utils/common"
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/references/common"
)
func TestNewTraitsCommandPersistentPreRunE(t *testing.T) {
io := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
fakeC := common2.Args{}
cmd := NewTraitCommand(fakeC, io)
assert.Nil(t, cmd.PersistentPreRunE(new(cobra.Command), []string{}))
}
func TestTraitsAppliedToAllWorkloads(t *testing.T) {
trait := types.Capability{
Name: "route",
+1 -4
View File
@@ -60,12 +60,9 @@ func NewUISchemaCommand(c common.Args, order string, ioStreams util.IOStreams) *
Annotations: map[string]string{
types.TagCommandType: types.TypeExtension,
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 {
return errors.New("please provider the uischema file or dir path")
return errors.New("please provider the ui schema file or dir path")
}
allUISchemaFiles, err := loadUISchemaFiles(args[0])
if err != nil {
-3
View File
@@ -43,9 +43,6 @@ func NewUpCommand(c common2.Args, order string, ioStream cmdutil.IOStreams) *cob
types.TagCommandOrder: order,
types.TagCommandType: types.TypeStart,
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
namespace, err := GetFlagNamespaceOrEnv(cmd, c)
if err != nil {
-9
View File
@@ -21,11 +21,9 @@ import (
"os"
"testing"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
common2 "github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/references/common"
)
@@ -43,10 +41,3 @@ func TestUp(t *testing.T) {
assert.Contains(t, msg, "App has been deployed")
assert.Contains(t, msg, fmt.Sprintf("App status: vela status %s", app.Name))
}
func TestNewUpCommandPersistentPreRunE(t *testing.T) {
io := util.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
fakeC := common2.Args{}
cmd := NewUpCommand(fakeC, "", io)
assert.Nil(t, cmd.PersistentPreRunE(new(cobra.Command), []string{}))
}
+57
View File
@@ -0,0 +1,57 @@
/*
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.
*/
package cli
import (
"context"
"fmt"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/velaql"
querytypes "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types"
)
// GetServiceEndpoints get service endpoints by velaQL
func GetServiceEndpoints(ctx context.Context, client client.Client, appName string, namespace string, velaC common.Args) ([]querytypes.ServiceEndpoint, error) {
dm, err := velaC.GetDiscoveryMapper()
if err != nil {
return nil, err
}
pd, err := velaC.GetPackageDiscover()
if err != nil {
return nil, err
}
queryView, err := velaql.ParseVelaQL(fmt.Sprintf("service-endpoints-view{appName=%s,appNs=%s}.endpoints", appName, namespace))
if err != nil {
return nil, err
}
config, err := velaC.GetConfig()
if err != nil {
return nil, err
}
queryValue, err := velaql.NewViewHandler(client, config, dm, pd).QueryView(ctx, queryView)
if err != nil {
return nil, err
}
var endpoints []querytypes.ServiceEndpoint
if err := queryValue.CueValue().Decode(&endpoints); err != nil {
return nil, err
}
return endpoints, nil
}
+10 -12
View File
@@ -76,12 +76,11 @@ func NewWorkflowSuspendCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra
if app.Status.Workflow == nil {
return fmt.Errorf("the workflow in application is not running")
}
kubecli, err := c.GetClient()
client, err := c.GetClient()
if err != nil {
return err
}
err = suspendWorkflow(kubecli, app)
err = suspendWorkflow(client, app)
if err != nil {
return err
}
@@ -124,12 +123,12 @@ func NewWorkflowResumeCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra.
}
return nil
}
kubecli, err := c.GetClient()
client, err := c.GetClient()
if err != nil {
return err
}
err = resumeWorkflow(kubecli, app)
err = resumeWorkflow(client, app)
if err != nil {
return err
}
@@ -165,12 +164,11 @@ func NewWorkflowTerminateCommand(c common.Args, ioStream cmdutil.IOStreams) *cob
if app.Status.Workflow == nil {
return fmt.Errorf("the workflow in application is not running")
}
kubecli, err := c.GetClient()
client, err := c.GetClient()
if err != nil {
return err
}
err = terminateWorkflow(kubecli, app)
err = terminateWorkflow(client, app)
if err != nil {
return err
}
@@ -206,12 +204,12 @@ func NewWorkflowRestartCommand(c common.Args, ioStream cmdutil.IOStreams) *cobra
if app.Status.Workflow == nil {
return fmt.Errorf("the workflow in application is not running")
}
kubecli, err := c.GetClient()
client, err := c.GetClient()
if err != nil {
return err
}
err = restartWorkflow(kubecli, app)
err = restartWorkflow(client, app)
if err != nil {
return err
}
@@ -247,12 +245,12 @@ func NewWorkflowRollbackCommand(c common.Args, ioStream cmdutil.IOStreams) *cobr
if app.Status.Workflow != nil && !app.Status.Workflow.Terminated && !app.Status.Workflow.Suspend && !app.Status.Workflow.Finished {
return fmt.Errorf("can not rollback a running workflow")
}
kubecli, err := c.GetClient()
client, err := c.GetClient()
if err != nil {
return err
}
err = rollbackWorkflow(kubecli, app)
err = rollbackWorkflow(client, app)
if err != nil {
return err
}
+31 -25
View File
@@ -103,12 +103,14 @@ func TestWorkflowSuspend(t *testing.T) {
initCommand(cmd)
// clean up the arguments before start
cmd.SetArgs([]string{})
client, err := c.GetClient()
r.NoError(err)
if tc.app != nil {
err := c.Client.Create(ctx, tc.app)
err := client.Create(ctx, tc.app)
r.NoError(err)
if tc.app.Namespace != corev1.NamespaceDefault {
err := c.Client.Create(ctx, &corev1.Namespace{
err := client.Create(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: tc.app.Namespace,
},
@@ -119,7 +121,7 @@ func TestWorkflowSuspend(t *testing.T) {
cmd.SetArgs([]string{tc.app.Name})
}
}
err := cmd.Execute()
err = cmd.Execute()
if tc.expectedErr != nil {
r.Equal(tc.expectedErr, err)
return
@@ -127,7 +129,7 @@ func TestWorkflowSuspend(t *testing.T) {
r.NoError(err)
wf := &v1beta1.Application{}
err = c.Client.Get(ctx, types.NamespacedName{
err = client.Get(ctx, types.NamespacedName{
Namespace: tc.app.Namespace,
Name: tc.app.Name,
}, wf)
@@ -210,13 +212,14 @@ func TestWorkflowResume(t *testing.T) {
r := require.New(t)
cmd := NewWorkflowResumeCommand(c, ioStream)
initCommand(cmd)
client, err := c.GetClient()
r.NoError(err)
if tc.app != nil {
err := c.Client.Create(ctx, tc.app)
err := client.Create(ctx, tc.app)
r.NoError(err)
if tc.app.Namespace != corev1.NamespaceDefault {
err := c.Client.Create(ctx, &corev1.Namespace{
err := client.Create(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: tc.app.Namespace,
},
@@ -227,7 +230,7 @@ func TestWorkflowResume(t *testing.T) {
cmd.SetArgs([]string{tc.app.Name})
}
}
err := cmd.Execute()
err = cmd.Execute()
if tc.expectedErr != nil {
r.Equal(tc.expectedErr, err)
return
@@ -235,7 +238,7 @@ func TestWorkflowResume(t *testing.T) {
r.NoError(err)
wf := &v1beta1.Application{}
err = c.Client.Get(ctx, types.NamespacedName{
err = client.Get(ctx, types.NamespacedName{
Namespace: tc.app.Namespace,
Name: tc.app.Name,
}, wf)
@@ -298,13 +301,14 @@ func TestWorkflowTerminate(t *testing.T) {
r := require.New(t)
cmd := NewWorkflowTerminateCommand(c, ioStream)
initCommand(cmd)
client, err := c.GetClient()
r.NoError(err)
if tc.app != nil {
err := c.Client.Create(ctx, tc.app)
err := client.Create(ctx, tc.app)
r.NoError(err)
if tc.app.Namespace != corev1.NamespaceDefault {
err := c.Client.Create(ctx, &corev1.Namespace{
err := client.Create(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: tc.app.Namespace,
},
@@ -315,7 +319,7 @@ func TestWorkflowTerminate(t *testing.T) {
cmd.SetArgs([]string{tc.app.Name})
}
}
err := cmd.Execute()
err = cmd.Execute()
if tc.expectedErr != nil {
r.Equal(tc.expectedErr, err)
return
@@ -323,7 +327,7 @@ func TestWorkflowTerminate(t *testing.T) {
r.NoError(err)
wf := &v1beta1.Application{}
err = c.Client.Get(ctx, types.NamespacedName{
err = client.Get(ctx, types.NamespacedName{
Namespace: tc.app.Namespace,
Name: tc.app.Name,
}, wf)
@@ -386,13 +390,14 @@ func TestWorkflowRestart(t *testing.T) {
r := require.New(t)
cmd := NewWorkflowRestartCommand(c, ioStream)
initCommand(cmd)
client, err := c.GetClient()
r.NoError(err)
if tc.app != nil {
err := c.Client.Create(ctx, tc.app)
err := client.Create(ctx, tc.app)
r.NoError(err)
if tc.app.Namespace != corev1.NamespaceDefault {
err := c.Client.Create(ctx, &corev1.Namespace{
err := client.Create(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: tc.app.Namespace,
},
@@ -403,7 +408,7 @@ func TestWorkflowRestart(t *testing.T) {
cmd.SetArgs([]string{tc.app.Name})
}
}
err := cmd.Execute()
err = cmd.Execute()
if tc.expectedErr != nil {
r.Equal(tc.expectedErr, err)
return
@@ -411,7 +416,7 @@ func TestWorkflowRestart(t *testing.T) {
r.NoError(err)
wf := &v1beta1.Application{}
err = c.Client.Get(ctx, types.NamespacedName{
err = client.Get(ctx, types.NamespacedName{
Namespace: tc.app.Namespace,
Name: tc.app.Name,
}, wf)
@@ -517,13 +522,14 @@ func TestWorkflowRollback(t *testing.T) {
r := require.New(t)
cmd := NewWorkflowRollbackCommand(c, ioStream)
initCommand(cmd)
client, err := c.GetClient()
r.NoError(err)
if tc.app != nil {
err := c.Client.Create(ctx, tc.app)
err := client.Create(ctx, tc.app)
r.NoError(err)
if tc.app.Namespace != corev1.NamespaceDefault {
err := c.Client.Create(ctx, &corev1.Namespace{
err := client.Create(ctx, &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: tc.app.Namespace,
},
@@ -535,10 +541,10 @@ func TestWorkflowRollback(t *testing.T) {
}
}
if tc.revision != nil {
err := c.Client.Create(ctx, tc.revision)
err := client.Create(ctx, tc.revision)
r.NoError(err)
}
err := cmd.Execute()
err = cmd.Execute()
if tc.expectedErr != nil {
r.Equal(tc.expectedErr, err)
return
@@ -546,7 +552,7 @@ func TestWorkflowRollback(t *testing.T) {
r.NoError(err)
wf := &v1beta1.Application{}
err = c.Client.Get(ctx, types.NamespacedName{
err = client.Get(ctx, types.NamespacedName{
Namespace: tc.app.Namespace,
Name: tc.app.Name,
}, wf)
-3
View File
@@ -34,9 +34,6 @@ func NewWorkloadsCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Com
Long: "List workloads",
Example: `vela workloads`,
Hidden: true,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
namespace, err := GetFlagNamespaceOrEnv(cmd, c)
if err != nil {
+5 -1
View File
@@ -150,7 +150,11 @@ func GetTraitsFromClusterWithValidateOption(ctx context.Context, namespace strin
if err != nil {
return nil, nil, err
}
dm, err := discoverymapper.New(c.Config)
config, err := c.GetConfig()
if err != nil {
return nil, nil, err
}
dm, err := discoverymapper.New(config)
if err != nil {
return nil, nil, err
}
+10 -17
View File
@@ -19,7 +19,6 @@ package plugins
import (
"context"
"encoding/json"
"fmt"
"os"
"cuelang.org/go/cue"
@@ -30,7 +29,6 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/yaml"
corev1beta1 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
@@ -114,13 +112,13 @@ var _ = Describe("DefinitionFiles", func() {
req, _ := labels.NewRequirement("usecase", selection.Equals, []string{"forplugintest"})
selector := labels.NewSelector().Add(*req)
// Notice!! DefinitionPath Object is Cluster Scope object
// which means objects created in other DefinitionNamespace will also affect here.
It("getcomponents", func() {
workloadDefs, _, err := GetComponentsFromCluster(context.Background(), DefinitionNamespace, common.Args{Config: cfg, Schema: scheme}, selector)
arg := common.Args{}
arg.SetClient(k8sClient)
workloadDefs, _, err := GetComponentsFromCluster(context.Background(), DefinitionNamespace, arg, selector)
Expect(err).Should(BeNil())
logf.Log.Info(fmt.Sprintf("Getting component definitions %v", workloadDefs))
for i := range workloadDefs {
// CueTemplate should always be fulfilled, even those whose CueTemplateURI is assigend,
By("check CueTemplate is fulfilled")
@@ -130,9 +128,10 @@ var _ = Describe("DefinitionFiles", func() {
Expect(cmp.Diff(workloadDefs, []types.Capability{deployment, websvc})).Should(BeEquivalentTo(""))
})
It("getall", func() {
alldef, err := GetCapabilitiesFromCluster(context.Background(), DefinitionNamespace, common.Args{Config: cfg, Schema: scheme}, selector)
arg := common.Args{}
arg.SetClient(k8sClient)
alldef, err := GetCapabilitiesFromCluster(context.Background(), DefinitionNamespace, arg, selector)
Expect(err).Should(BeNil())
logf.Log.Info(fmt.Sprintf("Getting all definitions %v", alldef))
for i := range alldef {
alldef[i].CueTemplate = ""
}
@@ -162,11 +161,8 @@ var _ = Describe("test GetCapabilityByName", func() {
trait3 string
)
BeforeEach(func() {
c = common.Args{
Client: k8sClient,
Config: cfg,
Schema: scheme,
}
c = common.Args{}
c.SetClient(k8sClient)
ctx = context.Background()
ns = "cluster-test-ns-suffix"
defaultNS = types.DefaultKubeVelaNS
@@ -293,11 +289,8 @@ var _ = Describe("test GetNamespacedCapabilitiesFromCluster", func() {
trait2 string
)
BeforeEach(func() {
c = common.Args{
Client: k8sClient,
Config: cfg,
Schema: scheme,
}
c = common.Args{}
c.SetClient(k8sClient)
ctx = context.Background()
ns = "cluster-test-ns"
defaultNS = types.DefaultKubeVelaNS
+1 -2
View File
@@ -49,7 +49,6 @@ import (
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
var cfg *rest.Config
var scheme *runtime.Scheme
var k8sClient client.Client
var testEnv *envtest.Environment
var definitionDir string
@@ -81,7 +80,7 @@ var _ = BeforeSuite(func(done Done) {
cfg, err = testEnv.Start()
Expect(err).ToNot(HaveOccurred())
Expect(cfg).ToNot(BeNil())
scheme = runtime.NewScheme()
scheme := runtime.NewScheme()
Expect(coreoam.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(clientgoscheme.AddToScheme(scheme)).NotTo(HaveOccurred())
Expect(v1beta1.AddToScheme(scheme)).NotTo(HaveOccurred())