diff --git a/pkg/velaql/providers/query/endpoint.go b/pkg/velaql/providers/query/endpoint.go index 58a5f519b..e7e2abb84 100644 --- a/pkg/velaql/providers/query/endpoint.go +++ b/pkg/velaql/providers/query/endpoint.go @@ -398,20 +398,7 @@ func selectorNodeIP(ctx context.Context, clusterName string, client client.Clien 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 { - return selectGatewayIP([]corev1.Node{*gatewayNode}) - } - return selectGatewayIP(workerNodes) + return selectGatewayIP(nodes.Items) } // judgeAppProtocol RFC-6335 and http://www.iana.org/assignments/service-names). @@ -432,11 +419,28 @@ func judgeAppProtocol(port int32) string { // selectGatewayIP will choose one gateway IP from all nodes, it will pick up external IP first. If there isn't any, it will pick the first node's internal IP. func selectGatewayIP(nodes []corev1.Node) string { - if len(nodes) == 0 { + var gatewayNode *corev1.Node + var workerNodes []corev1.Node + for i, node := range nodes { + if _, exist := node.Labels[apis.LabelNodeRoleGateway]; exist { + gatewayNode = &nodes[i] + break + } else if _, exist := node.Labels[apis.LabelNodeRoleWorker]; exist { + workerNodes = append(workerNodes, nodes[i]) + } + } + var candidates = nodes + if gatewayNode != nil { + candidates = []corev1.Node{*gatewayNode} + } else if len(workerNodes) > 0 { + candidates = workerNodes + } + + if len(candidates) == 0 { return "" } var addressMaps = make([]map[corev1.NodeAddressType]string, 0) - for _, node := range nodes { + for _, node := range candidates { var addressMap = make(map[corev1.NodeAddressType]string) for _, address := range node.Status.Addresses { addressMap[address.Type] = address.Address diff --git a/pkg/velaql/providers/query/endpoint_test.go b/pkg/velaql/providers/query/endpoint_test.go index 29d3f5dea..5a5728068 100644 --- a/pkg/velaql/providers/query/endpoint_test.go +++ b/pkg/velaql/providers/query/endpoint_test.go @@ -274,47 +274,108 @@ var _ = Describe("Test query endpoints", func() { }) It("Test select gateway IP", func() { - node1 := corev1.Node{ + masterNode := corev1.Node{ ObjectMeta: metav1.ObjectMeta{ - Name: "node-with-external-ip", + Name: "node-1", + Labels: map[string]string{ + "node-role.kubernetes.io/master": "true", + }, }, Status: corev1.NodeStatus{ Addresses: []corev1.NodeAddress{ - {Type: corev1.NodeExternalIP, Address: "node1-external-ip"}, - {Type: corev1.NodeInternalIP, Address: "node1-internal-ip"}, + { + Type: corev1.NodeInternalIP, + Address: "node1-internal-ip", + }, }, }, } - node2 := corev1.Node{ + workerNode1 := corev1.Node{ ObjectMeta: metav1.ObjectMeta{ - Name: "node-without-external-ip", + Name: "node-2", + Labels: map[string]string{ + "node-role.kubernetes.io/worker": "true", + }, }, Status: corev1.NodeStatus{ Addresses: []corev1.NodeAddress{ - {Type: corev1.NodeInternalIP, Address: "node2-internal-ip"}, + { + Type: corev1.NodeInternalIP, + Address: "node2-internal-ip", + }, + { + Type: corev1.NodeExternalIP, + Address: "node2-external-ip", + }, }, }, } - testCases := []struct { + workerNode2 := corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node-3", + Labels: map[string]string{ + "node-role.kubernetes.io/worker": "true", + }, + }, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: corev1.NodeInternalIP, + Address: "node3-internal-ip", + }, + }, + }, + } + gatewayNode := corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node-4", + Labels: map[string]string{ + "node-role.kubernetes.io/gateway": "true", + }, + }, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: corev1.NodeInternalIP, + Address: "node4-internal-ip", + }, + { + Type: corev1.NodeExternalIP, + Address: "node4-external-ip", + }, + }, + }, + } + testCase := []struct { + note string nodes []corev1.Node wantIP string }{ { - nodes: []corev1.Node{node1, node2}, - wantIP: "node1-external-ip", + note: "only master node", + nodes: []corev1.Node{masterNode}, + wantIP: "node1-internal-ip", }, { - nodes: []corev1.Node{node2}, - wantIP: "node2-internal-ip", + note: "with worker node, select external ip first", + nodes: []corev1.Node{masterNode, workerNode1}, + wantIP: "node2-external-ip", }, { - nodes: []corev1.Node{}, - wantIP: "", + note: "with worker node, select worker's internal ip", + nodes: []corev1.Node{masterNode, workerNode2}, + wantIP: "node3-internal-ip", + }, + { + note: "with gateway node, gateway node first", + nodes: []corev1.Node{masterNode, workerNode1, workerNode1, gatewayNode}, + wantIP: "node4-external-ip", }, } - for _, tc := range testCases { - gotIP := selectGatewayIP(tc.nodes) - Expect(gotIP).Should(BeEquivalentTo(tc.wantIP)) + for _, tc := range testCase { + By(tc.note) + ip := selectGatewayIP(tc.nodes) + Expect(ip).Should(Equal(tc.wantIP)) } }) }) diff --git a/pkg/velaql/providers/query/handler_test.go b/pkg/velaql/providers/query/handler_test.go index b5d50cf6f..9780aa250 100644 --- a/pkg/velaql/providers/query/handler_test.go +++ b/pkg/velaql/providers/query/handler_test.go @@ -19,7 +19,7 @@ package query import ( "context" "fmt" - "io/ioutil" + "os" "time" . "github.com/onsi/ginkgo" @@ -929,7 +929,7 @@ options: { } var objects []client.Object for _, resource := range resources { - data, err := ioutil.ReadFile(resource) + data, err := os.ReadFile(resource) Expect(err).Should(BeNil()) var route unstructured.Unstructured err = yaml.Unmarshal(data, &route) @@ -942,6 +942,46 @@ options: { Expect(err).Should(BeNil()) } + // Prepare nodes in test environment + masterNode := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node-1", + Labels: map[string]string{ + "node-role.kubernetes.io/master": "true", + }, + }, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: corev1.NodeInternalIP, + Address: "internal-ip-1", + }, + }, + }, + } + workerNode := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "node-2", + Labels: map[string]string{ + "node-role.kubernetes.io/worker": "true", + }, + }, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{ + { + Type: corev1.NodeInternalIP, + Address: "internal-ip-2", + }, + { + Type: corev1.NodeExternalIP, + Address: "external-ip-2", + }, + }, + }, + } + Expect(k8sClient.Create(ctx, masterNode)).Should(BeNil()) + Expect(k8sClient.Create(ctx, workerNode)).Should(BeNil()) + opt := `app: { name: "endpoints-app" namespace: "default" @@ -960,6 +1000,7 @@ options: { err = pr.CollectServiceEndpoints(logCtx, nil, v, nil) Expect(err).Should(BeNil()) gatewayIP := selectorNodeIP(ctx, "", k8sClient) + Expect(gatewayIP).Should(Equal("external-ip-2")) urls := []string{ "http://ingress.domain", "https://ingress.domain.https", diff --git a/references/cli/status.go b/references/cli/status.go index 3f91385c0..c070a9483 100644 --- a/references/cli/status.go +++ b/references/cli/status.go @@ -143,8 +143,18 @@ func NewAppStatusCommand(c common.Args, order string, ioStreams cmdutil.IOStream } return printAppPods(appName, namespace, f, c) } + + newClient, err := c.GetClient() + if err != nil { + return err + } + showEndpoints, err := cmd.Flags().GetBool("endpoint") if showEndpoints && err == nil { + _, err := loadRemoteApplication(newClient, namespace, appName) + if err != nil { + return err + } component, _ := cmd.Flags().GetString("component") cluster, _ := cmd.Flags().GetString("cluster") f := Filter{ @@ -153,10 +163,6 @@ func NewAppStatusCommand(c common.Args, order string, ioStreams cmdutil.IOStream } return printAppEndpoints(ctx, appName, namespace, f, c, false) } - newClient, err := c.GetClient() - if err != nil { - return err - } if outputFormat != "" { return printRawApplication(context.Background(), c, outputFormat, cmd.OutOrStdout(), namespace, appName) }