Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion cli/commands/commands_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ func addCommands(d *mflags.Dispatcher) {
// Server command is now defined in commands.go (renamed from dev)

// Cloud registration commands
d.Dispatch("server register", Infer("server register", "Register this cluster with miren.cloud", Register,
d.Dispatch("server register", Infer("server register", "Register this cluster with miren.cloud", RegisterStandalone,
WithExample(mflags.Example{
Name: "Register with cloud",
Body: "miren server register --name my-cluster",
Expand Down
34 changes: 32 additions & 2 deletions cli/commands/server_register.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package commands
import (
"context"
"fmt"
"os/exec"
"strings"
"time"

Expand All @@ -17,6 +18,18 @@ type RegisterOptions struct {
OutputDir string `short:"o" long:"output" description:"Output directory for registration" default:"/var/lib/miren/server"`
}

// RegisterStandalone is the CLI entrypoint for `miren server register`. It runs
// Register and then bounces the local miren.service if one is active, so the
// user doesn't have to restart manually. The install paths call Register
// directly because they own the service lifecycle themselves.
func RegisterStandalone(ctx *Context, opts RegisterOptions) error {
if err := Register(ctx, opts); err != nil {
return err
}
restartMirenServiceIfActive(ctx)
return nil
}

// Register handles cluster registration with miren.cloud
func Register(ctx *Context, opts RegisterOptions) error {
clean := map[string]string{}
Expand Down Expand Up @@ -201,11 +214,28 @@ func Register(ctx *Context, opts RegisterOptions) error {
}
ctx.Info("Configuration saved to: %s", opts.OutputDir)

ctx.Warn("If you're already running the miren server, you must now restart it to apply the new registration.")

return nil
}

// restartMirenServiceIfActive bounces the systemd miren.service so a newly
// saved registration takes effect, but only when systemd is managing a
// currently-running server. Other deployment styles (docker, manual, dev) are
// left alone — install paths run their own lifecycle steps afterward, and
// nothing the user needs to act on remains.
func restartMirenServiceIfActive(ctx *Context) {
if _, err := exec.LookPath("systemctl"); err != nil {
return
}
if err := exec.Command("systemctl", "is-active", "--quiet", "miren.service").Run(); err != nil {
return
}
if err := exec.Command("systemctl", "restart", "miren.service").Run(); err != nil {
ctx.Warn("Failed to restart miren.service: %v. Restart manually to apply the new registration.", err)
return
}
ctx.Info("Restarted miren.service to apply the new registration.")
}

// RegisterStatus displays the current registration status
func RegisterStatus(ctx *Context, opts struct {
Dir string `short:"d" long:"dir" description:"Registration directory" default:"/var/lib/miren/server"`
Expand Down
Loading