screenboard.py (11021B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\datadog\dogshell\screenboard.py 2 from __future__ import print_function 3 import argparse 4 import sys 5 import platform 6 import webbrowser 7 from datadog.util.format import pretty_json 8 from datadog import api 9 from datadog.dogshell.common import report_errors, report_warnings, print_err 10 from datadog.util.compat import json 11 from datetime import datetime 12 13 class ScreenboardClient(object): 14 15 @classmethod 16 def setup_parser(cls, subparsers): 17 parser = subparsers.add_parser('screenboard', help='Create, edit, and delete screenboards.') 18 parser.add_argument('--string_ids', action='store_true', dest='string_ids', help='Represent screenboard IDs as strings instead of ints in JSON') 19 verb_parsers = parser.add_subparsers(title='Verbs', dest='verb') 20 verb_parsers.required = True 21 post_parser = verb_parsers.add_parser('post', help='Create screenboards.') 22 post_parser.add_argument('title', help='title for the new screenboard') 23 post_parser.add_argument('description', help='short description of the screenboard') 24 post_parser.add_argument('graphs', help='graph definitions as a JSON string. if unset, reads from stdin.', nargs='?') 25 post_parser.add_argument('--template_variables', type=_template_variables, default=[], help="a json list of template variable dicts, e.g. [{'name': 'host', 'prefix': 'host', 'default': 'host:my-host'}]") 26 post_parser.add_argument('--width', type=int, default=None, help='screenboard width in pixels') 27 post_parser.add_argument('--height', type=int, default=None, help='screenboard height in pixels') 28 post_parser.set_defaults(func=cls._post) 29 update_parser = verb_parsers.add_parser('update', help='Update existing screenboards.') 30 update_parser.add_argument('screenboard_id', help='screenboard to replace with the new definition') 31 update_parser.add_argument('title', help='title for the new screenboard') 32 update_parser.add_argument('description', help='short description of the screenboard') 33 update_parser.add_argument('graphs', help='graph definitions as a JSON string. if unset, reads from stdin.', nargs='?') 34 update_parser.add_argument('--template_variables', type=_template_variables, default=[], help="a json list of template variable dicts, e.g. [{'name': 'host', 'prefix': 'host', 'default': 'host:my-host'}]") 35 update_parser.add_argument('--width', type=int, default=None, help='screenboard width in pixels') 36 update_parser.add_argument('--height', type=int, default=None, help='screenboard height in pixels') 37 update_parser.set_defaults(func=cls._update) 38 show_parser = verb_parsers.add_parser('show', help='Show a screenboard definition.') 39 show_parser.add_argument('screenboard_id', help='screenboard to show') 40 show_parser.set_defaults(func=cls._show) 41 delete_parser = verb_parsers.add_parser('delete', help='Delete a screenboard.') 42 delete_parser.add_argument('screenboard_id', help='screenboard to delete') 43 delete_parser.set_defaults(func=cls._delete) 44 share_parser = verb_parsers.add_parser('share', help="Share an existing screenboard's with a public URL.") 45 share_parser.add_argument('screenboard_id', help='screenboard to share') 46 share_parser.set_defaults(func=cls._share) 47 revoke_parser = verb_parsers.add_parser('revoke', help="Revoke an existing screenboard's with a public URL.") 48 revoke_parser.add_argument('screenboard_id', help='screenboard to revoke') 49 revoke_parser.set_defaults(func=cls._revoke) 50 pull_parser = verb_parsers.add_parser('pull', help='Pull a screenboard on the server into a local file') 51 pull_parser.add_argument('screenboard_id', help='ID of screenboard to pull') 52 pull_parser.add_argument('filename', help='file to pull screenboard into') 53 pull_parser.set_defaults(func=cls._pull) 54 push_parser = verb_parsers.add_parser('push', help='Push updates to screenboards from local files to the server') 55 push_parser.add_argument('--append_auto_text', action='store_true', dest='append_auto_text', help='When pushing to the server, appends filename and timestamp to the end of the screenboard description') 56 push_parser.add_argument('file', help='screenboard files to push to the server', nargs='+', type=argparse.FileType('r')) 57 push_parser.set_defaults(func=cls._push) 58 new_file_parser = verb_parsers.add_parser('new_file', help='Create a new screenboard and put its contents in a file') 59 new_file_parser.add_argument('filename', help='name of file to create with empty screenboard') 60 new_file_parser.add_argument('graphs', help='graph definitions as a JSON string. if unset, reads from stdin.', nargs='?') 61 new_file_parser.set_defaults(func=cls._new_file) 62 63 @classmethod 64 def _pull(cls, args): 65 cls._write_screen_to_file(args.screenboard_id, args.filename, args.timeout, args.format, args.string_ids) 66 67 @classmethod 68 def _push(cls, args): 69 api._timeout = args.timeout 70 for f in args.file: 71 try: 72 screen_obj = json.load(f) 73 except Exception as err: 74 raise Exception('Could not parse {0}: {1}'.format(f.name, err)) 75 76 if args.append_auto_text: 77 datetime_str = datetime.now().strftime('%x %X') 78 auto_text = '<br/>\nUpdated at {0} from {1} ({2}) on {3}'.format(datetime_str, f.name, screen_obj['id'], platform.node()) 79 screen_obj['description'] += auto_text 80 if 'id' in screen_obj: 81 screen_obj['id'] = int(screen_obj['id']) 82 res = api.Screenboard.update(**screen_obj) 83 else: 84 res = api.Screenboard.create(**screen_obj) 85 if 'errors' in res: 86 print_err('Upload of screenboard {0} from file {1} failed.'.format(screen_obj['id'], f.name)) 87 report_warnings(res) 88 report_errors(res) 89 if format == 'pretty': 90 print(pretty_json(res)) 91 else: 92 print(json.dumps(res)) 93 if args.format == 'pretty': 94 print('Uploaded file {0} (screenboard {1})'.format(f.name, screen_obj['id'])) 95 96 @classmethod 97 def _write_screen_to_file(cls, screenboard_id, filename, timeout, format = 'raw', string_ids = False): 98 with open(filename, 'w') as f: 99 res = api.Screenboard.get(screenboard_id) 100 report_warnings(res) 101 report_errors(res) 102 screen_obj = res 103 if 'resource' in screen_obj: 104 del screen_obj['resource'] 105 if 'url' in screen_obj: 106 del screen_obj['url'] 107 if string_ids: 108 screen_obj['id'] = str(screen_obj['id']) 109 json.dump(screen_obj, f, indent=2) 110 if format == 'pretty': 111 print('Downloaded screenboard {0} to file {1}'.format(screenboard_id, filename)) 112 else: 113 print('{0} {1}'.format(screenboard_id, filename)) 114 115 @classmethod 116 def _post(cls, args): 117 graphs = sys.stdin.read() 118 api._timeout = args.timeout 119 format = args.format 120 graphs = args.graphs 121 if args.graphs is None: 122 graphs = sys.stdin.read() 123 try: 124 graphs = json.loads(graphs) 125 except: 126 raise Exception('bad json parameter') 127 128 res = api.Screenboard.create(title=args.title, description=args.description, graphs=[graphs], template_variables=args.template_variables, width=args.width, height=args.height) 129 report_warnings(res) 130 report_errors(res) 131 if format == 'pretty': 132 print(pretty_json(res)) 133 else: 134 print(json.dumps(res)) 135 136 @classmethod 137 def _update(cls, args): 138 api._timeout = args.timeout 139 format = args.format 140 graphs = args.graphs 141 if args.graphs is None: 142 graphs = sys.stdin.read() 143 try: 144 graphs = json.loads(graphs) 145 except: 146 raise Exception('bad json parameter') 147 148 res = api.Screenboard.update(args.screenboard_id, title=args.title, description=args.description, graphs=graphs, template_variables=args.template_variables, width=args.width, height=args.height) 149 report_warnings(res) 150 report_errors(res) 151 if format == 'pretty': 152 print(pretty_json(res)) 153 else: 154 print(json.dumps(res)) 155 156 @classmethod 157 def _web_view(cls, args): 158 dash_id = json.load(args.file)['id'] 159 url = api._api_host + '/dash/dash/{0}'.format(dash_id) 160 webbrowser.open(url) 161 162 @classmethod 163 def _show(cls, args): 164 api._timeout = args.timeout 165 format = args.format 166 res = api.Screenboard.get(args.screenboard_id) 167 report_warnings(res) 168 report_errors(res) 169 if args.string_ids: 170 res['id'] = str(res['id']) 171 if format == 'pretty': 172 print(pretty_json(res)) 173 else: 174 print(json.dumps(res)) 175 176 @classmethod 177 def _delete(cls, args): 178 api._timeout = args.timeout 179 res = api.Screenboard.delete(args.screenboard_id) 180 if res is not None: 181 report_warnings(res) 182 report_errors(res) 183 184 @classmethod 185 def _share(cls, args): 186 api._timeout = args.timeout 187 format = args.format 188 res = api.Screenboard.share(args.screenboard_id) 189 if format == 'pretty': 190 print(pretty_json(res)) 191 else: 192 print(json.dumps(res)) 193 194 @classmethod 195 def _revoke(cls, args): 196 api._timeout = args.timeout 197 format = args.format 198 res = api.Screenboard.revoke(args.screenboard_id) 199 if format == 'pretty': 200 print(pretty_json(res)) 201 else: 202 print(json.dumps(res)) 203 204 @classmethod 205 def _new_file(cls, args): 206 api._timeout = args.timeout 207 format = args.format 208 graphs = args.graphs 209 if args.graphs is None: 210 graphs = sys.stdin.read() 211 try: 212 graphs = json.loads(graphs) 213 except: 214 raise Exception('bad json parameter') 215 216 res = api.Screenboard.create(title=args.filename, description='Description for {0}'.format(args.filename), graphs=[graphs]) 217 report_warnings(res) 218 report_errors(res) 219 cls._write_screen_to_file(res['id'], args.filename, args.timeout, format, args.string_ids) 220 if format == 'pretty': 221 print(pretty_json(res)) 222 else: 223 print(json.dumps(res)) 224 225 226 def _template_variables(tpl_var_input): 227 if '[' not in tpl_var_input: 228 return [ v.strip() for v in tpl_var_input.split(',') ] 229 try: 230 return json.loads(tpl_var_input) 231 except Exception: 232 raise argparse.ArgumentTypeError('bad template_variable json parameter')