def execute_docker_skillet(skillet_def: dict, args: dict) -> str: """ Execute a skillet of type 'docker'. This requires the calling application have access to the docker socket :param skillet_def: the skillet as loaded from the YAML file (dict) :param args: context arguments required for the given skillets. These will overwrite the 'variables' in the skillet :return: JSON encoded string with dict containing the following keys: {'returncode', 'out', 'err'} """ state = dict() full_output = '' err = '' rc = 0 docker_helper = DockerHelper() if skillet_def['type'] != 'docker' and skillet_def['type'] != 'terraform': rc = 255 err = f'Not a valid skillet type: {skillet_def["type"]}!' elif not docker_helper.check_docker_server(): rc = 240 err = 'Could not connect to Docker daemon, verify permissions on the docker socket! \n\n' \ 'See the documentation for details: https://panhandler.readthedocs.io/en/master/debugging.html' else: try: persistent_volumes = docker_helper.get_cnc_volumes() if 'app_data' not in skillet_def: skillet_def['app_data'] = dict() # always overwrite any volumes that may have snuck in here if persistent_volumes: skillet_def['app_data']['volumes'] = persistent_volumes else: # only this app should be setting app_data/volumes here, remove anything else if 'volumes' in skillet_def['app_data']: skillet_def['app_data'].pop('volumes') sl = SkilletLoader() skillet = sl.create_skillet(skillet_def) # FIX for #181 sanitized_args = __santize_args(args) output_generator = skillet.execute_async(sanitized_args) for out in output_generator: full_output += out current_task.update_state(state='PROGRESS', meta=full_output) r = skillet.get_results() # FIXME - docker skillets can run multiple snippets / cmds inside the container # should check for the output of each and determine if a single failure is considered a failure # for the entire skillet or only a failure for one step ? if isinstance(r, dict) and 'snippets' in r: for k, v in r['snippets'].items(): result = v.get('results', 'failure') if result == 'success': full_output = v.get('raw', '') elif result == 'error' or 'fail' in result: err = v.get('raw', 'error') rc = 2 else: full_output = v.get('raw', '') err = f'Unknown return value type {result}' rc = 3 else: full_output = r err = 'unknown output from skillet' except DockerHelperException as dee: logger.error(dee) rc = 1 err = str(dee) except SkilletLoaderException as sle: logger.error(sle) rc = 1 err = str(sle) state['returncode'] = rc state['out'] = full_output state['err'] = err return json.dumps(state)
# check we actually have some diffs if len(snippets) == 0: print('No Diffs found between these two configs') sys.exit(2) # SkilletLoader is used to... Load Skillets skillet_loader = SkilletLoader() # create_skillet will return a Skillet Object from the metadata dictionary passed in. # in this case, we create a minimal metadata dict and pass it in to create a simple 'template' skillet # a template skillet is a nice wrapper around the jinja engine template_skillet = skillet_loader.create_skillet( {'type': 'template', 'snippets': [ {'name': 'template', 'file': './ansible_pb_template.j2'} ] } ) # to execute this skillet, create the context object which includes any variables found in the template file context = dict() context['snippets'] = snippets context['playbook_name'] = 'Auto Generated PAN-OS Playbook' # execute the template skillet and get the returned output output = template_skillet.execute(context) # template skillets add the 'template' attribute into the output which contains the rendered template # print it out for the user print(output['template'])
# create the skillet definition from the 'skillet_content' dict we got from the environ skillet_dict_raw = oyaml.safe_load(skillet_content) # use skilletLoader to normalize the skillet definition and fix common config file errors skillet_dict = sl.normalize_skillet_dict(skillet_dict_raw) skillet_dict['snippet_path'] = '.' # create the skillet object from the skillet dict if 'pan_validation' in skillet_dict.get('type'): skillet: PanValidationSkillet = PanValidationSkillet( skillet_dict, device) elif 'pan' in skillet_dict.get('type'): skillet: PanosSkillet = PanosSkillet(skillet_dict, device) else: skillet: Skillet = sl.create_skillet(skillet_dict) # ensure all our variables from the environment / outer context is copied in and ready to go skillet.update_context(os.environ) # execute the skillet and return the results to us results = skillet.execute(context) print() print('=' * 137) print() print('Execution Results:') print() print('=' * 137) print() # in this case, just print them out for the user if skillet.type == 'pan_validation':
sys.exit(1) # check we actually have some diffs if len(snippets) == 0: print("No Diffs found between these two configs") sys.exit(2) # SkilletLoader is used to... Load Skillets skillet_loader = SkilletLoader() # create_skillet will return a Skillet Object from the metadata dictionary passed in. # in this case, we create a minimal metadata dict and pass it in to create a simple 'template' skillet # a template skillet is a nice wrapper around the jinja engine template_skillet = skillet_loader.create_skillet( {"type": "template", "snippets": [{"name": "template", "file": "./ansible_pb_template.j2"}]} ) # to execute this skillet, create the context object which includes any variables found in the template file context = dict() context["snippets"] = snippets context["playbook_name"] = "Auto Generated PAN-OS Playbook" # execute the template skillet and get the returned output output = template_skillet.execute(context) # template skillets add the 'template' attribute into the output which contains the rendered template # print it out for the user print(output["template"]) # later gator sys.exit(0)