Skip to content

Commit df0beab

Browse files
authored
fix(BRE2-825): Ensure sudo prompts are always visible (#332)
* fix(BRE2-825): Ensure sudo prompts are always visible * header details
1 parent 090deec commit df0beab

4 files changed

Lines changed: 29 additions & 77 deletions

File tree

pkg/cmd/deregister/deregister.go

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -157,36 +157,22 @@ func runDeregister(ctx context.Context, t *terminal.Terminal, s DeregisterStore,
157157
}
158158
}
159159

160-
const clearLine = "\033[2K\n"
161-
162160
t.Vprint(t.Yellow("[Step 1/4] Removing node from Brev..."))
163-
sp := t.NewSpinner()
164-
sp.Suffix = " Deregistering device..."
165-
sp.Start()
166161
client := deps.nodeClients.NewNodeClient(s, config.GlobalConfig.GetBrevPublicAPIURL())
167162
_, err = client.RemoveNode(ctx, connect.NewRequest(&nodev1.RemoveNodeRequest{
168163
ExternalNodeId: reg.ExternalNodeID,
169164
}))
170-
sp.FinalMSG = clearLine
171-
sp.Stop()
172165
if err != nil {
173166
return fmt.Errorf("failed to deregister node: %w", err)
174167
}
175168
t.Vprintf("%s Node removed from Brev.\n", t.Green(" ✓"))
176169
t.Vprint("")
177170

