Add undeploy command: full inverse of deploy
Implements `mcp undeploy <service>` which tears down all infrastructure for a service: removes mc-proxy routes, DNS records, TLS certificates, stops and removes containers, releases allocated ports, and marks the service inactive. This fills the gap between `stop` (temporary pause) and `purge` (registry cleanup). Undeploy is the complete teardown that returns the node to the state before the service was deployed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,7 @@ func main() {
|
||||
root.AddCommand(loginCmd())
|
||||
root.AddCommand(buildCmd())
|
||||
root.AddCommand(deployCmd())
|
||||
root.AddCommand(undeployCmd())
|
||||
root.AddCommand(stopCmd())
|
||||
root.AddCommand(startCmd())
|
||||
root.AddCommand(restartCmd())
|
||||
|
||||
63
cmd/mcp/undeploy.go
Normal file
63
cmd/mcp/undeploy.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
mcpv1 "git.wntrmute.dev/mc/mcp/gen/mcp/v1"
|
||||
"git.wntrmute.dev/mc/mcp/internal/config"
|
||||
"git.wntrmute.dev/mc/mcp/internal/servicedef"
|
||||
)
|
||||
|
||||
func undeployCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "undeploy <service>",
|
||||
Short: "Fully undeploy a service: remove routes, DNS, certs, and containers",
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
cfg, err := config.LoadCLIConfig(cfgPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load config: %w", err)
|
||||
}
|
||||
|
||||
serviceName := args[0]
|
||||
defPath := filepath.Join(cfg.Services.Dir, serviceName+".toml")
|
||||
|
||||
def, err := servicedef.Load(defPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load service def: %w", err)
|
||||
}
|
||||
|
||||
// Set active=false in the local file.
|
||||
active := false
|
||||
def.Active = &active
|
||||
if err := servicedef.Write(defPath, def); err != nil {
|
||||
return fmt.Errorf("write service def: %w", err)
|
||||
}
|
||||
|
||||
address, err := findNodeAddress(cfg, def.Node)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
client, conn, err := dialAgent(address, cfg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("dial agent: %w", err)
|
||||
}
|
||||
defer func() { _ = conn.Close() }()
|
||||
|
||||
resp, err := client.UndeployService(context.Background(), &mcpv1.UndeployServiceRequest{
|
||||
Name: serviceName,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("undeploy service: %w", err)
|
||||
}
|
||||
|
||||
printComponentResults(resp.GetResults())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user