add proxy log level
diff --git a/app/dubboctl/cmd/proxy.go b/app/dubboctl/cmd/proxy.go
index 2cb53b2..49dd267 100644
--- a/app/dubboctl/cmd/proxy.go
+++ b/app/dubboctl/cmd/proxy.go
@@ -19,20 +19,17 @@
import (
"context"
+ "fmt"
+ "github.com/apache/dubbo-kubernetes/pkg/core"
+ "github.com/apache/dubbo-kubernetes/pkg/util/proto"
+ "github.com/pkg/errors"
"io"
"os"
"path/filepath"
-)
-
-import (
- "github.com/pkg/errors"
+ "strings"
"github.com/spf13/cobra"
- "go.uber.org/zap/zapcore"
-)
-
-import (
mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
"github.com/apache/dubbo-kubernetes/app/dubboctl/internal/envoy"
"github.com/apache/dubbo-kubernetes/pkg/config/app/dubboctl"
@@ -42,7 +39,9 @@
"github.com/apache/dubbo-kubernetes/pkg/core/resources/model"
"github.com/apache/dubbo-kubernetes/pkg/core/resources/model/rest"
core_xds "github.com/apache/dubbo-kubernetes/pkg/core/xds"
+ dubbo_log "github.com/apache/dubbo-kubernetes/pkg/log"
"github.com/apache/dubbo-kubernetes/pkg/util/template"
+ "go.uber.org/zap/zapcore"
)
var runLog = controlPlaneLog.WithName("proxy")
@@ -92,14 +91,39 @@
func addProxy(opts dubbo_cmd.RunCmdOpts, cmd *cobra.Command) {
proxyArgs := DefaultProxyConfig()
+
cfg := proxyArgs.Config
var proxyResource model.Resource
+ arg := struct {
+ logLevel string
+ outputPath string
+ maxSize int
+ maxBackups int
+ maxAge int
+ }{}
+
proxyCmd := &cobra.Command{
Use: "proxy",
Short: "Commands related to proxy",
Long: "Commands help user to generate Ingress and Egress",
RunE: func(cmd *cobra.Command, args []string) error {
logger.InitCmdSugar(zapcore.AddSync(cmd.OutOrStdout()))
+ level, err := dubbo_log.ParseLogLevel(arg.logLevel)
+ if err != nil {
+ return err
+ }
+ proxyArgs.LogLevel = level
+ if arg.outputPath != "" {
+ output, err := filepath.Abs(arg.outputPath)
+ if err != nil {
+ return err
+ }
+
+ fmt.Printf("%s: logs will be stored in %q\n", "kuma-dp", output)
+ core.SetLogger(core.NewLoggerWithRotation(level, output, arg.maxSize, arg.maxBackups, arg.maxAge))
+ } else {
+ core.SetLogger(core.NewLogger(level))
+ }
return nil
},
PreRunE: func(cmd *cobra.Command, args []string) error {
@@ -110,6 +134,10 @@
if _, ok := proxyTypeMap[cfg.Dataplane.ProxyType]; !ok {
return errors.Errorf("invalid proxy type %q", cfg.Dataplane.ProxyType)
}
+ if cfg.DataplaneRuntime.EnvoyLogLevel == "" {
+ cfg.DataplaneRuntime.EnvoyLogLevel = proxyArgs.LogLevel.String()
+ }
+
proxyResource, err := readResource(cmd, &cfg.DataplaneRuntime)
if err != nil {
runLog.Error(err, "failed to read policy", "proxyType", cfg.Dataplane.ProxyType)
@@ -162,13 +190,12 @@
return errors.Errorf("Failed to generate Envoy bootstrap config. %v", err)
}
runLog.Info("received bootstrap configuration", "adminPort", bootstrap.GetAdmin().GetAddress().GetSocketAddress().GetPortValue())
+ opts.BootstrapConfig, err = proto.ToYAML(bootstrap)
+ if err != nil {
+ return errors.Errorf("could not convert to yaml. %v", err)
+ }
+ opts.AdminPort = bootstrap.GetAdmin().GetAddress().GetSocketAddress().GetPortValue()
- //runLog.Info("received bootstrap configuration", "adminPort", bootstrap.GetAdmin().GetAddress().GetSocketAddress().GetPortValue())
- //
- //opts.BootstrapConfig, err = proto.ToYAML(&bootstrap)
- //if err != nil {
- // return errors.Errorf("could not convert to yaml. %v", err)
- //}
stopComponents := make(chan struct{})
envoyComponent, err := envoy.New(opts)
err = envoyComponent.Start(stopComponents)
@@ -180,9 +207,24 @@
return nil
},
}
+
+ // root flags
+ cmd.PersistentFlags().StringVar(&arg.logLevel, "log-level", dubbo_log.InfoLevel.String(), UsageOptions("log level", dubbo_log.OffLevel, dubbo_log.InfoLevel, dubbo_log.DebugLevel))
+ cmd.PersistentFlags().StringVar(&arg.outputPath, "log-output-path", arg.outputPath, "path to the file that will be filled with logs. Example: if we set it to /tmp/kuma.log then after the file is rotated we will have /tmp/kuma-2021-06-07T09-15-18.265.log")
+ cmd.PersistentFlags().IntVar(&arg.maxBackups, "log-max-retained-files", 1000, "maximum number of the old log files to retain")
+ cmd.PersistentFlags().IntVar(&arg.maxSize, "log-max-size", 100, "maximum size in megabytes of a log file before it gets rotated")
+ cmd.PersistentFlags().IntVar(&arg.maxAge, "log-max-age", 30, "maximum number of days to retain old log files based on the timestamp encoded in their filename")
+
proxyCmd.PersistentFlags().StringVar(&cfg.Dataplane.Name, "name", cfg.Dataplane.Name, "Name of the Dataplane")
proxyCmd.PersistentFlags().StringVar(&cfg.Dataplane.Mesh, "mesh", cfg.Dataplane.Mesh, "Mesh that Dataplane belongs to")
proxyCmd.PersistentFlags().StringVar(&cfg.Dataplane.ProxyType, "proxy-type", "dataplane", `type of the Dataplane ("dataplane", "ingress")`)
proxyCmd.PersistentFlags().StringVar(&cfg.DataplaneRuntime.ResourcePath, "dataplane-file", "Path to Ingress and Egress template to apply (YAML or JSON)", "data-plane-file")
cmd.AddCommand(proxyCmd)
}
+func UsageOptions(desc string, options ...interface{}) string {
+ values := make([]string, 0, len(options))
+ for _, option := range options {
+ values = append(values, fmt.Sprintf("%v", option))
+ }
+ return fmt.Sprintf("%s: one of %s", desc, strings.Join(values, "|"))
+}
diff --git a/app/dubboctl/cmd/proxy_context.go b/app/dubboctl/cmd/proxy_context.go
index 8b6427d..33cbaff 100644
--- a/app/dubboctl/cmd/proxy_context.go
+++ b/app/dubboctl/cmd/proxy_context.go
@@ -18,6 +18,7 @@
package cmd
import (
+ "github.com/apache/dubbo-kubernetes/pkg/log"
"os"
"path/filepath"
"runtime"
@@ -47,6 +48,7 @@
Config *dubboctl.Config
BootstrapGenerator envoy.BootstrapConfigFactoryFunc
DataplaneTokenGenerator func(cfg *dubboctl.Config) (component.Component, error)
+ LogLevel log.LogLevel
}
var features = []string{core_xds.FeatureTCPAccessLogViaNamedPipe}
diff --git a/app/dubboctl/cmd/proxy_test.go b/app/dubboctl/cmd/proxy_test.go
new file mode 100644
index 0000000..ecb6552
--- /dev/null
+++ b/app/dubboctl/cmd/proxy_test.go
@@ -0,0 +1,266 @@
+//go:build !windows
+// +build !windows
+
+package cmd
+
+import (
+ "context"
+ "fmt"
+ dubbo_cmd "github.com/apache/dubbo-kubernetes/pkg/core/cmd"
+ "github.com/apache/dubbo-kubernetes/pkg/test"
+ . "github.com/onsi/ginkgo/v2"
+ . "github.com/onsi/gomega"
+ "io"
+ "os"
+ "path/filepath"
+ "strconv"
+ "strings"
+ "syscall"
+ "testing"
+)
+
+func TestCmd(t *testing.T) {
+ test.RunSpecs(t, "cmd Suite")
+}
+
+var _ = Describe("proxy", func() {
+ var cancel func()
+ var ctx context.Context
+ _ = dubbo_cmd.RunCmdOpts{
+ SetupSignalHandler: func() (context.Context, context.Context) {
+ return ctx, ctx
+ },
+ }
+ var tmpDir string
+ BeforeEach(func() {
+ ctx, cancel = context.WithCancel(context.Background())
+ var err error
+ tmpDir, err = os.MkdirTemp("", "")
+ Expect(err).ToNot(HaveOccurred())
+ })
+ AfterEach(func() {
+ if tmpDir != "" {
+ if tmpDir != "" {
+ // when
+ err := os.RemoveAll(tmpDir)
+ // then
+ Expect(err).ToNot(HaveOccurred())
+ }
+ }
+ })
+ type testCase struct {
+ envVars map[string]string
+ args []string
+ expectedFile string
+ }
+ DescribeTable("should be possible to start dataplane (Envoy) using `dubbo-proxy run`",
+ func(giveFunc func() testCase) {
+ given := giveFunc()
+
+ // setup
+ envoyPidFile := filepath.Join(tmpDir, "envoy-mock.pid")
+ envoyCmdlineFile := filepath.Join(tmpDir, "envoy-mock.cmdline")
+ corednsPidFile := filepath.Join(tmpDir, "coredns-mock.pid")
+ corednsCmdlineFile := filepath.Join(tmpDir, "coredns-mock.cmdline")
+
+ // and
+ env := given.envVars
+ env["ENVOY_MOCK_PID_FILE"] = envoyPidFile
+ env["ENVOY_MOCK_CMDLINE_FILE"] = envoyCmdlineFile
+ env["COREDNS_MOCK_PID_FILE"] = corednsPidFile
+ env["COREDNS_MOCK_CMDLINE_FILE"] = corednsCmdlineFile
+ for key, value := range env {
+ Expect(os.Setenv(key, value)).To(Succeed())
+ }
+
+ // given
+
+ reader, writer := io.Pipe()
+ go func() {
+ defer GinkgoRecover()
+ io.ReadAll(reader)
+ }()
+
+ cmd := getRootCmd([]string{"proxy", "--proxy-type=ingress", "--dataplane-file=/mnt/d/code/go/test/1.yaml"})
+ cmd.SetOut(writer)
+ cmd.SetErr(writer)
+ cancel()
+
+ // when
+ By("starting the Dubbo proxy")
+ errCh := make(chan error)
+ go func() {
+ defer close(errCh)
+ errCh <- cmd.Execute()
+ }()
+
+ // then
+ var actualConfigFile string
+ envoyPid := verifyComponentProcess("Envoy", envoyPidFile, envoyCmdlineFile, func(actualArgs []string) {
+ Expect(actualArgs[0]).To(Equal("--version"))
+ Expect(actualArgs[1]).To(Equal("--config-path"))
+ actualConfigFile = actualArgs[2]
+ Expect(actualConfigFile).To(BeARegularFile())
+ if given.expectedFile != "" {
+ Expect(actualArgs[2]).To(Equal(given.expectedFile))
+ }
+ })
+
+ err := <-errCh
+ Expect(err).ToNot(HaveOccurred())
+
+ By("waiting for dataplane (Envoy) to get stopped")
+ Eventually(func() bool {
+ //send sig 0 to check whether Envoy process still exists
+ err := syscall.Kill(int(envoyPid), syscall.Signal(0))
+ // we expect Envoy process to get killed by now
+ return err != nil
+ }, "5s", "100ms").Should(BeTrue())
+
+ },
+ Entry("can be launched with env vars", func() testCase {
+ return testCase{
+ envVars: map[string]string{
+ "DUBBO_CONTROL_PLANE_API_SERVER_URL": "http://localhost:1234",
+ "DUBBO_DATAPLANE_NAME": "example",
+ "DUBBO_DATAPLANE_MESH": "default",
+ "DUBBO_DATAPLANE_RUNTIME_BINARY_PATH": filepath.Join("testdata", "envoy-mock.sleep.sh"),
+ // Notice: DUBBO_DATAPLANE_RUNTIME_CONFIG_DIR is not set in order to let `dubbo-dp` to create a temporary directory
+ "DUBBO_DNS_CORE_DNS_BINARY_PATH": filepath.Join("testdata", "coredns-mock.sleep.sh"),
+ },
+ args: []string{},
+ expectedFile: "",
+ }
+ }),
+ Entry("can be launched with env vars and given config dir", func() testCase {
+ return testCase{
+ envVars: map[string]string{
+ "DUBBO_CONTROL_PLANE_API_SERVER_URL": "http://localhost:1234",
+ "DUBBO_DATAPLANE_NAME": "example",
+ "DUBBO_DATAPLANE_MESH": "default",
+ "DUBBO_DATAPLANE_RUNTIME_BINARY_PATH": filepath.Join("testdata", "envoy-mock.sleep.sh"),
+ "DUBBO_DATAPLANE_RUNTIME_CONFIG_DIR": tmpDir,
+ "DUBBO_DNS_CORE_DNS_BINARY_PATH": filepath.Join("testdata", "coredns-mock.sleep.sh"),
+ },
+ args: []string{},
+ expectedFile: filepath.Join(tmpDir, "bootstrap.yaml"),
+ }
+ }),
+ Entry("can be launched with args", func() testCase {
+ return testCase{
+ envVars: map[string]string{},
+ args: []string{
+ "--cp-address", "http://localhost:1234",
+ "--name", "example",
+ "--mesh", "default",
+ "--binary-path", filepath.Join("testdata", "envoy-mock.sleep.sh"),
+ // Notice: --config-dir is not set in order to let `dubbo-dp` to create a temporary directory
+ "--dns-coredns-path", filepath.Join("testdata", "coredns-mock.sleep.sh"),
+ },
+ expectedFile: "",
+ }
+ }),
+ Entry("can be launched with args and given config dir", func() testCase {
+ return testCase{
+ envVars: map[string]string{},
+ args: []string{
+ "--cp-address", "http://localhost:1234",
+ "--name", "example",
+ "--mesh", "default",
+ "--binary-path", filepath.Join("testdata", "envoy-mock.sleep.sh"),
+ "--config-dir", tmpDir,
+ "--dns-coredns-path", filepath.Join("testdata", "coredns-mock.sleep.sh"),
+ },
+ expectedFile: filepath.Join(tmpDir, "bootstrap.yaml"),
+ }
+ }),
+ Entry("can be launched with args and dataplane token", func() testCase {
+ return testCase{
+ envVars: map[string]string{},
+ args: []string{
+ "--cp-address", "http://localhost:1234",
+ "--name", "example",
+ "--mesh", "default",
+ "--binary-path", filepath.Join("testdata", "envoy-mock.sleep.sh"),
+ "--dataplane-token-file", filepath.Join("testdata", "token"),
+ // Notice: --config-dir is not set in order to let `dubbo-dp` to create a temporary directory
+ "--dns-coredns-path", filepath.Join("testdata", "coredns-mock.sleep.sh"),
+ },
+ expectedFile: "",
+ }
+ }),
+ Entry("can be launched without Envoy Admin API (env vars)", func() testCase {
+ return testCase{
+ envVars: map[string]string{
+ "DUBBO_CONTROL_PLANE_API_SERVER_URL": "http://localhost:1234",
+ "DUBBO_DATAPLANE_NAME": "example",
+ "DUBBO_DATAPLANE_MESH": "default",
+ "DUBBO_DATAPLANE_RUNTIME_BINARY_PATH": filepath.Join("testdata", "envoy-mock.sleep.sh"),
+ // Notice: DUBBO_DATAPLANE_RUNTIME_CONFIG_DIR is not set in order to let `dubbo-dp` to create a temporary directory
+ "DUBBO_DNS_CORE_DNS_BINARY_PATH": filepath.Join("testdata", "coredns-mock.sleep.sh"),
+ },
+ args: []string{},
+ expectedFile: "",
+ }
+ }),
+ Entry("can be launched without Envoy Admin API (command-line args)", func() testCase {
+ return testCase{
+ envVars: map[string]string{},
+ args: []string{
+ "--cp-address", "http://localhost:1234",
+ "--name", "example",
+ "--mesh", "default",
+ "--binary-path", filepath.Join("testdata", "envoy-mock.sleep.sh"),
+ // Notice: --config-dir is not set in order to let `dubbo-dp` to create a temporary directory
+ "--dns-coredns-path", filepath.Join("testdata", "coredns-mock.sleep.sh"),
+ },
+ expectedFile: "",
+ }
+ }),
+ Entry("can be launched with dataplane template", func() testCase {
+ return testCase{
+ envVars: map[string]string{},
+ args: []string{
+ "--cp-address", "http://localhost:1234",
+ "--binary-path", filepath.Join("testdata", "envoy-mock.sleep.sh"),
+ "--dataplane-token-file", filepath.Join("testdata", "token"),
+ "--dataplane-file", filepath.Join("testdata", "dataplane_template.yaml"),
+ "--dataplane-var", "name=example",
+ "--dataplane-var", "address=127.0.0.1",
+ "--dns-coredns-path", filepath.Join("testdata", "coredns-mock.sleep.sh"),
+ },
+ expectedFile: "",
+ }
+ }),
+ )
+
+})
+
+func verifyComponentProcess(processDescription, pidfile string, cmdlinefile string, argsVerifier func(expectedArgs []string)) int64 {
+ var pid int64
+ By(fmt.Sprintf("waiting for dataplane (%s) to get started", processDescription))
+ Eventually(func() bool {
+ data, err := os.ReadFile(pidfile)
+ if err != nil {
+ return false
+ }
+ pid, err = strconv.ParseInt(strings.TrimSpace(string(data)), 10, 32)
+ return err == nil
+ }, "5s", "100ms").Should(BeTrue())
+ Expect(pid).ToNot(BeZero())
+
+ By(fmt.Sprintf("verifying the arguments %s was launched with", processDescription))
+ // when
+ cmdline, err := os.ReadFile(cmdlinefile)
+
+ // then
+ Expect(err).ToNot(HaveOccurred())
+ // and
+ if argsVerifier != nil {
+ actualArgs := strings.FieldsFunc(string(cmdline), func(c rune) bool {
+ return c == '\n'
+ })
+ argsVerifier(actualArgs)
+ }
+ return pid
+}
diff --git a/app/dubboctl/internal/envoy/envoy.go b/app/dubboctl/internal/envoy/envoy.go
index fea3d39..fe4ef7d 100644
--- a/app/dubboctl/internal/envoy/envoy.go
+++ b/app/dubboctl/internal/envoy/envoy.go
@@ -183,6 +183,7 @@
err = command.Wait()
if err != nil && !errors.Is(err, context.Canceled) {
runLog.Error(err, "Envoy terminated with an error")
+
return err
}
runLog.Info("Envoy terminated successfully")
diff --git a/app/dubboctl/internal/envoy/remote_bootstrap.go b/app/dubboctl/internal/envoy/remote_bootstrap.go
index 63a2869..a963f12 100644
--- a/app/dubboctl/internal/envoy/remote_bootstrap.go
+++ b/app/dubboctl/internal/envoy/remote_bootstrap.go
@@ -36,6 +36,7 @@
"github.com/pkg/errors"
+ _ "github.com/apache/dubbo-kubernetes/pkg/xds/envoy"
"github.com/sethvargo/go-retry"
)
diff --git a/pkg/config/app/dubboctl/proxy_config.go b/pkg/config/app/dubboctl/proxy_config.go
index 2e37844..2d9d219 100644
--- a/pkg/config/app/dubboctl/proxy_config.go
+++ b/pkg/config/app/dubboctl/proxy_config.go
@@ -18,6 +18,7 @@
package dubboctl
import (
+ mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1"
"time"
)
@@ -177,3 +178,8 @@
// Drain time for listeners.
DrainTime config_types.Duration `json:"drainTime,omitempty" envconfig:"dubbo_dataplane_drain_time"`
}
+
+func (d *Dataplane) IsZoneProxy() bool {
+ return d.ProxyType == string(mesh_proto.IngressProxyType) ||
+ d.ProxyType == string(mesh_proto.EgressProxyType)
+}
diff --git a/pkg/xds/bootstrap/templatae_v3.go b/pkg/xds/bootstrap/template_v3.go
similarity index 100%
rename from pkg/xds/bootstrap/templatae_v3.go
rename to pkg/xds/bootstrap/template_v3.go