|
4 | 4 | requirements.""" |
5 | 5 |
|
6 | 6 | import argparse |
| 7 | +import os |
7 | 8 | import plistlib |
| 9 | +import sys |
| 10 | +from contextlib import contextmanager |
8 | 11 | from distutils.version import LooseVersion |
9 | 12 | from xml.parsers.expat import ExpatError |
10 | 13 |
|
|
15 | 18 | ) |
16 | 19 |
|
17 | 20 |
|
| 21 | +# Import AutoPkg libraries, but ignore any warnings generated by the import. |
| 22 | +@contextmanager |
| 23 | +def suppress_stdout(): |
| 24 | + with open(os.devnull, "w") as devnull: |
| 25 | + old_stdout = sys.stdout |
| 26 | + sys.stdout = devnull |
| 27 | + try: |
| 28 | + yield |
| 29 | + finally: |
| 30 | + sys.stdout = old_stdout |
| 31 | + |
| 32 | + |
| 33 | +sys.path.append("/Library/AutoPkg") |
| 34 | +try: |
| 35 | + with suppress_stdout(): |
| 36 | + from autopkglib import get_processor, processor_names |
| 37 | + |
| 38 | + HAS_AUTOPKGLIB = True |
| 39 | +except ImportError: |
| 40 | + # Silently skip checks that require autopkglib. |
| 41 | + HAS_AUTOPKGLIB = False |
| 42 | + |
| 43 | + |
18 | 44 | def build_argument_parser(): |
19 | 45 | """Build and return the argument parser.""" |
20 | 46 |
|
@@ -388,6 +414,56 @@ def validate_required_proc_for_types(process, filename): |
388 | 414 | return passed |
389 | 415 |
|
390 | 416 |
|
| 417 | +def validate_proc_args(process, filename): |
| 418 | + """Warn if invalid processor arguments are used.""" |
| 419 | + |
| 420 | + passed = True |
| 421 | + |
| 422 | + # List of argument names (lowercase) that will not be flagged as invalid. |
| 423 | + ignored_args = ("note", "notes", "comment", "comments") |
| 424 | + |
| 425 | + # Create dictionary of AutoPkg core processors and their inputs. |
| 426 | + core_procs = {} |
| 427 | + for proc in processor_names(): |
| 428 | + if hasattr(get_processor(proc), "input_variables"): |
| 429 | + core_procs[proc] = get_processor(proc).input_variables |
| 430 | + else: |
| 431 | + core_procs[proc] = {} |
| 432 | + |
| 433 | + for proc in process: |
| 434 | + if proc["Processor"] not in core_procs: |
| 435 | + # Skip input variable validation for non-core processors. |
| 436 | + continue |
| 437 | + for arg in proc.get("Arguments", {}): |
| 438 | + if arg.lower() in ignored_args: |
| 439 | + # Skip args in ignored list above. |
| 440 | + continue |
| 441 | + |
| 442 | + if not core_procs[proc["Processor"]]: |
| 443 | + print( |
| 444 | + "{}: Unknown argument {} for processor {}, " |
| 445 | + "which does not accept any arguments.".format( |
| 446 | + filename, |
| 447 | + arg, |
| 448 | + proc["Processor"], |
| 449 | + ) |
| 450 | + ) |
| 451 | + passed = False |
| 452 | + elif arg not in core_procs[proc["Processor"]]: |
| 453 | + print( |
| 454 | + "{}: Unknown argument {} for processor {}. " |
| 455 | + "Allowed arguments are: {}".format( |
| 456 | + filename, |
| 457 | + arg, |
| 458 | + proc["Processor"], |
| 459 | + ", ".join(core_procs[proc["Processor"]]), |
| 460 | + ) |
| 461 | + ) |
| 462 | + passed = False |
| 463 | + |
| 464 | + return passed |
| 465 | + |
| 466 | + |
391 | 467 | def main(argv=None): |
392 | 468 | """Main process.""" |
393 | 469 |
|
@@ -507,6 +583,10 @@ def main(argv=None): |
507 | 583 | if not validate_required_proc_for_types(process, filename): |
508 | 584 | retval = 1 |
509 | 585 |
|
| 586 | + if HAS_AUTOPKGLIB: |
| 587 | + if not validate_proc_args(process, filename): |
| 588 | + retval = 1 |
| 589 | + |
510 | 590 | return retval |
511 | 591 |
|
512 | 592 |
|
|
0 commit comments