def run_module() -> None: module_args = _module_args() result: Dict[str, Any] = dict( changed=False, ) # supports_check_mode=True is okay we just collecting data # and therefore no extra mechanism to address check_mode=true module = AnsibleModule( argument_spec=module_args, supports_check_mode=True ) params: Params = Params(copy.deepcopy(module.params)) func_run_command = functools.partial(AnsibleModule.run_command, module) func_log = logging.CachingLogger(module.log) try: registration_info: SpireAgentRegistrationInfo = SpireAgentRegistrationInfo( run_command=func_run_command, log_func=func_log, spire_server_install_dir=module.params.get("spire_server_install_dir"), spire_agent_spiffe_ids=module.params.get("spire_agent_spiffe_id"), spire_agent_attestation_types=module.params.get("spire_agent_attestation_type"), spire_agent_serial_numbers=module.params.get("spire_agent_serial_number"), spire_server_registration_uds_path=module.params.get("spire_server_registration_uds_path"), ) entry_data_list: List[AgentRegistrationEntry] = registration_info.find_registrations() AgentRegistrationEntry.to_ansible_result_registration_entry result["spire_agent_registrations"] = [ AgentRegistrationEntry.to_ansible_result_registration_entry(e) for e in entry_data_list ] result["debug_msg"] = str(func_log.messages) module.exit_json(**result) except Exception as e: module.fail_json(msg=f"Exception while running module:{func_log.messages}", exception=e)
def run_module() -> None: module_args = _module_args() # TODO check if check_mode does make any sens? module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) params: Params = Params(copy.deepcopy(module.params)) func_run_command = RunCommand(module) func_log = logging.CachingLogger(module.log) try: dirs: AgentDirs = AgentDirs( config_dir=module.params["spire_agent_config_dir"], data_dir=module.params["spire_agent_data_dir"], install_dir=module.params["spire_agent_install_dir"], log_dir=module.params["spire_agent_log_dir"], service_dir=module.params["spire_agent_service_dir"], service_name=module.params["spire_agent_service_name"], ) agent_info: SpireAgentInfo = SpireAgentInfo( run_command=func_run_command, log_func=func_log, dirs=dirs, socket_path=module.params["spire_agent_socket_path"], service_scope=module.params["spire_agent_service_scope"], expected_version=None # TODO not needed remove me ) state_snapshot: AgentStateSnapshot = AgentStateSnapshot(agent_info) result = { "changed": False, **state_snapshot.to_ansible_result(), "debug_msg": str(func_log.messages) } module.exit_json(**result) except Exception as e: module.fail_json( msg=f"Exception while running module:{func_log.messages}", exception=e)
def test_entries_having_same_identity( test_case: str, params: Dict[str, Union[List[str], str, bool]], entries: List[RegistrationEntry], expected: List[RegistrationEntry]) -> None: actual = entries_having_same_identity(Params(params), entries) assert actual == expected, f"case failed: {test_case}"
def test_need_change(test_case: str, params: Dict[str, Union[List[str], str, bool]], entry: Dict[str, Union[List[str], str]], expected: bool) -> None: actual = need_change(Params(params), RegistrationEntry(entry)) assert actual == expected, f"case failed: {test_case}"
def run_module() -> None: module_args = _module_args() module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) params: Params = Params(copy.deepcopy(module.params)) func_run_command = RunCommand(module) func_log = logging.CachingLogger(module.log) try: assert_not_handling_check_mode_since_action_reponsibility(module) server_dirs = ServerDirs.from_ansible_src( value_lookup_func=module.params.get) server_info: SpireServerInfo = _server_info_from_module_params( run_command=func_run_command, log_func=func_log, server_dirs=server_dirs, params=params) state_snapshot = ServerStateSnapshot(server_info) current_state: StateOfServer = state_snapshot.get_state_of_server() expected_state: StateOfServer = StateOfServer.from_task_args(params) changed = False func_log( f"state-of-server: actual={current_state}, expected={expected_state}" ) if expected_state.need_change(current_state): changed = True func_log(f"Change expected:state={expected_state.state}") service = systemd.SpireComponentService( service_name=module.params["spire_server_service_name"], scope=systemd.Scope.by_name( module.params["spire_server_service_scope"]), run_command=func_run_command, log_func=func_log) if expected_state.state == State.absent: service.teardown_service() dir_keys = [ "spire_server_config_dir", "spire_server_data_dir", "spire_server_install_dir", # "spire_server_service_dir" ] for dir_key in dir_keys: dir_value: str = module.params.get(dir_key) if dir_keys is not None and not dir_value.isspace(): shutil.rmtree(dir_value.strip()) log_dir: str = module.params.get("spire_server_log_dir") if log_dir is not None and pathlib.Path( log_dir.strip()) != pathlib.Path("/var/log"): shutil.rmtree(log_dir) else: if expected_state.need_srv_installation_change(current_state): if SubStateServiceInstallation.not_installed == expected_state.substate_service_installation: service.teardown_service() else: # all service related file are created by the ansible-action. # we just make sure the service as been installed (file as been copied) # This does not assess the runtime viability of the service server_info.assert_spire_component_and_srv_are_installed( ) if expected_state.substate_service_installation == SubStateServiceInstallation.enabled: service.enable() if expected_state.substate_service_status == SubStateServiceStatus.stopped: service.stop() else: # started or healthy service.start() if expected_state.substate_service_status == SubStateServiceStatus.healthy: timeout = module.params[ "spire_server_healthiness_probe_timeout_seconds"] healthcheck = healthchecks.CheckServer( run_command=func_run_command, file_spire_server_bin=server_info. get_executable_path(), readiness_probe_timeout_seconds=timeout, registration_uds_path=module.params[ "spire_server_registration_uds_path"]) healthcheck.wait_for_readiness() server_info = _server_info_from_module_params( run_command=func_run_command, log_func=func_log, server_dirs=server_dirs, params=params) state_snapshot = spire_server_info_cmd.ServerStateSnapshot( server_info) current_state = state_snapshot.get_state_of_server() func_log(f"issues = {state_snapshot.get_all_issues()}") result = { "changed": changed, **current_state.to_ansible_return_data(), "info": state_snapshot.to_ansible_result(), "debug_msg": func_log.messages, } module.exit_json(**result) except Exception as e: print(func_log.messages) module.fail_json( msg=f"Exception while running module:{str(e)}", exception=e, debug_msg=func_log.messages, )
def run_module() -> None: module_args = _module_args() module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) params: Params = Params(copy.deepcopy(module.params)) func_run_command = RunCommand(module) func_log = logging.CachingLogger(module.log) try: assert_not_handling_check_mode_since_action_reponsibility(module) dirs: AgentDirs = AgentDirs( config_dir=module.params["spire_agent_config_dir"], data_dir=module.params["spire_agent_data_dir"], log_dir=module.params["spire_agent_log_dir"], service_dir=module.params["spire_agent_service_dir"], install_dir=module.params["spire_agent_install_dir"], service_name=module.params["spire_agent_service_name"], ) agent_info: SpireAgentInfo = SpireAgentInfo( run_command=func_run_command, log_func=func_log, dirs=dirs, socket_path=module.params["spire_agent_socket_path"], service_scope=module.params["spire_agent_service_scope"], ) state_snapshot = spire_agent_info_cmd.AgentStateSnapshot(agent_info) current_state: StateOfAgent = state_snapshot.get_state_of_agent() expected_state: StateOfAgent = StateOfAgent.from_task_args(params) if expected_state.need_change(current_state): func_log(f"Change expected:state={expected_state.state}") service = systemd.SpireComponentService( service_name=module.params["spire_agent_service_name"], scope=systemd.Scope.by_name( module.params["spire_agent_service_scope"]), run_command=func_run_command, log_func=func_log) if expected_state.state == State.absent: service.teardown_service() dir_keys = [ "spire_agent_config_dir", "spire_agent_data_dir", "spire_agent_install_dir", # "spire_agent_service_dir" ] for dir_key in dir_keys: dir_value: str = module.params.get(dir_key) if dir_keys is not None and not dir_value.isspace(): shutil.rmtree(dir_value.strip()) log_dir: str = module.params.get("spire_agent_log_dir") if log_dir is not None and pathlib.Path( log_dir.strip()) != pathlib.Path("/var/log"): shutil.rmtree(log_dir) else: if expected_state.need_srv_installation_change(current_state): if SubStateServiceInstallation.not_installed == expected_state.substate_service_installation: service.teardown_service() else: # all service related file are created by the ansible-action. # we just make sure the service as been installed (file as been copied) # This does not assess the runtime viability of the service agent_info.assert_agent_and_srv_are_installed() if expected_state.substate_service_installation == SubStateServiceInstallation.enabled: service.enable() if expected_state.substate_service_status == SubStateServiceStatus.stopped: if expected_state.substate_agent_registered == SubStateAgentRegistered.yes: # registration is a collaborative job between agent and server. # we do not have access to the server from here. # we however know that an healthy agent must have a valid registration # So our strategy to ensure registration is to: # - starts the agent # - wait for its healthiness # - and and stop it service.start() timeout = module.params[ "spire_agent_healthiness_probe_timeout_seconds"] healthcheck = healthchecks.CheckAgent( run_command=func_run_command, file_spire_agent_bin=dirs.path_executable, readiness_probe_timeout_seconds=timeout, socket_path=module. params["spire_agent_socket_path"]) healthcheck.wait_for_readiness() service.stop() else: # started or healthy service.start() if expected_state.substate_service_status == SubStateServiceStatus.healthy: timeout = module.params[ "spire_agent_healthiness_probe_timeout_seconds"] healthcheck = healthchecks.CheckAgent( run_command=func_run_command, file_spire_agent_bin=dirs.path_executable, readiness_probe_timeout_seconds=timeout, socket_path=module. params["spire_agent_socket_path"]) healthcheck.wait_for_readiness() agent_info.reset_computed_base_state() state_snapshot = spire_agent_info_cmd.AgentStateSnapshot(agent_info) current_state = state_snapshot.get_state_of_agent() func_log(f"issues = {state_snapshot.get_issues_issues()}") result = { "changed": False, **current_state.to_ansible_return_data(), "debug_msg": func_log.messages, } module.exit_json(**result) except Exception as e: module.fail_json( msg=f"Exception while running module:{str(e)}", exception=e, debug_msg=func_log.messages, )
def run_module() -> None: module_args = _module_args() result = dict( state='absent', changed=False, ) module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) params: Params = Params(copy.deepcopy(module.params)) func_run_command = functools.partial(AnsibleModule.run_command, module) func_log = logging.CachingLogger(module.log) try: show_outcome: SpireServerEntryShowOutcome = spire_server_entry_cmd.cmd_server_entry_show( func_run_command, func_log, params, ) if show_outcome.exec_failed(): msg = f""" Fail to execute <entry show> cmd: parse_error={show_outcome.parse_error} rc={show_outcome.rc} stdout={show_outcome.stdout} stderr={show_outcome.stderr} entries={show_outcome.entries} """ raise RuntimeError(msg) if show_outcome.parsing_failed(): msg = f""" Fail to parse <entry show> output: parse_error={show_outcome.parse_error} rc={show_outcome.rc} stdout={show_outcome.stdout} stderr={show_outcome.stderr} entries={show_outcome.entries} """ raise RuntimeError(msg) # identity_params = params["identity_args"] actual_list = spire_server_entry_cmd.entries_having_same_identity( params, show_outcome.entries) if len(actual_list) > 1: module.fail_json( msg= f'Cannot handle more than one identified corresponding entries: {actual_list}' ) actual: RegistrationEntry = RegistrationEntry() if len( actual_list) == 0 else actual_list[0] need_change = spire_server_entry_cmd.need_change(params, actual) if need_change: debug_msg = f""" need_change={need_change} params={params} actual={actual} actual_list={actual_list} entries={show_outcome.entries} """ func_log(debug_msg) state = module.params['state'] result["state"] = state result["changed"] = need_change if need_change: if not module.check_mode: if state == "absent": # TODO actual is entry not a Param so merging is not type safe intro actual.to_params() # or params.to_entry(..) because it is the command being built # so command data format is needed which is entry data merged = {**actual, **params} spire_server_entry_cmd.cmd_server_entry_delete( func_run_command, func_log, merged) if state == "present": if not actual: spire_server_entry_cmd.cmd_server_entry_create( func_run_command, func_log, params) else: # TODO actual is entry not a Param so merging is not type safe merged = {**actual, **params} spire_server_entry_cmd.cmd_server_entry_update( func_run_command, func_log, merged) result["debug_msg"] = str(func_log.messages) module.exit_json(**result) except Exception as e: module.fail_json( msg=f"Exception while running module:{func_log.messages}", exception=str(e))