def _get_yaml_diff(new_yaml=None, old_yaml=None): if not new_yaml and not old_yaml: return None old_str = yaml.serialize(old_yaml, default_flow_style=False) new_str = yaml.serialize(new_yaml, default_flow_style=False) return difflib.unified_diff(old_str.split('\n'), new_str.split('\n'))
def run(): """ Serializes into YAML file. See `template.prepare` for context arguments on loading data, and `template.managed` for additional arguments when rendering the output. Arguments: root (str, optional): A colon separated string to nest all data before serializing to YAML. Example: /etc/app/config.yaml: file.managed: - template: py - source: salt://_templates/yaml2.py - context: source: app:config root: app:production default: cache: default: value Output: # Preamble app: production: cache: pillar: value default: value """ args = globals().get("context", {}) data = __salt__["template.prepare"](**args) if "root" in args: for level in reversed(args["root"].split(":")): data = {level: data} # sort_keys only exists in newer pyyaml versions if version_cmp(_pyyaml.__version__, "5.1") >= 0: out = yaml.serialize(data, default_flow_style=False, sort_keys=False) else: out = yaml.serialize(data, default_flow_style=False) return __salt__["template.managed"](out, **args)
def test_serialize_yaml(self): data = {"foo": "bar", "encrypted_data": EncryptedString("foo")} serialized = yaml.serialize(data) assert serialized == '{encrypted_data: !encrypted foo, foo: bar}', serialized deserialized = yaml.deserialize(serialized) assert deserialized == data, deserialized
def test_serialize_yaml(self): data = {"foo": "bar"} serialized = yaml.serialize(data) assert serialized == '{foo: bar}', serialized deserialized = yaml.deserialize(serialized) assert deserialized == data, deserialized
def test_serialize_yaml(self): data = { "foo": "bar" } serialized = yaml.serialize(data) assert serialized == '{foo: bar}', serialized deserialized = yaml.deserialize(serialized) assert deserialized == data, deserialized
def test_serialize_yaml(self): data = {"foo": "bar", "encrypted_data": EncryptedString("foo")} # The C dumper produces unquoted strings when serializing an # EncryptedString, while the non-C dumper produces quoted strings. expected = '{encrypted_data: !encrypted foo, foo: bar}' \ if hasattr(_yaml, 'CSafeDumper') \ else "{encrypted_data: !encrypted 'foo', foo: bar}" serialized = yaml.serialize(data) assert serialized == expected, serialized deserialized = yaml.deserialize(serialized) assert deserialized == data, deserialized
def test_serialize_complex_sls(self): data = OrderedDict([("foo", 1), ("bar", 2), ("baz", True)]) serialized = yamlex.serialize(data) assert serialized == "{foo: 1, bar: 2, baz: true}", serialized deserialized = yamlex.deserialize(serialized) assert deserialized == data, deserialized serialized = yaml.serialize(data) assert serialized == "{bar: 2, baz: true, foo: 1}", serialized deserialized = yaml.deserialize(serialized) assert deserialized == data, deserialized
def test_serialize_sls(self): data = {"foo": "bar"} serialized = yamlex.serialize(data) assert serialized == "{foo: bar}", serialized serialized = yamlex.serialize(data, default_flow_style=False) assert serialized == "foo: bar", serialized deserialized = yamlex.deserialize(serialized) assert deserialized == data, deserialized serialized = yaml.serialize(data) assert serialized == "{foo: bar}", serialized deserialized = yaml.deserialize(serialized) assert deserialized == data, deserialized serialized = yaml.serialize(data, default_flow_style=False) assert serialized == "foo: bar", serialized deserialized = yaml.deserialize(serialized) assert deserialized == data, deserialized
def test_compare_sls_vs_yaml_with_jinja(self): tpl = '{{ data }}' env = jinja2.Environment() src = '{foo: 1, bar: 2, baz: {qux: true}}' sls_src = env.from_string(tpl).render(data=yamlex.deserialize(src)) yml_src = env.from_string(tpl).render(data=yaml.deserialize(src)) sls_data = yamlex.deserialize(sls_src) yml_data = yaml.deserialize(yml_src) # ensure that sls & yaml have the same base assert isinstance(sls_data, dict) assert isinstance(yml_data, dict) # The below has been commented out because something the loader test # is modifying the yaml renderer to render things to unicode. Without # running the loader test, the below passes. Even reloading the module # from disk does not reset its internal state (per the Python docs). ## #assert sls_data == yml_data # ensure that sls is ordered, while yaml not assert isinstance(sls_data, OrderedDict) assert not isinstance(yml_data, OrderedDict) # prove that yaml does not handle well with OrderedDict # while sls is jinja friendly. obj = OrderedDict([ ('foo', 1), ('bar', 2), ('baz', {'qux': True}) ]) sls_obj = yamlex.deserialize(yamlex.serialize(obj)) try: yml_obj = yaml.deserialize(yaml.serialize(obj)) except SerializationError: # BLAAM! yaml was unable to serialize OrderedDict, # but it's not the purpose of the current test. yml_obj = obj.copy() sls_src = env.from_string(tpl).render(data=sls_obj) yml_src = env.from_string(tpl).render(data=yml_obj) final_obj = yaml.deserialize(sls_src) assert obj == final_obj # BLAAM! yml_src is not valid ! final_obj = OrderedDict(yaml.deserialize(yml_src)) assert obj != final_obj
def test_compare_sls_vs_yaml_with_jinja(self): tpl = '{{ data }}' env = jinja2.Environment() src = '{foo: 1, bar: 2, baz: {qux: true}}' sls_src = env.from_string(tpl).render(data=yamlex.deserialize(src)) yml_src = env.from_string(tpl).render(data=yaml.deserialize(src)) sls_data = yamlex.deserialize(sls_src) yml_data = yaml.deserialize(yml_src) # ensure that sls & yaml have the same base assert isinstance(sls_data, dict) assert isinstance(yml_data, dict) assert sls_data == yml_data # ensure that sls is ordered, while yaml not assert isinstance(sls_data, OrderedDict) assert not isinstance(yml_data, OrderedDict) # prove that yaml does not handle well with OrderedDict # while sls is jinja friendly. obj = OrderedDict([ ('foo', 1), ('bar', 2), ('baz', {'qux': True}) ]) sls_obj = yamlex.deserialize(yamlex.serialize(obj)) try: yml_obj = yaml.deserialize(yaml.serialize(obj)) except SerializationError: # BLAAM! yaml was unable to serialize OrderedDict, # but it's not the purpose of the current test. yml_obj = obj.copy() sls_src = env.from_string(tpl).render(data=sls_obj) yml_src = env.from_string(tpl).render(data=yml_obj) final_obj = yaml.deserialize(sls_src) assert obj == final_obj # BLAAM! yml_src is not valid ! final_obj = OrderedDict(yaml.deserialize(yml_src)) assert obj != final_obj
def add(princ, minion_id, tmp_keytab_dir='/root', # CONFIGURE THESE! pillarstack_dir='/srv/pillar/keytabs/id/', keytab_prov_user='******', keytab_prov_creds='/root/ktprov.keytab', kdc_type = 'mit', ad_dir = 'OU=Comps,OU=SomeOrg'): tmp_keytab = re.sub('[/@]', '_', princ) + '.keytab' fqdn = princ.split('/')[1].split('@')[0] # AD computer account name can only be 16 chars, select the last 14 of the principal ad_comp_name = "h-" + fqdn.split('.')[0][-14:] princ_type = princ.split('/')[0] krbDict = {'keytabs' : {tmp_keytab : ''}} id_yml = '{0}.yml'.format(minion_id) # Provision the principal if kdc_type == 'ad': subprocess.call('k5start {2} -f {3} -k /tmp/krbcc_keytab_state -- msktutil -b "{4}" -k {0}/{1} -h {5} -s {6} --computer-name {7}'.format(tmp_keytab_dir, tmp_keytab, keytab_prov_user, keytab_prov_creds, ad_dir, fqdn, princ_type, ad_comp_name), shell=True) else: subprocess.call('echo -e "ank -randkey {4}\nktadd -k {0}/{1} {4}" | kadmin -p {2} -k -t {3}'.format(tmp_keytab_dir, tmp_keytab, keytab_prov_user, keytab_prov_creds, princ), shell=True) # Add the principal to the minion's pillar with open('{0}/{1}'.format(tmp_keytab_dir, tmp_keytab), 'rb') as krbFile: krbDict['keytabs'][tmp_keytab] = base64.b64encode(krbFile.read()) fh = open('{0}/{1}'.format(pillarstack_dir, id_yml), 'wb') fh.write(yaml.serialize(krbDict)) fh.close() # Clean up temp keytab file os.remove('{0}/{1}'.format(tmp_keytab_dir, tmp_keytab)) # Wait for the minion to grab the keytab, then remove it from pillar time.sleep(20) os.remove('{0}/{1}'.format(pillarstack_dir, id_yml))
def test_reactor_is_leader( event_listener, salt_master, salt_run_cli, master_event_bus, reactor_event, salt_minion, event_listerner_timeout, ): """ If reactor system is unavailable, an exception is thrown. When leader is true (the default), the reacion event should return. When leader is set to false reactor should timeout/not do anything. """ ret = salt_run_cli.run("reactor.is_leader") assert ret.exitcode == 0 assert ( "salt.exceptions.CommandExecutionError: Reactor system is not running." in ret.stdout ) ret = salt_run_cli.run("reactor.set_leader", value=True) assert ret.exitcode == 0 assert ( "salt.exceptions.CommandExecutionError: Reactor system is not running." in ret.stdout ) ret = salt_run_cli.run("reactor.is_leader") assert ret.exitcode == 0 assert ( "salt.exceptions.CommandExecutionError: Reactor system is not running." in ret.stdout ) # make reactor not the leader; ensure reactor engine is available engines_config = salt_master.config.get("engines").copy() for idx, engine in enumerate(list(engines_config)): if "reactor" in engine: engines_config.pop(idx) engines_config.append( { "reactor": { "refresh_interval": 60, "worker_threads": 10, "worker_hwm": 10000, } } ) config_overrides = yaml.serialize({"engines": engines_config}) confd_dir = ( pathlib.Path(salt_master.config_dir) / pathlib.Path(salt_master.config["default_include"]).parent ) confd_dir.mkdir(exist_ok=True) # Now, with the temp config in place, ensure the reactor engine is running with pytest.helpers.temp_file("reactor-test.conf", config_overrides, confd_dir): ret = salt_run_cli.run("reactor.set_leader", value=True) assert ret.exitcode == 0 assert ( "CommandExecutionError" not in ret.stdout ), "reactor engine is not running" ret = salt_run_cli.run("reactor.is_leader") assert ret.exitcode == 0 assert ret.stdout.rstrip().splitlines()[-1] == "true" ret = salt_run_cli.run("reactor.set_leader", value=False) assert ret.exitcode == 0 ret = salt_run_cli.run("reactor.is_leader") assert ret.exitcode == 0 assert ret.stdout.rstrip().splitlines()[-1] == "false" start_time = time.time() master_event_bus.fire_event({"id": salt_minion.id}, reactor_event.tag) # Since leader is false, let's try and get the fire event to ensure it was triggered event_pattern = (salt_master.id, reactor_event.tag) matched_events = event_listener.wait_for_events( [event_pattern], after_time=start_time, timeout=event_listerner_timeout.catch, ) assert matched_events.found_all_events # Now that we matched the trigger event, let's confirm we don't get the reaction event event_pattern = (salt_master.id, reactor_event.event_tag) matched_events = event_listener.wait_for_events( [event_pattern], after_time=start_time, timeout=event_listerner_timeout.miss ) assert matched_events.found_all_events is not True # make reactor the leader again; ensure reactor engine is available ret = salt_run_cli.run("reactor.set_leader", value=True) assert ret.exitcode == 0 ret = salt_run_cli.run("reactor.is_leader") assert ret.exitcode == 0 assert ret.stdout.rstrip().splitlines()[-1] == "true" # trigger a reaction start_time = time.time() master_event_bus.fire_event({"id": salt_minion.id}, reactor_event.tag) event_pattern = (salt_master.id, reactor_event.event_tag) matched_events = event_listener.wait_for_events( [event_pattern], after_time=start_time, timeout=event_listerner_timeout.catch, ) assert matched_events.found_all_events for event in matched_events: assert event.data["test_reaction"] is True # Let's just confirm the engine is not running once again(because the config file is deleted by now) ret = salt_run_cli.run("reactor.is_leader") assert ret.exitcode == 0 assert ( "salt.exceptions.CommandExecutionError: Reactor system is not running." in ret.stdout )