66
77from django .contrib .auth .models import User
88from django .contrib .contenttypes .models import ContentType
9- from django .core .management .base import BaseCommand
9+ from django .core .management .base import BaseCommand , CommandError
1010from django .db import transaction
1111
1212from extras .api .serializers import ScriptOutputSerializer
1313from extras .choices import JobResultStatusChoices
1414from extras .context_managers import change_logging
1515from extras .models import JobResult
16- from extras .scripts import get_scripts
16+ from extras .scripts import get_script
1717from utilities .exceptions import AbortTransaction
1818from utilities .utils import NetBoxFakeRequest
1919
@@ -27,15 +27,11 @@ def add_arguments(self, parser):
2727 help = "Logging Level (default: info)" ,
2828 dest = 'loglevel' ,
2929 default = 'info' ,
30- choices = ['debug' , 'info' , 'warning' , 'error' ])
31- parser .add_argument ('--script' , help = "Script to run" , dest = 'script' )
32- parser .add_argument ('--user' , help = "Data as a json blob" , dest = 'user' )
33- parser .add_argument ('data' , help = "Data as a json blob" )
34-
35- @staticmethod
36- def _get_script (module , name ):
37- scripts = get_scripts ()
38- return scripts [module ][name ]()
30+ choices = ['debug' , 'info' , 'warning' , 'error' , 'critical' ])
31+ parser .add_argument ('--script' , help = "Script to run" , dest = 'script' , required = True )
32+ parser .add_argument ('--commit' , help = "Commit this script to database" , dest = 'commit' )
33+ parser .add_argument ('--user' , help = "User script is running as" , dest = 'user' )
34+ parser .add_argument ('data' , help = "Data as a JSON blob" )
3935
4036 def handle (self , * args , ** options ):
4137 def _run_script ():
@@ -72,7 +68,8 @@ def _run_script():
7268 # Params
7369 script = options ['script' ]
7470 loglevel = options ['loglevel' ]
75- data = json .loads (options ['data' ])
71+ data = json .loads (options ['data' ]) if options ['data' ] is not None else None
72+ commit = True if options ['commit' ] in ['1' , 'true' , 'True' ] else False
7673
7774 module , name = script .split ('.' , 1 )
7875
@@ -94,24 +91,32 @@ def _run_script():
9491 logger = logging .getLogger (f"netbox.scripts.{ module } .{ name } " )
9592 logger .addHandler (stdouthandler )
9693
97- if loglevel == 'debug' :
98- logger .setLevel (logging .DEBUG )
99- elif loglevel == 'info' :
100- logger .setLevel (logging .INFO )
101- elif loglevel == 'warning' :
102- logger .setLevel (logging .WARNING )
103- elif loglevel == 'error' :
104- logger .setLevel (logging .ERROR )
105- else :
106- logger .setLevel (logging .INFO )
94+ try :
95+ logger .setLevel ({
96+ 'critical' : logging .CRITICAL ,
97+ 'debug' : logging .DEBUG ,
98+ 'error' : logging .ERROR ,
99+ 'fatal' : logging .FATAL ,
100+ 'info' : logging .INFO ,
101+ 'warning' : logging .WARNING ,
102+ }[loglevel ])
103+ except KeyError :
104+ raise CommandError (f"Invalid log level: { loglevel } " )
107105
108106 # Get the script
109- script = self . _get_script (module , name )
107+ script = get_script (module , name )( )
110108 # Parse the parameters
111109 form = script .as_form (data , None )
112110
113111 script_content_type = ContentType .objects .get (app_label = 'extras' , model = 'script' )
114112
113+ # Delete any previous terminal state results
114+ JobResult .objects .filter (
115+ obj_type = script_content_type ,
116+ name = script .full_name ,
117+ status__in = JobResultStatusChoices .TERMINAL_STATE_CHOICES
118+ ).delete ()
119+
115120 # Create the job result
116121 job_result = JobResult .objects .create (
117122 name = script .full_name ,
@@ -134,27 +139,17 @@ def _run_script():
134139 job_result .status = JobResultStatusChoices .STATUS_RUNNING
135140 job_result .save ()
136141
137- commit = form .cleaned_data .pop ('_commit' )
138-
139142 logger .info (f"Running script (commit={ commit } )" )
140143 script .request = request
141144
142145 # Execute the script. If commit is True, wrap it with the change_logging context manager to ensure we process
143146 # change logging, webhooks, etc.
144- if commit :
145- with change_logging (request ):
146- _run_script ()
147- else :
147+ with change_logging (request ):
148148 _run_script ()
149-
150- # Delete any previous terminal state results
151- JobResult .objects .filter (
152- obj_type = job_result .obj_type ,
153- name = job_result .name ,
154- status__in = JobResultStatusChoices .TERMINAL_STATE_CHOICES
155- ).exclude (
156- pk = job_result .pk
157- ).delete ()
158149 else :
150+ logger .error ('Data is not valid:' )
151+ for field , errors in form .errors .get_json_data ().items ():
152+ for error in errors :
153+ logger .error (f'\t { field } : { error .get ("message" )} ' )
159154 job_result .status = JobResultStatusChoices .STATUS_ERRORED
160155 job_result .save ()
0 commit comments