diff --git a/Dockerfile.cli b/Dockerfile.cli index 0fcd90c3d..fdbf2cb5b 100644 --- a/Dockerfile.cli +++ b/Dockerfile.cli @@ -40,4 +40,5 @@ WORKDIR / ARG TARGETARCH COPY --from=builder /workspace/vela-${TARGETARCH} /vela +COPY /vela /bin/ ENTRYPOINT ["/vela"] diff --git a/pkg/utils/common/common.go b/pkg/utils/common/common.go index 4c286595c..eab724ea0 100644 --- a/pkg/utils/common/common.go +++ b/pkg/utils/common/common.go @@ -394,8 +394,7 @@ func clusterObjectReferenceTypeFilterGenerator(allowedKinds ...string) clusterOb } var isWorkloadClusterObjectReferenceFilter = clusterObjectReferenceTypeFilterGenerator("Deployment", "StatefulSet", "CloneSet", "Job", "Configuration") -var isPortForwardEndpointClusterObjectReferenceFilter = clusterObjectReferenceTypeFilterGenerator("Deployment", - "StatefulSet", "CloneSet", "Job", "Service", "HelmRelease") + var resourceNameClusterObjectReferenceFilter = func(resourceName []string) clusterObjectReferenceFilter { return func(reference common.ClusterObjectReference) bool { if len(resourceName) == 0 { @@ -533,14 +532,6 @@ func AskToChooseOneEnvResource(app *v1beta1.Application, resourceName ...string) return askToChooseOneResource(app, filters...) } -// AskToChooseOnePortForwardEndpoint will ask user to select one applied resource as port forward endpoint -func AskToChooseOnePortForwardEndpoint(app *v1beta1.Application, resourceName ...string) (*common.ClusterObjectReference, error) { - filters := []clusterObjectReferenceFilter{isPortForwardEndpointClusterObjectReferenceFilter} - _resourceName := removeEmptyString(resourceName) - filters = append(filters, resourceNameClusterObjectReferenceFilter(_resourceName)) - return askToChooseOneResource(app, filters...) -} - func askToChooseOneInApplication(category string, options []string) (decision string, err error) { if len(options) == 0 { return "", fmt.Errorf("no %s exists in the application", category) diff --git a/pkg/velaql/providers/query/types/type.go b/pkg/velaql/providers/query/types/type.go index aaa9185b9..1d6dd52b9 100644 --- a/pkg/velaql/providers/query/types/type.go +++ b/pkg/velaql/providers/query/types/type.go @@ -47,6 +47,9 @@ type ServiceEndpoint struct { // String return endpoint URL func (s *ServiceEndpoint) String() string { + if s.Endpoint.Host == "" && s.Endpoint.Port == 0 { + return "-" + } protocol := strings.ToLower(string(s.Endpoint.Protocol)) if s.Endpoint.AppProtocol != nil && *s.Endpoint.AppProtocol != "" { protocol = *s.Endpoint.AppProtocol diff --git a/references/cli/portforward.go b/references/cli/portforward.go index 6879f9b25..bfe17c4c7 100644 --- a/references/cli/portforward.go +++ b/references/cli/portforward.go @@ -19,16 +19,15 @@ package cli import ( "context" "fmt" - "net" "net/http" "net/url" - "reflect" "strconv" "strings" + "github.com/AlecAivazis/survey/v2" + "github.com/pkg/errors" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" - types2 "k8s.io/apimachinery/pkg/types" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -39,21 +38,15 @@ import ( "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client" - common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" - "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/multicluster" "github.com/oam-dev/kubevela/pkg/utils/common" "github.com/oam-dev/kubevela/pkg/utils/util" + types2 "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" "github.com/oam-dev/kubevela/references/appfile" ) -const ( - fluxcdNameLabel = "helm.toolkit.fluxcd.io/name" - fluxcdNameSpaceLabel = "helm.toolkit.fluxcd.io/namespace" -) - // VelaPortForwardOptions for vela port-forward type VelaPortForwardOptions struct { Cmd *cobra.Command @@ -64,13 +57,12 @@ type VelaPortForwardOptions struct { VelaC common.Args Env *types.EnvMeta App *v1beta1.Application - targetResource *common2.ClusterObjectReference + targetResource *types2.ServiceEndpoint f k8scmdutil.Factory kcPortForwardOptions *cmdpf.PortForwardOptions ClientSet kubernetes.Interface Client client.Client - routeTrait bool namespace string } @@ -130,7 +122,6 @@ func NewPortForwardCommand(c common.Args, order string, ioStreams util.IOStreams cmd.Flags().Duration(podRunningTimeoutFlag, defaultPodExecTimeout, "The length of time (like 5s, 2m, or 3h, higher than zero) to wait until at least one pod is running", ) - cmd.Flags().BoolVar(&o.routeTrait, "route", false, "forward ports from route trait service") addNamespaceAndEnvArg(cmd) return cmd @@ -148,30 +139,66 @@ func (o *VelaPortForwardOptions) Init(ctx context.Context, cmd *cobra.Command, a } o.App = app - targetResource, err := common.AskToChooseOnePortForwardEndpoint(o.App) + rawEndpoints, err := GetServiceEndpoints(o.Ctx, o.App.Name, o.namespace, o.VelaC, Filter{}) + if err != nil { + return err + } + var endpoints []types2.ServiceEndpoint + for _, ep := range rawEndpoints { + if ep.Ref.Kind != "Service" { + continue + } + endpoints = append(endpoints, ep) + } + if len(endpoints) == 0 { + inSide := func(str string) bool { + for _, s := range []string{"Deployment", "StatefulSet", "CloneSet", "Job"} { + if str == s { + return true + } + } + return false + } + for _, ap := range app.Status.AppliedResources { + if !inSide(ap.Kind) { + continue + } + endpoints = append(endpoints, types2.ServiceEndpoint{ + Endpoint: types2.Endpoint{}, + Ref: corev1.ObjectReference{ + Namespace: ap.Namespace, + Name: ap.Name, + Kind: ap.Kind, + APIVersion: ap.APIVersion, + }, + Cluster: ap.Cluster, + }) + } + } + targetResource, err := AskToChooseOnePortForwardEndpoint(endpoints) if err != nil { return err } cf := genericclioptions.NewConfigFlags(true) - cf.Namespace = pointer.String(targetResource.Namespace) + cf.Namespace = pointer.String(o.namespace) cf.WrapConfigFn = func(cfg *rest.Config) *rest.Config { cfg.Wrap(multicluster.NewClusterGatewayRoundTripperWrapperGenerator(targetResource.Cluster)) return cfg } o.f = k8scmdutil.NewFactory(k8scmdutil.NewMatchVersionFlags(cf)) - o.targetResource = targetResource + o.targetResource = &targetResource o.Ctx = multicluster.ContextWithClusterName(ctx, targetResource.Cluster) config, err := o.VelaC.GetConfig() if err != nil { return err } config.Wrap(multicluster.NewSecretModeMultiClusterRoundTripper) - client, err := client.New(config, client.Options{Scheme: common.Scheme}) + forwardClient, err := client.New(config, client.Options{Scheme: common.Scheme}) if err != nil { return err } - o.VelaC.SetClient(client) + o.VelaC.SetClient(forwardClient) if o.ClientSet == nil { c, err := kubernetes.NewForConfig(config) if err != nil { @@ -182,160 +209,79 @@ func (o *VelaPortForwardOptions) Init(ctx context.Context, cmd *cobra.Command, a return nil } -func getRouteServiceName(appconfig *v1alpha2.ApplicationConfiguration, svcName string) string { - for _, comp := range appconfig.Status.Workloads { - if comp.ComponentName != svcName { - continue +// getPortsFromApp works for compatible +func getPortsFromApp(app *v1beta1.Application) int { + if app == nil || len(app.Spec.Components) == 0 { + return 0 + } + _, configs := appfile.GetApplicationSettings(app, app.Spec.Components[0].Name) + for k, v := range configs { + portConv := func(v interface{}) int { + switch pv := v.(type) { + case int: + return pv + case string: + data, err := strconv.ParseInt(pv, 10, 64) + if err != nil { + return 0 + } + return int(data) + case float64: + return int(pv) + } + return 0 } - for _, tr := range comp.Traits { - // TODO check from Capability - if tr.Reference.Kind == "Route" && tr.Reference.APIVersion == "standard.oam.dev/v1alpha1" { - return tr.Reference.Name + if k == "port" { + return portConv(v) + } + if k == "ports" { + portArray := v.([]interface{}) + for _, p := range portArray { + return portConv(p.(map[string]interface{})["port"]) } } } - return "" -} - -func getSvcNameAndPortFromHelmRelease(ctx context.Context, cli client.Client, o common2.ClusterObjectReference) (string, string, error) { - svcList := corev1.ServiceList{} - if err := cli.List(ctx, &svcList, client.InNamespace(o.Namespace), client.MatchingLabels{ - fluxcdNameLabel: o.Name, - fluxcdNameSpaceLabel: o.Namespace, - }); err != nil { - return "", "", err - } - for _, svc := range svcList.Items { - if strings.HasPrefix(svc.Name, o.Name) { - // avoid panic - if len(svc.Spec.Ports) == 0 { - continue - } - port := svc.Spec.Ports[0].Port - return svc.Name, strconv.Itoa(int(port)), nil - } - } - return "", "", fmt.Errorf("have not found svc from helmRelease: %s", o.Name) + return 0 } // Complete will complete the config of port-forward func (o *VelaPortForwardOptions) Complete() error { - client, err := o.VelaC.GetClient() - if err != nil { - return err - } - compName, err := getCompNameFromClusterObjectReference(o.Ctx, client, o.targetResource) - if err != nil { - return err - } - if compName == "" { - return fmt.Errorf("failed to get component name") - } - if o.routeTrait { - appconfig, err := appfile.GetAppConfig(o.Ctx, client, o.App, o.Env) + + var forwardTypeName string + switch o.targetResource.Ref.Kind { + case "Service": + forwardTypeName = "svc/" + o.targetResource.Ref.Name + case "Deployment", "StatefulSet", "CloneSet", "Job": + var err error + forwardTypeName, err = getPodNameForResource(o.Ctx, o.ClientSet, o.targetResource.Ref.Name, o.targetResource.Ref.Namespace) if err != nil { return err } - routeSvc := getRouteServiceName(appconfig, compName) - if routeSvc == "" { - return fmt.Errorf("no route trait found in %s %s", o.App.Name, compName) - } - var svc = corev1.Service{} - err = client.Get(o.Ctx, types2.NamespacedName{Name: routeSvc, Namespace: o.Env.Namespace}, &svc) - if err != nil { - return err - } - if len(svc.Spec.Ports) == 0 { - return fmt.Errorf("no port found in service %s", routeSvc) - } - val := strconv.Itoa(int(svc.Spec.Ports[0].Port)) - if val == "80" { - val = "8080:80" - } else if val == "443" { - val = "8443:443" - } - o.Args = append(o.Args, val) - args := make([]string, len(o.Args)) - copy(args, o.Args) - args[0] = "svc/" + routeSvc - return o.kcPortForwardOptions.Complete(o.f, o.Cmd, args) } - if o.targetResource.Kind == "HelmRelease" { - svcName, port, err := getSvcNameAndPortFromHelmRelease(o.Ctx, o.Client, *o.targetResource) - if err != nil { - return err - } - var val string - switch port { - case "80": - val = "8080:80" - case "443": - val = "8443:443" - default: - val = net.JoinHostPort(port, port) - } - o.Args[0] = fmt.Sprintf("svc/%s", svcName) - o.Args = append(o.Args, val) - return o.kcPortForwardOptions.Complete(o.f, o.Cmd, o.Args) - } - - var podName string - if o.targetResource.Kind == "Service" { - podName = "svc/" + o.targetResource.Name - } else { - podName, err = getPodNameForResource(o.Ctx, o.ClientSet, o.targetResource.Name, o.targetResource.Namespace) - if err != nil { - return err - } - } if len(o.Args) < 2 { - var found bool - _, configs := appfile.GetApplicationSettings(o.App, compName) - for k, v := range configs { - portConv := func(o *VelaPortForwardOptions, v interface{}, k string) (bool, error) { - var val string - switch pv := v.(type) { - case int: - val = strconv.Itoa(pv) - case string: - val = pv - case float64: - val = strconv.Itoa(int(pv)) - default: - return false, fmt.Errorf("invalid type '%s' of port %v", reflect.TypeOf(v), k) - } - if val == "80" { - val = "8080:80" - } else if val == "443" { - val = "8443:443" - } - o.Args = append(o.Args, val) - return true, nil - } - if k == "port" { - found, err = portConv(o, v, k) - if err != nil { - return err - } - } - if k == "ports" { - portArray := v.([]interface{}) - for _, p := range portArray { - found, err = portConv(o, p.(map[string]interface{})["port"], k) - if err != nil { - return err - } - } + formatPort := func(p int) string { + val := strconv.Itoa(p) + if val == "80" { + val = "8080:80" + } else if val == "443" { + val = "8443:443" } + return val } - if !found { - return fmt.Errorf("no port found in app or arguments") + pt := o.targetResource.Endpoint.Port + if pt == 0 { + pt = getPortsFromApp(o.App) } + if pt == 0 { + return errors.New("not port specified for port-forward") + } + o.Args = append(o.Args, formatPort(pt)) } args := make([]string, len(o.Args)) copy(args, o.Args) - args[0] = podName + args[0] = forwardTypeName + o.ioStreams.Infof("trying to connect the remote endpoint %s ..", strings.Join(args, " ")) return o.kcPortForwardOptions.Complete(o.f, o.Cmd, args) } @@ -378,3 +324,35 @@ func (f *defaultPortForwarder) ForwardPorts(method string, url *url.URL, opts cm } return fw.ForwardPorts() } + +// AskToChooseOnePortForwardEndpoint will ask user to select one applied resource as port forward endpoint +func AskToChooseOnePortForwardEndpoint(endpoints []types2.ServiceEndpoint) (types2.ServiceEndpoint, error) { + if len(endpoints) == 0 { + return types2.ServiceEndpoint{}, errors.New("no endpoint found in your application") + } + if len(endpoints) == 1 { + return endpoints[0], nil + } + lines := formatEndpoints(endpoints) + header := strings.Join(lines[0], " | ") + var ops []string + for i := 1; i < len(lines); i++ { + ops = append(ops, strings.Join(lines[i], " | ")) + } + prompt := &survey.Select{ + Message: fmt.Sprintf("You have %d endpoints in your app. Please choose one:\n%s", len(ops), header), + Options: ops, + } + var selectedRsc string + err := survey.AskOne(prompt, &selectedRsc) + if err != nil { + return types2.ServiceEndpoint{}, fmt.Errorf("choosing endpoint err %w", err) + } + for k, resource := range ops { + if selectedRsc == resource { + return endpoints[k], nil + } + } + // it should never happen. + return types2.ServiceEndpoint{}, errors.New("no endpoint match for your choice") +} diff --git a/references/cli/status.go b/references/cli/status.go index a5bdd2c85..7509e0a07 100644 --- a/references/cli/status.go +++ b/references/cli/status.go @@ -45,6 +45,7 @@ import ( "github.com/oam-dev/kubevela/pkg/resourcetracker" "github.com/oam-dev/kubevela/pkg/utils/common" cmdutil "github.com/oam-dev/kubevela/pkg/utils/util" + types2 "github.com/oam-dev/kubevela/pkg/velaql/providers/query/types" "github.com/oam-dev/kubevela/references/appfile" ) @@ -179,6 +180,22 @@ func printAppStatus(_ context.Context, c client.Client, ioStreams cmdutil.IOStre return loopCheckStatus(c, ioStreams, appName, namespace) } +func formatEndpoints(endpoints []types2.ServiceEndpoint) [][]string { + var result [][]string + result = append(result, []string{"Cluster", "Component", "Ref(Kind/Namespace/Name)", "Endpoint", "Inner"}) + + for _, endpoint := range endpoints { + if endpoint.Cluster == "" { + endpoint.Cluster = multicluster.ClusterLocalName + } + if endpoint.Component == "" { + endpoint.Component = "-" + } + result = append(result, []string{endpoint.Cluster, endpoint.Component, fmt.Sprintf("%s/%s/%s", endpoint.Ref.Kind, endpoint.Ref.Namespace, endpoint.Ref.Name), endpoint.String(), fmt.Sprintf("%v", endpoint.Endpoint.Inner)}) + } + return result +} + func printAppEndpoints(ctx context.Context, appName string, namespace string, f Filter, velaC common.Args, skipEmptyTable bool) error { config, err := velaC.GetConfig() if err != nil { @@ -188,7 +205,8 @@ func printAppEndpoints(ctx context.Context, appName string, namespace string, f if err != nil { return err } - endpoints, err := GetServiceEndpoints(ctx, client, appName, namespace, velaC, f) + velaC.SetClient(client) + endpoints, err := GetServiceEndpoints(ctx, appName, namespace, velaC, f) if err != nil { return err } @@ -198,12 +216,11 @@ func printAppEndpoints(ctx context.Context, appName string, namespace string, f fmt.Printf("Please access %s from the following endpoints:\n", appName) table := tablewriter.NewWriter(os.Stdout) table.SetColWidth(100) - table.SetHeader([]string{"Cluster", "Component", "Ref(Kind/Namespace/Name)", "Endpoint", "Inner"}) - for _, endpoint := range endpoints { - if endpoint.Cluster == "" { - endpoint.Cluster = multicluster.ClusterLocalName - } - table.Append([]string{endpoint.Cluster, endpoint.Component, fmt.Sprintf("%s/%s/%s", endpoint.Ref.Kind, endpoint.Ref.Namespace, endpoint.Ref.Name), endpoint.String(), fmt.Sprintf("%v", endpoint.Endpoint.Inner)}) + + printablePoints := formatEndpoints(endpoints) + table.SetHeader(printablePoints[0]) + for i := 1; i < len(printablePoints); i++ { + table.Append(printablePoints[i]) } table.Render() return nil diff --git a/references/cli/utils.go b/references/cli/utils.go index f9bfc6316..3e22bcd93 100644 --- a/references/cli/utils.go +++ b/references/cli/utils.go @@ -29,17 +29,12 @@ import ( "github.com/pkg/errors" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" "k8s.io/client-go/util/jsonpath" "k8s.io/kubectl/pkg/cmd/get" - "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/yaml" - common2 "github.com/oam-dev/kubevela/apis/core.oam.dev/common" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1" - "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/utils/common" ) @@ -60,24 +55,6 @@ func getPodNameForResource(ctx context.Context, clientSet kubernetes.Interface, return common.AskToChooseOnePods(pods) } -func getCompNameFromClusterObjectReference(ctx context.Context, k8sClient client.Client, r *common2.ClusterObjectReference) (string, error) { - u := &unstructured.Unstructured{} - u.SetGroupVersionKind(r.GroupVersionKind()) - if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: r.Namespace, Name: r.Name}, u); err != nil { - return "", err - } - labels := u.GetLabels() - if labels == nil { - return "", nil - } - // Addon observability --> some Helm typed components --> some fluxcd objects --> some services. Those services - // are not labeled with oam.LabelAppComponent - if r.Name == common.AddonObservabilityGrafanaSvc { - return r.Name, nil - } - return labels[oam.LabelAppComponent], nil -} - // UserInput user input in command type UserInput struct { Writer io.Writer diff --git a/references/cli/velaql.go b/references/cli/velaql.go index 8f20cef92..5ab211ead 100644 --- a/references/cli/velaql.go +++ b/references/cli/velaql.go @@ -25,7 +25,6 @@ import ( "strings" "github.com/spf13/cobra" - "sigs.k8s.io/controller-runtime/pkg/client" "github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/pkg/cue/model/value" @@ -91,19 +90,15 @@ export: "status" if cueFile == "" && querySts == "" && len(args) == 0 { return fmt.Errorf("please specify at least one VelaQL statement or VelaQL file path") } - newClient, err := c.GetClient() - if err != nil { - return err - } if cueFile != "" { - return queryFromView(ctx, newClient, c, cueFile, cmd) + return queryFromView(ctx, c, cueFile, cmd) } if querySts == "" { // for compatibility querySts = args[0] } - return queryFromStatement(ctx, newClient, c, querySts, cmd) + return queryFromStatement(ctx, c, querySts, cmd) }, Annotations: map[string]string{ types.TagCommandOrder: order, @@ -202,12 +197,12 @@ If view name cannot be inferred, or you are reading from stdin (-f -), you must } // queryFromStatement print velaQL result from query statement with inner query view -func queryFromStatement(ctx context.Context, client client.Client, velaC common.Args, velaQLStatement string, cmd *cobra.Command) error { +func queryFromStatement(ctx context.Context, velaC common.Args, velaQLStatement string, cmd *cobra.Command) error { queryView, err := velaql.ParseVelaQL(velaQLStatement) if err != nil { return err } - queryValue, err := QueryValue(ctx, client, velaC, &queryView) + queryValue, err := QueryValue(ctx, velaC, &queryView) if err != nil { return err } @@ -215,12 +210,12 @@ func queryFromStatement(ctx context.Context, client client.Client, velaC common. } // queryFromView print velaQL result from query view -func queryFromView(ctx context.Context, client client.Client, velaC common.Args, velaQLViewPath string, cmd *cobra.Command) error { +func queryFromView(ctx context.Context, velaC common.Args, velaQLViewPath string, cmd *cobra.Command) error { queryView, err := velaql.ParseVelaQLFromPath(velaQLViewPath) if err != nil { return err } - queryValue, err := QueryValue(ctx, client, velaC, queryView) + queryValue, err := QueryValue(ctx, velaC, queryView) if err != nil { return err } @@ -255,7 +250,7 @@ func MakeVelaQL(view string, params map[string]string, action string) string { } // GetServiceEndpoints get service endpoints by velaQL -func GetServiceEndpoints(ctx context.Context, client client.Client, appName string, namespace string, velaC common.Args, f Filter) ([]querytypes.ServiceEndpoint, error) { +func GetServiceEndpoints(ctx context.Context, appName string, namespace string, velaC common.Args, f Filter) ([]querytypes.ServiceEndpoint, error) { params := map[string]string{ "appName": appName, "appNs": namespace, @@ -273,7 +268,7 @@ func GetServiceEndpoints(ctx context.Context, client client.Client, appName stri if err != nil { return nil, err } - queryValue, err := QueryValue(ctx, client, velaC, &queryView) + queryValue, err := QueryValue(ctx, velaC, &queryView) if err != nil { return nil, err } @@ -291,7 +286,7 @@ func GetServiceEndpoints(ctx context.Context, client client.Client, appName stri } // QueryValue get queryValue from velaQL -func QueryValue(ctx context.Context, client client.Client, velaC common.Args, queryView *velaql.QueryView) (*value.Value, error) { +func QueryValue(ctx context.Context, velaC common.Args, queryView *velaql.QueryView) (*value.Value, error) { dm, err := velaC.GetDiscoveryMapper() if err != nil { return nil, err @@ -304,6 +299,10 @@ func QueryValue(ctx context.Context, client client.Client, velaC common.Args, qu if err != nil { return nil, err } + client, err := velaC.GetClient() + if err != nil { + return nil, err + } queryValue, err := velaql.NewViewHandler(client, config, dm, pd).QueryView(ctx, *queryView) if err != nil { return nil, err diff --git a/references/cli/velaql_test.go b/references/cli/velaql_test.go index a409f89ba..745a65103 100644 --- a/references/cli/velaql_test.go +++ b/references/cli/velaql_test.go @@ -77,7 +77,7 @@ export: "status" cmd := NewCommand() var buff = bytes.NewBufferString("") cmd.SetOut(buff) - Expect(queryFromView(context.TODO(), k8sClient, arg, name, cmd)).Should(BeNil()) + Expect(queryFromView(context.TODO(), arg, name, cmd)).Should(BeNil()) Expect(strings.TrimSpace(buff.String())).Should(BeEquivalentTo("my-value")) }) }) @@ -428,7 +428,7 @@ var _ = Describe("Test velaQL", func() { Expect(err).Should(BeNil()) err = k8sClient.Create(context.Background(), &cm) Expect(err).Should(BeNil()) - endpoints, err := GetServiceEndpoints(context.TODO(), k8sClient, appName, namespace, arg, Filter{}) + endpoints, err := GetServiceEndpoints(context.TODO(), appName, namespace, arg, Filter{}) Expect(err).Should(BeNil()) urls := []string{ "http://ingress.domain", diff --git a/references/common/application.go b/references/common/application.go index 4e5ef873e..450765677 100644 --- a/references/common/application.go +++ b/references/common/application.go @@ -421,6 +421,9 @@ func (o *AppfileOptions) apply(app *corev1beta1.Application, scopes []oam.Object func Info(app *corev1beta1.Application) string { yellow := color.New(color.FgYellow) appName := app.Name + if app.Namespace != "" && app.Namespace != "default" { + appName += " -n " + app.Namespace + } var appUpMessage = "✅ App has been deployed 🚀🚀🚀\n" + " Port forward: " + yellow.Sprintf("vela port-forward %s\n", appName) + " SSH: " + yellow.Sprintf("vela exec %s\n", appName) + diff --git a/references/docgen/def-doc/trait/service-account.eg.md b/references/docgen/def-doc/trait/service-account.eg.md new file mode 100644 index 000000000..927a38f29 --- /dev/null +++ b/references/docgen/def-doc/trait/service-account.eg.md @@ -0,0 +1,21 @@ +```yaml +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: vela-doc + namespace: vela-system +spec: + components: + - name: frontend + type: webservice + properties: + image: oamdev/vela-cli:v1.5.0-beta.1 + cmd: ["/vela","show"] + ports: + - port: 18081 + expose: true + traits: + - type: service-account + properties: + name: kubevela-vela-core +``` \ No newline at end of file diff --git a/references/docgen/parser.go b/references/docgen/parser.go index ffb1c124a..b72904ec5 100644 --- a/references/docgen/parser.go +++ b/references/docgen/parser.go @@ -302,7 +302,7 @@ func extractTypeFromError(paraValue cue.Value) string { } str = err.Error() sll := strings.Split(str, "cannot use value (") - if len(sll) < 1 { + if len(sll) < 2 { return str } str = sll[1]