v3.3.0 b164fe9

config.go RawHistoryFolder

1package cli
2
3import (
4	"context"
5	"fmt"
6	"io"
7	"sort"
8
9	"github.com/bnema/gordon/internal/adapters/in/cli/remote"
10	"github.com/bnema/gordon/internal/adapters/in/cli/ui/components"
11	"github.com/spf13/cobra"
12)
13
14func newConfigCmd() *cobra.Command {
15	cmd := &cobra.Command{
16		Use:   "config",
17		Short: "Inspect Gordon configuration",
18	}
19
20	cmd.AddCommand(newConfigShowCmd(), newConfigValidateCmd())
21
22	return cmd
23}
24
25func newConfigShowCmd() *cobra.Command {
26	var jsonOut bool
27
28	cmd := &cobra.Command{
29		Use:   "show",
30		Short: "Show server configuration",
31		Long: `Display the full Gordon server configuration including server settings,
32auto-route, network isolation, routes, and external routes.
33
34Examples:
35  gordon daemon config show
36  gordon daemon config show --json
37  gordon daemon config show --remote prod`,
38		RunE: func(cmd *cobra.Command, _ []string) error {
39			ctx := cmd.Context()
40			handle, err := resolveControlPlane(cliConfigPath)
41			if err != nil {
42				return err
43			}
44			defer handle.close()
45			return runConfigShow(ctx, handle.plane, cmd.OutOrStdout(), jsonOut)
46		},
47	}
48
49	cmd.Flags().BoolVar(&jsonOut, "json", false, "Output as JSON")
50
51	return cmd
52}
53
54func runConfigShow(ctx context.Context, cp ControlPlane, out io.Writer, jsonOut bool) error {
55	config, err := cp.GetConfig(ctx)
56	if err != nil {
57		return fmt.Errorf("failed to get config: %w", err)
58	}
59
60	if config == nil {
61		return fmt.Errorf("no config available")
62	}
63
64	if jsonOut {
65		return writeJSON(out, config)
66	}
67
68	return renderConfigTable(out, config)
69}
70
71func renderConfigTable(out io.Writer, config *remote.Config) error {
72	if err := renderConfigSummary(out, config); err != nil {
73		return err
74	}
75	return renderConfigExternalRoutes(out, config)
76}
77
78func renderConfigSummary(out io.Writer, config *remote.Config) error {
79	if err := cliWriteLine(out, cliRenderTitle("Gordon Configuration")); err != nil {
80		return err
81	}
82	if err := cliWriteLine(out, ""); err != nil {
83		return err
84	}
85	if err := cliWriteLine(out, cliRenderMeta("Server Port:", fmt.Sprintf("%d", config.Server.Port))); err != nil {
86		return err
87	}
88	if err := cliWriteLine(out, cliRenderMeta("Registry Port:", fmt.Sprintf("%d", config.Server.RegistryPort))); err != nil {
89		return err
90	}
91	if err := cliWriteLine(out, cliRenderMeta("Registry Domain:", config.Server.RegistryDomain)); err != nil {
92		return err
93	}
94	if config.Server.DataDir != "" {
95		if err := cliWriteLine(out, cliRenderMeta("Data Directory:", config.Server.DataDir)); err != nil {
96			return err
97		}
98	}
99	if err := cliWriteLine(out, cliRenderMeta("Network Isolation:", fmt.Sprintf("%v", config.NetworkIsolation.Enabled))); err != nil {
100		return err
101	}
102	if config.NetworkIsolation.Prefix != "" {
103		if err := cliWriteLine(out, cliRenderMeta("Network Prefix:", config.NetworkIsolation.Prefix)); err != nil {
104			return err
105		}
106	}
107	return nil
108}
109
110func renderConfigExternalRoutes(out io.Writer, config *remote.Config) error {
111	if err := cliWriteLine(out, ""); err != nil {
112		return err
113	}
114	if len(config.ExternalRoutes) == 0 {
115		if err := cliWriteLine(out, cliRenderTitle("External Routes")); err != nil {
116			return err
117		}
118		return cliWriteLine(out, cliRenderMuted("No external routes configured"))
119	}
120
121	if err := cliWriteLine(out, cliRenderTitle("External Routes")); err != nil {
122		return err
123	}
124	routes := append([]remote.ExternalRoute(nil), config.ExternalRoutes...)
125	sort.Slice(routes, func(i, j int) bool { return routes[i].Domain < routes[j].Domain })
126
127	rows := make([][]string, 0, len(routes))
128	for _, route := range routes {
129		target := route.Target
130		if target == "" {
131			target = "[redacted]"
132		}
133		rows = append(rows, []string{route.Domain, target})
134	}
135	table := components.NewTable(
136		components.WithColumns([]components.TableColumn{
137			{Title: "Domain", Width: 30},
138			{Title: "Target", Width: 45},
139		}),
140		components.WithRows(rows),
141	)
142	return cliWriteLine(out, table.View())
143}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close