mirror of
https://github.com/alibaba/higress.git
synced 2026-03-07 10:00:48 +08:00
feat: add support for hgctl gateway-config to retrieve higress gateway config (#274)
Signed-off-by: bitliu <bitliu@tencent.com>
This commit is contained in:
@@ -26,6 +26,7 @@ header:
|
||||
- 'VERSION'
|
||||
- 'tools/'
|
||||
- 'test/README.md'
|
||||
- 'pkg/cmd/hgctl/testdata/config'
|
||||
|
||||
comment: on-failure
|
||||
dependency:
|
||||
|
||||
65
pkg/cmd/hgctl/configBootstrap.go
Normal file
65
pkg/cmd/hgctl/configBootstrap.go
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
)
|
||||
|
||||
func bootstrapConfigCmd() *cobra.Command {
|
||||
configCmd := &cobra.Command{
|
||||
Use: "bootstrap <pod-name>",
|
||||
Aliases: []string{"b"},
|
||||
Short: "Retrieves bootstrap Envoy xDS resources from the specified Higress Gateway Pod",
|
||||
Long: `Retrieves information about bootstrap Envoy xDS resources from the specified Higress Gateway Pod`,
|
||||
Example: ` # Retrieve summary about bootstrap configuration for a given pod from Envoy.
|
||||
hgctl gateway-config bootstrap <pod-name> -n <pod-namespace>
|
||||
|
||||
# Retrieve full configuration dump as YAML
|
||||
hgctl gateway-config bootstrap <pod-name> -n <pod-namespace> -o yaml
|
||||
|
||||
# Retrieve full configuration dump with short syntax
|
||||
hgctl gc b <pod-name> -n <pod-namespace>
|
||||
`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(runBootstrapConfig(c, args))
|
||||
},
|
||||
}
|
||||
|
||||
return configCmd
|
||||
}
|
||||
|
||||
func runBootstrapConfig(c *cobra.Command, args []string) error {
|
||||
configDump, err := retrieveConfigDump(args, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bootstrap, err := GetXDSResource(BootstrapEnvoyConfigType, configDump)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := formatGatewayConfig(bootstrap, output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(c.OutOrStdout(), string(out))
|
||||
return err
|
||||
}
|
||||
64
pkg/cmd/hgctl/configCluster.go
Normal file
64
pkg/cmd/hgctl/configCluster.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
)
|
||||
|
||||
func clusterConfigCmd() *cobra.Command {
|
||||
configCmd := &cobra.Command{
|
||||
Use: "cluster <pod-name>",
|
||||
Short: "Retrieves cluster Envoy xDS resources from the specified Higress Gateway Pod",
|
||||
Aliases: []string{"c"},
|
||||
Long: `Retrieves information about cluster Envoy xDS resources from the specified Higress Gateway Pod`,
|
||||
Example: ` # Retrieve summary about cluster configuration for a given pod from Envoy.
|
||||
hgctl gateway-config cluster <pod-name> -n <pod-namespace>
|
||||
|
||||
# Retrieve full configuration dump as YAML
|
||||
hgctl gateway-config cluster <pod-name> -n <pod-namespace> -o yaml
|
||||
|
||||
# Retrieve full configuration dump with short syntax
|
||||
hgctl gc c <pod-name> -n <pod-namespace>
|
||||
`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(runClusterConfig(c, args))
|
||||
},
|
||||
}
|
||||
|
||||
return configCmd
|
||||
}
|
||||
|
||||
func runClusterConfig(c *cobra.Command, args []string) error {
|
||||
configDump, err := retrieveConfigDump(args, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cluster, err := GetXDSResource(ClusterEnvoyConfigType, configDump)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := formatGatewayConfig(cluster, output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(c.OutOrStdout(), string(out))
|
||||
return err
|
||||
}
|
||||
79
pkg/cmd/hgctl/configCmd.go
Normal file
79
pkg/cmd/hgctl/configCmd.go
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/alibaba/higress/pkg/cmd/options"
|
||||
"github.com/spf13/cobra"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
)
|
||||
|
||||
func newConfigCommand() *cobra.Command {
|
||||
cfgCommand := &cobra.Command{
|
||||
Use: "gateway-config",
|
||||
Aliases: []string{"gc"},
|
||||
Short: "Retrieve Higress Gateway configuration.",
|
||||
Long: "Retrieve information about Higress Gateway Configuration.",
|
||||
}
|
||||
|
||||
cfgCommand.AddCommand(allConfigCmd())
|
||||
cfgCommand.AddCommand(bootstrapConfigCmd())
|
||||
cfgCommand.AddCommand(clusterConfigCmd())
|
||||
cfgCommand.AddCommand(endpointConfigCmd())
|
||||
cfgCommand.AddCommand(listenerConfigCmd())
|
||||
cfgCommand.AddCommand(routeConfigCmd())
|
||||
|
||||
flags := cfgCommand.Flags()
|
||||
options.AddKubeConfigFlags(flags)
|
||||
|
||||
cfgCommand.PersistentFlags().StringVarP(&output, "output", "o", "json", "One of 'yaml' or 'json'")
|
||||
cfgCommand.PersistentFlags().StringVarP(&podNamespace, "namespace", "n", "higress-system", "Namespace where envoy proxy pod are installed.")
|
||||
|
||||
return cfgCommand
|
||||
}
|
||||
|
||||
func allConfigCmd() *cobra.Command {
|
||||
configCmd := &cobra.Command{
|
||||
Use: "all <pod-name>",
|
||||
Short: "Retrieves all Envoy xDS resources from the specified Higress Gateway Pod",
|
||||
Long: `Retrieves information about all Envoy xDS resources from the specified Higress Gateway Pod`,
|
||||
Example: ` # Retrieve summary about all configuration for a given pod from Envoy.
|
||||
hgctl gateway-config all <pod-name> -n <pod-namespace>
|
||||
|
||||
# Retrieve full configuration dump as YAML
|
||||
hgctl gateway-config all <pod-name> -n <pod-namespace> -o yaml
|
||||
|
||||
# Retrieve full configuration dump with short syntax
|
||||
hgctl gc all <pod-name> -n <pod-namespace>
|
||||
`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(runAllConfig(c, args))
|
||||
},
|
||||
}
|
||||
|
||||
return configCmd
|
||||
}
|
||||
|
||||
func runAllConfig(c *cobra.Command, args []string) error {
|
||||
configDump, err := retrieveConfigDump(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(c.OutOrStdout(), string(configDump))
|
||||
return err
|
||||
}
|
||||
65
pkg/cmd/hgctl/configEndpoint.go
Normal file
65
pkg/cmd/hgctl/configEndpoint.go
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
)
|
||||
|
||||
func endpointConfigCmd() *cobra.Command {
|
||||
configCmd := &cobra.Command{
|
||||
Use: "endpoint <pod-name>",
|
||||
Short: "Retrieves endpoint Envoy xDS resources from the specified Higress Gateway Pod",
|
||||
Aliases: []string{"e"},
|
||||
Long: `Retrieves information about endpoint Envoy xDS resources from the specified Higress Gateway Pod`,
|
||||
Example: ` # Retrieve summary about endpoint configuration for a given pod from Envoy.
|
||||
hgctl gateway-config endpoint <pod-name> -n <pod-namespace>
|
||||
|
||||
# Retrieve configuration dump as YAML
|
||||
hgctl gateway-config endpoint <pod-name> -n <pod-namespace> -o yaml
|
||||
|
||||
# Retrieve configuration dump with short syntax
|
||||
hgctl gc e <pod-name> -n <pod-namespace>
|
||||
`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(runEndpointConfig(c, args))
|
||||
},
|
||||
}
|
||||
|
||||
return configCmd
|
||||
}
|
||||
|
||||
func runEndpointConfig(c *cobra.Command, args []string) error {
|
||||
configDump, err := retrieveConfigDump(args, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
endpoint, err := GetXDSResource(EndpointEnvoyConfigType, configDump)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := formatGatewayConfig(endpoint, output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(c.OutOrStdout(), string(out))
|
||||
return err
|
||||
}
|
||||
65
pkg/cmd/hgctl/configListener.go
Normal file
65
pkg/cmd/hgctl/configListener.go
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
)
|
||||
|
||||
func listenerConfigCmd() *cobra.Command {
|
||||
configCmd := &cobra.Command{
|
||||
Use: "listener <pod-name>",
|
||||
Aliases: []string{"l"},
|
||||
Short: "Retrieves listener Envoy xDS resources from the specified Higress Gateway Pod",
|
||||
Long: `Retrieves information about listener Envoy xDS resources from the specified Higress Gateway Pod`,
|
||||
Example: ` # Retrieve summary about listener configuration for a given pod from Envoy.
|
||||
hgctl gateway-config listener <pod-name> -n <pod-namespace>
|
||||
|
||||
# Retrieve full configuration dump as YAML
|
||||
hgctl gateway-config listener <pod-name> -n <pod-namespace> -o yaml
|
||||
|
||||
# Retrieve full configuration dump with short syntax
|
||||
hgctl gc l <pod-name> -n <pod-namespace>
|
||||
`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(runListenerConfig(c, args))
|
||||
},
|
||||
}
|
||||
|
||||
return configCmd
|
||||
}
|
||||
|
||||
func runListenerConfig(c *cobra.Command, args []string) error {
|
||||
configDump, err := retrieveConfigDump(args, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
listener, err := GetXDSResource(ListenerEnvoyConfigType, configDump)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := formatGatewayConfig(listener, output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(c.OutOrStdout(), string(out))
|
||||
return err
|
||||
}
|
||||
151
pkg/cmd/hgctl/configRetriever.go
Normal file
151
pkg/cmd/hgctl/configRetriever.go
Normal file
@@ -0,0 +1,151 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/alibaba/higress/pkg/cmd/hgctl/kubernetes"
|
||||
"github.com/alibaba/higress/pkg/cmd/options"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
var (
|
||||
output string
|
||||
podName string
|
||||
podNamespace string
|
||||
)
|
||||
|
||||
const (
|
||||
adminPort = 15000
|
||||
containerName = "envoy"
|
||||
)
|
||||
|
||||
func retrieveConfigDump(args []string, includeEds bool) ([]byte, error) {
|
||||
if len(args) != 0 {
|
||||
podName = args[0]
|
||||
}
|
||||
|
||||
if podNamespace == "" {
|
||||
return nil, fmt.Errorf("pod namespace is required")
|
||||
}
|
||||
|
||||
if podName == "" || len(args) == 0 {
|
||||
c, err := kubernetes.NewCLIClient(options.DefaultConfigFlags.ToRawKubeConfigLoader())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build kubernetes client: %w", err)
|
||||
}
|
||||
podList, err := c.PodsForSelector(podNamespace, "app=higress-gateway")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(podList.Items) == 0 {
|
||||
return nil, fmt.Errorf("higress gateway pod is not existed in namespace %s", podNamespace)
|
||||
}
|
||||
|
||||
podName = podList.Items[0].GetName()
|
||||
}
|
||||
|
||||
fw, err := portForwarder(types.NamespacedName{
|
||||
Namespace: podNamespace,
|
||||
Name: podName,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := fw.Start(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fw.Stop()
|
||||
|
||||
configDump, err := fetchGatewayConfig(fw, includeEds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return configDump, nil
|
||||
}
|
||||
|
||||
func portForwarder(nn types.NamespacedName) (kubernetes.PortForwarder, error) {
|
||||
c, err := kubernetes.NewCLIClient(options.DefaultConfigFlags.ToRawKubeConfigLoader())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("build CLI client fail: %w", err)
|
||||
}
|
||||
|
||||
pod, err := c.Pod(nn)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("get pod %s fail: %w", nn, err)
|
||||
}
|
||||
if pod.Status.Phase != "Running" {
|
||||
return nil, fmt.Errorf("pod %s is not running", nn)
|
||||
}
|
||||
|
||||
fw, err := kubernetes.NewLocalPortForwarder(c, nn, 0, adminPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return fw, nil
|
||||
}
|
||||
|
||||
func formatGatewayConfig(configDump any, output string) ([]byte, error) {
|
||||
out, err := json.MarshalIndent(configDump, "", " ")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if output == "yaml" {
|
||||
out, err = yaml.JSONToYAML(out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func fetchGatewayConfig(fw kubernetes.PortForwarder, includeEds bool) ([]byte, error) {
|
||||
out, err := configDumpRequest(fw.Address(), includeEds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func configDumpRequest(address string, includeEds bool) ([]byte, error) {
|
||||
url := fmt.Sprintf("http://%s/config_dump", address)
|
||||
if includeEds {
|
||||
url = fmt.Sprintf("%s?include_eds", url)
|
||||
}
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
return io.ReadAll(resp.Body)
|
||||
}
|
||||
65
pkg/cmd/hgctl/configRoute.go
Normal file
65
pkg/cmd/hgctl/configRoute.go
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
)
|
||||
|
||||
func routeConfigCmd() *cobra.Command {
|
||||
configCmd := &cobra.Command{
|
||||
Use: "route <pod-name>",
|
||||
Aliases: []string{"r"},
|
||||
Short: "Retrieves route Envoy xDS resources from the specified Higress Gateway Pod",
|
||||
Long: `Retrieves information about route Envoy xDS resources from the specified Higress Gateway Pod`,
|
||||
Example: ` # Retrieve summary about route configuration for a given pod from Envoy.
|
||||
hgctl gateway-config route <pod-name> -n <pod-namespace>
|
||||
|
||||
# Retrieve full configuration dump as YAML
|
||||
hgctl gateway-config route <pod-name> -n <pod-namespace> -o yaml
|
||||
|
||||
# Retrieve full configuration dump with short syntax
|
||||
hgctl gc r <pod-name> -n <pod-namespace>
|
||||
`,
|
||||
Run: func(c *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(runRouteConfig(c, args))
|
||||
},
|
||||
}
|
||||
|
||||
return configCmd
|
||||
}
|
||||
|
||||
func runRouteConfig(c *cobra.Command, args []string) error {
|
||||
configDump, err := retrieveConfigDump(args, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
route, err := GetXDSResource(RouteEnvoyConfigType, configDump)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := formatGatewayConfig(route, output)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = fmt.Fprintln(c.OutOrStdout(), string(out))
|
||||
return err
|
||||
}
|
||||
220
pkg/cmd/hgctl/config_test.go
Normal file
220
pkg/cmd/hgctl/config_test.go
Normal file
@@ -0,0 +1,220 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/alibaba/higress/pkg/cmd/hgctl/kubernetes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var _ kubernetes.PortForwarder = &fakePortForwarder{}
|
||||
|
||||
type fakePortForwarder struct {
|
||||
responseBody []byte
|
||||
localPort int
|
||||
l net.Listener
|
||||
mux *http.ServeMux
|
||||
}
|
||||
|
||||
func newFakePortForwarder(b []byte) (kubernetes.PortForwarder, error) {
|
||||
p, err := kubernetes.LocalAvailablePort()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fw := &fakePortForwarder{
|
||||
responseBody: b,
|
||||
localPort: p,
|
||||
mux: http.NewServeMux(),
|
||||
}
|
||||
fw.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write(fw.responseBody)
|
||||
})
|
||||
|
||||
return fw, nil
|
||||
}
|
||||
|
||||
func (fw *fakePortForwarder) Start() error {
|
||||
l, err := net.Listen("tcp", fw.Address())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fw.l = l
|
||||
|
||||
go func() {
|
||||
if err := http.Serve(l, fw.mux); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fw *fakePortForwarder) Stop() {}
|
||||
|
||||
func (fw *fakePortForwarder) Address() string {
|
||||
return fmt.Sprintf("localhost:%d", fw.localPort)
|
||||
}
|
||||
|
||||
func TestExtractAllConfigDump(t *testing.T) {
|
||||
input, err := readInputConfig("in.all.json")
|
||||
assert.NoError(t, err)
|
||||
fw, err := newFakePortForwarder(input)
|
||||
assert.NoError(t, err)
|
||||
err = fw.Start()
|
||||
assert.NoError(t, err)
|
||||
|
||||
cases := []struct {
|
||||
output string
|
||||
expected string
|
||||
resourceType string
|
||||
}{
|
||||
{
|
||||
output: "json",
|
||||
expected: "out.all.json",
|
||||
},
|
||||
{
|
||||
output: "yaml",
|
||||
expected: "out.all.yaml",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.output, func(t *testing.T) {
|
||||
configDump, err := fetchGatewayConfig(fw, true)
|
||||
assert.NoError(t, err)
|
||||
data, err := GetXDSResource(AllEnvoyConfigType, configDump)
|
||||
assert.NoError(t, err)
|
||||
got, err := formatGatewayConfig(data, tc.output)
|
||||
assert.NoError(t, err)
|
||||
out, err := readOutputConfig(tc.expected)
|
||||
assert.NoError(t, err)
|
||||
if tc.output == "yaml" {
|
||||
assert.YAMLEq(t, string(out), string(got))
|
||||
} else {
|
||||
assert.JSONEq(t, string(out), string(got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fw.Stop()
|
||||
}
|
||||
|
||||
func TestExtractSubResourcesConfigDump(t *testing.T) {
|
||||
input, err := readInputConfig("in.all.json")
|
||||
assert.NoError(t, err)
|
||||
fw, err := newFakePortForwarder(input)
|
||||
assert.NoError(t, err)
|
||||
err = fw.Start()
|
||||
assert.NoError(t, err)
|
||||
|
||||
cases := []struct {
|
||||
output string
|
||||
expected string
|
||||
resourceType envoyConfigType
|
||||
}{
|
||||
{
|
||||
output: "json",
|
||||
resourceType: BootstrapEnvoyConfigType,
|
||||
expected: "out.bootstrap.json",
|
||||
},
|
||||
{
|
||||
output: "yaml",
|
||||
resourceType: BootstrapEnvoyConfigType,
|
||||
expected: "out.bootstrap.yaml",
|
||||
}, {
|
||||
output: "json",
|
||||
resourceType: ClusterEnvoyConfigType,
|
||||
expected: "out.cluster.json",
|
||||
},
|
||||
{
|
||||
output: "yaml",
|
||||
resourceType: ClusterEnvoyConfigType,
|
||||
expected: "out.cluster.yaml",
|
||||
}, {
|
||||
output: "json",
|
||||
resourceType: ListenerEnvoyConfigType,
|
||||
expected: "out.listener.json",
|
||||
},
|
||||
{
|
||||
output: "yaml",
|
||||
resourceType: ListenerEnvoyConfigType,
|
||||
expected: "out.listener.yaml",
|
||||
}, {
|
||||
output: "json",
|
||||
resourceType: RouteEnvoyConfigType,
|
||||
expected: "out.route.json",
|
||||
},
|
||||
{
|
||||
output: "yaml",
|
||||
resourceType: RouteEnvoyConfigType,
|
||||
expected: "out.route.yaml",
|
||||
},
|
||||
{
|
||||
output: "json",
|
||||
resourceType: EndpointEnvoyConfigType,
|
||||
expected: "out.endpoints.json",
|
||||
},
|
||||
{
|
||||
output: "yaml",
|
||||
resourceType: EndpointEnvoyConfigType,
|
||||
expected: "out.endpoints.yaml",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.output, func(t *testing.T) {
|
||||
configDump, err := fetchGatewayConfig(fw, false)
|
||||
assert.NoError(t, err)
|
||||
resource, err := GetXDSResource(tc.resourceType, configDump)
|
||||
assert.NoError(t, err)
|
||||
got, err := formatGatewayConfig(resource, tc.output)
|
||||
assert.NoError(t, err)
|
||||
out, err := readOutputConfig(tc.expected)
|
||||
assert.NoError(t, err)
|
||||
if tc.output == "yaml" {
|
||||
assert.YAMLEq(t, string(out), string(got))
|
||||
} else {
|
||||
assert.JSONEq(t, string(out), string(got))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fw.Stop()
|
||||
}
|
||||
|
||||
func readInputConfig(filename string) ([]byte, error) {
|
||||
b, err := os.ReadFile(path.Join("testdata", "config", "input", filename))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func readOutputConfig(filename string) ([]byte, error) {
|
||||
b, err := os.ReadFile(path.Join("testdata", "config", "output", filename))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
@@ -27,6 +27,7 @@ func GetRootCommand() *cobra.Command {
|
||||
}
|
||||
|
||||
rootCmd.AddCommand(newVersionCommand())
|
||||
rootCmd.AddCommand(newConfigCommand())
|
||||
|
||||
return rootCmd
|
||||
}
|
||||
|
||||
2247
pkg/cmd/hgctl/testdata/config/input/in.all.json
vendored
Normal file
2247
pkg/cmd/hgctl/testdata/config/input/in.all.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2247
pkg/cmd/hgctl/testdata/config/output/out.all.json
vendored
Normal file
2247
pkg/cmd/hgctl/testdata/config/output/out.all.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1305
pkg/cmd/hgctl/testdata/config/output/out.all.yaml
vendored
Normal file
1305
pkg/cmd/hgctl/testdata/config/output/out.all.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1966
pkg/cmd/hgctl/testdata/config/output/out.bootstrap.json
vendored
Normal file
1966
pkg/cmd/hgctl/testdata/config/output/out.bootstrap.json
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1121
pkg/cmd/hgctl/testdata/config/output/out.bootstrap.yaml
vendored
Normal file
1121
pkg/cmd/hgctl/testdata/config/output/out.bootstrap.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
98
pkg/cmd/hgctl/testdata/config/output/out.cluster.json
vendored
Normal file
98
pkg/cmd/hgctl/testdata/config/output/out.cluster.json
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.admin.v3.ClustersConfigDump",
|
||||
"version_info": "2",
|
||||
"static_clusters": [{
|
||||
"cluster": {
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "xds_cluster",
|
||||
"type": "STRICT_DNS",
|
||||
"connect_timeout": "1s",
|
||||
"transport_socket": {
|
||||
"name": "envoy.transport_sockets.tls",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
|
||||
"common_tls_context": {
|
||||
"tls_params": {
|
||||
"tls_maximum_protocol_version": "TLSv1_3"
|
||||
},
|
||||
"tls_certificate_sds_secret_configs": [{
|
||||
"name": "xds_certificate",
|
||||
"sds_config": {
|
||||
"resource_api_version": "V3",
|
||||
"path_config_source": {
|
||||
"path": "/sds/xds-certificate.json"
|
||||
}
|
||||
}
|
||||
}],
|
||||
"validation_context_sds_secret_config": {
|
||||
"name": "xds_trusted_ca",
|
||||
"sds_config": {
|
||||
"resource_api_version": "V3",
|
||||
"path_config_source": {
|
||||
"path": "/sds/xds-trusted-ca.json"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"load_assignment": {
|
||||
"cluster_name": "xds_cluster",
|
||||
"endpoints": [{
|
||||
"lb_endpoints": [{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socket_address": {
|
||||
"address": "higress",
|
||||
"port_value": 18000
|
||||
}
|
||||
}
|
||||
}
|
||||
}]
|
||||
}]
|
||||
},
|
||||
"typed_extension_protocol_options": {
|
||||
"envoy.extensions.upstreams.http.v3.HttpProtocolOptions": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions",
|
||||
"explicit_http_config": {
|
||||
"http2_protocol_options": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"last_updated": "2023-02-23T09:05:23.436Z"
|
||||
}],
|
||||
"dynamic_active_clusters": [{
|
||||
"version_info": "2a0a1698a9d3e05b802047b0cd36b52a070afa49042e1ba267168c5265c7cabf",
|
||||
"cluster": {
|
||||
"@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster",
|
||||
"name": "default-backend-rule-0-match-0-www.example.com",
|
||||
"type": "STATIC",
|
||||
"connect_timeout": "5s",
|
||||
"dns_lookup_family": "V4_ONLY",
|
||||
"outlier_detection": {},
|
||||
"common_lb_config": {
|
||||
"locality_weighted_lb_config": {}
|
||||
},
|
||||
"load_assignment": {
|
||||
"cluster_name": "default-backend-rule-0-match-0-www.example.com",
|
||||
"endpoints": [{
|
||||
"locality": {},
|
||||
"lb_endpoints": [{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socket_address": {
|
||||
"address": "0.0.0.0",
|
||||
"port_value": 3000
|
||||
}
|
||||
}
|
||||
},
|
||||
"load_balancing_weight": 1
|
||||
}],
|
||||
"load_balancing_weight": 1
|
||||
}]
|
||||
}
|
||||
},
|
||||
"last_updated": "2023-02-23T09:05:38.443Z"
|
||||
}]
|
||||
}
|
||||
67
pkg/cmd/hgctl/testdata/config/output/out.cluster.yaml
vendored
Normal file
67
pkg/cmd/hgctl/testdata/config/output/out.cluster.yaml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
"@type": type.googleapis.com/envoy.admin.v3.ClustersConfigDump
|
||||
version_info: '2'
|
||||
static_clusters:
|
||||
- cluster:
|
||||
"@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
|
||||
name: xds_cluster
|
||||
type: STRICT_DNS
|
||||
connect_timeout: 1s
|
||||
transport_socket:
|
||||
name: envoy.transport_sockets.tls
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
|
||||
common_tls_context:
|
||||
tls_params:
|
||||
tls_maximum_protocol_version: TLSv1_3
|
||||
tls_certificate_sds_secret_configs:
|
||||
- name: xds_certificate
|
||||
sds_config:
|
||||
resource_api_version: V3
|
||||
path_config_source:
|
||||
path: "/sds/xds-certificate.json"
|
||||
validation_context_sds_secret_config:
|
||||
name: xds_trusted_ca
|
||||
sds_config:
|
||||
resource_api_version: V3
|
||||
path_config_source:
|
||||
path: "/sds/xds-trusted-ca.json"
|
||||
load_assignment:
|
||||
cluster_name: xds_cluster
|
||||
endpoints:
|
||||
- lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: higress
|
||||
port_value: 18000
|
||||
typed_extension_protocol_options:
|
||||
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
|
||||
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
|
||||
explicit_http_config:
|
||||
http2_protocol_options: {}
|
||||
last_updated: '2023-02-23T09:05:23.436Z'
|
||||
dynamic_active_clusters:
|
||||
- version_info: 2a0a1698a9d3e05b802047b0cd36b52a070afa49042e1ba267168c5265c7cabf
|
||||
cluster:
|
||||
"@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
|
||||
name: default-backend-rule-0-match-0-www.example.com
|
||||
type: STATIC
|
||||
connect_timeout: 5s
|
||||
dns_lookup_family: V4_ONLY
|
||||
outlier_detection: {}
|
||||
common_lb_config:
|
||||
locality_weighted_lb_config: {}
|
||||
load_assignment:
|
||||
cluster_name: default-backend-rule-0-match-0-www.example.com
|
||||
endpoints:
|
||||
- locality: {}
|
||||
lb_endpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socket_address:
|
||||
address: 0.0.0.0
|
||||
port_value: 3000
|
||||
load_balancing_weight: 1
|
||||
load_balancing_weight: 1
|
||||
last_updated: '2023-02-23T09:05:38.443Z'
|
||||
30
pkg/cmd/hgctl/testdata/config/output/out.endpoints.json
vendored
Normal file
30
pkg/cmd/hgctl/testdata/config/output/out.endpoints.json
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump",
|
||||
"staticEndpointConfigs": [{
|
||||
"endpointConfig": {
|
||||
"@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment",
|
||||
"clusterName": "xds_cluster",
|
||||
"endpoints": [{
|
||||
"locality": {},
|
||||
"lbEndpoints": [{
|
||||
"endpoint": {
|
||||
"address": {
|
||||
"socketAddress": {
|
||||
"address": "0.0.0.0",
|
||||
"portValue": 18000
|
||||
}
|
||||
},
|
||||
"healthCheckConfig": {},
|
||||
"hostname": "higress"
|
||||
},
|
||||
"healthStatus": "HEALTHY",
|
||||
"metadata": {},
|
||||
"loadBalancingWeight": 1
|
||||
}]
|
||||
}],
|
||||
"policy": {
|
||||
"overprovisioningFactor": 140
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
21
pkg/cmd/hgctl/testdata/config/output/out.endpoints.yaml
vendored
Normal file
21
pkg/cmd/hgctl/testdata/config/output/out.endpoints.yaml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
"@type": type.googleapis.com/envoy.admin.v3.EndpointsConfigDump
|
||||
staticEndpointConfigs:
|
||||
- endpointConfig:
|
||||
"@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment
|
||||
clusterName: xds_cluster
|
||||
endpoints:
|
||||
- locality: {}
|
||||
lbEndpoints:
|
||||
- endpoint:
|
||||
address:
|
||||
socketAddress:
|
||||
address: 0.0.0.0
|
||||
portValue: 18000
|
||||
healthCheckConfig: {}
|
||||
hostname: higress
|
||||
healthStatus: HEALTHY
|
||||
metadata: {}
|
||||
loadBalancingWeight: 1
|
||||
policy:
|
||||
overprovisioningFactor: 140
|
||||
77
pkg/cmd/hgctl/testdata/config/output/out.listener.json
vendored
Normal file
77
pkg/cmd/hgctl/testdata/config/output/out.listener.json
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.admin.v3.ListenersConfigDump",
|
||||
"version_info": "2",
|
||||
"dynamic_listeners": [{
|
||||
"name": "default-higress-http",
|
||||
"active_state": {
|
||||
"version_info": "42c71fb50c315ee3a32b327da69f8cc0baf420bc84b747e82d9c38e1b0c33eb2",
|
||||
"listener": {
|
||||
"@type": "type.googleapis.com/envoy.config.listener.v3.Listener",
|
||||
"name": "default-higress-http",
|
||||
"address": {
|
||||
"socket_address": {
|
||||
"address": "0.0.0.0",
|
||||
"port_value": 10080
|
||||
}
|
||||
},
|
||||
"access_log": [{
|
||||
"name": "envoy.access_loggers.file",
|
||||
"filter": {
|
||||
"response_flag_filter": {
|
||||
"flags": [
|
||||
"NR"
|
||||
]
|
||||
}
|
||||
},
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog",
|
||||
"path": "/dev/stdout"
|
||||
}
|
||||
}],
|
||||
"default_filter_chain": {
|
||||
"filters": [{
|
||||
"name": "envoy.filters.network.http_connection_manager",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager",
|
||||
"stat_prefix": "http",
|
||||
"rds": {
|
||||
"config_source": {
|
||||
"api_config_source": {
|
||||
"api_type": "DELTA_GRPC",
|
||||
"grpc_services": [{
|
||||
"envoy_grpc": {
|
||||
"cluster_name": "xds_cluster"
|
||||
}
|
||||
}],
|
||||
"set_node_on_first_message_only": true,
|
||||
"transport_api_version": "V3"
|
||||
},
|
||||
"resource_api_version": "V3"
|
||||
},
|
||||
"route_config_name": "default-higress-http"
|
||||
},
|
||||
"http_filters": [{
|
||||
"name": "envoy.filters.http.router",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router"
|
||||
}
|
||||
}],
|
||||
"access_log": [{
|
||||
"name": "envoy.access_loggers.file",
|
||||
"typed_config": {
|
||||
"@type": "type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog",
|
||||
"path": "/dev/stdout"
|
||||
}
|
||||
}],
|
||||
"use_remote_address": true,
|
||||
"upgrade_configs": [{
|
||||
"upgrade_type": "websocket"
|
||||
}]
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
"last_updated": "2023-02-23T09:05:38.446Z"
|
||||
}
|
||||
}]
|
||||
}
|
||||
53
pkg/cmd/hgctl/testdata/config/output/out.listener.yaml
vendored
Normal file
53
pkg/cmd/hgctl/testdata/config/output/out.listener.yaml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
---
|
||||
"@type": type.googleapis.com/envoy.admin.v3.ListenersConfigDump
|
||||
version_info: '2'
|
||||
dynamic_listeners:
|
||||
- name: default-higress-http
|
||||
active_state:
|
||||
version_info: 42c71fb50c315ee3a32b327da69f8cc0baf420bc84b747e82d9c38e1b0c33eb2
|
||||
listener:
|
||||
"@type": type.googleapis.com/envoy.config.listener.v3.Listener
|
||||
name: default-higress-http
|
||||
address:
|
||||
socket_address:
|
||||
address: 0.0.0.0
|
||||
port_value: 10080
|
||||
access_log:
|
||||
- name: envoy.access_loggers.file
|
||||
filter:
|
||||
response_flag_filter:
|
||||
flags:
|
||||
- NR
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
|
||||
path: "/dev/stdout"
|
||||
default_filter_chain:
|
||||
filters:
|
||||
- name: envoy.filters.network.http_connection_manager
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
|
||||
stat_prefix: http
|
||||
rds:
|
||||
config_source:
|
||||
api_config_source:
|
||||
api_type: DELTA_GRPC
|
||||
grpc_services:
|
||||
- envoy_grpc:
|
||||
cluster_name: xds_cluster
|
||||
set_node_on_first_message_only: true
|
||||
transport_api_version: V3
|
||||
resource_api_version: V3
|
||||
route_config_name: default-higress-http
|
||||
http_filters:
|
||||
- name: envoy.filters.http.router
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
|
||||
access_log:
|
||||
- name: envoy.access_loggers.file
|
||||
typed_config:
|
||||
"@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
|
||||
path: "/dev/stdout"
|
||||
use_remote_address: true
|
||||
upgrade_configs:
|
||||
- upgrade_type: websocket
|
||||
last_updated: '2023-02-23T09:05:38.446Z'
|
||||
31
pkg/cmd/hgctl/testdata/config/output/out.route.json
vendored
Normal file
31
pkg/cmd/hgctl/testdata/config/output/out.route.json
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"@type": "type.googleapis.com/envoy.admin.v3.RoutesConfigDump",
|
||||
"dynamic_route_configs": [{
|
||||
"version_info": "cb1e51997a9c3aa6f4d920f39fd5bdbd966e9382b7b6bdf42efca8c22c6c3442",
|
||||
"route_config": {
|
||||
"@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration",
|
||||
"name": "default-higress-http",
|
||||
"virtual_hosts": [{
|
||||
"name": "default-higress-http",
|
||||
"domains": [
|
||||
"*"
|
||||
],
|
||||
"routes": [{
|
||||
"match": {
|
||||
"prefix": "/",
|
||||
"headers": [{
|
||||
"name": ":authority",
|
||||
"string_match": {
|
||||
"exact": "www.example.com"
|
||||
}
|
||||
}]
|
||||
},
|
||||
"route": {
|
||||
"cluster": "default-backend-rule-0-match-0-www.example.com"
|
||||
}
|
||||
}]
|
||||
}]
|
||||
},
|
||||
"last_updated": "2023-02-23T09:05:38.448Z"
|
||||
}]
|
||||
}
|
||||
21
pkg/cmd/hgctl/testdata/config/output/out.route.yaml
vendored
Normal file
21
pkg/cmd/hgctl/testdata/config/output/out.route.yaml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
"@type": type.googleapis.com/envoy.admin.v3.RoutesConfigDump
|
||||
dynamic_route_configs:
|
||||
- version_info: cb1e51997a9c3aa6f4d920f39fd5bdbd966e9382b7b6bdf42efca8c22c6c3442
|
||||
route_config:
|
||||
"@type": type.googleapis.com/envoy.config.route.v3.RouteConfiguration
|
||||
name: default-higress-http
|
||||
virtual_hosts:
|
||||
- name: default-higress-http
|
||||
domains:
|
||||
- "*"
|
||||
routes:
|
||||
- match:
|
||||
prefix: "/"
|
||||
headers:
|
||||
- name: ":authority"
|
||||
string_match:
|
||||
exact: www.example.com
|
||||
route:
|
||||
cluster: default-backend-rule-0-match-0-www.example.com
|
||||
last_updated: '2023-02-23T09:05:38.448Z'
|
||||
81
pkg/cmd/hgctl/utils.go
Normal file
81
pkg/cmd/hgctl/utils.go
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package hgctl
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type envoyConfigType string
|
||||
|
||||
var (
|
||||
BootstrapEnvoyConfigType envoyConfigType = "bootstrap"
|
||||
ClusterEnvoyConfigType envoyConfigType = "cluster"
|
||||
EndpointEnvoyConfigType envoyConfigType = "endpoint"
|
||||
ListenerEnvoyConfigType envoyConfigType = "listener"
|
||||
RouteEnvoyConfigType envoyConfigType = "route"
|
||||
AllEnvoyConfigType envoyConfigType = "all"
|
||||
)
|
||||
|
||||
func GetXDSResource(resourceType envoyConfigType, configDump []byte) (any, error) {
|
||||
cd := map[string]any{}
|
||||
if err := json.Unmarshal(configDump, &cd); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resourceType == AllEnvoyConfigType {
|
||||
return cd, nil
|
||||
}
|
||||
configs := cd["configs"]
|
||||
globalConfigs := configs.([]any)
|
||||
|
||||
switch resourceType {
|
||||
case BootstrapEnvoyConfigType:
|
||||
for _, config := range globalConfigs {
|
||||
if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump" {
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
case EndpointEnvoyConfigType:
|
||||
for _, config := range globalConfigs {
|
||||
if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump" {
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
|
||||
case ClusterEnvoyConfigType:
|
||||
for _, config := range globalConfigs {
|
||||
if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.ClustersConfigDump" {
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
case ListenerEnvoyConfigType:
|
||||
for _, config := range globalConfigs {
|
||||
if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.ListenersConfigDump" {
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
case RouteEnvoyConfigType:
|
||||
for _, config := range globalConfigs {
|
||||
if config.(map[string]interface{})["@type"] == "type.googleapis.com/envoy.admin.v3.RoutesConfigDump" {
|
||||
return config, nil
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown resourceType %s", resourceType)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown resourceType %s", resourceType)
|
||||
}
|
||||
Reference in New Issue
Block a user