Skip to content
Open

dns #1099

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
07a412c
Upgrade cilium/ebpf from v0.11.0 to v0.18.0 …
cvaroqui Aug 25, 2026
6ac349b
Fix undue ZoneRecordUpdated,ZoneRecordDeleted events
cvaroqui Aug 26, 2026
507aa41
Use a map[recordKey] in the dns to store a instance ips state
cvaroqui Aug 26, 2026
d1325e0
Remove the "alive" dns uds socket trace log
cvaroqui Aug 26, 2026
d98b2a3
Truncate the dns uds response trace log to 1024 bytes
cvaroqui Aug 26, 2026
bfa8cc4
More dns fixes
cvaroqui Aug 26, 2026
8d57bc5
Use a dns name cache to serve lookups faster
cvaroqui Aug 26, 2026
b392943
Don't parse /proc/mountinfo on every poll timeout
cvaroqui Aug 26, 2026
a8295f8
Implement tcp conn pooling in hb.ucast
cvaroqui Aug 26, 2026
ce5d666
make dns ignore the ipaddr when the resource is not up
cvaroqui Aug 26, 2026
9575c5c
Better dns uds trace logs
cvaroqui Aug 26, 2026
ac8ae58
Remove dead func from hb.ucast
cvaroqui Aug 26, 2026
7a4e936
Don't set a deadline on hb.ucast rx sock operations
cvaroqui Aug 26, 2026
3988c20
Bootstrap the dns zone before serving the first uds request
cvaroqui Aug 27, 2026
8a62e10
Fix a hb.ucast locking issue
cvaroqui Aug 27, 2026
dec51a3
Serialize sends to the same node in hb.ucast to prevent goroutine acc…
cvaroqui Aug 27, 2026
4b6bbde
Simplify hb.ucast: remove conn pool, workers manage their own connect…
cvaroqui Aug 27, 2026
9b5aed9
Fix frame loss in encryptconn: use persistent scanner per connection
cvaroqui Aug 27, 2026
fb8c962
Fix hb.ucast shutdown: make workers cancellation-aware
cvaroqui Aug 27, 2026
1d4cfae
Fix hb.ucast rx resource exhaustion: one handler per peer, replace co…
cvaroqui Aug 27, 2026
d0bba9d
Fix encryptconn scanner buffer recycling race: don't pool the buffer
cvaroqui Aug 27, 2026
18d4823
Fix hb.ucast tx Stop panic on send to closed queue
cvaroqui Aug 27, 2026
c063b34
Don't defer the dial cancel in the hb.ucast tx worker loop
cvaroqui Aug 27, 2026
0eeaf00
Fix hb.ucast tx localIP data race, and pick up local ip changes
cvaroqui Aug 27, 2026
344b5ad
Close hb.ucast rx peer connections when the accept loop stops
cvaroqui Aug 27, 2026
c868373
Maintain the dns name index incrementally
cvaroqui Aug 27, 2026
29f4245
Frame the hb.ucast tx message once, not in every worker
cvaroqui Aug 27, 2026
1a6b6a4
Create the hb.ucast send queues once, in Start
cvaroqui Aug 27, 2026
e5e2ca1
Tell hb.ucast rx read failures apart, and report them
cvaroqui Aug 27, 2026
4f88afa
Trim the hb.ucast per message traces
cvaroqui Aug 27, 2026
5a3f84e
Make hb.ucast rx decrypt with the current heartbeat secret
cvaroqui Aug 27, 2026
dc79c49
Make hb.mcast rx decrypt with the current heartbeat secret
cvaroqui Aug 27, 2026
86c92e3
Let the daemon tests run on a node where a daemon is alive
cvaroqui Aug 27, 2026
5dc07e2
Test TCPPortAvailable on a free port, not on the daemon one
cvaroqui Aug 27, 2026
b05e6b4
Re-resolve the hb.ucast rx peers when an unknown address connects
cvaroqui Aug 27, 2026
0948711
Don't hold a max sized read buffer per hb.ucast rx connection
cvaroqui Aug 27, 2026
1a00b3e
Close the hb.ucast tx connections on stop, not just the queues
cvaroqui Aug 27, 2026
c42f223
Fix the tui lockup on page down in the heartbeats and relay views
cvaroqui Aug 28, 2026
bdfc710
Organize the tui views in a registry, with a navigation stack of frames
cvaroqui Aug 28, 2026
3cff5b0
Fix the tui deadlock on entering the log view
cvaroqui Aug 28, 2026
46e01ea
Stop the tui events view from racing with the tview loop
cvaroqui Aug 28, 2026
5bcdd2e
Stop the tui log and events views from racing with the tview loop
cvaroqui Aug 28, 2026
94c96ea
Stop the tui errors bar from racing with the tview loop
cvaroqui Aug 28, 2026
0f8b9a0
Guard the sse ReadCloser closed flag against concurrent Read and Close
cvaroqui Aug 28, 2026
9b0f77c
Publish the tui cluster snapshot from the tview loop
cvaroqui Aug 28, 2026
2cf374d
Show the resource run in progress in the instance cell
cvaroqui Aug 28, 2026
66bcd7b
Exit non zero when the om and ox args name no command
cvaroqui Aug 28, 2026
e69b93d
Fix the daemon argv naming commands that no longer exist
cvaroqui Aug 28, 2026
7b4df88
Drop the empty group sections from the command help
cvaroqui Aug 28, 2026
037ee35
Sort the remaining subsystem commands in their parent help section
cvaroqui Aug 28, 2026
ce4130e
Run the instance ingest command on the api sync ingest action
cvaroqui Aug 28, 2026
39b8d29
Drop the duplicate ox monitor command
cvaroqui Aug 28, 2026
f78dbae
Sort the root commands in help sections
cvaroqui Aug 28, 2026
b74f3d7
Share the command tree help checks between om and ox
cvaroqui Aug 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions core/commoncmd/args.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package commoncmd

