1 | |
2 |
|
3 | async function connect(auth: RT.F5Bigip): Promise<{ |
4 | base: string |
5 | headers: { [key: string]: string } |
6 | release: () => Promise<void> |
7 | }> { |
8 | const base = auth.base_url.replace(/\/+$/, "") |
9 | if (auth.auth_method === "basic") { |
10 | return { |
11 | base, |
12 | headers: { |
13 | Authorization: `Basic ${btoa(`${auth.username}:${auth.password}`)}`, |
14 | }, |
15 | release: async () => {}, |
16 | } |
17 | } |
18 | const login = await fetch(`${base}/mgmt/shared/authn/login`, { |
19 | method: "POST", |
20 | headers: { "Content-Type": "application/json", Accept: "application/json" }, |
21 | body: JSON.stringify({ |
22 | username: auth.username, |
23 | password: auth.password, |
24 | loginProviderName: auth.login_provider_name || "tmos", |
25 | }), |
26 | }) |
27 | if (!login.ok) { |
28 | throw new Error(`${login.status} ${await login.text()}`) |
29 | } |
30 | const token: string = (await login.json()).token.token |
31 | return { |
32 | base, |
33 | headers: { "X-F5-Auth-Token": token }, |
34 | release: async () => { |
35 | await fetch( |
36 | `${base}/mgmt/shared/authz/tokens/${encodeURIComponent(token)}`, |
37 | { |
38 | method: "DELETE", |
39 | headers: { "X-F5-Auth-Token": token }, |
40 | } |
41 | ) |
42 | }, |
43 | } |
44 | } |
45 |
|
46 | |
47 | |
48 | function ref(name: string, partition: string | undefined) { |
49 | const path = name.startsWith("/") ? name : `/${partition || "Common"}/${name}` |
50 | return path.replace(/\//g, "~").replace(/[%?#]/g, encodeURIComponent) |
51 | } |
52 |
|
53 | |
54 | * Set pool member state |
55 | * Enable a pool member, disable it (only persistent or active connections are allowed) or force it offline (only active connections are allowed). Same as the Enabled / Disabled / Forced Offline choice in the BIG-IP UI. |
56 | */ |
57 | export async function main( |
58 | auth: RT.F5Bigip, |
59 | pool: string, |
60 | member: string, |
61 | state: "enabled" | "disabled" | "forced_offline", |
62 | partition: string | undefined |
63 | ) { |
64 | const body = |
65 | state === "enabled" |
66 | ? { session: "user-enabled", state: "user-up" } |
67 | : state === "disabled" |
68 | ? { session: "user-disabled", state: "user-up" } |
69 | : { session: "user-disabled", state: "user-down" } |
70 |
|
71 | const f5 = await connect(auth) |
72 | try { |
73 | const response = await fetch( |
74 | `${f5.base}/mgmt/tm/ltm/pool/${ref(pool, partition)}/members/${ref(member, partition)}`, |
75 | { |
76 | method: "PATCH", |
77 | headers: { |
78 | ...f5.headers, |
79 | "Content-Type": "application/json", |
80 | Accept: "application/json", |
81 | }, |
82 | body: JSON.stringify(body), |
83 | } |
84 | ) |
85 |
|
86 | if (!response.ok) { |
87 | throw new Error(`${response.status} ${await response.text()}`) |
88 | } |
89 |
|
90 | return await response.json() |
91 | } finally { |
92 | await f5.release() |
93 | } |
94 | } |
95 |
|