cliswitch.bend

cswap-bend-cli@0.1.0.0 · 118 lines · 18 definitions

1import Base
2import cswap-bend-cli@0.1.0.0/setload.bend as Setload
3import cswap-bend-cli@0.1.0.0/store/base.bend as SBase
4import cswap-bend-cli@0.1.0.0/store/seq.bend as SSeq
5import cswap-bend-cli@0.1.0.0/json.bend as Json
6import cswap-bend-cli@0.1.0.0/fs.bend as Fs
7import cswap-bend-cli@0.1.0.0/act.bend as Act
8import cswap-bend-cli@0.1.0.0/cmd.bend as Cmd
9import cswap-bend-cli@0.1.0.0/settings.bend as Settings
10import cswap-bend-cli@0.1.0.0/swbase.bend as SwBase
11import cswap-bend-cli@0.1.0.0/swlive.bend as SwLive
12import cswap-bend-cli@0.1.0.0/switch.bend as Switch
13
14def delay_of(r: Result<&1, &1, U32 & String, String>) -> U32:
15  match r:
16    case Fail{e}:
17      2000
18    case Done{v}:
19      Maybe.default(&2, U32, U32.read(v), 2000)
20
21def oracle_of(r: Result<&1, &1, U32 & String, String>) -> SwLive.Oracle:
22  match r:
23    case Fail{e}:
24      SwLive.OHttp{}
25    case Done{p}:
26      SwLive.OFile{p}
27
28def opts_of(d: Result<&1, &1, U32 & String, String>, o: Result<&1, &1, U32 & String, String>) -> SwLive.Opts:
29  SwLive.Opts{delay_of(d), oracle_of(o)}
30
31# How long to wait before the post-switch re-read ($CSWAP_SWITCH_VERIFY_DELAY_MS,
32# default 2000 ms) and where the ownership lookup comes from ($CSWAP_SWITCH_ORACLE_FILE
33# names a JSON file in tests; unset means the profile endpoint).
34def switch_opts() -> IO(SwLive.Opts):
35  IO.bind(Result<&1, &1, U32 & String, String>, SwLive.Opts, IO.get_env("CSWAP_SWITCH_VERIFY_DELAY_MS"),
36    d => IO.bind(Result<&1, &1, U32 & String, String>, SwLive.Opts, IO.get_env("CSWAP_SWITCH_ORACLE_FILE"), o => IO.pure(SwLive.Opts, opts_of(d, o))))
37
38def warns_text(ws: List<&2, Json.Json>) -> String:
39  match ws:
40    case Nil{}:
41      ""
42    case Con{Json.JStr{w}, t}:
43      "Warning: " ++ w ++ "\n" ++ warns_text(t)
44    case Con{h, t}:
45      warns_text(t)
46
47def switch_text(+j: Json.Json) -> String:
48  warns_text(Json.to_list(Maybe.default(&2, Json.Json, Json.get("warnings", j), Json.JNull{}))) ++ SSeq.field_str(j, "message") ++ "\n"
49
50def switch_ok(+json: Bool, +j: Json.Json) -> Cmd.Out:
51  match json:
52    case True{}:
53      Cmd.doc(j)
54    case False{}:
55      Cmd.Out{0, switch_text(j), ""}
56
57def switch_fail2(+json: Bool, +c: U32, +m: String) -> Cmd.Out:
58  match json:
59    case True{}:
60      Cmd.Out{1, Json.emit_pretty(SwBase.error_envelope(c, m)) ++ "\n", ""}
61    case False{}:
62      Cmd.fail(m)
63
64def switch_fail(+json: Bool, ce: U32 & String) -> Cmd.Out:
65  (c, m) = ce
66  switch_fail2(json, c, m)
67
68def switch_out(+json: Bool, r: Fs.Res(Json.Json), +models: List<&2, String>, +source: String) -> Cmd.Out:
69  match r:
70    case Fail{e}:
71      switch_fail(json, e)
72    case Done{j}:
73      switch_ok(json, SwBase.with_models(j, models, source))
74
75# The models that gate a strategy switch: --model wins, else the
76# autoswitch.model setting; none for a plain rotation or a direct switch.
77type Gate is Data:
78  Gate{models: List<&2, String>, source: String}
79
80def gate_model(model: Maybe<&2, String>, +cfg: Json.Json) -> Gate:
81  match model:
82    case Some{m}:
83      Gate{Setload.model_names(m), "cli"}
84    case None{}:
85      Gate{Setload.model(cfg), "autoswitch.model"}
86
87def gate_of(strategy: Maybe<&2, String>, model: Maybe<&2, String>, +cfg: Json.Json) -> Gate:
88  match strategy:
89    case None{}:
90      Gate{[], ""}
91    case Some{s}:
92      gate_model(model, cfg)
93
94def gate_models(g: Gate) -> List<&2, String>:
95  match g:
96    case Gate{m, s}:
97      m
98
99def switch_run(+ctx: SBase.Ctx, ident: Maybe<&2, String>, +force: Bool, +strategy: Maybe<&2, String>, +gate: Gate, +opts: SwLive.Opts) -> Act.of(Json.Json):
100  match ident:
101    case Some{id}:
102      Switch.switch_to(ctx, id, force, opts)
103    case None{}:
104      Switch.switch_auto(ctx, Maybe.default(&2, String, strategy, ""), gate_models(gate), opts)
105
106def gate_source(g: Gate) -> String:
107  match g:
108    case Gate{m, s}:
109      s
110
111def switch_cmd2(+ctx: SBase.Ctx, ident: Maybe<&2, String>, +force: Bool, +strategy: Maybe<&2, String>, +gate: Gate, +json: Bool, +opts: SwLive.Opts) -> IO(Cmd.Out):
112  IO.bind(Fs.Res(Json.Json), Cmd.Out, switch_run(ctx, ident, force, strategy, gate, opts),
113    r => IO.pure(Cmd.Out, switch_out(json, r, gate_models(gate), gate_source(gate))))
114
115def switch_cmd(+ctx: SBase.Ctx, ident: Maybe<&2, String>, +force: Bool, +strategy: Maybe<&2, String>, model: Maybe<&2, String>, +json: Bool) -> IO(Cmd.Out):
116  IO.bind(SwLive.Opts, Cmd.Out, switch_opts(),
117    opts => IO.bind(Json.Json, Cmd.Out, Setload.load(SBase.root_of(ctx)),
118      cfg => switch_cmd2(ctx, ident, force, strategy, gate_of(strategy, model, cfg), json, opts)))