Add Galaxy repository API and clients
This commit is contained in:
@@ -8,8 +8,10 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"gitea.dohertylan.com/dohertj2/mxaccessgw/clients/go/mxgateway"
|
||||
@@ -88,6 +90,14 @@ func runWithIO(ctx context.Context, args []string, stdout, stderr io.Writer) err
|
||||
return runStreamEvents(ctx, args[1:], stdout, stderr)
|
||||
case "smoke":
|
||||
return runSmoke(ctx, args[1:], stdout, stderr)
|
||||
case "galaxy-test-connection":
|
||||
return runGalaxyTestConnection(ctx, args[1:], stdout, stderr)
|
||||
case "galaxy-last-deploy":
|
||||
return runGalaxyLastDeploy(ctx, args[1:], stdout, stderr)
|
||||
case "galaxy-discover":
|
||||
return runGalaxyDiscover(ctx, args[1:], stdout, stderr)
|
||||
case "galaxy-watch":
|
||||
return runGalaxyWatch(ctx, args[1:], stdout, stderr)
|
||||
default:
|
||||
writeUsage(stderr)
|
||||
return fmt.Errorf("unknown command %q", args[0])
|
||||
@@ -651,5 +661,226 @@ type protojsonMessage interface {
|
||||
}
|
||||
|
||||
func writeUsage(writer io.Writer) {
|
||||
fmt.Fprintln(writer, "usage: mxgw-go <version|open-session|close-session|register|add-item|advise|subscribe-bulk|unsubscribe-bulk|write|stream-events|smoke>")
|
||||
fmt.Fprintln(writer, "usage: mxgw-go <version|open-session|close-session|register|add-item|advise|subscribe-bulk|unsubscribe-bulk|write|stream-events|smoke|galaxy-test-connection|galaxy-last-deploy|galaxy-discover|galaxy-watch>")
|
||||
}
|
||||
|
||||
func dialGalaxyForCommand(ctx context.Context, common *commonOptions) (*mxgateway.GalaxyClient, commonOptions, error) {
|
||||
options, err := common.resolved()
|
||||
if err != nil {
|
||||
return nil, options, err
|
||||
}
|
||||
|
||||
client, err := mxgateway.DialGalaxy(ctx, mxgateway.Options{
|
||||
Endpoint: options.Endpoint,
|
||||
APIKey: options.apiKeyValue,
|
||||
Plaintext: options.Plaintext,
|
||||
CACertFile: options.CACertFile,
|
||||
ServerNameOverride: options.ServerName,
|
||||
CallTimeout: options.timeout,
|
||||
})
|
||||
return client, options, err
|
||||
}
|
||||
|
||||
func runGalaxyTestConnection(ctx context.Context, args []string, stdout, stderr io.Writer) error {
|
||||
flags := flag.NewFlagSet("galaxy-test-connection", flag.ContinueOnError)
|
||||
flags.SetOutput(stderr)
|
||||
common := bindCommonFlags(flags)
|
||||
jsonOutput := flags.Bool("json", false, "write JSON output")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, options, err := dialGalaxyForCommand(ctx, common)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
ok, err := client.TestConnection(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *jsonOutput {
|
||||
return writeJSON(stdout, map[string]any{
|
||||
"command": "galaxy-test-connection",
|
||||
"options": options,
|
||||
"ok": ok,
|
||||
})
|
||||
}
|
||||
fmt.Fprintln(stdout, ok)
|
||||
return nil
|
||||
}
|
||||
|
||||
func runGalaxyLastDeploy(ctx context.Context, args []string, stdout, stderr io.Writer) error {
|
||||
flags := flag.NewFlagSet("galaxy-last-deploy", flag.ContinueOnError)
|
||||
flags.SetOutput(stderr)
|
||||
common := bindCommonFlags(flags)
|
||||
jsonOutput := flags.Bool("json", false, "write JSON output")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, options, err := dialGalaxyForCommand(ctx, common)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
deployTime, present, err := client.GetLastDeployTime(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *jsonOutput {
|
||||
payload := map[string]any{
|
||||
"command": "galaxy-last-deploy",
|
||||
"options": options,
|
||||
"present": present,
|
||||
}
|
||||
if present {
|
||||
payload["timeOfLastDeploy"] = deployTime.UTC().Format(time.RFC3339Nano)
|
||||
}
|
||||
return writeJSON(stdout, payload)
|
||||
}
|
||||
if !present {
|
||||
fmt.Fprintln(stdout, "absent")
|
||||
return nil
|
||||
}
|
||||
fmt.Fprintln(stdout, deployTime.UTC().Format(time.RFC3339Nano))
|
||||
return nil
|
||||
}
|
||||
|
||||
func runGalaxyDiscover(ctx context.Context, args []string, stdout, stderr io.Writer) error {
|
||||
flags := flag.NewFlagSet("galaxy-discover", flag.ContinueOnError)
|
||||
flags.SetOutput(stderr)
|
||||
common := bindCommonFlags(flags)
|
||||
jsonOutput := flags.Bool("json", false, "write JSON output")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, options, err := dialGalaxyForCommand(ctx, common)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
objects, err := client.DiscoverHierarchy(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if *jsonOutput {
|
||||
marshaled := make([]json.RawMessage, 0, len(objects))
|
||||
for _, obj := range objects {
|
||||
marshaled = append(marshaled, mustMarshalProto(obj))
|
||||
}
|
||||
return writeJSON(stdout, map[string]any{
|
||||
"command": "galaxy-discover",
|
||||
"options": options,
|
||||
"objects": marshaled,
|
||||
})
|
||||
}
|
||||
for _, obj := range objects {
|
||||
fmt.Fprintf(stdout, "%d\t%s\t%s\t(attrs=%d)\n", obj.GetGobjectId(), obj.GetTagName(), obj.GetContainedName(), len(obj.GetAttributes()))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func runGalaxyWatch(ctx context.Context, args []string, stdout, stderr io.Writer) error {
|
||||
flags := flag.NewFlagSet("galaxy-watch", flag.ContinueOnError)
|
||||
flags.SetOutput(stderr)
|
||||
common := bindCommonFlags(flags)
|
||||
jsonOutput := flags.Bool("json", false, "write JSON output")
|
||||
lastSeen := flags.String("last-seen-deploy-time", "", "RFC3339 timestamp; when set, suppresses the bootstrap event")
|
||||
limit := flags.Int("limit", 0, "maximum events to read; 0 means unbounded (Ctrl+C to stop)")
|
||||
|
||||
if err := flags.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var lastSeenPtr *time.Time
|
||||
if *lastSeen != "" {
|
||||
parsed, err := time.Parse(time.RFC3339, *lastSeen)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid -last-seen-deploy-time: %w", err)
|
||||
}
|
||||
lastSeenPtr = &parsed
|
||||
}
|
||||
|
||||
client, _, err := dialGalaxyForCommand(ctx, common)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
signalCtx, stopSignals := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
|
||||
defer stopSignals()
|
||||
|
||||
streamCtx, cancelStream := context.WithCancel(signalCtx)
|
||||
defer cancelStream()
|
||||
|
||||
events, errs, err := client.WatchDeployEvents(streamCtx, lastSeenPtr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
count := 0
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-events:
|
||||
if !ok {
|
||||
// Drain any terminal error before returning.
|
||||
if streamErr, errOk := <-errs; errOk && streamErr != nil {
|
||||
return streamErr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if *jsonOutput {
|
||||
fmt.Fprintln(stdout, string(mustMarshalProto(event)))
|
||||
} else {
|
||||
fmt.Fprintln(stdout, formatDeployEvent(event))
|
||||
}
|
||||
count++
|
||||
if *limit > 0 && count >= *limit {
|
||||
cancelStream()
|
||||
return nil
|
||||
}
|
||||
case streamErr, ok := <-errs:
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if streamErr != nil {
|
||||
return streamErr
|
||||
}
|
||||
case <-signalCtx.Done():
|
||||
cancelStream()
|
||||
// Allow goroutine to drain.
|
||||
for range events {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func formatDeployEvent(event *mxgateway.DeployEvent) string {
|
||||
observed := ""
|
||||
if ts := event.GetObservedAt(); ts != nil {
|
||||
observed = ts.AsTime().UTC().Format(time.RFC3339Nano)
|
||||
}
|
||||
deploy := "absent"
|
||||
if event.GetTimeOfLastDeployPresent() {
|
||||
if ts := event.GetTimeOfLastDeploy(); ts != nil {
|
||||
deploy = ts.AsTime().UTC().Format(time.RFC3339Nano)
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
"seq=%d observed=%s deploy=%s objects=%d attributes=%d",
|
||||
event.GetSequence(),
|
||||
observed,
|
||||
deploy,
|
||||
event.GetObjectCount(),
|
||||
event.GetAttributeCount(),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user