-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ScriptCommands() for collecting commands
Add the ScriptCmd* types for providing script commands within hive and the ScriptCommands() method for pulling them out from *Hive. Signed-off-by: Jussi Maki <[email protected]>
- Loading branch information
Showing
6 changed files
with
306 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright Authors of Cilium | ||
|
||
package hive | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"io" | ||
"log/slog" | ||
"os" | ||
"time" | ||
|
||
"github.com/cilium/hive/cell" | ||
"github.com/cilium/hive/script" | ||
"golang.org/x/term" | ||
) | ||
|
||
func NewScriptCmd(name string, cmd script.Cmd) ScriptCmdOut { | ||
return ScriptCmdOut{ScriptCmd: ScriptCmd{name, cmd}} | ||
} | ||
|
||
func NewScriptCmds(cmds map[string]script.Cmd) (out ScriptCmdsOut) { | ||
out.ScriptCmds = make([]ScriptCmd, 0, len(cmds)) | ||
for name, cmd := range cmds { | ||
out.ScriptCmds = append(out.ScriptCmds, ScriptCmd{name, cmd}) | ||
} | ||
return out | ||
} | ||
|
||
type ScriptCmd struct { | ||
Name string | ||
Cmd script.Cmd | ||
} | ||
|
||
type ScriptCmds struct { | ||
cell.In | ||
|
||
ScriptCmds []ScriptCmd `group:"script-commands"` | ||
} | ||
|
||
func (sc ScriptCmds) Map() map[string]script.Cmd { | ||
m := make(map[string]script.Cmd, len(sc.ScriptCmds)) | ||
for _, c := range sc.ScriptCmds { | ||
m[c.Name] = c.Cmd | ||
} | ||
return m | ||
} | ||
|
||
type ScriptCmdOut struct { | ||
cell.Out | ||
|
||
ScriptCmd ScriptCmd `group:"script-commands"` | ||
} | ||
|
||
type ScriptCmdsOut struct { | ||
cell.Out | ||
|
||
ScriptCmds []ScriptCmd `group:"script-commands,flatten"` | ||
} | ||
|
||
func hiveScriptCmd(h *Hive, log *slog.Logger) script.Cmd { | ||
const defaultTimeout = time.Minute | ||
return script.Command( | ||
script.CmdUsage{ | ||
Summary: "inspect and manipulate the hive", | ||
Args: "cmd args...", | ||
}, | ||
func(s *script.State, args ...string) (script.WaitFunc, error) { | ||
if len(args) < 1 { | ||
return nil, fmt.Errorf("hive cmd args...\n'cmd' is one of: start, stop, jobs or inspect") | ||
} | ||
switch args[0] { | ||
case "start": | ||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) | ||
defer cancel() | ||
return nil, h.Start(log, ctx) | ||
case "stop": | ||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout) | ||
defer cancel() | ||
return nil, h.Stop(log, ctx) | ||
} | ||
return nil, fmt.Errorf("unknown hive command %q, expected one of: start, stop, jobs or inspect", args[0]) | ||
}, | ||
) | ||
} | ||
|
||
func RunRepl(h *Hive, in *os.File, out *os.File, prompt string) { | ||
// Try to set the input into raw mode. | ||
prev, err := term.MakeRaw(int(in.Fd())) | ||
if err == nil { | ||
defer term.Restore(int(in.Fd()), prev) | ||
} | ||
inout := struct { | ||
io.Reader | ||
io.Writer | ||
}{in, out} | ||
term := term.NewTerminal(inout, prompt) | ||
log := slog.New(slog.NewTextHandler(term, nil)) | ||
|
||
cmds, err := h.ScriptCommands(log) | ||
if err != nil { | ||
log.Error("ScriptCommands()", "error", err) | ||
return | ||
} | ||
for name, cmd := range script.DefaultCmds() { | ||
cmds[name] = cmd | ||
} | ||
|
||
e := script.Engine{ | ||
Cmds: cmds, | ||
Conds: nil, | ||
} | ||
s, err := script.NewState(context.TODO(), "/tmp", nil) | ||
if err != nil { | ||
log.Error("script.NewState", "error", err) | ||
return | ||
} | ||
for { | ||
line, err := term.ReadLine() | ||
if err != nil { | ||
if errors.Is(err, io.EOF) { | ||
return | ||
} else { | ||
panic(err) | ||
} | ||
} | ||
err = e.ExecuteLine(s, line, term) | ||
if err != nil { | ||
fmt.Fprintln(term, err.Error()) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright Authors of Cilium | ||
|
||
package hive_test | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"context" | ||
"strings" | ||
"testing" | ||
|
||
"github.com/cilium/hive" | ||
"github.com/cilium/hive/cell" | ||
"github.com/cilium/hive/hivetest" | ||
"github.com/cilium/hive/script" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func exampleCmd() hive.ScriptCmdOut { | ||
return hive.NewScriptCmd( | ||
"example", | ||
script.Command( | ||
script.CmdUsage{ | ||
Summary: "Example command", | ||
}, | ||
func(s *script.State, args ...string) (script.WaitFunc, error) { | ||
s.Logf("hello") | ||
return nil, nil | ||
}, | ||
), | ||
) | ||
} | ||
|
||
func TestScriptCommands(t *testing.T) { | ||
h := hive.New( | ||
cell.Provide(exampleCmd), | ||
) | ||
cmds, err := h.ScriptCommands(hivetest.Logger(t)) | ||
require.NoError(t, err, "ScriptCommands") | ||
e := script.Engine{ | ||
Cmds: cmds, | ||
} | ||
s, err := script.NewState(context.TODO(), "/tmp", nil) | ||
require.NoError(t, err, "NewState") | ||
script := ` | ||
hive start | ||
example | ||
hive stop | ||
` | ||
bio := bufio.NewReader(bytes.NewBufferString(script)) | ||
var stdout bytes.Buffer | ||
err = e.Execute(s, "", bio, &stdout) | ||
require.NoError(t, err, "Execute") | ||
|
||
expected := `> hive start.*> example.*hello.*> hive stop` | ||
require.Regexp(t, expected, strings.ReplaceAll(stdout.String(), "\n", " ")) | ||
} |