mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 03:56:36 +00:00
Feat: adapt vela port-forward with the velaql (#4439)
Signed-off-by: Jianbo Sun <jianbo.sjb@alibaba-inc.com>
This commit is contained in:
@@ -40,4 +40,5 @@ WORKDIR /
|
||||
|
||||
ARG TARGETARCH
|
||||
COPY --from=builder /workspace/vela-${TARGETARCH} /vela
|
||||
COPY /vela /bin/
|
||||
ENTRYPOINT ["/vela"]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+130
-152
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+13
-14
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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) +
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user