From 6717497662a77a8137cd72c525b6d11105419a08 Mon Sep 17 00:00:00 2001 From: shawnh2 Date: Sun, 17 Mar 2024 20:41:48 +0800 Subject: [PATCH 1/3] add xRoute and xPolicy support for egctl x status Signed-off-by: shawnh2 --- ...{envoy_dashboard.go => dashboard_envoy.go} | 0 .../egctl/{envoy_stats.go => stats_envoy.go} | 0 internal/cmd/egctl/status.go | 262 +++++++----- internal/cmd/egctl/status_test.go | 379 +++++++++++++++--- internal/gatewayapi/translator.go | 34 +- .../en/latest/user/operations/egctl.md | 35 +- 6 files changed, 525 insertions(+), 185 deletions(-) rename internal/cmd/egctl/{envoy_dashboard.go => dashboard_envoy.go} (100%) rename internal/cmd/egctl/{envoy_stats.go => stats_envoy.go} (100%) diff --git a/internal/cmd/egctl/envoy_dashboard.go b/internal/cmd/egctl/dashboard_envoy.go similarity index 100% rename from internal/cmd/egctl/envoy_dashboard.go rename to internal/cmd/egctl/dashboard_envoy.go diff --git a/internal/cmd/egctl/envoy_stats.go b/internal/cmd/egctl/stats_envoy.go similarity index 100% rename from internal/cmd/egctl/envoy_stats.go rename to internal/cmd/egctl/stats_envoy.go diff --git a/internal/cmd/egctl/status.go b/internal/cmd/egctl/status.go index 3a23b36afe4..d201bf35c27 100644 --- a/internal/cmd/egctl/status.go +++ b/internal/cmd/egctl/status.go @@ -22,13 +22,28 @@ import ( gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/gatewayapi" ) -// supportedTypes list all the resource types that status command supports. -var supportedTypes = []string{ - "GatewayClass", "Gateway", "HTTPRoute", "GRPCRoute", - "TLSRoute", "TCPRoute", "UDPRoute", "BackendTLSPolicy", - "BackendTrafficPolicy", "ClientTrafficPolicy", "EnvoyPatchPolicy", "SecurityPolicy", +var ( + supportedXRouteTypes = []string{ + gatewayapi.KindHTTPRoute, gatewayapi.KindGRPCRoute, gatewayapi.KindTCPRoute, + gatewayapi.KindUDPRoute, gatewayapi.KindTLSRoute, + } + + supportedXPolicyTypes = []string{ + gatewayapi.KindBackendTLSPolicy, gatewayapi.KindBackendTrafficPolicy, gatewayapi.KindClientTrafficPolicy, + gatewayapi.KindSecurityPolicy, gatewayapi.KindEnvoyPatchPolicy, + } + + supportedAllTypes = []string{ + gatewayapi.KindGatewayClass, gatewayapi.KindGateway, + } +) + +func init() { + supportedAllTypes = append(supportedAllTypes, supportedXRouteTypes...) + supportedAllTypes = append(supportedAllTypes, supportedXPolicyTypes...) } func newStatusCommand() *cobra.Command { @@ -52,8 +67,8 @@ func newStatusCommand() *cobra.Command { # Show the status of httproute resources with details under a specific namespace. egctl x status httproute -v -n foobar - # Show the status of httproute resources under all namespaces. - egctl x status httproute -A + # Show the status of all route resources under all namespaces. + egctl x status xroute -A # Show the status of all resources under all namespaces. egctl x status all -A @@ -74,14 +89,29 @@ func newStatusCommand() *cobra.Command { return fmt.Errorf("invalid args: must specific a resources type") } - if resourceType == "all" { - for _, rt := range supportedTypes { + switch strings.ToLower(resourceType) { + case "all": + for _, rt := range supportedAllTypes { + if err = runStatus(ctx, k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil { + return err + } + } + return nil + case "xroute": + for _, rt := range supportedXRouteTypes { + if err = runStatus(ctx, k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil { + return err + } + } + return nil + case "xpolicy": + for _, rt := range supportedXPolicyTypes { if err = runStatus(ctx, k8sClient, rt, namespace, quiet, verbose, allNamespaces, true, true); err != nil { return err } } return nil - } else { + default: return runStatus(ctx, k8sClient, resourceType, namespace, quiet, verbose, allNamespaces, false, false) } }, @@ -99,17 +129,18 @@ func newStatusTableWriter(out io.Writer) *tabwriter.Writer { return tabwriter.NewWriter(out, 10, 0, 3, ' ', 0) } -func writeStatusTable(table *tabwriter.Writer, headers []string, bodies [][]string) { - fmt.Fprintln(table, strings.Join(headers, "\t")) - for _, body := range bodies { - fmt.Fprintln(table, strings.Join(body, "\t")) +func writeStatusTable(table *tabwriter.Writer, header []string, body [][]string) { + fmt.Fprintln(table, strings.Join(header, "\t")) + for _, b := range body { + fmt.Fprintln(table, strings.Join(b, "\t")) } } // runStatus find and write the summary table of status for a specific resource type. -func runStatus(ctx context.Context, cli client.Client, resourceType, namespace string, quiet, verbose, allNamespaces, ignoreEmpty, typedName bool) error { +func runStatus(ctx context.Context, cli client.Client, inputResourceType, namespace string, quiet, verbose, allNamespaces, ignoreEmpty, typedName bool) error { var ( resourcesList client.ObjectList + resourceKind string table = newStatusTableWriter(os.Stdout) ) @@ -117,13 +148,14 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s namespace = "" } - switch strings.ToLower(resourceType) { + switch strings.ToLower(inputResourceType) { case "gc", "gatewayclass": gc := gwv1.GatewayClassList{} if err := cli.List(ctx, &gc, client.InNamespace(namespace)); err != nil { return err } resourcesList = &gc + resourceKind = gatewayapi.KindGatewayClass case "gtw", "gateway": gtw := gwv1.GatewayList{} @@ -131,6 +163,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = >w + resourceKind = gatewayapi.KindGateway case "httproute": httproute := gwv1.HTTPRouteList{} @@ -138,6 +171,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &httproute + resourceKind = gatewayapi.KindHTTPRoute case "grpcroute": grpcroute := gwv1a2.GRPCRouteList{} @@ -145,6 +179,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &grpcroute + resourceKind = gatewayapi.KindGRPCRoute case "tcproute": tcproute := gwv1a2.TCPRouteList{} @@ -152,6 +187,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &tcproute + resourceKind = gatewayapi.KindTCPRoute case "udproute": udproute := gwv1a2.UDPRouteList{} @@ -159,6 +195,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &udproute + resourceKind = gatewayapi.KindUDPRoute case "tlsroute": tlsroute := gwv1a2.TLSRouteList{} @@ -166,6 +203,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &tlsroute + resourceKind = gatewayapi.KindTLSRoute case "btlspolicy", "backendtlspolicy": btlspolicy := gwv1a2.BackendTLSPolicyList{} @@ -173,6 +211,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &btlspolicy + resourceKind = gatewayapi.KindBackendTLSPolicy case "btp", "backendtrafficpolicy": btp := egv1a1.BackendTrafficPolicyList{} @@ -180,6 +219,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &btp + resourceKind = gatewayapi.KindBackendTrafficPolicy case "ctp", "clienttrafficpolicy": ctp := egv1a1.ClientTrafficPolicyList{} @@ -187,6 +227,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &ctp + resourceKind = gatewayapi.KindClientTrafficPolicy case "epp", "envoypatchpolicy": epp := egv1a1.EnvoyPatchPolicyList{} @@ -194,6 +235,7 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &epp + resourceKind = gatewayapi.KindEnvoyPatchPolicy case "sp", "securitypolicy": sp := egv1a1.SecurityPolicyList{} @@ -201,9 +243,11 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return err } resourcesList = &sp + resourceKind = gatewayapi.KindSecurityPolicy default: - return fmt.Errorf("unknown resource type: %s, supported types are: %s", resourceType, strings.Join(supportedTypes, ",")) + return fmt.Errorf("unknown input resource type: %s, supported input types are: %s", + inputResourceType, strings.Join(supportedAllTypes, ", ")) } namespaced, err := cli.IsObjectNamespaced(resourcesList) @@ -212,17 +256,14 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s } needNamespaceHeader := allNamespaces && namespaced - headers := fetchStatusHeaders(verbose, needNamespaceHeader) - bodies, err := fetchStatusBodies(resourcesList, resourceType, quiet, verbose, needNamespaceHeader, typedName) - if err != nil { - return err - } + header := fetchStatusHeader(resourceKind, verbose, needNamespaceHeader) + body := fetchStatusBody(resourcesList, resourceKind, quiet, verbose, needNamespaceHeader, typedName) - if ignoreEmpty && len(bodies) == 0 { + if ignoreEmpty && len(body) == 0 { return nil } - writeStatusTable(table, headers, bodies) + writeStatusTable(table, header, body) if err = table.Flush(); err != nil { return err } @@ -235,38 +276,64 @@ func runStatus(ctx context.Context, cli client.Client, resourceType, namespace s return nil } -func fetchStatusHeaders(verbose, needNamespace bool) []string { - headers := []string{"NAME", "TYPE", "STATUS", "REASON"} - +// extendStatusHeader extends header in the way of: +// - Insert `NAMESPACE` at first if needed +// - Append various details if verbose is on +func extendStatusHeader(header []string, verbose, needNamespace bool) []string { if needNamespace { - headers = append([]string{"NAMESPACE"}, headers...) + header = append([]string{"NAMESPACE"}, header...) } if verbose { - headers = append(headers, []string{"MESSAGE", "OBSERVED GENERATION", "LAST TRANSITION TIME"}...) + header = append(header, []string{"MESSAGE", "OBSERVED GENERATION", "LAST TRANSITION TIME"}...) } - return headers + return header } -func fetchStatusBodies(resourcesList client.ObjectList, resourceType string, quiet, verbose, needNamespace, typedName bool) ([][]string, error) { - v := reflect.ValueOf(resourcesList).Elem() +// extendStatusBodyWithNamespaceAndName extends current body with namespace and name at head. +func extendStatusBodyWithNamespaceAndName(body [][]string, namespace, name string, needNamespace bool) [][]string { + for i := 0; i < len(body); i++ { + if needNamespace { + body[i] = append([]string{namespace, name}, body[i]...) + } else { + body[i] = append([]string{name}, body[i]...) + } + // Only display once for the first row. + namespace, name = "", "" + } + return body +} - itemsField := v.FieldByName("Items") - if !itemsField.IsValid() { - return nil, fmt.Errorf("failed to load `.Items` field from %s", resourceType) +func fetchStatusHeader(resourceKind string, verbose, needNamespace bool) (header []string) { + defaultHeader := []string{"NAME", "TYPE", "STATUS", "REASON"} + xRouteHeader := []string{"NAME", "PARENT", "TYPE", "STATUS", "REASON"} + xPolicyHeader := []string{"NAME", "ANCESTOR REFERENCE", "TYPE", "STATUS", "REASON"} + + switch { + case strings.HasSuffix(resourceKind, "Route"): + return extendStatusHeader(xRouteHeader, verbose, needNamespace) + case strings.HasSuffix(resourceKind, "Policy"): + return extendStatusHeader(xPolicyHeader, verbose, needNamespace) + default: + return extendStatusHeader(defaultHeader, verbose, needNamespace) } +} + +func fetchStatusBody(resourcesList client.ObjectList, resourceKind string, quiet, verbose, needNamespace, typedName bool) (body [][]string) { + v := reflect.ValueOf(resourcesList).Elem() + itemsField := v.FieldByName("Items") - var body [][]string for i := 0; i < itemsField.Len(); i++ { - item := itemsField.Index(i) + var ( + name, namespace string + rows [][]string + item = itemsField.Index(i) + nameField = item.FieldByName("Name") + statusField = item.FieldByName("Status") + ) - // There's no need to check whether Name, Namespace and Kind field is valid, - // since all the objects in ObjectList are implemented k8s Object interface. - var name, namespace string - nameField := item.FieldByName("Name") if typedName { - kindField := item.FieldByName("Kind") - name = strings.ToLower(kindField.String()) + "/" + nameField.String() + name = strings.ToLower(resourceKind) + "/" + nameField.String() } else { name = nameField.String() } @@ -276,86 +343,71 @@ func fetchStatusBodies(resourcesList client.ObjectList, resourceType string, qui namespace = namespaceField.String() } - statusField := item.FieldByName("Status") - if !statusField.IsValid() { - return nil, fmt.Errorf("failed to find `.Items[i].Status` field from %s", resourceType) - } - - // Different resources store the conditions at different position. - switch strings.ToLower(resourceType) { - case "httproute", "grpcroute", "tlsroute", "tcproute", "udproute": - // Scrape conditions from `Resource.Status.Parents[i].Conditions` field + switch { + // For xRoute, the conditions are storing in `Resource.Status.Parents[i].Conditions`. + case strings.HasSuffix(resourceKind, "Route"): parentsField := statusField.FieldByName("Parents") - if !parentsField.IsValid() { - return nil, fmt.Errorf("failed to find `.Items[i].Status.Parents` field from %s", resourceType) - } - for j := 0; j < parentsField.Len(); j++ { parentItem := parentsField.Index(j) - rows, err := fetchConditionsField(parentItem, resourceType, name, namespace, quiet, verbose, needNamespace) - if err != nil { - return nil, err + conditions := fetchConditions(parentItem, quiet, verbose) + + // Extend conditions with parent. + parentRef := parentItem.FieldByName("ParentRef") + parentName := fmt.Sprintf("%s/%s", + parentRef.FieldByName("Kind").Elem().String(), + parentRef.FieldByName("Name").String()) + for k := 0; k < len(conditions); k++ { + conditions[k] = append([]string{parentName}, conditions[k]...) + parentName = "" } - body = append(body, rows...) + rows = append(rows, conditions...) } - case "btlspolicy", "backendtlspolicy": - // Scrape conditions from `Resource.Status.Ancestors[i].Conditions` field + // For xPolicy, the conditions are storing in `Resource.Status.Ancestors[i].Conditions`. + case strings.HasSuffix(resourceKind, "Policy"): ancestorsField := statusField.FieldByName("Ancestors") - if !ancestorsField.IsValid() { - return nil, fmt.Errorf("failed to find `.Items[i].Status.Ancestors` field from %s", resourceType) - } - for j := 0; j < ancestorsField.Len(); j++ { - ancestorItem := ancestorsField.Index(j) - rows, err := fetchConditionsField(ancestorItem, resourceType, name, namespace, quiet, verbose, needNamespace) - if err != nil { - return nil, err + policyAncestorStatus := ancestorsField.Index(j) + conditions := fetchConditions(policyAncestorStatus, quiet, verbose) + + // Extend conditions with ancestor. + ancestorRef := policyAncestorStatus.FieldByName("AncestorRef") + ancestorName := fmt.Sprintf("%s/%s", + ancestorRef.FieldByName("Kind").Elem().String(), + ancestorRef.FieldByName("Name").String()) + for k := 0; k < len(conditions); k++ { + conditions[k] = append([]string{ancestorName}, conditions[k]...) + ancestorName = "" } - body = append(body, rows...) + rows = append(rows, conditions...) } + // For others, the conditions are storing in `Resource.Status.Conditions`. default: - // Scrape conditions from `Resource.Status.Conditions` field - rows, err := fetchConditionsField(statusField, resourceType, name, namespace, quiet, verbose, needNamespace) - if err != nil { - return nil, err - } - - body = append(body, rows...) + conditions := fetchConditions(statusField, quiet, verbose) + rows = append(rows, conditions...) } - } - - return body, nil -} - -func fetchConditionsField(parent reflect.Value, resourceType, name, namespace string, quiet, verbose, needNamespace bool) ([][]string, error) { - conditionsField := parent.FieldByName("Conditions") - if !conditionsField.IsValid() { - return nil, fmt.Errorf("failed to find `Conditions` field for %s", resourceType) - } - conditions, ok := conditionsField.Interface().([]metav1.Condition) - if !ok { - return nil, fmt.Errorf("failed to convert `Conditions` field to type `[]metav1.Condition`") + rows = extendStatusBodyWithNamespaceAndName(rows, namespace, name, needNamespace) + body = append(body, rows...) } - rows := fetchConditions(conditions, name, namespace, quiet, verbose, needNamespace) - return rows, nil + return body } -func fetchConditions(conditions []metav1.Condition, name, namespace string, quiet, verbose, needNamespace bool) [][]string { +// fetchConditions fetches conditions from the `Conditions` field of parent +// by calling fetchCondition for each condition. +func fetchConditions(parent reflect.Value, quiet, verbose bool) [][]string { var rows [][]string - // Sort in descending order by time of each condition. - for i := len(conditions) - 1; i >= 0; i-- { - if i < len(conditions)-1 { - name, namespace = "", "" - } + conditionsField := parent.FieldByName("Conditions") + conditions := conditionsField.Interface().([]metav1.Condition) - row := fetchCondition(conditions[i], name, namespace, verbose, needNamespace) + // All conditions are sorted in descending order by time. + for i := len(conditions) - 1; i >= 0; i-- { + row := fetchCondition(conditions[i], verbose) rows = append(rows, row) if quiet { @@ -366,13 +418,11 @@ func fetchConditions(conditions []metav1.Condition, name, namespace string, quie return rows } -func fetchCondition(condition metav1.Condition, name, namespace string, verbose, needNamespace bool) []string { - row := []string{name, condition.Type, string(condition.Status), condition.Reason} +// fetchCondition fetches the Type, Status, Reason of one condition, and more if verbose. +func fetchCondition(condition metav1.Condition, verbose bool) []string { + row := []string{condition.Type, string(condition.Status), condition.Reason} - // Write conditions corresponding to its headers. - if needNamespace { - row = append([]string{namespace}, row...) - } + // Write more details about this condition if verbose is on. if verbose { row = append(row, []string{ condition.Message, diff --git a/internal/cmd/egctl/status_test.go b/internal/cmd/egctl/status_test.go index 9ffccabf893..9cc863138ca 100644 --- a/internal/cmd/egctl/status_test.go +++ b/internal/cmd/egctl/status_test.go @@ -15,6 +15,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" gwv1 "sigs.k8s.io/gateway-api/apis/v1" gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + + egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/gatewayapi" ) func TestWriteStatus(t *testing.T) { @@ -24,27 +27,25 @@ func TestWriteStatus(t *testing.T) { name string resourceNamespaced bool resourceList client.ObjectList - resourceType string + resourceKind string namespace string quiet bool verbose bool allNamespaces bool typedName bool outputs string - expect bool }{ { name: "egctl x status gc -v, but no resources", resourceList: &gwv1.GatewayClassList{}, resourceNamespaced: false, - resourceType: "gatewayclass", + resourceKind: gatewayapi.KindGatewayClass, quiet: false, verbose: true, allNamespaces: false, typedName: false, outputs: `NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME `, - expect: true, }, { name: "egctl x status gc", @@ -78,7 +79,7 @@ func TestWriteStatus(t *testing.T) { }, }, resourceNamespaced: false, - resourceType: "gatewayclass", + resourceKind: gatewayapi.KindGatewayClass, quiet: false, verbose: false, allNamespaces: false, @@ -87,7 +88,6 @@ func TestWriteStatus(t *testing.T) { gc foobar2 test-status-2 test reason 2 foobar1 test-status-1 test reason 1 `, - expect: true, }, { name: "egctl x status gc -v", @@ -121,7 +121,7 @@ gc foobar2 test-status-2 test reason 2 }, }, resourceNamespaced: false, - resourceType: "gatewayclass", + resourceKind: gatewayapi.KindGatewayClass, quiet: false, verbose: true, allNamespaces: false, @@ -130,7 +130,6 @@ gc foobar2 test-status-2 test reason 2 gc foobar2 test-status-2 test reason 2 test message 2 123457 2024-01-01 01:00:00 +0000 UTC foobar1 test-status-1 test reason 1 test message 1 123456 2024-01-01 00:00:00 +0000 UTC `, - expect: true, }, { name: "egctl x status gc -v -q", @@ -164,7 +163,7 @@ gc foobar2 test-status-2 test reason 2 test message 2 123457 }, }, resourceNamespaced: false, - resourceType: "gatewayclass", + resourceKind: gatewayapi.KindGatewayClass, quiet: true, verbose: true, allNamespaces: false, @@ -172,20 +171,18 @@ gc foobar2 test-status-2 test reason 2 test message 2 123457 outputs: `NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME gc foobar2 test-status-2 test reason 2 test message 2 123457 2024-01-01 01:00:00 +0000 UTC `, - expect: true, }, { name: "egctl x status gtw -v -A, no resources", resourceList: &gwv1.GatewayList{}, resourceNamespaced: true, - resourceType: "gateway", + resourceKind: gatewayapi.KindGateway, quiet: false, verbose: true, allNamespaces: true, typedName: false, outputs: `NAMESPACE NAME TYPE STATUS REASON MESSAGE OBSERVED GENERATION LAST TRANSITION TIME `, - expect: true, }, { name: "egctl x status gtw -v -A", @@ -220,7 +217,7 @@ gc foobar2 test-status-2 test reason 2 test message 2 123457 }, }, resourceNamespaced: true, - resourceType: "gateway", + resourceKind: gatewayapi.KindGateway, quiet: false, verbose: true, allNamespaces: true, @@ -229,7 +226,6 @@ gc foobar2 test-status-2 test reason 2 test message 2 123457 default gtw foobar2 test-status-2 test reason 2 test message 2 123457 2024-01-01 01:00:00 +0000 UTC foobar1 test-status-1 test reason 1 test message 1 123456 2024-01-01 00:00:00 +0000 UTC `, - expect: true, }, { name: "egctl x status gtw -v -q -A", @@ -290,7 +286,7 @@ default gtw foobar2 test-status-2 test reason 2 test message 2 }, }, resourceNamespaced: true, - resourceType: "gateway", + resourceKind: gatewayapi.KindGateway, quiet: true, verbose: true, allNamespaces: true, @@ -299,7 +295,6 @@ default gtw foobar2 test-status-2 test reason 2 test message 2 default1 gtw1 foobar2 test-status-2 test reason 2 test message 2 123457 2024-01-01 01:00:00 +0000 UTC default2 gtw2 foobar4 test-status-4 test reason 4 test message 4 123459 2024-01-01 03:00:00 +0000 UTC `, - expect: true, }, { name: "egctl x status httproute -A", @@ -314,6 +309,10 @@ default2 gtw2 foobar4 test-status-4 test reason 4 test message 4 RouteStatus: gwv1.RouteStatus{ Parents: []gwv1.RouteParentStatus{ { + ParentRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-1"), + }, Conditions: []metav1.Condition{ { Type: "foobar1", @@ -346,6 +345,10 @@ default2 gtw2 foobar4 test-status-4 test reason 4 test message 4 RouteStatus: gwv1.RouteStatus{ Parents: []gwv1.RouteParentStatus{ { + ParentRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-2"), + }, Conditions: []metav1.Condition{ { Type: "foobar3", @@ -372,18 +375,17 @@ default2 gtw2 foobar4 test-status-4 test reason 4 test message 4 }, }, resourceNamespaced: true, - resourceType: "httproute", + resourceKind: gatewayapi.KindHTTPRoute, quiet: false, verbose: false, allNamespaces: true, typedName: false, - outputs: `NAMESPACE NAME TYPE STATUS REASON -default1 http1 foobar2 test-status-2 test reason 2 - foobar1 test-status-1 test reason 1 -default2 http2 foobar4 test-status-4 test reason 4 - foobar3 test-status-3 test reason 3 + outputs: `NAMESPACE NAME PARENT TYPE STATUS REASON +default1 http1 Gateway/test-1 foobar2 test-status-2 test reason 2 + foobar1 test-status-1 test reason 1 +default2 http2 Gateway/test-2 foobar4 test-status-4 test reason 4 + foobar3 test-status-3 test reason 3 `, - expect: true, }, { name: "egctl x status httproute -q -n default1", @@ -398,6 +400,10 @@ default2 http2 foobar4 test-status-4 test reason 4 RouteStatus: gwv1.RouteStatus{ Parents: []gwv1.RouteParentStatus{ { + ParentRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-1"), + }, Conditions: []metav1.Condition{ { Type: "foobar1", @@ -430,6 +436,10 @@ default2 http2 foobar4 test-status-4 test reason 4 RouteStatus: gwv1.RouteStatus{ Parents: []gwv1.RouteParentStatus{ { + ParentRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-2"), + }, Conditions: []metav1.Condition{ { Type: "foobar3", @@ -456,17 +466,16 @@ default2 http2 foobar4 test-status-4 test reason 4 }, }, resourceNamespaced: true, - resourceType: "httproute", + resourceKind: gatewayapi.KindHTTPRoute, quiet: true, verbose: false, allNamespaces: false, typedName: false, namespace: "default1", - outputs: `NAME TYPE STATUS REASON -http1 foobar2 test-status-2 test reason 2 -http2 foobar4 test-status-4 test reason 4 + outputs: `NAME PARENT TYPE STATUS REASON +http1 Gateway/test-1 foobar2 test-status-2 test reason 2 +http2 Gateway/test-2 foobar4 test-status-4 test reason 4 `, - expect: true, }, { name: "egctl x status btlspolicy", @@ -480,6 +489,10 @@ http2 foobar4 test-status-4 test reason 4 Status: gwv1a2.PolicyStatus{ Ancestors: []gwv1a2.PolicyAncestorStatus{ { + AncestorRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test"), + }, Conditions: []metav1.Condition{ { Type: "foobar1", @@ -505,18 +518,298 @@ http2 foobar4 test-status-4 test reason 4 }, }, resourceNamespaced: true, - resourceType: "btlspolicy", + resourceKind: gatewayapi.KindBackendTLSPolicy, quiet: false, verbose: false, allNamespaces: false, typedName: false, - outputs: `NAME TYPE STATUS REASON -btls foobar2 test-status-2 test reason 2 - foobar1 test-status-1 test reason 1 + outputs: `NAME ANCESTOR REFERENCE TYPE STATUS REASON +btls Gateway/test foobar2 test-status-2 test reason 2 + foobar1 test-status-1 test reason 1 +`, + }, + { + name: "multiple httproutes with multiple parents", + resourceList: &gwv1.HTTPRouteList{ + Items: []gwv1.HTTPRoute{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "http1", + Namespace: "default1", + }, + Status: gwv1.HTTPRouteStatus{ + RouteStatus: gwv1.RouteStatus{ + Parents: []gwv1.RouteParentStatus{ + { + ParentRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-1"), + }, + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + { + ParentRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-2"), + }, + Conditions: []metav1.Condition{ + { + Type: "foobar3", + Status: metav1.ConditionStatus("test-status-3"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 3", + Message: "test message 3", + }, + { + Type: "foobar4", + Status: metav1.ConditionStatus("test-status-4"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 4", + Message: "test message 4", + }, + }, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "http2", + Namespace: "default2", + }, + Status: gwv1.HTTPRouteStatus{ + RouteStatus: gwv1.RouteStatus{ + Parents: []gwv1.RouteParentStatus{ + { + ParentRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-3"), + }, + Conditions: []metav1.Condition{ + { + Type: "foobar5", + Status: metav1.ConditionStatus("test-status-5"), + ObservedGeneration: 123458, + LastTransitionTime: metav1.NewTime(testTime.Add(2 * time.Hour)), + Reason: "test reason 5", + Message: "test message 5", + }, + { + Type: "foobar6", + Status: metav1.ConditionStatus("test-status-6"), + ObservedGeneration: 123459, + LastTransitionTime: metav1.NewTime(testTime.Add(3 * time.Hour)), + Reason: "test reason 6", + Message: "test message 6", + }, + }, + }, + { + ParentRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-4"), + }, + Conditions: []metav1.Condition{ + { + Type: "foobar7", + Status: metav1.ConditionStatus("test-status-7"), + ObservedGeneration: 123458, + LastTransitionTime: metav1.NewTime(testTime.Add(2 * time.Hour)), + Reason: "test reason 7", + Message: "test message 7", + }, + { + Type: "foobar8", + Status: metav1.ConditionStatus("test-status-8"), + ObservedGeneration: 123459, + LastTransitionTime: metav1.NewTime(testTime.Add(3 * time.Hour)), + Reason: "test reason 8", + Message: "test message 8", + }, + }, + }, + }, + }, + }, + }, + }, + }, + resourceNamespaced: true, + resourceKind: gatewayapi.KindHTTPRoute, + quiet: false, + verbose: false, + allNamespaces: true, + typedName: false, + outputs: `NAMESPACE NAME PARENT TYPE STATUS REASON +default1 http1 Gateway/test-1 foobar2 test-status-2 test reason 2 + foobar1 test-status-1 test reason 1 + Gateway/test-2 foobar4 test-status-4 test reason 4 + foobar3 test-status-3 test reason 3 +default2 http2 Gateway/test-3 foobar6 test-status-6 test reason 6 + foobar5 test-status-5 test reason 5 + Gateway/test-4 foobar8 test-status-8 test reason 8 + foobar7 test-status-7 test reason 7 +`, + }, + { + name: "multiple backendtrafficpolicy with multiple ancestors", + resourceList: &egv1a1.BackendTrafficPolicyList{ + Items: []egv1a1.BackendTrafficPolicy{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "btp-1", + Namespace: "default", + }, + Status: gwv1a2.PolicyStatus{ + Ancestors: []gwv1a2.PolicyAncestorStatus{ + { + AncestorRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-1"), + }, + Conditions: []metav1.Condition{ + { + Type: "foobar1", + Status: metav1.ConditionStatus("test-status-1"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 1", + Message: "test message 1", + }, + { + Type: "foobar2", + Status: metav1.ConditionStatus("test-status-2"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 2", + Message: "test message 2", + }, + }, + }, + { + AncestorRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindHTTPRoute), + Name: gwv1.ObjectName("test-2"), + }, + Conditions: []metav1.Condition{ + { + Type: "foobar3", + Status: metav1.ConditionStatus("test-status-3"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 3", + Message: "test message 3", + }, + { + Type: "foobar4", + Status: metav1.ConditionStatus("test-status-4"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 4", + Message: "test message 4", + }, + }, + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "btp-2", + Namespace: "default", + }, + Status: gwv1a2.PolicyStatus{ + Ancestors: []gwv1a2.PolicyAncestorStatus{ + { + AncestorRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGateway), + Name: gwv1.ObjectName("test-3"), + }, + Conditions: []metav1.Condition{ + { + Type: "foobar5", + Status: metav1.ConditionStatus("test-status-5"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 5", + Message: "test message 5", + }, + { + Type: "foobar6", + Status: metav1.ConditionStatus("test-status-6"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 6", + Message: "test message 6", + }, + }, + }, + { + AncestorRef: gwv1.ParentReference{ + Kind: gatewayapi.KindPtr(gatewayapi.KindGRPCRoute), + Name: gwv1.ObjectName("test-4"), + }, + Conditions: []metav1.Condition{ + { + Type: "foobar7", + Status: metav1.ConditionStatus("test-status-7"), + ObservedGeneration: 123456, + LastTransitionTime: metav1.NewTime(testTime), + Reason: "test reason 7", + Message: "test message 7", + }, + { + Type: "foobar8", + Status: metav1.ConditionStatus("test-status-8"), + ObservedGeneration: 123457, + LastTransitionTime: metav1.NewTime(testTime.Add(1 * time.Hour)), + Reason: "test reason 8", + Message: "test message 8", + }, + }, + }, + }, + }, + }, + }, + }, + resourceNamespaced: true, + resourceKind: gatewayapi.KindBackendTrafficPolicy, + quiet: false, + verbose: false, + allNamespaces: false, + typedName: false, + outputs: `NAME ANCESTOR REFERENCE TYPE STATUS REASON +btp-1 Gateway/test-1 foobar2 test-status-2 test reason 2 + foobar1 test-status-1 test reason 1 + HTTPRoute/test-2 foobar4 test-status-4 test reason 4 + foobar3 test-status-3 test reason 3 +btp-2 Gateway/test-3 foobar6 test-status-6 test reason 6 + foobar5 test-status-5 test reason 5 + GRPCRoute/test-4 foobar8 test-status-8 test reason 8 + foobar7 test-status-7 test reason 7 `, - expect: true, }, - // TODO(sh2): add a policy status test for egctl x status cmd } for _, tc := range testCases { @@ -525,19 +818,13 @@ btls foobar2 test-status-2 test reason 2 tab := newStatusTableWriter(&out) needNamespace := tc.allNamespaces && tc.resourceNamespaced - headers := fetchStatusHeaders(tc.verbose, needNamespace) - bodies, err := fetchStatusBodies(tc.resourceList, tc.resourceType, tc.quiet, tc.verbose, needNamespace, tc.typedName) - if tc.expect { - require.NoError(t, err) - - writeStatusTable(tab, headers, bodies) - err = tab.Flush() - require.NoError(t, err) + header := fetchStatusHeader(tc.resourceKind, tc.verbose, needNamespace) + body := fetchStatusBody(tc.resourceList, tc.resourceKind, tc.quiet, tc.verbose, needNamespace, tc.typedName) + writeStatusTable(tab, header, body) + err := tab.Flush() + require.NoError(t, err) - require.Equal(t, tc.outputs, out.String()) - } else { - require.EqualError(t, err, tc.outputs) - } + require.Equal(t, tc.outputs, out.String()) }) } } diff --git a/internal/gatewayapi/translator.go b/internal/gatewayapi/translator.go index 83a819fbd23..aaf912dae67 100644 --- a/internal/gatewayapi/translator.go +++ b/internal/gatewayapi/translator.go @@ -16,22 +16,24 @@ import ( ) const ( - KindConfigMap = "ConfigMap" - KindClientTrafficPolicy = "ClientTrafficPolicy" - KindBackendTLSPolicy = "BackendTLSPolicy" - KindEnvoyProxy = "EnvoyProxy" - KindGateway = "Gateway" - KindGatewayClass = "GatewayClass" - KindGRPCRoute = "GRPCRoute" - KindHTTPRoute = "HTTPRoute" - KindNamespace = "Namespace" - KindTLSRoute = "TLSRoute" - KindTCPRoute = "TCPRoute" - KindUDPRoute = "UDPRoute" - KindService = "Service" - KindServiceImport = "ServiceImport" - KindSecret = "Secret" - KindSecurityPolicy = "SecurityPolicy" + KindConfigMap = "ConfigMap" + KindClientTrafficPolicy = "ClientTrafficPolicy" + KindBackendTrafficPolicy = "BackendTrafficPolicy" + KindBackendTLSPolicy = "BackendTLSPolicy" + KindEnvoyPatchPolicy = "EnvoyPatchPolicy" + KindSecurityPolicy = "SecurityPolicy" + KindEnvoyProxy = "EnvoyProxy" + KindGateway = "Gateway" + KindGatewayClass = "GatewayClass" + KindGRPCRoute = "GRPCRoute" + KindHTTPRoute = "HTTPRoute" + KindNamespace = "Namespace" + KindTLSRoute = "TLSRoute" + KindTCPRoute = "TCPRoute" + KindUDPRoute = "UDPRoute" + KindService = "Service" + KindServiceImport = "ServiceImport" + KindSecret = "Secret" GroupMultiClusterService = "multicluster.x-k8s.io" // OwningGatewayNamespaceLabel is the owner reference label used for managed infra. diff --git a/site/content/en/latest/user/operations/egctl.md b/site/content/en/latest/user/operations/egctl.md index 75855ad68d9..6c4240ec3f2 100644 --- a/site/content/en/latest/user/operations/egctl.md +++ b/site/content/en/latest/user/operations/egctl.md @@ -768,9 +768,11 @@ display the latest condition, or add `--verbose` to display more details about c {{% alert title="Note" color="primary" %}} -Currently, this subcommand only supports: `GatewayClass`, `Gateway`, `HTTPRoute`, `GRPCRoute`, -`TLSRoute`, `TCPRoute`, `UDPRoute`, `BackendTLSPolicy`, -`BackendTrafficPolicy`, `ClientTrafficPolicy`, `EnvoyPatchPolicy`, `SecurityPolicy` resource types and `all`. +The resource types that this subcommand currently supports: + +- `xRoute`, `HTTPRoute`, `GRPCRoute`, `TLSRoute`, `TCPRoute`, `UDPRoute` +- `xPolicy`, `BackendTLSPolicy`, `BackendTrafficPolicy`, `ClientTrafficPolicy`, `EnvoyPatchPolicy`, `SecurityPolicy` +- `all`, `GatewayClass`, `Gateway` {{% /alert %}} @@ -801,11 +803,11 @@ marketing gateway/eg Programmed True Programmed product gateway/eg Programmed True Programmed Accepted True Accepted -NAMESPACE NAME TYPE STATUS REASON -marketing httproute/backend ResolvedRefs True ResolvedRefs - Accepted True Accepted -product httproute/backend ResolvedRefs True ResolvedRefs - Accepted True Accepted +NAMESPACE NAME PARENT TYPE STATUS REASON +marketing httproute/backend Gateway/eg ResolvedRefs True ResolvedRefs + Accepted True Accepted +product httproute/backend Gateway/eg ResolvedRefs True ResolvedRefs + Accepted True Accepted ``` - Show the summary of all the Gateways with details under all namespaces. @@ -820,7 +822,7 @@ product eg Programmed True Programmed Address assigned to th Accepted True Accepted The Gateway has been scheduled by Envoy Gateway 1 2024-02-01 17:52:42 +0800 CST ``` -- Show the summary of latest Gateways condition under `product` namespace. +- Show the summary of the latest Gateways condition under `product` namespace. ```console ~ egctl x status gateway --quiet -n product @@ -834,16 +836,11 @@ eg Programmed True Programmed ```console ~ egctl x status httproute --quiet --all-namespaces -NAMESPACE NAME TYPE STATUS REASON -marketing backend ResolvedRefs True ResolvedRefs -product backend ResolvedRefs True ResolvedRefs +NAMESPACE NAME PARENT TYPE STATUS REASON +marketing backend Gateway/eg ResolvedRefs True ResolvedRefs +product backend Gateway/eg ResolvedRefs True ResolvedRefs ``` - -[Multi-tenancy]: ../deployment-mode#multi-tenancy -[EnvoyProxy]: ../../../api/extension_types#envoyproxy - - ## egctl experimental dashboard This subcommand streamlines the process for users to access the Envoy admin dashboard. By executing the following command: @@ -860,3 +857,7 @@ http://localhost:19000 ``` the Envoy admin dashboard will automatically open in your default web browser. This eliminates the need to manually locate and expose the admin port. + + +[Multi-tenancy]: ../deployment-mode#multi-tenancy +[EnvoyProxy]: ../../../api/extension_types#envoyproxy From 4fa497f3f5b281e925683e6e676d24f4c879eafe Mon Sep 17 00:00:00 2001 From: shawnh2 Date: Tue, 23 Apr 2024 13:33:27 +0800 Subject: [PATCH 2/3] change kind name to lower case and update latest doc Signed-off-by: shawnh2 --- internal/cmd/egctl/status.go | 16 ++++++--- .../en/latest/tasks/operations/egctl.md | 27 +++++++------- .../en/v1.0.1/tasks/operations/egctl.md | 35 +++++++++---------- 3 files changed, 42 insertions(+), 36 deletions(-) diff --git a/internal/cmd/egctl/status.go b/internal/cmd/egctl/status.go index d201bf35c27..1d70dc02294 100644 --- a/internal/cmd/egctl/status.go +++ b/internal/cmd/egctl/status.go @@ -304,6 +304,10 @@ func extendStatusBodyWithNamespaceAndName(body [][]string, namespace, name strin return body } +func kindName(kind, name string) string { + return strings.ToLower(kind) + "/" + name +} + func fetchStatusHeader(resourceKind string, verbose, needNamespace bool) (header []string) { defaultHeader := []string{"NAME", "TYPE", "STATUS", "REASON"} xRouteHeader := []string{"NAME", "PARENT", "TYPE", "STATUS", "REASON"} @@ -333,7 +337,7 @@ func fetchStatusBody(resourcesList client.ObjectList, resourceKind string, quiet ) if typedName { - name = strings.ToLower(resourceKind) + "/" + nameField.String() + name = kindName(resourceKind, nameField.String()) } else { name = nameField.String() } @@ -353,9 +357,10 @@ func fetchStatusBody(resourcesList client.ObjectList, resourceKind string, quiet // Extend conditions with parent. parentRef := parentItem.FieldByName("ParentRef") - parentName := fmt.Sprintf("%s/%s", + parentName := kindName( parentRef.FieldByName("Kind").Elem().String(), - parentRef.FieldByName("Name").String()) + parentRef.FieldByName("Name").String(), + ) for k := 0; k < len(conditions); k++ { conditions[k] = append([]string{parentName}, conditions[k]...) parentName = "" @@ -373,9 +378,10 @@ func fetchStatusBody(resourcesList client.ObjectList, resourceKind string, quiet // Extend conditions with ancestor. ancestorRef := policyAncestorStatus.FieldByName("AncestorRef") - ancestorName := fmt.Sprintf("%s/%s", + ancestorName := kindName( ancestorRef.FieldByName("Kind").Elem().String(), - ancestorRef.FieldByName("Name").String()) + ancestorRef.FieldByName("Name").String(), + ) for k := 0; k < len(conditions); k++ { conditions[k] = append([]string{ancestorName}, conditions[k]...) ancestorName = "" diff --git a/site/content/en/latest/tasks/operations/egctl.md b/site/content/en/latest/tasks/operations/egctl.md index 3b25bc23456..ac1f13d7a61 100644 --- a/site/content/en/latest/tasks/operations/egctl.md +++ b/site/content/en/latest/tasks/operations/egctl.md @@ -768,9 +768,11 @@ display the latest condition, or add `--verbose` to display more details about c {{% alert title="Note" color="primary" %}} -Currently, this subcommand only supports: `GatewayClass`, `Gateway`, `HTTPRoute`, `GRPCRoute`, -`TLSRoute`, `TCPRoute`, `UDPRoute`, `BackendTLSPolicy`, -`BackendTrafficPolicy`, `ClientTrafficPolicy`, `EnvoyPatchPolicy`, `SecurityPolicy` resource types and `all`. +The resource types that this subcommand currently supports: + +- `xRoute`, `HTTPRoute`, `GRPCRoute`, `TLSRoute`, `TCPRoute`, `UDPRoute` +- `xPolicy`, `BackendTLSPolicy`, `BackendTrafficPolicy`, `ClientTrafficPolicy`, `EnvoyPatchPolicy`, `SecurityPolicy` +- `all`, `GatewayClass`, `Gateway` {{% /alert %}} @@ -801,11 +803,11 @@ marketing gateway/eg Programmed True Programmed product gateway/eg Programmed True Programmed Accepted True Accepted -NAMESPACE NAME TYPE STATUS REASON -marketing httproute/backend ResolvedRefs True ResolvedRefs - Accepted True Accepted -product httproute/backend ResolvedRefs True ResolvedRefs - Accepted True Accepted +NAMESPACE NAME PARENT TYPE STATUS REASON +marketing httproute/backend gateway/eg ResolvedRefs True ResolvedRefs + Accepted True Accepted +product httproute/backend gateway/eg ResolvedRefs True ResolvedRefs + Accepted True Accepted ``` - Show the summary of all the Gateways with details under all namespaces. @@ -820,7 +822,7 @@ product eg Programmed True Programmed Address assigned to th Accepted True Accepted The Gateway has been scheduled by Envoy Gateway 1 2024-02-01 17:52:42 +0800 CST ``` -- Show the summary of latest Gateways condition under `product` namespace. +- Show the summary of the latest Gateways condition under `product` namespace. ```console ~ egctl x status gateway --quiet -n product @@ -834,12 +836,11 @@ eg Programmed True Programmed ```console ~ egctl x status httproute --quiet --all-namespaces -NAMESPACE NAME TYPE STATUS REASON -marketing backend ResolvedRefs True ResolvedRefs -product backend ResolvedRefs True ResolvedRefs +NAMESPACE NAME PARENT TYPE STATUS REASON +marketing backend gateway/eg ResolvedRefs True ResolvedRefs +product backend gateway/eg ResolvedRefs True ResolvedRefs ``` - [Multi-tenancy]: ../deployment-mode#multi-tenancy [EnvoyProxy]: ../../../api/extension_types#envoyproxy diff --git a/site/content/en/v1.0.1/tasks/operations/egctl.md b/site/content/en/v1.0.1/tasks/operations/egctl.md index 6c4240ec3f2..84c2c51f1c5 100644 --- a/site/content/en/v1.0.1/tasks/operations/egctl.md +++ b/site/content/en/v1.0.1/tasks/operations/egctl.md @@ -768,11 +768,9 @@ display the latest condition, or add `--verbose` to display more details about c {{% alert title="Note" color="primary" %}} -The resource types that this subcommand currently supports: - -- `xRoute`, `HTTPRoute`, `GRPCRoute`, `TLSRoute`, `TCPRoute`, `UDPRoute` -- `xPolicy`, `BackendTLSPolicy`, `BackendTrafficPolicy`, `ClientTrafficPolicy`, `EnvoyPatchPolicy`, `SecurityPolicy` -- `all`, `GatewayClass`, `Gateway` +Currently, this subcommand only supports: `GatewayClass`, `Gateway`, `HTTPRoute`, `GRPCRoute`, +`TLSRoute`, `TCPRoute`, `UDPRoute`, `BackendTLSPolicy`, +`BackendTrafficPolicy`, `ClientTrafficPolicy`, `EnvoyPatchPolicy`, `SecurityPolicy` resource types and `all`. {{% /alert %}} @@ -803,11 +801,11 @@ marketing gateway/eg Programmed True Programmed product gateway/eg Programmed True Programmed Accepted True Accepted -NAMESPACE NAME PARENT TYPE STATUS REASON -marketing httproute/backend Gateway/eg ResolvedRefs True ResolvedRefs - Accepted True Accepted -product httproute/backend Gateway/eg ResolvedRefs True ResolvedRefs - Accepted True Accepted +NAMESPACE NAME TYPE STATUS REASON +marketing httproute/backend ResolvedRefs True ResolvedRefs + Accepted True Accepted +product httproute/backend ResolvedRefs True ResolvedRefs + Accepted True Accepted ``` - Show the summary of all the Gateways with details under all namespaces. @@ -822,7 +820,7 @@ product eg Programmed True Programmed Address assigned to th Accepted True Accepted The Gateway has been scheduled by Envoy Gateway 1 2024-02-01 17:52:42 +0800 CST ``` -- Show the summary of the latest Gateways condition under `product` namespace. +- Show the summary of latest Gateways condition under `product` namespace. ```console ~ egctl x status gateway --quiet -n product @@ -836,11 +834,16 @@ eg Programmed True Programmed ```console ~ egctl x status httproute --quiet --all-namespaces -NAMESPACE NAME PARENT TYPE STATUS REASON -marketing backend Gateway/eg ResolvedRefs True ResolvedRefs -product backend Gateway/eg ResolvedRefs True ResolvedRefs +NAMESPACE NAME TYPE STATUS REASON +marketing backend ResolvedRefs True ResolvedRefs +product backend ResolvedRefs True ResolvedRefs ``` + +[Multi-tenancy]: ../deployment-mode#multi-tenancy +[EnvoyProxy]: ../../../api/extension_types#envoyproxy + + ## egctl experimental dashboard This subcommand streamlines the process for users to access the Envoy admin dashboard. By executing the following command: @@ -857,7 +860,3 @@ http://localhost:19000 ``` the Envoy admin dashboard will automatically open in your default web browser. This eliminates the need to manually locate and expose the admin port. - - -[Multi-tenancy]: ../deployment-mode#multi-tenancy -[EnvoyProxy]: ../../../api/extension_types#envoyproxy From 511884bb8a0b2c478397e8400c840d1d0da07d43 Mon Sep 17 00:00:00 2001 From: shawnh2 Date: Tue, 23 Apr 2024 13:39:22 +0800 Subject: [PATCH 3/3] fix test and doc Signed-off-by: shawnh2 --- internal/cmd/egctl/status_test.go | 26 +++++++++---------- .../en/v1.0.1/tasks/operations/egctl.md | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/internal/cmd/egctl/status_test.go b/internal/cmd/egctl/status_test.go index 9cc863138ca..648fd58d140 100644 --- a/internal/cmd/egctl/status_test.go +++ b/internal/cmd/egctl/status_test.go @@ -381,9 +381,9 @@ default2 gtw2 foobar4 test-status-4 test reason 4 test message 4 allNamespaces: true, typedName: false, outputs: `NAMESPACE NAME PARENT TYPE STATUS REASON -default1 http1 Gateway/test-1 foobar2 test-status-2 test reason 2 +default1 http1 gateway/test-1 foobar2 test-status-2 test reason 2 foobar1 test-status-1 test reason 1 -default2 http2 Gateway/test-2 foobar4 test-status-4 test reason 4 +default2 http2 gateway/test-2 foobar4 test-status-4 test reason 4 foobar3 test-status-3 test reason 3 `, }, @@ -473,8 +473,8 @@ default2 http2 Gateway/test-2 foobar4 test-status-4 test reason 4 typedName: false, namespace: "default1", outputs: `NAME PARENT TYPE STATUS REASON -http1 Gateway/test-1 foobar2 test-status-2 test reason 2 -http2 Gateway/test-2 foobar4 test-status-4 test reason 4 +http1 gateway/test-1 foobar2 test-status-2 test reason 2 +http2 gateway/test-2 foobar4 test-status-4 test reason 4 `, }, { @@ -524,7 +524,7 @@ http2 Gateway/test-2 foobar4 test-status-4 test reason 4 allNamespaces: false, typedName: false, outputs: `NAME ANCESTOR REFERENCE TYPE STATUS REASON -btls Gateway/test foobar2 test-status-2 test reason 2 +btls gateway/test foobar2 test-status-2 test reason 2 foobar1 test-status-1 test reason 1 `, }, @@ -661,13 +661,13 @@ btls Gateway/test foobar2 test-status-2 test reason 2 allNamespaces: true, typedName: false, outputs: `NAMESPACE NAME PARENT TYPE STATUS REASON -default1 http1 Gateway/test-1 foobar2 test-status-2 test reason 2 +default1 http1 gateway/test-1 foobar2 test-status-2 test reason 2 foobar1 test-status-1 test reason 1 - Gateway/test-2 foobar4 test-status-4 test reason 4 + gateway/test-2 foobar4 test-status-4 test reason 4 foobar3 test-status-3 test reason 3 -default2 http2 Gateway/test-3 foobar6 test-status-6 test reason 6 +default2 http2 gateway/test-3 foobar6 test-status-6 test reason 6 foobar5 test-status-5 test reason 5 - Gateway/test-4 foobar8 test-status-8 test reason 8 + gateway/test-4 foobar8 test-status-8 test reason 8 foobar7 test-status-7 test reason 7 `, }, @@ -800,13 +800,13 @@ default2 http2 Gateway/test-3 foobar6 test-status-6 test reason 6 allNamespaces: false, typedName: false, outputs: `NAME ANCESTOR REFERENCE TYPE STATUS REASON -btp-1 Gateway/test-1 foobar2 test-status-2 test reason 2 +btp-1 gateway/test-1 foobar2 test-status-2 test reason 2 foobar1 test-status-1 test reason 1 - HTTPRoute/test-2 foobar4 test-status-4 test reason 4 + httproute/test-2 foobar4 test-status-4 test reason 4 foobar3 test-status-3 test reason 3 -btp-2 Gateway/test-3 foobar6 test-status-6 test reason 6 +btp-2 gateway/test-3 foobar6 test-status-6 test reason 6 foobar5 test-status-5 test reason 5 - GRPCRoute/test-4 foobar8 test-status-8 test reason 8 + grpcroute/test-4 foobar8 test-status-8 test reason 8 foobar7 test-status-7 test reason 7 `, }, diff --git a/site/content/en/v1.0.1/tasks/operations/egctl.md b/site/content/en/v1.0.1/tasks/operations/egctl.md index 84c2c51f1c5..75855ad68d9 100644 --- a/site/content/en/v1.0.1/tasks/operations/egctl.md +++ b/site/content/en/v1.0.1/tasks/operations/egctl.md @@ -769,7 +769,7 @@ display the latest condition, or add `--verbose` to display more details about c {{% alert title="Note" color="primary" %}} Currently, this subcommand only supports: `GatewayClass`, `Gateway`, `HTTPRoute`, `GRPCRoute`, -`TLSRoute`, `TCPRoute`, `UDPRoute`, `BackendTLSPolicy`, +`TLSRoute`, `TCPRoute`, `UDPRoute`, `BackendTLSPolicy`, `BackendTrafficPolicy`, `ClientTrafficPolicy`, `EnvoyPatchPolicy`, `SecurityPolicy` resource types and `all`. {{% /alert %}}