import (
"fmt"
"io"
"strings"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

// discardValue stands for a real flag value in the throwaway flag set
// firstNonFlag() parses with. Parsing must not write the values cobra is
// about to parse itself: a repeated parse would append twice to the slice
// flags.
type discardValue struct {
typ string
}

func (t discardValue) String() string { return "" }
func (t discardValue) Set(string) error { return nil }
func (t discardValue) Type() string { return t.typ }

// ValidateArgs returns an error when args name a command that does not exist.
//
// cobra walks the command chain and, when the deepest command it reaches has
// no Run function, prints that command help and returns no error, silently
// dropping whatever was typed after it. A stale or mistyped command path
// exits 0 that way, which is how the daemon scheduler and the api exec kept
// reporting successful runs of commands renamed under their hard-coded argv.
func ValidateArgs(root *cobra.Command, args []string) error {
if len(args) == 0 {
return nil
}
if strings.HasPrefix(args[0], "__complete") {
// shell completion: cobra answers with candidates, it does not run
return nil
}
cmd, rest, err := root.Find(args)
if err != nil || cmd == nil || cmd.Runnable() {
// an unknown first word is reported by cobra itself
return nil
}
name, ok := firstNonFlag(cmd, rest)
if !ok {
// no command name left: the user asked for the command list
return nil
}
return fmt.Errorf("unknown command %q for %q", name, cmd.CommandPath())
}

// firstNonFlag returns the first positional argument left in args once the
// flags cmd accepts are stripped.
func firstNonFlag(cmd *cobra.Command, args []string) (string, bool) {
fs := pflag.NewFlagSet(cmd.Name(), pflag.ContinueOnError)
fs.ParseErrorsWhitelist.UnknownFlags = true
fs.SetOutput(io.Discard)

add := func(f *pflag.Flag) {
if fs.Lookup(f.Name) != nil {
return
}
shorthand := f.Shorthand
if shorthand != "" && fs.ShorthandLookup(shorthand) != nil {
shorthand = ""
}
fs.AddFlag(&pflag.Flag{
Name: f.Name,
Shorthand: shorthand,
Value: discardValue{typ: f.Value.Type()},
DefValue: f.DefValue,
// carried over so the valueless flags don't eat the next word
NoOptDefVal: f.NoOptDefVal,
})
}
// InheritedFlags() and LocalFlags() both merge the parents persistent
// flags into cmd.Flags() on the way, which Flags() alone does not do
// before the command runs.
cmd.InheritedFlags().VisitAll(add)
cmd.LocalFlags().VisitAll(add)
cmd.Flags().VisitAll(add)

if err := fs.Parse(args); err != nil {
// a flag error is cobra's to report
return "", false
}
if rest := fs.Args(); len(rest) > 0 {
return rest[0], true
}
return "", false
}
101 changes: 101 additions & 0 deletions core/commoncmd/args_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package commoncmd

import (
"testing"

"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

// newTestTree returns a command tree shaped like the om one: a non runnable
// root, non runnable subsystem levels, and a runnable leaf.
func newTestTree() (*cobra.Command, *string) {
var selector string
root := &cobra.Command{Use: "om"}
root.PersistentFlags().StringVar(new(string), "color", "auto", "")
root.PersistentFlags().StringVarP(&selector, "selector", "s", "", "")
root.PersistentFlags().Bool("debug", false, "")

svc := &cobra.Command{Use: "svc"}
instance := &cobra.Command{Use: "instance"}
status := &cobra.Command{
Use: "status",
RunE: func(*cobra.Command, []string) error {
return nil
},
}
status.Flags().BoolP("refresh", "r", false, "")

instance.AddCommand(status)
svc.AddCommand(instance)
root.AddCommand(svc)
return root, &selector
}

func TestValidateArgs(t *testing.T) {
for name, test := range map[string]struct {
args []string
unknown string
}{
"a runnable leaf": {
args: []string{"svc", "instance", "status"},
},
"a runnable leaf and its flags": {
args: []string{"svc", "instance", "status", "-r"},
},
"a bare subsystem asks for the command list": {
args: []string{"svc", "instance"},
},
"no argument at all": {
args: nil,
},
"a valueless flag does not eat the next word": {
args: []string{"svc", "instance", "--debug"},
},
"an unknown command under a subsystem": {
args: []string{"svc", "instance", "resource", "info", "push"},
unknown: "resource",
},
"a flag value is not mistaken for a command": {
args: []string{"svc", "-s", "test/svc/s1", "instance", "resource", "info", "push"},
unknown: "resource",
},
"a flag value passed with an equal sign": {
args: []string{"svc", "--color=no", "instance", "bogus"},
unknown: "bogus",
},
"a valueless flag before an unknown command": {
args: []string{"svc", "instance", "--debug", "bogus"},
unknown: "bogus",
},
"an unknown first word is left to cobra": {
args: []string{"nosuchsubsystem", "instance"},
},
"shell completion never runs a command": {
args: []string{"__complete", "svc", "instance", "bogus"},
},
} {
t.Run(name, func(t *testing.T) {
root, _ := newTestTree()
err := ValidateArgs(root, test.args)
if test.unknown == "" {
assert.NoError(t, err)
return
}
require.Error(t, err)
assert.Contains(t, err.Error(), `"`+test.unknown+`"`)
})
}
}

// ValidateArgs parses the args to tell the flags from the command names, and
// cobra parses them again right after: it must not have written anything.
func TestValidateArgsLeavesTheFlagValuesAlone(t *testing.T) {
root, selector := newTestTree()
args := []string{"svc", "-s", "test/svc/s1", "instance", "bogus"}

require.Error(t, ValidateArgs(root, args))
assert.Equal(t, "", *selector, "the selector flag value was written")
assert.False(t, root.PersistentFlags().Lookup("selector").Changed)
}
23 changes: 21 additions & 2 deletions core/commoncmd/cobra_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,25 @@ func formatArgText(arg string) string {
return strings.Join(lines, "\n")
}

func init() {
cobra.AddTemplateFunc("hasGroupCommands", hasGroupCommands)
}

// hasGroupCommands is true when at least one command of cmd shows up in the
// group. The usage template asks before printing a group title, so a group
// holding no command, or only hidden ones, leaves no empty section behind.
func hasGroupCommands(cmd *cobra.Command, groupID string) bool {
for _, sub := range cmd.Commands() {
if sub.GroupID != groupID {
continue
}
if sub.IsAvailableCommand() || sub.Name() == "help" {
return true
}
}
return false
}

// usageTemplate is the custom template that conditionally includes Arguments section
// Note: We cannot use nindent as it's a Cobra internal function, so we rely on the fact
// that the data is already properly formatted
Expand All @@ -64,10 +83,10 @@ Examples:
{{.Example}}{{end}}{{if .HasAvailableSubCommands}}{{$cmds := .Commands}}{{if eq (len .Groups) 0}}

Available Commands:{{range $cmds}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{else}}{{range $group := .Groups}}{{if hasGroupCommands $ $group.ID}}

{{.Title}}{{range $cmds}}{{if (and (eq .GroupID $group.ID) (or .IsAvailableCommand (eq .Name "help")))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{if not .AllChildCommandsHaveGroup}}

Additional Commands:{{range $cmds}}{{if (and (eq .GroupID "") (or .IsAvailableCommand (eq .Name "help")))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{end}}{{end}}{{if .Annotations.args}}
Expand Down
25 changes: 15 additions & 10 deletions core/commoncmd/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,41 @@ import "github.com/spf13/cobra"

func NewCmdDaemon() *cobra.Command {
return &cobra.Command{
Use: "daemon",
Short: "manage the daemon and its components",
GroupID: GroupIDSubsystems,
Use: "daemon",
Short: "manage the daemon and its components",
}
}

func NewCmdDaemonDNS() *cobra.Command {
return &cobra.Command{
Use: "dns",
Short: "manage the nameserver",
GroupID: GroupIDSubsystems,
Use: "dns",
Short: "manage the nameserver",
}
}

func NewCmdDaemonHeartbeat() *cobra.Command {
return &cobra.Command{
Use: "hb",
Short: "manage heartbeats",
GroupID: GroupIDSubsystems,
Use: "hb",
Short: "manage heartbeats",
}
}

func NewCmdDaemonListener() *cobra.Command {
return &cobra.Command{
Use: "listener",
Short: "manage listeners",
GroupID: GroupIDSubsystems,
Use: "listener",
Short: "manage listeners",
}
}

func NewCmdDaemonRelay() *cobra.Command {
return &cobra.Command{
Use: "relay",
Short: "manage the relay server",
GroupID: GroupIDSubsystems,
Use: "relay",
Short: "manage the relay server",
}
}

Expand Down
Loading