-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathdigConfigs.ts
More file actions
240 lines (192 loc) · 8.7 KB
/
digConfigs.ts
File metadata and controls
240 lines (192 loc) · 8.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
'use strict';
import logger from './logger';
import { BigipConfObj, TmosApp } from './models'
import { RegExTree } from './regex';
import { pathValueFromKey } from './objects';
import { poolsInPolicy } from './pools';
/**
* scans vs config, and discovers child configs
* @param vsName virtual server name
* @param vsConfig virtual server tmos config body
*/
export async function digVsConfig(vsName: string, vsConfig: BigipConfObj["ltm"]['virtual']['key'], configTree: BigipConfObj, rx: RegExTree) {
/**
*
* What do we need to map on next on the virtual servers?:
* - oneConnect?
* - expand the discovery of all profiles (apm and supporting)
*
* Or do we expand the irule references like pools/policies?
*
*/
logger.info(`digging vs config for ${vsName}`);
// clone the app config
const tmpObj = JSON.parse(JSON.stringify(vsConfig));
// move and recrate the original config line
delete tmpObj.line;
const originalCfg = `ltm virtual ${vsName} {${vsConfig.line}}`
tmpObj.lines = [originalCfg];
// name and partition are already set by the parser from vsConfig
const appObj = tmpObj as TmosApp;
if (appObj.pool) {
// dig pool details
// just reassign the parsed pool details into the vs
const body = configTree.ltm?.pool?.[vsConfig.pool];
if (body) {
appObj.lines.push(`ltm pool ${appObj.pool} {${body.line}}`);
}
// raw copy the pool config
appObj.pool = JSON.parse(JSON.stringify(configTree.ltm?.pool?.[vsConfig.pool]));
delete appObj.pool.line;
if (appObj.pool?.members) {
// Clean up line properties from members
delete (appObj.pool.members as any).line;
Object.keys(appObj.pool.members).forEach(n => {
const member = (appObj.pool.members as any)[n];
if (member && typeof member === 'object') {
delete member.line;
}
// loop through all the pool members and get the node details
const name = n.split(':')[0];
const body = configTree.ltm?.node?.[name]
if (body) {
appObj.lines.push(`ltm node ${name} {${body.line}}`);
}
})
}
if (appObj?.pool?.monitor) {
// Handle both string (single monitor) and array (multiple monitors or min X of)
const monitors = Array.isArray(appObj.pool.monitor)
? appObj.pool.monitor
: [appObj.pool.monitor];
const processedMonitors: any[] = [];
monitors.forEach(x => {
if (typeof x !== 'string') {
processedMonitors.push(x); // Already processed
return;
}
const p = pathValueFromKey(configTree.ltm?.monitor, x)
if (p) {
// clone the monitor config
const tmpObj = JSON.parse(JSON.stringify(p.value));
delete tmpObj.line;
processedMonitors.push(tmpObj);
appObj.lines.push(`ltm monitor ${p.path} ${p.key} { ${p.value?.line || ''} }`);
}
})
// Always store monitors as array for consistency
appObj.pool.monitor = processedMonitors;
}
}
if (appObj.profiles) {
// dig profiles details
// profiles is now an object with profile names as keys
// todo: dig profiles deeper => deep parse profiles/settings
// Get profile names from object keys, excluding 'line'
const profileNames = typeof appObj.profiles === 'object' && !Array.isArray(appObj.profiles)
? Object.keys(appObj.profiles).filter(k => k !== 'line')
: (Array.isArray(appObj.profiles) ? appObj.profiles : []);
// Convert profiles to array format for TmosApp compatibility
appObj.profiles = profileNames as any;
profileNames.forEach(name => {
// check the ltm profiles
const x = pathValueFromKey(configTree.ltm?.profile, name);
if (x) {
appObj.lines.push(`ltm profile ${x.path} ${x.key} {${x.value?.line || ''}}`);
}
// check apm profiles
const y = pathValueFromKey(configTree?.apm?.profile?.access, name);
if (y) {
appObj.lines.push(`apm profile access ${y.path} ${y.key} {${y.value?.line || ''}}`);
}
// check asm profile
const z = pathValueFromKey(configTree?.asm?.policy, name);
if (z) {
appObj.lines.push(`asm policy ${z.path} ${z.key} {${z.value?.line || ''}}`);
}
})
}
if (appObj.rules) {
// dig iRule details
// rules is now an object with rule names as keys
// todo: dig deeper like digRuleConfigs() in digConfigs.ts.331
// Get rule names from object keys, excluding 'line'
const ruleNames = typeof appObj.rules === 'object' && !Array.isArray(appObj.rules)
? Object.keys(appObj.rules).filter(k => k !== 'line')
: (Array.isArray(appObj.rules) ? appObj.rules : []);
// Convert rules to array format for TmosApp compatibility
appObj.rules = ruleNames as any;
ruleNames.forEach(name => {
const x = pathValueFromKey(configTree.ltm?.rule, name)
if (x) {
appObj.lines.push(`ltm rule ${x.key} {${x.value}}`);
}
})
}
if (appObj.snat) {
// dig snat details
// if this snat string is the name of a snat pool, then replace with snatpool details
// if not, then its 'automap' or 'none' => nothing to add here
if (configTree.ltm?.snatpool?.[vsConfig.snat]) {
const c = JSON.parse(JSON.stringify(configTree.ltm.snatpool[vsConfig.snat]));
appObj.lines.push(`ltm snatpool ${vsConfig.snat} { ${c.line} }`)
delete c.line;
appObj.snat = c;
}
}
if (appObj.policies) {
// dig policies details
// policies is now an object with policy names as keys
// Get policy names from object keys, excluding 'line'
const policyNames = typeof appObj.policies === 'object' && !Array.isArray(appObj.policies)
? Object.keys(appObj.policies).filter(k => k !== 'line')
: (Array.isArray(appObj.policies) ? appObj.policies : []);
// Convert policies to array format for TmosApp compatibility
appObj.policies = policyNames as any;
policyNames.forEach(name => {
const x = pathValueFromKey(configTree.ltm?.policy, name)
if (x) {
appObj.lines.push(`ltm policy ${x.key} {${x.value?.line || ''}}`);
// got through each policy and dig references (like pools)
const pools = poolsInPolicy(x.value?.line || '')
if (pools) {
pools.forEach(pool => {
const cfg = configTree.ltm?.pool?.[pool]
// if we got here there should be a pool for the reference,
// but just in case, we confirm with (if) statement
if (cfg) {
// push pool config to list
logger.debug(`policy [${x.key}], pool found [${cfg.name}]`);
appObj.lines.push(`ltm pool ${cfg.name} {${cfg.line || ''}}`)
}
})
}
}
})
}
if (appObj.persist) {
// dig persistence details
const x = pathValueFromKey(configTree.ltm?.persistence, appObj.persist)
if (x) {
appObj.lines.push(`ltm persistence ${x.path} ${x.key} {${x.value?.line || ''}}`);
}
}
if (appObj['fallback-persistence']) {
// dig fallback-persistence details
const x = pathValueFromKey(configTree.ltm?.persistence, appObj['fallback-persistence'])
if (x) {
appObj.lines.push(`ltm persistence ${x.path} ${x.key} {${x.value?.line || ''}}`);
}
}
return appObj;
}
/**
* get hostname from json config tree (if present)
* @param configObject to search for hostname
*/
export function getHostname(configObject: BigipConfObj): string | undefined {
if (configObject?.sys?.['global-settings']?.hostname) {
const hostname = configObject.sys["global-settings"].hostname;
return hostname;
}
}