package main import ( "context" "encoding/json" "flag" "fmt" "log" "net/http" ) // ---- carlos system cancel-activation ----------------------------------- // runSystemCancelActivation releases an executable activation reservation // that was never published (claim plan 9, I-4). While one is held, every // other promote and every rollback of its channel is refused, and no box can // complete it because no box ever saw it. The console fences the pointer // before it removes the reservation, and refuses one that was published: // that one is released when its boxes report completion. func runSystemCancelActivation(args []string) { fs := flag.NewFlagSet("system cancel-activation", flag.ExitOnError) consoleFlag := consoleOption(fs, "console origin (default: the only logged-in one)") channel := fs.String("channel", "", "canary or stable (required)") activation := fs.String("activation", "", "the activation ID you expect; refused if a different one is held") yes := fs.Bool("yes", false, "do not ask") fs.Usage = flagUsage(fs, "") fs.Parse(args) if *channel == "" { log.Fatal("--channel is required") } sess := requireDeployAPISession(*consoleFlag) if !*yes { if !interactiveTerminal() { log.Fatal("no terminal to confirm on; pass --yes") } if !promptYes(stdout, fmt.Sprintf("cancel the unpublished activation held for %s? no box changes release [y/N] ", *channel)) { return } } body := map[string]string{"channel": *channel} if *activation != "" { body["activation"] = *activation } st, raw, err := sess.postJSON(context.Background(), "/api/cli/system/activation/cancel", body) if err != nil { log.Fatalf("carlos system cancel-activation: %v", err) } if st != http.StatusOK { log.Fatalf("carlos system cancel-activation: %s", apiErrorFromBody(st, raw)) } var out struct { Activation string `json:"activation"` } _ = json.Unmarshal(raw, &out) fmt.Fprintf(stdout, "%s %s on %s\n", colorFor(stdout).ok("cancelled activation"), out.Activation, *channel) }