178171
t.Vprint(t.Yellow("[Step 2/4] Removing Brev SSH keys..."))
179-
sp = t.NewSpinner()
180-
sp.Suffix = " Deregistering device..."
181-
sp.Start()
182172
if osUser == nil {
183-
sp.FinalMSG = clearLine
184-
sp.Stop()
185173
t.Vprintf(" %s\n", t.Yellow("Skipped: could not determine current user"))
186174
} else {
187175
removed, kerr := deps.sshKeys.RemoveBrevKeys(osUser)
188-
sp.FinalMSG = clearLine
189-
sp.Stop()
190176
switch {
191177
case kerr != nil:
192178
t.Vprintf(" %s\n", t.Yellow(fmt.Sprintf("Warning: failed to remove Brev SSH keys: %v", kerr)))
@@ -202,12 +188,7 @@ func runDeregister(ctx context.Context, t *terminal.Terminal, s DeregisterStore,
202188
t.Vprint("")
203189

204190
t.Vprint(t.Yellow("[Step 3/4] Removing Brev tunnel..."))
205-
sp = t.NewSpinner()
206-
sp.Suffix = " Deregistering device..."
207-
sp.Start()
208191
err = deps.netbird.Uninstall()
209-
sp.FinalMSG = clearLine
210-
sp.Stop()
211192
if err != nil {
212193
t.Vprintf(" %s\n", t.Yellow(fmt.Sprintf("Warning: failed to remove Brev tunnel: %v", err)))
213194
} else {
@@ -216,12 +197,7 @@ func runDeregister(ctx context.Context, t *terminal.Terminal, s DeregisterStore,
216197
t.Vprint("")
217198

218199
t.Vprint(t.Yellow("[Step 4/4] Removing registration data..."))
219-
sp = t.NewSpinner()
220-
sp.Suffix = " Deregistering device..."
221-
sp.Start()
222200
err = deps.registrationStore.Delete()
223-
sp.FinalMSG = clearLine
224-
sp.Stop()
225201
if err != nil {
226202
t.Vprintf(" %s\n", t.Yellow(fmt.Sprintf("Warning: failed to remove local registration file: %v", err)))
227203
t.Vprint(" You can manually remove it with: rm /etc/brev/device_registration.json")

pkg/cmd/register/device_registration_store.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,12 @@ func (s *FileRegistrationStore) Exists() (bool, error) {
120120
// sudoWriteFile creates the parent directory and writes data to path using sudo.
121121
func sudoWriteFile(path string, data []byte) error {
122122
dir := filepath.Dir(path)
123-
if err := exec.Command("sudo", "mkdir", "-p", dir).Run(); err != nil { //nolint:gosec // fixed base path
124-
return fmt.Errorf("sudo mkdir %s failed: %w", dir, err)
125-
}
126-
cmd := exec.Command("sudo", "tee", path) //nolint:gosec // fixed base path
123+
script := fmt.Sprintf("mkdir -p '%s' && tee '%s' > /dev/null && chmod 644 '%s'", dir, path, path)
124+
cmd := exec.Command("sudo", "bash", "-c", script) //nolint:gosec // fixed base path
127125
cmd.Stdin = bytes.NewReader(data)
128-
cmd.Stdout = nil // suppress tee's stdout echo
126+
cmd.Stderr = os.Stderr
129127
if err := cmd.Run(); err != nil {
130-
return fmt.Errorf("sudo tee %s failed: %w", path, err)
131-
}
132-
if err := exec.Command("sudo", "chmod", "644", path).Run(); err != nil { //nolint:gosec // fixed base path
133-
return fmt.Errorf("sudo chmod %s failed: %w", path, err)
128+
return fmt.Errorf("failed to write %s: %w", path, err)
134129
}
135130
return nil
136131
}

pkg/cmd/register/netbird.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func InstallNetbird() error {
1414

1515
script := `(curl -fsSL https://pkgs.netbird.io/install.sh | sh) || (curl -fsSL https://pkgs.netbird.io/install.sh | sh -s -- --update)`
1616

17-
cmd := exec.Command("bash", "-c", script) // #nosec G204
17+
cmd := exec.Command("sudo", "bash", "-c", script) // #nosec G204
1818
if err := cmd.Run(); err != nil {
1919
return fmt.Errorf("failed to install Brev tunnel: %w", err)
2020
}
@@ -28,7 +28,7 @@ func runSetupCommand(script string) error {
2828
if !strings.HasPrefix(strings.TrimSpace(script), "netbird up") {
2929
return fmt.Errorf("unexpected setup command")
3030
}
31-
cmd := exec.Command("bash", "-c", script) // #nosec G204
31+
cmd := exec.Command("sudo", "bash", "-c", script) // #nosec G204
3232
if err := cmd.Run(); err != nil {
3333
return fmt.Errorf("setup command failed: %w", err)
3434
}
@@ -42,28 +42,28 @@ func runSetupCommand(script string) error {
4242
// disconnected or stopped after deregistration.
4343
func UninstallNetbird() error {
4444
script := `
45-
sudo netbird down 2>/dev/null
46-
sudo netbird service stop 2>/dev/null
47-
sudo netbird service uninstall 2>/dev/null
45+
netbird down 2>/dev/null || true
46+
netbird service stop 2>/dev/null || true
47+
netbird service uninstall 2>/dev/null || true
4848
4949
PKG_MGR="bin"
5050
if [ -f /etc/netbird/install.conf ]; then
5151
PKG_MGR=$(grep -oP '(?<=package_manager=)\S+' /etc/netbird/install.conf 2>/dev/null || echo "bin")
5252
fi
5353
5454
case "$PKG_MGR" in
55-
apt) sudo apt-get remove -y netbird || true ;;
56-
dnf) sudo dnf remove -y netbird || true ;;
57-
yum) sudo yum remove -y netbird || true ;;
58-
*) sudo rm -f /usr/bin/netbird /usr/local/bin/netbird ;;
55+
apt) apt-get remove -y netbird || true ;;
56+
dnf) dnf remove -y netbird || true ;;
57+
yum) yum remove -y netbird || true ;;
58+
*) rm -f /usr/bin/netbird /usr/local/bin/netbird ;;
5959
esac
6060
61-
sudo rm -rf /etc/netbird
62-
sudo rm -rf /var/lib/netbird
63-
sudo rm -f /usr/bin/netbird /usr/local/bin/netbird
61+
rm -rf /etc/netbird
62+
rm -rf /var/lib/netbird
63+
rm -f /usr/bin/netbird /usr/local/bin/netbird
6464
`
6565

66-
cmd := exec.Command("bash", "-c", script) // #nosec G204
66+
cmd := exec.Command("sudo", "bash", "-c", script) // #nosec G204
6767
if err := cmd.Run(); err != nil {
6868
return fmt.Errorf("failed to uninstall Brev tunnel: %w", err)
6969
}

pkg/cmd/register/register.go

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010

1111
nodev1 "buf.build/gen/go/brevdev/devplane/protocolbuffers/go/devplaneapi/v1"
1212
"connectrpc.com/connect"
13-
"github.com/briandowns/spinner"
1413
"github.com/google/uuid"
1514

1615
"github.com/brevdev/brev-cli/pkg/config"
@@ -212,9 +211,11 @@ func runRegister(ctx context.Context, t *terminal.Terminal, s RegisterStore, opt
212211
t.Vprintf(" %s %s\n", t.Green(fmt.Sprintf("%-14s", "Organization:")), t.BoldBlue(org.Name+" ("+org.ID+")"))
213212
t.Vprint("")
214213
t.Vprint(t.Yellow(" This will:"))
215-
t.Vprint(" 1. Set up Brev tunnel")
214+
t.Vprint(" 1. Download and install Brev tunnel")
216215
t.Vprint(" 2. Collect hardware profile")
217216
t.Vprint(" 3. Register this machine with Brev")
217+
t.Vprint(" 4. Store registration data")
218+
t.Vprint(" 5. Connect device to Brev")
218219
t.Vprint("")
219220

220221
if opts.interactive {
@@ -260,38 +261,18 @@ func runRegister(ctx context.Context, t *terminal.Terminal, s RegisterStore, opt
260261
// runRegisterSteps performs netbird install, hardware profile, AddNode, save registration, and runSetup.
261262
// It does not prompt or enable SSH. Used by both flag-driven and prompt-driven flows.
262263
func runRegisterSteps(ctx context.Context, t *terminal.Terminal, s RegisterStore, name string, org *entity.Organization, deps registerDeps) (*DeviceRegistration, error) {
263-
const clearLine = "\033[2K\n"
264264
t.Vprint("")
265265

266-
// Stop spinner (and clear its line) before any of our prints so stdout and stderr don't interleave.
267-
var sp *spinner.Spinner
268-
stopSpinner := func() {
269-
if sp != nil {
270-
sp.FinalMSG = clearLine
271-
sp.Stop()
272-
sp = nil
273-
}
274-
}
275-
defer stopSpinner()
276-
277-
t.Vprint(t.Yellow("[Step 1/3] Setting up Brev tunnel..."))
278-
sp = t.NewSpinner()
279-
sp.Suffix = " Registering device..."
280-
sp.Start()
266+
t.Vprint(t.Yellow("[Step 1/5] Downloading and installing Brev tunnel..."))
281267
err := deps.netbird.Install()
282-
stopSpinner()
283268
if err != nil {
284269
return nil, fmt.Errorf("brev tunnel setup failed: %w", err)
285270
}
286271
t.Vprintf("%s Brev tunnel ready.\n", t.Green(" ✓"))
287272

288273
t.Vprint("")
289-
t.Vprint(t.Yellow("[Step 2/3] Collecting hardware profile..."))
290-
sp = t.NewSpinner()
291-
sp.Suffix = " Registering device..."
292-
sp.Start()
274+
t.Vprint(t.Yellow("[Step 2/5] Collecting hardware profile..."))
293275
hwProfile, err := deps.hardwareProfiler.Profile()
294-
stopSpinner()
295276
if err != nil {
296277
return nil, fmt.Errorf("failed to collect hardware profile: %w", err)
297278
}
@@ -301,10 +282,7 @@ func runRegisterSteps(ctx context.Context, t *terminal.Terminal, s RegisterStore
301282
t.Vprint(FormatHardwareProfile(hwProfile))
302283

303284
t.Vprint("")
304-
t.Vprint(t.Yellow("[Step 3/3] Registering with Brev..."))
305-
sp = t.NewSpinner()
306-
sp.Suffix = " Registering device..."
307-
sp.Start()
285+
t.Vprint(t.Yellow("[Step 3/5] Registering device with Brev..."))
308286
deviceID := uuid.New().String()
309287
client := deps.nodeClients.NewNodeClient(s, config.GlobalConfig.GetBrevPublicAPIURL())
310288
addResp, err := client.AddNode(ctx, connect.NewRequest(&nodev1.AddNodeRequest{
@@ -314,7 +292,6 @@ func runRegisterSteps(ctx context.Context, t *terminal.Terminal, s RegisterStore
314292
NodeSpec: toProtoNodeSpec(hwProfile),
315293
}))
316294
if err != nil {
317-
stopSpinner()
318295
return nil, fmt.Errorf("failed to register node: %w", err)
319296
}
320297

@@ -328,13 +305,17 @@ func runRegisterSteps(ctx context.Context, t *terminal.Terminal, s RegisterStore
328305
RegisteredAt: time.Now().UTC().Format(time.RFC3339),
329306
HardwareProfile: *hwProfile,
330307
}
308+
309+
t.Vprint("")
310+
t.Vprint(t.Yellow("[Step 4/5] Storing registration data..."))
331311
if err := deps.registrationStore.Save(reg); err != nil {
332-
stopSpinner()
333312
return nil, fmt.Errorf("node registered but failed to save locally: %w", err)
334313
}
335314

315+
t.Vprint("")
316+
t.Vprint(t.Yellow("[Step 5/5] Connecting device to Brev..."))
336317
runSetup(node, t, deps)
337-
stopSpinner()
318+
338319
t.Vprintf("%s Node registered.\n", t.Green(" ✓"))
339320
t.Vprintf("%s Registration complete.\n", t.Green(" ✓"))
340321
return reg, nil

0 commit comments

Comments
 (0)