"""Unit tests for Ansible credential argv/env construction (task 548).""" import json from steward.ansible.executor import ansible_env, build_bootstrap, build_credentials def test_no_creds_is_empty(): assert build_credentials({}, "/td") == ([], []) assert build_credentials(None, "/td") == ([], []) def test_ssh_key_via_file(): args, files = build_credentials({"ssh_private_key": "KEYDATA"}, "/td") assert args == ["--private-key", "/td/id_key"] assert files == [("/td/id_key", "KEYDATA\n")] def test_ssh_key_keeps_existing_trailing_newline(): _, files = build_credentials({"ssh_private_key": "KEY\n"}, "/td") assert files == [("/td/id_key", "KEY\n")] def test_vault_password_via_file(): args, files = build_credentials({"vault_password": "vpw"}, "/td") assert args == ["--vault-password-file", "/td/vault_pass"] assert files == [("/td/vault_pass", "vpw\n")] def test_become_password_uses_vars_file_not_argv(): pw = "p@ss word" args, files = build_credentials({"become_password": pw}, "/td") assert args == ["-e", "@/td/become.yml"] assert files[0][0] == "/td/become.yml" assert files[0][1] == "ansible_become_password: " + json.dumps(pw) + "\n" # The password must never appear on the command line. assert pw not in " ".join(args) def test_all_three_combined(): args, files = build_credentials( {"ssh_private_key": "K", "vault_password": "V", "become_password": "B"}, "/td") assert "--private-key" in args assert "--vault-password-file" in args assert "-e" in args assert len(files) == 3 def test_ansible_env_host_key_checking_toggle(): assert ansible_env({"host_key_checking": True}, {})["ANSIBLE_HOST_KEY_CHECKING"] == "True" assert ansible_env({"host_key_checking": False}, {})["ANSIBLE_HOST_KEY_CHECKING"] == "False" assert ansible_env({}, {})["ANSIBLE_HOST_KEY_CHECKING"] == "False" assert ansible_env(None, {})["ANSIBLE_HOST_KEY_CHECKING"] == "False" def test_ansible_env_preserves_base(): env = ansible_env({}, {"FOO": "bar"}) assert env["FOO"] == "bar" # ── Bootstrap connection override (first-contact provisioning) ───────────────── def test_bootstrap_empty_is_noop(): assert build_bootstrap({}, "/td") == ([], []) assert build_bootstrap(None, "/td") == ([], []) def test_bootstrap_user_only(): args, files = build_bootstrap({"user": "root"}, "/td") assert args == ["-e", "@/td/bootstrap.yml"] assert files == [("/td/bootstrap.yml", 'ansible_user: "root"\n')] def test_bootstrap_password_doubles_as_become_and_stays_off_argv(): pw = "p@ss word" args, files = build_bootstrap({"user": "admin", "password": pw}, "/td") assert args == ["-e", "@/td/bootstrap.yml"] body = files[0][1] assert 'ansible_user: "admin"\n' in body assert "ansible_password: " + json.dumps(pw) + "\n" in body # Bare password becomes the become password too. assert "ansible_become_password: " + json.dumps(pw) + "\n" in body # Secret must never reach the command line. assert pw not in " ".join(args) def test_bootstrap_explicit_become_password(): _, files = build_bootstrap( {"user": "u", "password": "sshpw", "become_password": "sudopw"}, "/td") body = files[0][1] assert 'ansible_password: "sshpw"\n' in body assert 'ansible_become_password: "sudopw"\n' in body