besapi 3.7.6__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.6/src/besapi.egg-info → besapi-3.7.8}/PKG-INFO +1 -1
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi/besapi.py +1 -1
- {besapi-3.7.6 → besapi-3.7.8/src/besapi.egg-info}/PKG-INFO +1 -1
- {besapi-3.7.6 → besapi-3.7.8}/src/bescli/bescli.py +106 -39
- {besapi-3.7.6 → besapi-3.7.8}/tests/tests.py +4 -2
- {besapi-3.7.6 → besapi-3.7.8}/LICENSE.txt +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/MANIFEST.in +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/README.md +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/pyproject.toml +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/setup.cfg +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/setup.py +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi/__init__.py +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi/__main__.py +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi/plugin_utilities.py +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi/schemas/BES.xsd +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi/schemas/BESAPI.xsd +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi/schemas/BESActionSettings.xsd +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi.egg-info/SOURCES.txt +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi.egg-info/dependency_links.txt +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi.egg-info/requires.txt +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/besapi.egg-info/top_level.txt +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/bescli/__init__.py +0 -0
- {besapi-3.7.6 → besapi-3.7.8}/src/bescli/__main__.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
|
|
@@ -39,6 +40,13 @@ class BESCLInterface(Cmd):
|
|
|
39
40
|
|
|
40
41
|
def __init__(self, **kwargs):
|
|
41
42
|
Cmd.__init__(self, **kwargs)
|
|
43
|
+
|
|
44
|
+
# set an intro message
|
|
45
|
+
self.intro = (
|
|
46
|
+
f"\nWelcome to the BigFix REST API Interactive Python Module v{__version__}"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# sets the prompt look:
|
|
42
50
|
self.prompt = "BigFix> "
|
|
43
51
|
|
|
44
52
|
self.num_errors = 0
|
|
@@ -49,8 +57,50 @@ class BESCLInterface(Cmd):
|
|
|
49
57
|
# set default config file path
|
|
50
58
|
self.conf_path = os.path.expanduser("~/.besapi.conf")
|
|
51
59
|
self.CONFPARSER = SafeConfigParser()
|
|
60
|
+
# for completion:
|
|
61
|
+
self.api_resources = []
|
|
52
62
|
self.do_conf()
|
|
53
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
|
+
|
|
54
104
|
def do_get(self, line):
|
|
55
105
|
"""Perform get request to BigFix server using provided api endpoint argument"""
|
|
56
106
|
|
|
@@ -73,16 +123,18 @@ class BESCLInterface(Cmd):
|
|
|
73
123
|
b = self.bes_conn.get(robjs[0])
|
|
74
124
|
# print objectify.ObjectPath(robjs[1:])
|
|
75
125
|
if b:
|
|
76
|
-
|
|
126
|
+
self.poutput(eval("b()." + ".".join(robjs[1:])))
|
|
77
127
|
else:
|
|
78
128
|
output_item = self.bes_conn.get(line)
|
|
79
|
-
#
|
|
80
|
-
|
|
81
|
-
#
|
|
82
|
-
#
|
|
129
|
+
# self.poutput(type(output_item))
|
|
130
|
+
self.poutput(output_item)
|
|
131
|
+
# self.poutput(output_item.besdict)
|
|
132
|
+
# self.poutput(output_item.besjson)
|
|
83
133
|
else:
|
|
84
134
|
self.pfeedback("Not currently logged in. Type 'login'.")
|
|
85
135
|
|
|
136
|
+
complete_delete = complete_api_resources
|
|
137
|
+
|
|
86
138
|
def do_delete(self, line):
|
|
87
139
|
"""Perform delete request to BigFix server using provided api endpoint argument"""
|
|
88
140
|
|
|
@@ -97,16 +149,18 @@ class BESCLInterface(Cmd):
|
|
|
97
149
|
if self.bes_conn:
|
|
98
150
|
output_item = self.bes_conn.delete(line)
|
|
99
151
|
|
|
100
|
-
|
|
101
|
-
#
|
|
102
|
-
#
|
|
152
|
+
self.poutput(output_item)
|
|
153
|
+
# self.poutput(output_item.besdict)
|
|
154
|
+
# self.poutput(output_item.besjson)
|
|
103
155
|
else:
|
|
104
156
|
self.pfeedback("Not currently logged in. Type 'login'.")
|
|
105
157
|
|
|
158
|
+
complete_post = complete_api_resources
|
|
159
|
+
|
|
106
160
|
def do_post(self, statement):
|
|
107
161
|
"""post file as data to path"""
|
|
108
|
-
|
|
109
|
-
|
|
162
|
+
self.poutput(statement)
|
|
163
|
+
self.poutput("not yet implemented")
|
|
110
164
|
|
|
111
165
|
def do_config(self, conf_file=None):
|
|
112
166
|
"""Attempt to load config info from file and login"""
|
|
@@ -237,7 +291,7 @@ class BESCLInterface(Cmd):
|
|
|
237
291
|
else:
|
|
238
292
|
self.perror("Login Error!")
|
|
239
293
|
|
|
240
|
-
def do_logout(self,
|
|
294
|
+
def do_logout(self, _=None):
|
|
241
295
|
"""Logout and clear session"""
|
|
242
296
|
if self.bes_conn:
|
|
243
297
|
self.bes_conn.logout()
|
|
@@ -247,7 +301,7 @@ class BESCLInterface(Cmd):
|
|
|
247
301
|
|
|
248
302
|
def do_debug(self, setting):
|
|
249
303
|
"""Enable or Disable Debug Mode"""
|
|
250
|
-
|
|
304
|
+
self.poutput(bool(setting))
|
|
251
305
|
self.debug = bool(setting)
|
|
252
306
|
self.echo = bool(setting)
|
|
253
307
|
self.quiet = bool(setting)
|
|
@@ -281,12 +335,12 @@ class BESCLInterface(Cmd):
|
|
|
281
335
|
"""save current config to file"""
|
|
282
336
|
self.do_saveconf(arg)
|
|
283
337
|
|
|
284
|
-
def do_saveconf(self,
|
|
338
|
+
def do_saveconf(self, _=None):
|
|
285
339
|
"""save current config to file"""
|
|
286
340
|
if not self.bes_conn:
|
|
287
341
|
self.do_login()
|
|
288
342
|
if not self.bes_conn:
|
|
289
|
-
|
|
343
|
+
self.poutput("Can't save config without working login")
|
|
290
344
|
else:
|
|
291
345
|
conf_file_path = self.conf_path
|
|
292
346
|
self.pfeedback(f"Saving Config File to: {conf_file_path}")
|
|
@@ -297,29 +351,31 @@ class BESCLInterface(Cmd):
|
|
|
297
351
|
"""List the current settings and connection status"""
|
|
298
352
|
self.do_ls(arg)
|
|
299
353
|
|
|
300
|
-
def do_ls(self,
|
|
354
|
+
def do_ls(self, _=None):
|
|
301
355
|
"""List the current settings and connection status"""
|
|
302
|
-
|
|
303
|
-
|
|
356
|
+
self.poutput(" Connected: " + str(bool(self.bes_conn)))
|
|
357
|
+
self.poutput(
|
|
304
358
|
" BES_ROOT_SERVER: "
|
|
305
359
|
+ (self.BES_ROOT_SERVER if self.BES_ROOT_SERVER else "")
|
|
306
360
|
)
|
|
307
|
-
|
|
361
|
+
self.poutput(
|
|
308
362
|
" BES_USER_NAME: " + (self.BES_USER_NAME if self.BES_USER_NAME else "")
|
|
309
363
|
)
|
|
310
|
-
|
|
364
|
+
self.poutput(
|
|
311
365
|
" Password Length: "
|
|
312
366
|
+ str(len(self.BES_PASSWORD if self.BES_PASSWORD else ""))
|
|
313
367
|
)
|
|
314
|
-
|
|
368
|
+
self.poutput(" Config File Path: " + self.conf_path)
|
|
315
369
|
if self.bes_conn:
|
|
316
|
-
|
|
370
|
+
self.poutput(
|
|
371
|
+
"Current Site Path: " + self.bes_conn.get_current_site_path(None)
|
|
372
|
+
)
|
|
317
373
|
|
|
318
|
-
def do_error_count(self,
|
|
374
|
+
def do_error_count(self, _=None):
|
|
319
375
|
"""Output the number of errors"""
|
|
320
376
|
self.poutput(f"Error Count: {self.num_errors}")
|
|
321
377
|
|
|
322
|
-
def do_exit(self,
|
|
378
|
+
def do_exit(self, _=None):
|
|
323
379
|
"""Exit this application"""
|
|
324
380
|
self.exit_code = self.num_errors
|
|
325
381
|
# no matter what I try I can't get anything but exit code 0 on windows
|
|
@@ -340,7 +396,7 @@ class BESCLInterface(Cmd):
|
|
|
340
396
|
self.pfeedback("A: ")
|
|
341
397
|
self.poutput(rel_result)
|
|
342
398
|
|
|
343
|
-
def do_version(self,
|
|
399
|
+
def do_version(self, _=None):
|
|
344
400
|
"""output version of besapi"""
|
|
345
401
|
self.poutput(f"besapi version: {__version__}")
|
|
346
402
|
|
|
@@ -354,7 +410,7 @@ class BESCLInterface(Cmd):
|
|
|
354
410
|
result_op = self.bes_conn.get_user(statement)
|
|
355
411
|
self.poutput(result_op)
|
|
356
412
|
|
|
357
|
-
def do_get_current_site(self,
|
|
413
|
+
def do_get_current_site(self, _=None):
|
|
358
414
|
"""output current site path context"""
|
|
359
415
|
self.poutput(
|
|
360
416
|
f"Current Site Path: `{ self.bes_conn.get_current_site_path(None) }`"
|
|
@@ -368,11 +424,11 @@ class BESCLInterface(Cmd):
|
|
|
368
424
|
|
|
369
425
|
def do_get_content(self, resource_url):
|
|
370
426
|
"""get a specific item by resource url"""
|
|
371
|
-
|
|
427
|
+
self.poutput(self.bes_conn.get_content_by_resource(resource_url))
|
|
372
428
|
|
|
373
429
|
def do_export_item_by_resource(self, statement):
|
|
374
430
|
"""export content itemb to current folder"""
|
|
375
|
-
|
|
431
|
+
self.poutput(self.bes_conn.export_item_by_resource(statement))
|
|
376
432
|
|
|
377
433
|
def do_export_site(self, site_path):
|
|
378
434
|
"""export site contents to current folder"""
|
|
@@ -380,7 +436,7 @@ class BESCLInterface(Cmd):
|
|
|
380
436
|
site_path, verbose=True, include_site_folder=False, include_item_ids=False
|
|
381
437
|
)
|
|
382
438
|
|
|
383
|
-
def do_export_all_sites(self,
|
|
439
|
+
def do_export_all_sites(self, _=None):
|
|
384
440
|
"""export site contents to current folder"""
|
|
385
441
|
self.bes_conn.export_all_sites(verbose=False)
|
|
386
442
|
|
|
@@ -402,47 +458,58 @@ class BESCLInterface(Cmd):
|
|
|
402
458
|
def do_upload(self, file_path):
|
|
403
459
|
"""upload file to root server"""
|
|
404
460
|
if not os.access(file_path, os.R_OK):
|
|
405
|
-
|
|
461
|
+
self.poutput(file_path, "is not a readable file")
|
|
406
462
|
else:
|
|
407
463
|
upload_result = self.bes_conn.upload(file_path)
|
|
408
|
-
|
|
409
|
-
|
|
464
|
+
self.poutput(upload_result)
|
|
465
|
+
self.poutput(self.bes_conn.parse_upload_result_to_prefetch(upload_result))
|
|
410
466
|
|
|
411
467
|
complete_create_group = Cmd.path_complete
|
|
412
468
|
|
|
413
469
|
def do_create_group(self, file_path):
|
|
414
470
|
"""create bigfix group from bes file"""
|
|
415
471
|
if not os.access(file_path, os.R_OK):
|
|
416
|
-
|
|
472
|
+
self.poutput(file_path, "is not a readable file")
|
|
417
473
|
else:
|
|
418
|
-
|
|
474
|
+
self.poutput(self.bes_conn.create_group_from_file(file_path))
|
|
419
475
|
|
|
420
476
|
complete_create_user = Cmd.path_complete
|
|
421
477
|
|
|
422
478
|
def do_create_user(self, file_path):
|
|
423
479
|
"""create bigfix user from bes file"""
|
|
424
480
|
if not os.access(file_path, os.R_OK):
|
|
425
|
-
|
|
481
|
+
self.poutput(file_path, "is not a readable file")
|
|
426
482
|
else:
|
|
427
|
-
|
|
483
|
+
self.poutput(self.bes_conn.create_user_from_file(file_path))
|
|
428
484
|
|
|
429
485
|
complete_create_site = Cmd.path_complete
|
|
430
486
|
|
|
431
487
|
def do_create_site(self, file_path):
|
|
432
488
|
"""create bigfix site from bes file"""
|
|
433
489
|
if not os.access(file_path, os.R_OK):
|
|
434
|
-
|
|
490
|
+
self.poutput(file_path, "is not a readable file")
|
|
435
491
|
else:
|
|
436
|
-
|
|
492
|
+
self.poutput(self.bes_conn.create_site_from_file(file_path))
|
|
437
493
|
|
|
438
494
|
complete_update_item = Cmd.path_complete
|
|
439
495
|
|
|
440
496
|
def do_update_item(self, file_path):
|
|
441
497
|
"""update bigfix content item from bes file"""
|
|
442
498
|
if not os.access(file_path, os.R_OK):
|
|
443
|
-
|
|
499
|
+
self.poutput(file_path, "is not a readable file")
|
|
444
500
|
else:
|
|
445
|
-
|
|
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))
|
|
446
513
|
|
|
447
514
|
|
|
448
515
|
def main():
|
|
@@ -107,7 +107,9 @@ bigfix_cli.do_conf()
|
|
|
107
107
|
# this should really only run if the config file is present:
|
|
108
108
|
if bigfix_cli.bes_conn:
|
|
109
109
|
# session relevance tests require functioning web reports server
|
|
110
|
-
|
|
110
|
+
assert (
|
|
111
|
+
int(bigfix_cli.bes_conn.session_relevance_string("number of bes computers")) > 0
|
|
112
|
+
)
|
|
111
113
|
assert (
|
|
112
114
|
"test session relevance string result"
|
|
113
115
|
in bigfix_cli.bes_conn.session_relevance_string(
|
|
@@ -134,7 +136,7 @@ if bigfix_cli.bes_conn:
|
|
|
134
136
|
var_name = "TestVarName"
|
|
135
137
|
var_value = "TestVarValue " + str(random.randint(0, 9999))
|
|
136
138
|
|
|
137
|
-
|
|
139
|
+
assert var_value in str(
|
|
138
140
|
bigfix_cli.bes_conn.set_dashboard_variable_value(
|
|
139
141
|
dashboard_name, var_name, var_value
|
|
140
142
|
)
|
|
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
|