| 1 | package console |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "strings" |
| 6 | ) |
| 7 | |
| 8 | // The nearest-region feature's API and operator messages (spec §19), as |
| 9 | // approved in the nearest-region copy record. Change none of them without a |
| 10 | // new copy review. |
| 11 | // |
| 12 | // Where a message takes a list ("Choose from: %s."), the caller passes the |
| 13 | // region codes and the message joins them with ", ". An empty list never |
| 14 | // renders as a list: the b variant drops the list sentence (codex plan-R4 2, |
| 15 | // a list names only what the door would accept, so it can be empty). |
| 16 | |
| 17 | // reasonText turns a refusal reason (absent, not-hosting, no-secrets-key, |
| 18 | // not-eligible) into the words C16 puts in its brackets (R-absent, |
| 19 | // R-not-hosting, R-no-secrets-key, R-not-eligible). An unknown reason passes |
| 20 | // through unchanged. |
| 21 | func reasonText(reason string) string { |
| 22 | switch reason { |
| 23 | case "absent": |
| 24 | return "no box runs there now" |
| 25 | case "not-hosting": |
| 26 | return "boxes there can't start instances" |
| 27 | case "no-secrets-key": |
| 28 | return "boxes there can't open this deployment's secrets" |
| 29 | case "not-eligible": |
| 30 | return "boxes there don't take ordinary instances" |
| 31 | } |
| 32 | return reason |
| 33 | } |
| 34 | |
| 35 | // msgAppRegionUnavailable is C16, or C16b when can is empty. The verbs are |
| 36 | // the app's region code, the reason text and the joined list. |
| 37 | func msgAppRegionUnavailable(code, reason string, can []string) string { |
| 38 | if len(can) == 0 { |
| 39 | return fmt.Sprintf("this app's region %s can't take new instances right now (%s), and no other region this app may use can either. Try again later.", |
| 40 | code, reasonText(reason)) |
| 41 | } |
| 42 | return fmt.Sprintf("this app's region %s can't take new instances right now (%s). Pass a region to place this instance elsewhere. Regions that can: %s.", |
| 43 | code, reasonText(reason), strings.Join(can, ", ")) |
| 44 | } |
| 45 | |
| 46 | // msgAppRegionNotAllowed is C17, or C17b when allowed is empty. |
| 47 | func msgAppRegionNotAllowed(code string, allowed []string) string { |
| 48 | if len(allowed) == 0 { |
| 49 | return fmt.Sprintf("this app's region %s is not one its instances may use, and no region they may use can take new instances right now. Try again later.", code) |
| 50 | } |
| 51 | return fmt.Sprintf("this app's region %s is not one its instances may use. Allowed: %s. Pass a region to choose one.", |
| 52 | code, strings.Join(allowed, ", ")) |
| 53 | } |
| 54 | |
| 55 | // msgRegionUnknown is C18, or C18b when choices is empty. |
| 56 | func msgRegionUnknown(code string, choices []string) string { |
| 57 | if len(choices) == 0 { |
| 58 | return fmt.Sprintf("region %s is not one this platform runs in. Run the command without --region.", code) |
| 59 | } |
| 60 | return fmt.Sprintf("region %s is not one this platform runs in. Choose from: %s.", code, strings.Join(choices, ", ")) |
| 61 | } |
| 62 | |
| 63 | // msgRegionNotArmed is C19, or C19b when choices is empty. |
| 64 | func msgRegionNotArmed(code string, choices []string) string { |
| 65 | if len(choices) == 0 { |
| 66 | return fmt.Sprintf("region %s can't take new apps right now. Run the command without --region.", code) |
| 67 | } |
| 68 | return fmt.Sprintf("region %s can't take new apps right now. Choose from: %s.", code, strings.Join(choices, ", ")) |
| 69 | } |
| 70 | |
| 71 | // msgAppRegionUnreadable is C20. |
| 72 | const msgAppRegionUnreadable = "could not read this app's region. Try again." |
| 73 | |
| 74 | // msgReplicaOverlap is C26. The region code fills both verbs. |
| 75 | func msgReplicaOverlap(code string) string { |
| 76 | return fmt.Sprintf("this app's region %s is also one of this instance's replica placements. Pass a region for the instance, or drop %s from replicas.", code, code) |
| 77 | } |
| 78 | |
| 79 | // msgPolicyUnreadable is C27. |
| 80 | const msgPolicyUnreadable = "could not read this app's instance policy, so there is no region suggestion. Try again." |
| 81 | |
| 82 | // msgAppRegionUnconfirmed is C28. |
| 83 | func msgAppRegionUnconfirmed(code string) string { |
| 84 | return fmt.Sprintf("could not confirm that this app's region %s can take new instances. Try again, or pass a region.", code) |
| 85 | } |
| 86 | |
| 87 | // msgPlacementDiscrepancy is C29, an operator log line. The app name fills |
| 88 | // the second and third verbs. |
| 89 | func msgPlacementDiscrepancy(host, app, code string) string { |
| 90 | return fmt.Sprintf("possible placement discrepancy: %s of %s has no region, but %s's region is %s. It may be a deliberate home override; review it.", host, app, app, code) |
| 91 | } |
| 92 | |
| 93 | // msgNoSecretsKey is C31 (R9). |
| 94 | func msgNoSecretsKey(code string) string { |
| 95 | return fmt.Sprintf("region %s can't run instances right now: its boxes don't hold this deployment's secrets key, so an instance there would start without its config or secrets. Choose another region.", code) |
| 96 | } |
| 97 | |