besapi 3.7.7__tar.gz → 3.7.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {besapi-3.7.7/src/besapi.egg-info → besapi-3.7.8}/PKG-INFO +1 -1
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi/besapi.py +1 -1
- {besapi-3.7.7 → besapi-3.7.8/src/besapi.egg-info}/PKG-INFO +1 -1
- {besapi-3.7.7 → besapi-3.7.8}/src/bescli/bescli.py +99 -39
- {besapi-3.7.7 → besapi-3.7.8}/LICENSE.txt +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/MANIFEST.in +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/README.md +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/pyproject.toml +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/setup.cfg +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/setup.py +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi/__init__.py +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi/__main__.py +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi/plugin_utilities.py +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi/schemas/BES.xsd +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi/schemas/BESAPI.xsd +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi/schemas/BESActionSettings.xsd +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi.egg-info/SOURCES.txt +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi.egg-info/dependency_links.txt +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi.egg-info/requires.txt +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/besapi.egg-info/top_level.txt +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/bescli/__init__.py +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/src/bescli/__main__.py +0 -0
- {besapi-3.7.7 → besapi-3.7.8}/tests/tests.py +0 -0
|
@@ -10,6 +10,7 @@ Simple command line interface for the BES (BigFix) REST API.
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
import getpass
|
|
13
|
+
import json
|
|
13
14
|
import logging
|
|
14
15
|
import os
|
|
15
16
|
import site
|
|
@@ -56,8 +57,50 @@ class BESCLInterface(Cmd):
|
|
|
56
57
|
# set default config file path
|
|
57
58
|
self.conf_path = os.path.expanduser("~/.besapi.conf")
|
|
58
59
|
self.CONFPARSER = SafeConfigParser()
|
|
60
|
+
# for completion:
|
|
61
|
+
self.api_resources = []
|
|
59
62
|
self.do_conf()
|
|
60
63
|
|
|
64
|
+
def parse_help_resources(self):
|
|
65
|
+
"""get api resources from help"""
|
|
66
|
+
if self.bes_conn:
|
|
67
|
+
help_result = self.bes_conn.get("help")
|
|
68
|
+
help_result = help_result.text.split("\n")
|
|
69
|
+
# print(help_result)
|
|
70
|
+
help_resources = []
|
|
71
|
+
for item in help_result:
|
|
72
|
+
if "/api/" in item:
|
|
73
|
+
_, _, res = item.partition("/api/")
|
|
74
|
+
# strip whitespace just in case:
|
|
75
|
+
help_resources.append(res.strip())
|
|
76
|
+
|
|
77
|
+
return help_resources
|
|
78
|
+
else:
|
|
79
|
+
return [
|
|
80
|
+
"actions",
|
|
81
|
+
"clientqueryresults",
|
|
82
|
+
"dashboardvariables",
|
|
83
|
+
"help",
|
|
84
|
+
"login",
|
|
85
|
+
"query",
|
|
86
|
+
"relaysites",
|
|
87
|
+
"serverinfo",
|
|
88
|
+
"sites",
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
def complete_api_resources(self, text, line, begidx, endidx):
|
|
92
|
+
"""define completion for apis"""
|
|
93
|
+
|
|
94
|
+
# only initialize once
|
|
95
|
+
if not self.api_resources:
|
|
96
|
+
self.api_resources = self.parse_help_resources()
|
|
97
|
+
|
|
98
|
+
# TODO: make this work to complete only the first word after get/post/delete
|
|
99
|
+
# return the matching subset:
|
|
100
|
+
return [name for name in self.api_resources if name.startswith(text)]
|
|
101
|
+
|
|
102
|
+
complete_get = complete_api_resources
|
|
103
|
+
|
|
61
104
|
def do_get(self, line):
|
|
62
105
|
"""Perform get request to BigFix server using provided api endpoint argument"""
|
|
63
106
|
|
|
@@ -80,16 +123,18 @@ class BESCLInterface(Cmd):
|
|
|
80
123
|
b = self.bes_conn.get(robjs[0])
|
|
81
124
|
# print objectify.ObjectPath(robjs[1:])
|
|
82
125
|
if b:
|
|
83
|
-
|
|
126
|
+
self.poutput(eval("b()." + ".".join(robjs[1:])))
|
|
84
127
|
else:
|
|
85
128
|
output_item = self.bes_conn.get(line)
|
|
86
|
-
#
|
|
87
|
-
|
|
88
|
-
#
|
|
89
|
-
#
|
|
129
|
+
# self.poutput(type(output_item))
|
|
130
|
+
self.poutput(output_item)
|
|
131
|
+
# self.poutput(output_item.besdict)
|
|
132
|
+
# self.poutput(output_item.besjson)
|
|
90
133
|
else:
|
|
91
134
|
self.pfeedback("Not currently logged in. Type 'login'.")
|
|
92
135
|
|
|
136
|
+
complete_delete = complete_api_resources
|
|
137
|
+
|
|
93
138
|
def do_delete(self, line):
|
|
94
139
|
"""Perform delete request to BigFix server using provided api endpoint argument"""
|
|
95
140
|
|
|
@@ -104,16 +149,18 @@ class BESCLInterface(Cmd):
|
|
|
104
149
|
if self.bes_conn:
|
|
105
150
|
output_item = self.bes_conn.delete(line)
|
|
106
151
|
|
|
107
|
-
|
|
108
|
-
#
|
|
109
|
-
#
|
|
152
|
+
self.poutput(output_item)
|
|
153
|
+
# self.poutput(output_item.besdict)
|
|
154
|
+
# self.poutput(output_item.besjson)
|
|
110
155
|
else:
|
|
111
156
|
self.pfeedback("Not currently logged in. Type 'login'.")
|
|
112
157
|
|
|
158
|
+
complete_post = complete_api_resources
|
|
159
|
+
|
|
113
160
|
def do_post(self, statement):
|
|
114
161
|
"""post file as data to path"""
|
|
115
|
-
|
|
116
|
-
|
|
162
|
+
self.poutput(statement)
|
|
163
|
+
self.poutput("not yet implemented")
|
|
117
164
|
|
|
118
165
|
def do_config(self, conf_file=None):
|
|
119
166
|
"""Attempt to load config info from file and login"""
|
|
@@ -244,7 +291,7 @@ class BESCLInterface(Cmd):
|
|
|
244
291
|
else:
|
|
245
292
|
self.perror("Login Error!")
|
|
246
293
|
|
|
247
|
-
def do_logout(self,
|
|
294
|
+
def do_logout(self, _=None):
|
|
248
295
|
"""Logout and clear session"""
|
|
249
296
|
if self.bes_conn:
|
|
250
297
|
self.bes_conn.logout()
|
|
@@ -254,7 +301,7 @@ class BESCLInterface(Cmd):
|
|
|
254
301
|
|
|
255
302
|
def do_debug(self, setting):
|
|
256
303
|
"""Enable or Disable Debug Mode"""
|
|
257
|
-
|
|
304
|
+
self.poutput(bool(setting))
|
|
258
305
|
self.debug = bool(setting)
|
|
259
306
|
self.echo = bool(setting)
|
|
260
307
|
self.quiet = bool(setting)
|
|
@@ -288,12 +335,12 @@ class BESCLInterface(Cmd):
|
|
|
288
335
|
"""save current config to file"""
|
|
289
336
|
self.do_saveconf(arg)
|
|
290
337
|
|
|
291
|
-
def do_saveconf(self,
|
|
338
|
+
def do_saveconf(self, _=None):
|
|
292
339
|
"""save current config to file"""
|
|
293
340
|
if not self.bes_conn:
|
|
294
341
|
self.do_login()
|
|
295
342
|
if not self.bes_conn:
|
|
296
|
-
|
|
343
|
+
self.poutput("Can't save config without working login")
|
|
297
344
|
else:
|
|
298
345
|
conf_file_path = self.conf_path
|
|
299
346
|
self.pfeedback(f"Saving Config File to: {conf_file_path}")
|
|
@@ -304,29 +351,31 @@ class BESCLInterface(Cmd):
|
|
|
304
351
|
"""List the current settings and connection status"""
|
|
305
352
|
self.do_ls(arg)
|
|
306
353
|
|
|
307
|
-
def do_ls(self,
|
|
354
|
+
def do_ls(self, _=None):
|
|
308
355
|
"""List the current settings and connection status"""
|
|
309
|
-
|
|
310
|
-
|
|
356
|
+
self.poutput(" Connected: " + str(bool(self.bes_conn)))
|
|
357
|
+
self.poutput(
|
|
311
358
|
" BES_ROOT_SERVER: "
|
|
312
359
|
+ (self.BES_ROOT_SERVER if self.BES_ROOT_SERVER else "")
|
|
313
360
|
)
|
|
314
|
-
|
|
361
|
+
self.poutput(
|
|
315
362
|
" BES_USER_NAME: " + (self.BES_USER_NAME if self.BES_USER_NAME else "")
|
|
316
363
|
)
|
|
317
|
-
|
|
364
|
+
self.poutput(
|
|
318
365
|
" Password Length: "
|
|
319
366
|
+ str(len(self.BES_PASSWORD if self.BES_PASSWORD else ""))
|
|
320
367
|
)
|
|
321
|
-
|
|
368
|
+
self.poutput(" Config File Path: " + self.conf_path)
|
|
322
369
|
if self.bes_conn:
|
|
323
|
-
|
|
370
|
+
self.poutput(
|
|
371
|
+
"Current Site Path: " + self.bes_conn.get_current_site_path(None)
|
|
372
|
+
)
|
|
324
373
|
|
|
325
|
-
def do_error_count(self,
|
|
374
|
+
def do_error_count(self, _=None):
|
|
326
375
|
"""Output the number of errors"""
|
|
327
376
|
self.poutput(f"Error Count: {self.num_errors}")
|
|
328
377
|
|
|
329
|
-
def do_exit(self,
|
|
378
|
+
def do_exit(self, _=None):
|
|
330
379
|
"""Exit this application"""
|
|
331
380
|
self.exit_code = self.num_errors
|
|
332
381
|
# no matter what I try I can't get anything but exit code 0 on windows
|
|
@@ -347,7 +396,7 @@ class BESCLInterface(Cmd):
|
|
|
347
396
|
self.pfeedback("A: ")
|
|
348
397
|
self.poutput(rel_result)
|
|
349
398
|
|
|
350
|
-
def do_version(self,
|
|
399
|
+
def do_version(self, _=None):
|
|
351
400
|
"""output version of besapi"""
|
|
352
401
|
self.poutput(f"besapi version: {__version__}")
|
|
353
402
|
|
|
@@ -361,7 +410,7 @@ class BESCLInterface(Cmd):
|
|
|
361
410
|
result_op = self.bes_conn.get_user(statement)
|
|
362
411
|
self.poutput(result_op)
|
|
363
412
|
|
|
364
|
-
def do_get_current_site(self,
|
|
413
|
+
def do_get_current_site(self, _=None):
|
|
365
414
|
"""output current site path context"""
|
|
366
415
|
self.poutput(
|
|
367
416
|
f"Current Site Path: `{ self.bes_conn.get_current_site_path(None) }`"
|
|
@@ -375,11 +424,11 @@ class BESCLInterface(Cmd):
|
|
|
375
424
|
|
|
376
425
|
def do_get_content(self, resource_url):
|
|
377
426
|
"""get a specific item by resource url"""
|
|
378
|
-
|
|
427
|
+
self.poutput(self.bes_conn.get_content_by_resource(resource_url))
|
|
379
428
|
|
|
380
429
|
def do_export_item_by_resource(self, statement):
|
|
381
430
|
"""export content itemb to current folder"""
|
|
382
|
-
|
|
431
|
+
self.poutput(self.bes_conn.export_item_by_resource(statement))
|
|
383
432
|
|
|
384
433
|
def do_export_site(self, site_path):
|
|
385
434
|
"""export site contents to current folder"""
|
|
@@ -387,7 +436,7 @@ class BESCLInterface(Cmd):
|
|
|
387
436
|
site_path, verbose=True, include_site_folder=False, include_item_ids=False
|
|
388
437
|
)
|
|
389
438
|
|
|
390
|
-
def do_export_all_sites(self,
|
|
439
|
+
def do_export_all_sites(self, _=None):
|
|
391
440
|
"""export site contents to current folder"""
|
|
392
441
|
self.bes_conn.export_all_sites(verbose=False)
|
|
393
442
|
|
|
@@ -409,47 +458,58 @@ class BESCLInterface(Cmd):
|
|
|
409
458
|
def do_upload(self, file_path):
|
|
410
459
|
"""upload file to root server"""
|
|
411
460
|
if not os.access(file_path, os.R_OK):
|
|
412
|
-
|
|
461
|
+
self.poutput(file_path, "is not a readable file")
|
|
413
462
|
else:
|
|
414
463
|
upload_result = self.bes_conn.upload(file_path)
|
|
415
|
-
|
|
416
|
-
|
|
464
|
+
self.poutput(upload_result)
|
|
465
|
+
self.poutput(self.bes_conn.parse_upload_result_to_prefetch(upload_result))
|
|
417
466
|
|
|
418
467
|
complete_create_group = Cmd.path_complete
|
|
419
468
|
|
|
420
469
|
def do_create_group(self, file_path):
|
|
421
470
|
"""create bigfix group from bes file"""
|
|
422
471
|
if not os.access(file_path, os.R_OK):
|
|
423
|
-
|
|
472
|
+
self.poutput(file_path, "is not a readable file")
|
|
424
473
|
else:
|
|
425
|
-
|
|
474
|
+
self.poutput(self.bes_conn.create_group_from_file(file_path))
|
|
426
475
|
|
|
427
476
|
complete_create_user = Cmd.path_complete
|
|
428
477
|
|
|
429
478
|
def do_create_user(self, file_path):
|
|
430
479
|
"""create bigfix user from bes file"""
|
|
431
480
|
if not os.access(file_path, os.R_OK):
|
|
432
|
-
|
|
481
|
+
self.poutput(file_path, "is not a readable file")
|
|
433
482
|
else:
|
|
434
|
-
|
|
483
|
+
self.poutput(self.bes_conn.create_user_from_file(file_path))
|
|
435
484
|
|
|
436
485
|
complete_create_site = Cmd.path_complete
|
|
437
486
|
|
|
438
487
|
def do_create_site(self, file_path):
|
|
439
488
|
"""create bigfix site from bes file"""
|
|
440
489
|
if not os.access(file_path, os.R_OK):
|
|
441
|
-
|
|
490
|
+
self.poutput(file_path, "is not a readable file")
|
|
442
491
|
else:
|
|
443
|
-
|
|
492
|
+
self.poutput(self.bes_conn.create_site_from_file(file_path))
|
|
444
493
|
|
|
445
494
|
complete_update_item = Cmd.path_complete
|
|
446
495
|
|
|
447
496
|
def do_update_item(self, file_path):
|
|
448
497
|
"""update bigfix content item from bes file"""
|
|
449
498
|
if not os.access(file_path, os.R_OK):
|
|
450
|
-
|
|
499
|
+
self.poutput(file_path, "is not a readable file")
|
|
451
500
|
else:
|
|
452
|
-
|
|
501
|
+
self.poutput(self.bes_conn.update_item_from_file(file_path))
|
|
502
|
+
|
|
503
|
+
def do_serverinfo(self, _=None):
|
|
504
|
+
"""get server info and return formatted"""
|
|
505
|
+
|
|
506
|
+
# not sure what the minimum version for this is:
|
|
507
|
+
result = self.bes_conn.get("serverinfo")
|
|
508
|
+
|
|
509
|
+
result_json = json.loads(result.text)
|
|
510
|
+
|
|
511
|
+
self.poutput(f"\nServer Info for {self.BES_ROOT_SERVER}")
|
|
512
|
+
self.poutput(json.dumps(result_json, indent=2))
|
|
453
513
|
|
|
454
514
|
|
|
455
515
|
def main():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|