async def setup(self, serverdirect: OrchestrationService, resource_service: ResourceService, env: data.Environment, sid: UUID): for version in range(0, len(self.versions)): # allocate a bunch of versions! v = await env.get_next_version() assert v == version + 1 if self.versions[version]: res = await serverdirect.put_version( env=env, version=version, resources=self.versions[version], unknowns=[], version_info={}, resource_state={}, compiler_version=get_compiler_version(), ) assert res == 200 result, _ = await serverdirect.release_version( env, version, False) assert result == 200 for rid, state in self.states.items(): # Start the deploy action_id = uuid.uuid4() now = datetime.now() if state == const.ResourceState.available: # initial state can not be set continue if state not in const.TRANSIENT_STATES: finished = now else: finished = None result = await resource_service.resource_action_update( env, [rid], action_id, ResourceAction.deploy, now, finished, status=state, messages=[], changes={}, change=None, send_events=False, ) assert result == 200 allresources = {} for agent, results in self.results.items(): result, payload = await resource_service.get_resources_for_agent( env, agent, version=None, incremental_deploy=True, sid=sid) assert sorted([x["resource_id"] for x in payload["resources"]]) == sorted(results) allresources.update( {r["resource_id"]: r for r in payload["resources"]}) return allresources
async def test_version_removal(client, server): """ Test auto removal of older deploy model versions """ result = await client.create_project("env-test") assert result.code == 200 project_id = result.result["project"]["id"] result = await client.create_environment(project_id=project_id, name="dev") env_id = result.result["environment"]["id"] for _i in range(20): version = (await client.reserve_version(env_id)).result["data"] await server.get_slice(SLICE_ORCHESTRATION)._purge_versions() res = await client.put_version(tid=env_id, version=version, resources=[], unknowns=[], version_info={}, compiler_version=get_compiler_version()) assert res.code == 200 result = await client.get_project(id=project_id) versions = await client.list_versions(tid=env_id) assert versions.result["count"] <= opt.server_version_to_keep.get() + 1
async def _deploy_resources(client, environment, resources, version, push, agent_trigger_method=None): result = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 # do a deploy result = await client.release_version(environment, version, push, agent_trigger_method) assert result.code == 200 assert not result.result["model"]["deployed"] assert result.result["model"]["released"] assert result.result["model"]["total"] == len(resources) result = await client.get_version(environment, version) assert result.code == 200 return result
async def test_version(server, client, clienthelper, environment, cli, push_method): version = str(await clienthelper.get_version()) resources = [ { "key": "key1", "value": "value1", "id": "test::Resource[agent1,key=key1],v=" + version, "send_event": False, "purged": False, "requires": ["test::Resource[agent1,key=key2],v=" + version], }, { "key": "key2", "value": "value2", "id": "test::Resource[agent1,key=key2],v=" + version, "send_event": False, "requires": [], "purged": False, }, { "key": "key3", "value": None, "id": "test::Resource[agent1,key=key3],v=" + version, "send_event": False, "requires": [], "purged": True, }, ] result = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 result = await cli.run("version", "list", "-e", environment) assert result.exit_code == 0 assert version in result.output assert "pending" in result.output result = await cli.run("version", "release", "-e", environment, version, *push_method) assert result.exit_code == 0 assert version in result.output result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["result"] == "deploying" result = await cli.run("version", "report", "-e", environment, "-i", version) assert result.exit_code == 0
async def test_send_events(resource_container, environment, server, client, agent, clienthelper): """ Send and receive events within one agent """ resource_container.Provider.reset() version = await clienthelper.get_version() res_id_1 = "test::Resource[agent1,key=key1],v=%d" % version resources = [ { "key": "key1", "value": "value1", "id": res_id_1, "send_event": False, "purged": False, "requires": ["test::Resource[agent1,key=key2],v=%d" % version], }, { "key": "key2", "value": "value2", "id": "test::Resource[agent1,key=key2],v=%d" % version, "send_event": True, "requires": [], "purged": False, }, ] result = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 # do a deploy result = await client.release_version( environment, version, True, const.AgentTriggerMethod.push_full_deploy) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 await _wait_until_deployment_finishes(client, environment, version) events = resource_container.Provider.getevents("agent1", "key1") assert len(events) == 1 for res_id, res in events[0].items(): assert res_id.agent_name == "agent1" assert res_id.attribute_value == "key2" assert res["status"] == const.ResourceState.deployed assert res["change"] == const.Change.created
async def put_version_simple(self, resources, version): res = await self.client.put_version( tid=self.environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200, res.result
async def test_code_upload(server, client, agent, environment): """Test upload of a single code definition""" version = (await client.reserve_version(environment)).result["data"] resources = [{ "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1.dev.inmanta.com,path=/etc/sysconfig/network],v=%d" % version, "owner": "root", "path": "/etc/sysconfig/network", "permissions": 644, "purged": False, "reload": False, "requires": [], "version": version, }] res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 sources = make_source({}, "a.py", "std.test", "wlkvsdbhewvsbk vbLKBVWE wevbhbwhBH", []) sources = make_source(sources, "b.py", "std.xxx", "rvvWBVWHUvejIVJE UWEBVKW", ["pytest"]) res = await client.upload_code(tid=environment, id=version, resource="std::File", sources=sources) assert res.code == 200 res = await agent._client.get_code(tid=environment, id=version, resource="std::File") assert res.code == 200 assert res.result["sources"] == sources
async def push_version_to_environment() -> None: res = await client.reserve_version(env_id) assert res.code == 200 version = res.result["data"] result = await client.put_version( tid=env_id, version=version, resources=[], unknowns=[], compiler_version=get_compiler_version(), ) assert result.code == 200
async def environment_decommission( self, env: data.Environment, metadata: Optional[model.ModelMetadata]) -> int: is_protected_environment = await env.get(data.PROTECTED_ENVIRONMENT) if is_protected_environment: raise Forbidden( f"Environment {env.id} is protected. See environment setting: {data.PROTECTED_ENVIRONMENT}" ) version = await env.get_next_version() if metadata is None: metadata = model.ModelMetadata( message="Decommission of environment", type="api") version_info = model.ModelVersionInfo(export_metadata=metadata) await self.orchestration_service.put_version(env, version, [], {}, [], version_info.dict(), get_compiler_version()) return version
async def test_clear_environment(client, server, clienthelper, environment): """ Test clearing out an environment """ version = await clienthelper.get_version() result = await client.put_version(tid=environment, version=version, resources=[], unknowns=[], version_info={}, compiler_version=get_compiler_version()) assert result.code == 200 result = await client.get_environment(id=environment, versions=10) assert result.code == 200 assert len(result.result["environment"]["versions"]) == 1 # trigger multiple compiles and wait for them to complete in order to test cascade deletion of collapsed compiles (#2350) result = await client.notify_change_get(id=environment) assert result.code == 200 result = await client.notify_change_get(id=environment) assert result.code == 200 result = await client.notify_change_get(id=environment) assert result.code == 200 async def compile_done(): return (await client.is_compiling(environment)).code == 204 await retry_limited(compile_done, 10) # Wait for env directory to appear slice = server.get_slice(SLICE_SERVER) env_dir = os.path.join(slice._server_storage["environments"], environment) while not os.path.exists(env_dir): await asyncio.sleep(0.1) result = await client.clear_environment(id=environment) assert result.code == 200 assert not os.path.exists(env_dir) result = await client.get_environment(id=environment, versions=10) assert result.code == 200 assert len(result.result["environment"]["versions"]) == 0
async def test_get_environment(client, clienthelper, server, environment): for i in range(10): version = await clienthelper.get_version() resources = [] for j in range(i): resources.append({ "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1.dev.inmanta.com,path=/tmp/file%d],v=%d" % (j, version), "owner": "root", "path": "/tmp/file%d" % j, "permissions": 644, "purged": False, "reload": False, "requires": [], "version": version, }) res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 result = await client.get_environment(environment, versions=5, resources=1) assert result.code == 200 assert len(result.result["environment"]["versions"]) == 5 assert len(result.result["environment"]["resources"]) == 9
async def test_resource_action_log(server, client, environment): version = (await client.reserve_version(environment)).result["data"] resources = [{ "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1.dev.inmanta.com,path=/etc/sysconfig/network],v=%d" % version, "owner": "root", "path": "/etc/sysconfig/network", "permissions": 644, "purged": False, "reload": False, "requires": [], "version": version, }] res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 resource_action_log = server.get_slice( SLICE_RESOURCE).get_resource_action_log_file(environment) assert os.path.isfile(resource_action_log) assert os.stat(resource_action_log).st_size != 0 with open(resource_action_log, "r") as f: contents = f.read() parts = contents.split(" ") # Date and time parser.parse(f"{parts[0]} {parts[1]}")
async def test_disable_purge_on_delete(client, clienthelper, server, environment): """ Test disable purge on delete of resources """ agent = Agent("localhost", {"blah": "localhost"}, environment=environment, code_loader=False) await agent.start() aclient = agent._client env = await data.Environment.get_by_id(environment) await env.set(data.PURGE_ON_DELETE, False) version = await clienthelper.get_version() resources = [{ "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file1],v=%d" % version, "owner": "root", "path": "/tmp/file1", "permissions": 644, "purged": False, "reload": False, "requires": [], "purge_on_delete": True, "version": version, }] res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 # Release the model and set all resources as deployed result = await client.release_version(environment, version, False) assert result.code == 200 now = datetime.now() result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file1],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["result"] == const.VersionState.success.name # Empty version version = await clienthelper.get_version() result = await client.put_version(tid=environment, version=version, resources=[], unknowns=[], version_info={}, compiler_version=get_compiler_version()) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["total"] == 0 await agent.stop()
def commit_resources(self, version: int, resources: List[Dict[str, str]], metadata: Dict[str, str], model: Dict) -> None: """ Commit the entire list of resource to the configurations server. """ tid = cfg_env.get() if tid is None: LOGGER.error("The environment for this model should be set!") raise Exception("The environment for this model should be set!") conn = protocol.SyncClient("compiler") self.deploy_code(conn, tid, version) LOGGER.info("Uploading %d files" % len(self._file_store)) # collect all hashes and send them at once to the server to check # if they are already uploaded hashes = list(self._file_store.keys()) res = conn.stat_files(files=hashes) if res.code != 200: raise Exception("Unable to check status of files at server") to_upload = res.result["files"] LOGGER.info("Only %d files are new and need to be uploaded" % len(to_upload)) for hash_id in to_upload: content = self._file_store[hash_id] res = conn.upload_file( id=hash_id, content=base64.b64encode(content).decode("ascii")) if res.code != 200: LOGGER.error("Unable to upload file with hash %s" % hash_id) else: LOGGER.debug("Uploaded file with hash %s" % hash_id) # Collecting version information version_info = {const.EXPORT_META_DATA: metadata, "model": model} # TODO: start transaction LOGGER.info("Sending resource updates to server") for res in resources: LOGGER.debug(" %s", res["id"]) res = conn.put_version( tid=tid, version=version, resources=resources, unknowns=unknown_parameters, resource_state=self._resource_state, version_info=version_info, compiler_version=get_compiler_version(), ) if res.code != 200: LOGGER.error("Failed to commit resource updates (%s)", res.result["message"]) raise Exception("Failed to commit resource updates (%s)" % res.result["message"])
async def test_deploy(server, agent: Agent, environment, caplog): """ Test basic deploy mechanism mocking """ with caplog.at_level(logging.WARNING): # acquire raw server orchestration_service = server.get_slice(SLICE_ORCHESTRATION) resource_service = server.get_slice(SLICE_RESOURCE) sid = agent.sessionid # acquire env object env = await data.Environment.get_by_id(uuid.UUID(environment)) version = await env.get_next_version() def make_resources(version): return [ { "key": "key1", "id": "test::Resource[agent1,key=key1],v=%d" % version, "send_event": False, "purged": False, "requires": [], }, { "key": "key2", "id": "test::Resource[agent1,key=key2],v=%d" % version, "send_event": False, "requires": ["test::Resource[agent1,key=key2],v=%d" % version], "purged": False, }, { "key": "key3", "id": "test::Resource[agent1,key=key3],v=%d" % version, "send_event": False, "requires": ["test::Resource[agent2,key=key4],v=%d" % version], "purged": True, }, { "key": "key4", "id": "test::Resource[agent2,key=key4],v=%d" % version, "send_event": False, "requires": [] }, ] resources = make_resources(version) res = await orchestration_service.put_version( env=env, version=version, resources=resources, unknowns=[], version_info={}, resource_state={}, compiler_version=get_compiler_version(), ) assert res == 200 result, _ = await orchestration_service.release_version( env, version, False) assert result == 200 resource_ids = [x["id"] for x in resources] # Start the deploy action_id = uuid.uuid4() now = datetime.now() result = await resource_service.resource_action_update( env, resource_ids, action_id, const.ResourceAction.deploy, now, now, status=ResourceState.deployed, messages=[], changes={}, change=None, send_events=False, ) assert result == 200 result, payload = await orchestration_service.get_version(env, version) assert result == 200 assert payload["model"].done == len(resources) # second, identical check_version v2 = await env.get_next_version() resources = make_resources(v2) res = await orchestration_service.put_version( env=env, version=v2, resources=resources, unknowns=[], version_info={}, resource_state={}, compiler_version=get_compiler_version(), ) assert res == 200 result, payload = await resource_service.get_resources_for_agent( env, "agent1", version=None, incremental_deploy=True, sid=sid) assert len(payload["resources"]) == 0 # Cannot request increment for specific version result, _ = await resource_service.get_resources_for_agent( env, "agent1", version=version, incremental_deploy=True, sid=sid) assert result == 500 result, _ = await resource_service.get_resources_for_agent( env, "agent1", version=v2, incremental_deploy=True, sid=sid) assert result == 500 for record in caplog.records: assert record.levelname != "WARNING"
async def test_get_resource_for_agent(server_multi, client_multi, environment_multi): """ Test the server to manage the updates on a model during agent deploy """ agent = Agent("localhost", {"nvblah": "localhost"}, environment=environment_multi, code_loader=False) await agent.add_end_point_name("vm1.dev.inmanta.com") await agent.add_end_point_name("vm2.dev.inmanta.com") await agent.start() aclient = agent._client version = (await client_multi.reserve_version(environment_multi)).result["data"] resources = [ { "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1.dev.inmanta.com,path=/etc/sysconfig/network],v=%d" % version, "owner": "root", "path": "/etc/sysconfig/network", "permissions": 644, "purged": False, "reload": False, "requires": [], "version": version, }, { "group": "root", "hash": "b4350bef50c3ec3ee532d4a3f9d6daedec3d2aba", "id": "std::File[vm2.dev.inmanta.com,path=/etc/motd],v=%d" % version, "owner": "root", "path": "/etc/motd", "permissions": 644, "purged": False, "reload": False, "requires": [], "version": version, }, { "group": "root", "hash": "3bfcdad9ab7f9d916a954f1a96b28d31d95593e4", "id": "std::File[vm1.dev.inmanta.com,path=/etc/hostname],v=%d" % version, "owner": "root", "path": "/etc/hostname", "permissions": 644, "purged": False, "reload": False, "requires": [], "version": version, }, { "id": "std::Service[vm1.dev.inmanta.com,name=network],v=%d" % version, "name": "network", "onboot": True, "requires": [ "std::File[vm1.dev.inmanta.com,path=/etc/sysconfig/network],v=%d" % version ], "state": "running", "version": version, }, ] res = await client_multi.put_version( tid=environment_multi, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 result = await client_multi.list_versions(environment_multi) assert result.code == 200 assert result.result["count"] == 1 result = await client_multi.release_version(environment_multi, version, False) assert result.code == 200 result = await client_multi.get_version(environment_multi, version) assert result.code == 200 assert result.result["model"]["version"] == version assert result.result["model"]["total"] == len(resources) assert result.result["model"]["released"] assert result.result["model"]["result"] == "deploying" result = await aclient.get_resources_for_agent(environment_multi, "vm1.dev.inmanta.com") assert result.code == 200 assert len(result.result["resources"]) == 3 action_id = uuid.uuid4() now = datetime.now() result = await aclient.resource_action_update( environment_multi, [ "std::File[vm1.dev.inmanta.com,path=/etc/sysconfig/network],v=%d" % version ], action_id, "deploy", now, now, "deployed", [], {}, ) assert result.code == 200 result = await client_multi.get_version(environment_multi, version) assert result.code == 200 assert result.result["model"]["done"] == 1 action_id = uuid.uuid4() now = datetime.now() result = await aclient.resource_action_update( environment_multi, ["std::File[vm1.dev.inmanta.com,path=/etc/hostname],v=%d" % version], action_id, "deploy", now, now, "deployed", [], {}, ) assert result.code == 200 result = await client_multi.get_version(environment_multi, version) assert result.code == 200 assert result.result["model"]["done"] == 2 await agent.stop()
async def test_dryrun_and_deploy(server, client, resource_container, environment): """ dryrun and deploy a configuration model There is a second agent with an undefined resource. The server will shortcut the dryrun and deploy for this resource without an agent being present. """ agentmanager = server.get_slice(SLICE_AGENT_MANAGER) agent = Agent(hostname="node1", environment=environment, agent_map={"agent1": "localhost"}, code_loader=False) await agent.add_end_point_name("agent1") await agent.start() await retry_limited(lambda: len(agentmanager.sessions) == 1, 10) resource_container.Provider.set("agent1", "key2", "incorrect_value") resource_container.Provider.set("agent1", "key3", "value") clienthelper = ClientHelper(client, environment) version = await clienthelper.get_version() resources = [ { "key": "key1", "value": "value1", "id": "test::Resource[agent1,key=key1],v=%d" % version, "send_event": False, "purged": False, "requires": ["test::Resource[agent1,key=key2],v=%d" % version], }, { "key": "key2", "value": "value2", "id": "test::Resource[agent1,key=key2],v=%d" % version, "send_event": False, "requires": [], "purged": False, }, { "key": "key3", "value": None, "id": "test::Resource[agent1,key=key3],v=%d" % version, "send_event": False, "requires": [], "purged": True, }, { "key": "key4", "value": execute.util.Unknown(source=None), "id": "test::Resource[agent2,key=key4],v=%d" % version, "send_event": False, "requires": [], "purged": False, }, { "key": "key5", "value": "val", "id": "test::Resource[agent2,key=key5],v=%d" % version, "send_event": False, "requires": ["test::Resource[agent2,key=key4],v=%d" % version], "purged": False, }, { "key": "key6", "value": "val", "id": "test::Resource[agent2,key=key6],v=%d" % version, "send_event": False, "requires": ["test::Resource[agent2,key=key5],v=%d" % version], "purged": False, }, ] status = {"test::Resource[agent2,key=key4]": const.ResourceState.undefined} result = await client.put_version( tid=environment, version=version, resources=resources, resource_state=status, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 mod_db = await data.ConfigurationModel.get_version(uuid.UUID(environment), version) undep = await mod_db.get_undeployable() assert undep == ["test::Resource[agent2,key=key4]"] undep = await mod_db.get_skipped_for_undeployable() assert undep == [ "test::Resource[agent2,key=key5]", "test::Resource[agent2,key=key6]" ] # request a dryrun result = await client.dryrun_request(environment, version) assert result.code == 200 assert result.result["dryrun"]["total"] == len(resources) assert result.result["dryrun"]["todo"] == len(resources) # get the dryrun results result = await client.dryrun_list(environment, version) assert result.code == 200 assert len(result.result["dryruns"]) == 1 while result.result["dryruns"][0]["todo"] > 0: result = await client.dryrun_list(environment, version) await asyncio.sleep(0.1) dry_run_id = result.result["dryruns"][0]["id"] result = await client.dryrun_report(environment, dry_run_id) assert result.code == 200 changes = result.result["dryrun"]["resources"] assert changes[resources[0]["id"]]["changes"]["purged"]["current"] assert not changes[resources[0]["id"]]["changes"]["purged"]["desired"] assert changes[resources[0]["id"]]["changes"]["value"]["current"] is None assert changes[resources[0]["id"]]["changes"]["value"][ "desired"] == resources[0]["value"] assert changes[resources[1] ["id"]]["changes"]["value"]["current"] == "incorrect_value" assert changes[resources[1]["id"]]["changes"]["value"][ "desired"] == resources[1]["value"] assert not changes[resources[2]["id"]]["changes"]["purged"]["current"] assert changes[resources[2]["id"]]["changes"]["purged"]["desired"] # do a deploy result = await client.release_version( environment, version, True, const.AgentTriggerMethod.push_full_deploy) assert result.code == 200 assert not result.result["model"]["deployed"] assert result.result["model"]["released"] assert result.result["model"]["total"] == 6 assert result.result["model"]["result"] == "deploying" result = await client.get_version(environment, version) assert result.code == 200 await _wait_until_deployment_finishes(client, environment, version) result = await client.get_version(environment, version) assert result.result["model"]["done"] == len(resources) assert resource_container.Provider.isset("agent1", "key1") assert resource_container.Provider.get("agent1", "key1") == "value1" assert resource_container.Provider.get("agent1", "key2") == "value2" assert not resource_container.Provider.isset("agent1", "key3") actions = await data.ResourceAction.get_list() assert sum([ len(x.resource_version_ids) for x in actions if x.status == const.ResourceState.undefined ]) == 1 assert sum([ len(x.resource_version_ids) for x in actions if x.status == const.ResourceState.skipped_for_undefined ]) == 2 await agent.stop()
async def test_purged_facts(resource_container, client, clienthelper, agent, environment, no_agent_backoff, caplog): """ Test if facts are purged when the resource is purged. """ resource_container.Provider.set("agent1", "key", "value") version = await clienthelper.get_version() resource_id_wov = "test::Resource[agent1,key=key]" resource_id = "%s,v=%d" % (resource_id_wov, version) resources = [{ "key": "key", "value": "value", "id": resource_id, "requires": [], "purged": False, "send_event": False }] await clienthelper.put_version_simple(resources, version) result = await client.release_version( environment, version, True, const.AgentTriggerMethod.push_full_deploy) assert result.code == 200 result = await client.get_param(environment, "length", resource_id_wov) assert result.code == 503 env_uuid = uuid.UUID(environment) params = await data.Parameter.get_list(environment=env_uuid, resource_id=resource_id_wov) while len(params) < 3: params = await data.Parameter.get_list(environment=env_uuid, resource_id=resource_id_wov) await asyncio.sleep(0.1) result = await client.get_param(environment, "key1", resource_id_wov) assert result.code == 200 # Purge the resource version = await clienthelper.get_version() resources[0]["id"] = "%s,v=%d" % (resource_id_wov, version) resources[0]["purged"] = True result = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 result = await client.release_version( environment, version, True, const.AgentTriggerMethod.push_full_deploy) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 await _wait_until_deployment_finishes(client, environment, version) result = await client.get_version(environment, version) assert result.result["model"]["done"] == len(resources) # The resource facts should be purged result = await client.get_param(environment, "length", resource_id_wov) assert result.code == 503 no_error_in_logs(caplog)
async def test_get_resource_actions(postgresql_client, client, clienthelper, server, environment, agent): """ Test querying resource actions via the API """ aclient = agent._client version = await clienthelper.get_version() resources = [] for j in range(10): resources.append({ "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file%d],v=%d" % (j, version), "owner": "root", "path": "/tmp/file%d" % j, "permissions": 644, "purged": False, "reload": False, "requires": [], "version": version, }) res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 result = await client.release_version(environment, version, False) assert result.code == 200 resource_ids = [x["id"] for x in resources] # Start the deploy action_id = uuid.uuid4() now = datetime.now() result = await aclient.resource_action_update( environment, resource_ids, action_id, "deploy", now, status=const.ResourceState.deploying) assert result.code == 200 # Get the status from a resource result = await client.get_resource_actions(tid=environment) assert result.code == 200 result = await client.get_resource_actions(tid=environment, attribute="path") assert result.code == 400 result = await client.get_resource_actions(tid=environment, attribute_value="/tmp/file") assert result.code == 400 result = await client.get_resource_actions(tid=environment, attribute="path", attribute_value="/tmp/file1") assert result.code == 200 assert len(result.result["data"]) == 2 # Query actions happening earlier than the deploy result = await client.get_resource_actions(tid=environment, last_timestamp=now) assert result.code == 200 assert len(result.result["data"]) == 1 assert result.result["data"][0]["action"] == "store" # Query actions happening later than the start of the test case result = await client.get_resource_actions(tid=environment, first_timestamp=now - timedelta(minutes=1)) assert result.code == 200 assert len(result.result["data"]) == 2 result = await client.get_resource_actions(tid=environment, first_timestamp=now - timedelta(minutes=1), last_timestamp=now) assert result.code == 400 result = await client.get_resource_actions(tid=environment, action_id=action_id) assert result.code == 400 result = await client.get_resource_actions(tid=environment, first_timestamp=now - timedelta(minutes=1), action_id=action_id) assert result.code == 200 assert len(result.result["data"]) == 2
async def test_resource_update(postgresql_client, client, clienthelper, server, environment): """ Test updating resources and logging """ agent = Agent("localhost", {"blah": "localhost"}, environment=environment, code_loader=False) await agent.start() aclient = agent._client version = await clienthelper.get_version() resources = [] for j in range(10): resources.append({ "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file%d],v=%d" % (j, version), "owner": "root", "path": "/tmp/file%d" % j, "permissions": 644, "purged": False, "reload": False, "requires": [], "version": version, }) res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 result = await client.release_version(environment, version, False) assert result.code == 200 resource_ids = [x["id"] for x in resources] # Start the deploy action_id = uuid.uuid4() now = datetime.now() result = await aclient.resource_action_update( environment, resource_ids, action_id, "deploy", now, status=const.ResourceState.deploying) assert result.code == 200 # Get the status from a resource result = await client.get_resource(tid=environment, id=resource_ids[0], logs=True) assert result.code == 200 logs = {x["action"]: x for x in result.result["logs"]} assert "deploy" in logs assert "finished" not in logs["deploy"] assert "messages" not in logs["deploy"] assert "changes" not in logs["deploy"] # Send some logs result = await aclient.resource_action_update( environment, resource_ids, action_id, "deploy", status=const.ResourceState.deploying, messages=[ data.LogLine.log(const.LogLevel.INFO, "Test log %(a)s %(b)s", a="a", b="b") ], ) assert result.code == 200 # Get the status from a resource result = await client.get_resource(tid=environment, id=resource_ids[0], logs=True) assert result.code == 200 logs = {x["action"]: x for x in result.result["logs"]} assert "deploy" in logs assert "messages" in logs["deploy"] assert len(logs["deploy"]["messages"]) == 1 assert logs["deploy"]["messages"][0]["msg"] == "Test log a b" assert "finished" not in logs["deploy"] assert "changes" not in logs["deploy"] # Finish the deploy now = datetime.now() changes = { x: { "owner": { "old": "root", "current": "inmanta" } } for x in resource_ids } result = await aclient.resource_action_update(environment, resource_ids, action_id, "deploy", finished=now, changes=changes) assert result.code == 400 result = await aclient.resource_action_update( environment, resource_ids, action_id, "deploy", status=const.ResourceState.deployed, finished=now, changes=changes) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["done"] == 10 await agent.stop()
async def test_dryrun_v2(server, client, resource_container, environment, agent_factory): """ Dryrun a configuration model with the v2 api, where applicable """ await agent_factory( hostname="node1", environment=environment, agent_map={"agent1": "localhost"}, code_loader=False, agent_names=["agent1"], ) resource_container.Provider.set("agent1", "key2", "incorrect_value") resource_container.Provider.set( "agent1", "key_mod", {"first_level": { "nested": [5, 3, 2, 1, 1] }}) resource_container.Provider.set("agent1", "key3", "value") resource_container.Provider.set("agent1", "key_unmodified", "the_same") clienthelper = ClientHelper(client, environment) version = await clienthelper.get_version() resources = [ { "key": "key1", "value": "value1", "id": "test::Resource[agent1,key=key1],v=%d" % version, "send_event": False, "purged": False, "requires": ["test::Resource[agent1,key=key2],v=%d" % version], }, { "key": "key2", "value": "value2", "id": "test::Resource[agent1,key=key2],v=%d" % version, "send_event": False, "requires": [], "purged": False, }, { "key": "key3", "value": None, "id": "test::Resource[agent1,key=key3],v=%d" % version, "send_event": False, "requires": [], "purged": True, }, { "key": "key_mod", "value": { "first_level": { "nested": { "one_more_level": [5, 3, 2, 1, 1] } } }, "id": "test::Resource[agent1,key=key_mod],v=%d" % version, "send_event": False, "requires": [], "purged": False, }, { "key": "key_unmodified", "value": "the_same", "id": "test::Resource[agent1,key=key_unmodified],v=%d" % version, "send_event": False, "purged": False, "requires": ["test::Resource[agent1,key=key2],v=%d" % version], }, { "key": "key4", "value": execute.util.Unknown(source=None), "id": "test::Resource[agent2,key=key4],v=%d" % version, "send_event": False, "requires": [], "purged": False, }, { "key": "key5", "value": "val", "id": "test::Resource[agent2,key=key5],v=%d" % version, "send_event": False, "requires": ["test::Resource[agent2,key=key4],v=%d" % version], "purged": False, }, { "key": "key6", "value": "val", "id": "test::Resource[agent2,key=key6],v=%d" % version, "send_event": False, "requires": ["test::Resource[agent2,key=key5],v=%d" % version], "purged": False, }, { "key": "key7", "value": "val", "id": "test::Resource[agent3,key=key7],v=%d" % version, "send_event": False, "requires": [], "purged": False, }, ] status = {"test::Resource[agent2,key=key4]": const.ResourceState.undefined} result = await client.put_version( tid=environment, version=version, resources=resources, resource_state=status, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 mod_db = await data.ConfigurationModel.get_version(uuid.UUID(environment), version) undep = await mod_db.get_undeployable() assert undep == ["test::Resource[agent2,key=key4]"] undep = await mod_db.get_skipped_for_undeployable() assert undep == [ "test::Resource[agent2,key=key5]", "test::Resource[agent2,key=key6]" ] result = await client.dryrun_trigger(uuid.uuid4(), version) assert result.code == 404 result = await client.dryrun_trigger(environment, 123456789) assert result.code == 404 result = await client.list_dryruns(uuid.uuid4(), version) assert result.code == 404 result = await client.list_dryruns(environment, 123456789) assert result.code == 404 result = await client.list_dryruns(environment, version) assert result.code == 200 assert len(result.result["data"]) == 0 # request a dryrun with correct parameters result = await client.dryrun_trigger(environment, version) assert result.code == 200 dry_run_id = result.result["data"] # get the dryrun results result = await client.list_dryruns(environment, version) assert result.code == 200 assert len(result.result["data"]) == 1 async def dryrun_finished(): result = await client.list_dryruns(environment, version) return result.result["data"][0]["todo"] == 0 await retry_limited(dryrun_finished, 10) result = await client.get_dryrun_diff(uuid.uuid4(), version, dry_run_id) assert result.code == 404 result = await client.get_dryrun_diff(environment, version, uuid.uuid4()) assert result.code == 404 result = await client.get_dryrun_diff(environment, version, dry_run_id) assert result.code == 200 assert len(result.result["data"]["diff"]) == len(resources) changes = result.result["data"]["diff"] assert changes[0]["status"] == "added" assert changes[0]["attributes"]["value"] == { "from_value": None, "from_value_compare": "", "to_value": resources[0]["value"], "to_value_compare": resources[0]["value"], } assert changes[1]["status"] == "modified" assert changes[1]["attributes"]["value"] == { "from_value": "incorrect_value", "from_value_compare": "incorrect_value", "to_value": resources[1]["value"], "to_value_compare": resources[1]["value"], } assert changes[2]["status"] == "deleted" assert changes[3]["status"] == "modified" assert changes[3]["attributes"]["value"] == { "from_value": { "first_level": { "nested": [5, 3, 2, 1, 1] } }, "from_value_compare": json.dumps({"first_level": { "nested": [5, 3, 2, 1, 1] }}, indent=4, sort_keys=True), "to_value": resources[3]["value"], "to_value_compare": json.dumps(resources[3]["value"], indent=4, sort_keys=True), } assert changes[4]["status"] == "unmodified" assert changes[5]["status"] == "undefined" assert changes[6]["status"] == "skipped_for_undefined" assert changes[7]["status"] == "skipped_for_undefined" assert changes[8]["status"] == "agent_down" # Changes for undeployable resources are empty for i in range(4, 9): assert changes[i]["attributes"] == {} # Change a value for a new dryrun res = await data.Resource.get( environment, "test::Resource[agent1,key=key1],v=%d" % version) await res.update(attributes={**res.attributes, "value": "updated_value"}) result = await client.dryrun_trigger(environment, version) assert result.code == 200 new_dry_run_id = result.result["data"] result = await client.list_dryruns(environment, version) assert result.code == 200 assert len(result.result["data"]) == 2 # Check if the dryruns are ordered correctly assert result.result["data"][0]["id"] == new_dry_run_id assert result.result["data"][0]["date"] > result.result["data"][1]["date"] await retry_limited(dryrun_finished, 10) # The new dryrun should have the updated value result = await client.get_dryrun_diff(environment, version, new_dry_run_id) assert result.code == 200 assert result.result["data"]["diff"][0]["attributes"]["value"][ "to_value"] == "updated_value"
async def test_send_events_cross_agent(resource_container, environment, server, client, async_finalizer, clienthelper): """ Send and receive events over agents """ agentmanager = server.get_slice(SLICE_AGENT_MANAGER) resource_container.Provider.reset() agent = Agent(hostname="node1", environment=environment, agent_map={"agent1": "localhost"}, code_loader=False) async_finalizer.add(agent.stop) await agent.add_end_point_name("agent1") await agent.start() await retry_limited(lambda: len(agentmanager.sessions) == 1, 10) agent2 = Agent(hostname="node2", environment=environment, agent_map={"agent2": "localhost"}, code_loader=False) async_finalizer.add(agent2.stop) await agent2.add_end_point_name("agent2") await agent2.start() await retry_limited(lambda: len(agentmanager.sessions) == 2, 10) version = await clienthelper.get_version() res_id_1 = "test::Resource[agent1,key=key1],v=%d" % version resources = [ { "key": "key1", "value": "value1", "id": res_id_1, "send_event": False, "purged": False, "requires": ["test::Resource[agent2,key=key2],v=%d" % version], }, { "key": "key2", "value": "value2", "id": "test::Resource[agent2,key=key2],v=%d" % version, "send_event": True, "requires": [], "purged": False, }, ] result = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 # do a deploy result = await client.release_version( environment, version, True, const.AgentTriggerMethod.push_full_deploy) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 await _wait_until_deployment_finishes(client, environment, version) assert resource_container.Provider.get("agent1", "key1") == "value1" assert resource_container.Provider.get("agent2", "key2") == "value2" events = resource_container.Provider.getevents("agent1", "key1") assert len(events) == 1 for res_id, res in events[0].items(): assert res_id.agent_name == "agent2" assert res_id.attribute_value == "key2" assert res["status"] == const.ResourceState.deployed assert res["change"] == const.Change.created
async def test_purge_on_delete(client, clienthelper, server, environment): """ Test purge on delete of resources """ agent = Agent("localhost", {"blah": "localhost"}, environment=environment, code_loader=False) await agent.start() aclient = agent._client version = await clienthelper.get_version() resources = [ { "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file1],v=%d" % version, "owner": "root", "path": "/tmp/file1", "permissions": 644, "purged": False, "reload": False, "requires": [], "purge_on_delete": True, "version": version, }, { "group": "root", "hash": "b4350bef50c3ec3ee532d4a3f9d6daedec3d2aba", "id": "std::File[vm1,path=/tmp/file2],v=%d" % version, "owner": "root", "path": "/tmp/file2", "permissions": 644, "purged": False, "reload": False, "purge_on_delete": True, "requires": ["std::File[vm1,path=/tmp/file1],v=%d" % version], "version": version, }, { "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file3],v=%d" % version, "owner": "root", "path": "/tmp/file3", "permissions": 644, "purged": False, "reload": False, "requires": [], "purge_on_delete": True, "version": version, }, ] res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 # Release the model and set all resources as deployed result = await client.release_version(environment, version, False) assert result.code == 200 now = datetime.now() result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file1],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file2],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file3],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["version"] == version assert result.result["model"]["total"] == len(resources) assert result.result["model"]["done"] == len(resources) assert result.result["model"]["released"] assert result.result["model"]["result"] == const.VersionState.success.name # New version with only file3 version = await clienthelper.get_version() res3 = { "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file3],v=%d" % version, "owner": "root", "path": "/tmp/file3", "permissions": 644, "purged": False, "reload": False, "requires": [], "purge_on_delete": True, "version": version, } result = await client.put_version( tid=environment, version=version, resources=[res3], unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["total"] == 3 # validate requires and provides file1 = [x for x in result.result["resources"] if "file1" in x["id"]][0] file2 = [x for x in result.result["resources"] if "file2" in x["id"]][0] file3 = [x for x in result.result["resources"] if "file3" in x["id"]][0] assert file1["attributes"]["purged"] assert file2["attributes"]["purged"] assert not file3["attributes"]["purged"] await agent.stop()
async def test_send_events_cross_agent_deploying(resource_container, environment, server, client, no_agent_backoff, async_finalizer, clienthelper): """ Send and receive events over agents """ agentmanager = server.get_slice(SLICE_AGENT_MANAGER) resource_container.Provider.reset() agent = Agent(hostname="node1", environment=environment, agent_map={"agent1": "localhost"}, code_loader=False) async_finalizer.add(agent.stop) await agent.add_end_point_name("agent1") await agent.start() await retry_limited(lambda: len(agentmanager.sessions) == 1, 10) agent2 = Agent(hostname="node2", environment=environment, agent_map={"agent2": "localhost"}, code_loader=False) async_finalizer.add(agent2.stop) await agent2.add_end_point_name("agent2") await agent2.start() await retry_limited(lambda: len(agentmanager.sessions) == 2, 10) version = await clienthelper.get_version() res_id_1 = "test::Resource[agent1,key=key1],v=%d" % version resources = [ { "key": "key1", "value": "value1", "id": res_id_1, "send_event": False, "purged": False, "requires": ["test::Wait[agent2,key=key2],v=%d" % version], }, { "key": "key2", "value": "value2", "id": "test::Wait[agent2,key=key2],v=%d" % version, "send_event": True, "requires": [], "purged": False, }, ] result = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert result.code == 200 # do a deploy result = await client.release_version( environment, version, True, const.AgentTriggerMethod.push_full_deploy) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 await _wait_for_n_deploying(client, environment, version, 1) # restart deploy result = await client.release_version( environment, version, True, const.AgentTriggerMethod.push_full_deploy) assert result.code == 200 await resource_container.wait_for_done_with_waiters( client, environment, version) # incorrect CAD handling causes skip, which completes deploy without writing assert resource_container.Provider.get("agent1", "key1") == "value1"
async def test_purge_on_delete_ignore(client, clienthelper, server, environment): """ Test purge on delete behavior for resources that have not longer purged_on_delete set """ agent = Agent("localhost", {"blah": "localhost"}, environment=environment, code_loader=False) await agent.start() aclient = agent._client # Version 1 with purge_on_delete true version = await clienthelper.get_version() resources = [{ "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file1],v=%d" % version, "owner": "root", "path": "/tmp/file1", "permissions": 644, "purged": False, "reload": False, "requires": [], "purge_on_delete": True, "version": version, }] res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 # Release the model and set all resources as deployed result = await client.release_version(environment, version, False) assert result.code == 200 now = datetime.now() result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file1],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["version"] == version assert result.result["model"]["total"] == len(resources) assert result.result["model"]["done"] == len(resources) assert result.result["model"]["released"] assert result.result["model"]["result"] == const.VersionState.success.name # Version 2 with purge_on_delete false version = await clienthelper.get_version() resources = [{ "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file1],v=%d" % version, "owner": "root", "path": "/tmp/file1", "permissions": 644, "purged": False, "reload": False, "requires": [], "purge_on_delete": False, "version": version, }] res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 # Release the model and set all resources as deployed result = await client.release_version(environment, version, False) assert result.code == 200 now = datetime.now() result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file1],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["version"] == version assert result.result["model"]["total"] == len(resources) assert result.result["model"]["done"] == len(resources) assert result.result["model"]["released"] assert result.result["model"]["result"] == const.VersionState.success.name # Version 3 with no resources version = await clienthelper.get_version() resources = [] res = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, compiler_version=get_compiler_version(), ) assert res.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["version"] == version assert result.result["model"]["total"] == len(resources) await agent.stop()
async def test_purge_on_delete_compile_failed(client, server, clienthelper, environment): """ Test purge on delete of resources """ agent = Agent("localhost", {"blah": "localhost"}, environment=environment, code_loader=False) await agent.start() aclient = agent._client version = await clienthelper.get_version() resources = [ { "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file1],v=%d" % version, "owner": "root", "path": "/tmp/file1", "permissions": 644, "purged": False, "reload": False, "requires": [], "purge_on_delete": True, "version": version, }, { "group": "root", "hash": "b4350bef50c3ec3ee532d4a3f9d6daedec3d2aba", "id": "std::File[vm1,path=/tmp/file2],v=%d" % version, "owner": "root", "path": "/tmp/file2", "permissions": 644, "purged": False, "reload": False, "purge_on_delete": True, "requires": ["std::File[vm1,path=/tmp/file1],v=%d" % version], "version": version, }, { "group": "root", "hash": "89bf880a0dc5ffc1156c8d958b4960971370ee6a", "id": "std::File[vm1,path=/tmp/file3],v=%d" % version, "owner": "root", "path": "/tmp/file3", "permissions": 644, "purged": False, "reload": False, "requires": [], "purge_on_delete": True, "version": version, }, ] await clienthelper.put_version_simple(resources, version) # Release the model and set all resources as deployed result = await client.release_version(environment, version, False) assert result.code == 200 now = datetime.now() result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file1],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file2],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await aclient.resource_action_update( environment, ["std::File[vm1,path=/tmp/file3],v=%d" % version], uuid.uuid4(), "deploy", now, now, "deployed", [], {}) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["version"] == version assert result.result["model"]["total"] == len(resources) assert result.result["model"]["done"] == len(resources) assert result.result["model"]["released"] assert result.result["model"]["result"] == const.VersionState.success.name # New version with only file3 version = await clienthelper.get_version() result = await client.put_version( tid=environment, version=version, resources=[], unknowns=[{ "parameter": "a", "source": "b" }], version_info={ const.EXPORT_META_DATA: { const.META_DATA_COMPILE_STATE: const.Compilestate.failed } }, compiler_version=get_compiler_version(), ) assert result.code == 200 result = await client.get_version(environment, version) assert result.code == 200 assert result.result["model"]["total"] == 0 await agent.stop() assert len(result.result["unknowns"]) == 1
async def test_get_facts_extended(server, client, agent, clienthelper, resource_container, environment, caplog): """ dryrun and deploy a configuration model automatically """ caplog.set_level(logging.ERROR) agentmanager = server.get_slice(SLICE_AGENT_MANAGER) # allow very rapid fact refresh agentmanager._fact_resource_block = 0.1 resource_container.Provider.reset() version = await clienthelper.get_version() # mark some as existing resource_container.Provider.set("agent1", "key1", "value") resource_container.Provider.set("agent1", "key2", "value") resource_container.Provider.set("agent1", "key4", "value") resource_container.Provider.set("agent1", "key5", "value") resource_container.Provider.set("agent1", "key6", "value") resource_container.Provider.set("agent1", "key7", "value") resources = [ { "key": "key1", "value": "value1", "id": "test::Fact[agent1,key=key1],v=%d" % version, "send_event": False, "purged": False, "skip": True, "skipFact": False, "factvalue": "fk1", "requires": [], }, { "key": "key2", "value": "value1", "id": "test::Fact[agent1,key=key2],v=%d" % version, "send_event": False, "purged": False, "skip": False, "skipFact": False, "factvalue": "fk2", "requires": [], }, { "key": "key3", "value": "value1", "id": "test::Fact[agent1,key=key3],v=%d" % version, "send_event": False, "purged": False, "skip": False, "skipFact": False, "factvalue": "fk3", "requires": [], }, { "key": "key4", "value": "value1", "id": "test::Fact[agent1,key=key4],v=%d" % version, "send_event": False, "purged": False, "skip": False, "skipFact": False, "factvalue": "fk4", "requires": [], }, { "key": "key5", "value": "value1", "id": "test::Fact[agent1,key=key5],v=%d" % version, "send_event": False, "purged": False, "skip": False, "skipFact": True, "factvalue": None, "requires": [], }, { "key": "key6", "value": "value1", "id": "test::Fact[agent1,key=key6],v=%d" % version, "send_event": False, "purged": False, "skip": False, "skipFact": False, "factvalue": None, "requires": [], }, { "key": "key7", "value": "value1", "id": "test::Fact[agent1,key=key7],v=%d" % version, "send_event": False, "purged": False, "skip": False, "skipFact": False, "factvalue": "", "requires": [], }, ] resource_states = { "test::Fact[agent1,key=key4],v=%d" % version: const.ResourceState.undefined, "test::Fact[agent1,key=key5],v=%d" % version: const.ResourceState.undefined, } async def get_fact(rid, result_code=200, limit=10, lower_limit=2): lower_limit = limit - lower_limit result = await client.get_param(environment, "fact", rid) # add minimal nr of reps or failure cases while (result.code != result_code and limit > 0) or limit > lower_limit: limit -= 1 await asyncio.sleep(0.1) result = await client.get_param(environment, "fact", rid) assert result.code == result_code return result result = await client.put_version( tid=environment, version=version, resources=resources, unknowns=[], version_info={}, resource_state=resource_states, compiler_version=get_compiler_version(), ) assert result.code == 200 await get_fact("test::Fact[agent1,key=key1]") # undeployable await get_fact("test::Fact[agent1,key=key2]") # normal await get_fact("test::Fact[agent1,key=key3]", 503) # not present await get_fact("test::Fact[agent1,key=key4]") # unknown await get_fact("test::Fact[agent1,key=key5]", 503) # broken f6 = await get_fact("test::Fact[agent1,key=key6]") # normal f7 = await get_fact("test::Fact[agent1,key=key7]") # normal assert f6.result["parameter"]["value"] == "None" assert f7.result["parameter"]["value"] == "" result = await client.release_version( environment, version, True, const.AgentTriggerMethod.push_full_deploy) assert result.code == 200 await _wait_until_deployment_finishes(client, environment, version) await get_fact("test::Fact[agent1,key=key1]") # undeployable await get_fact("test::Fact[agent1,key=key2]") # normal await get_fact("test::Fact[agent1,key=key3]") # not present -> present await get_fact("test::Fact[agent1,key=key4]") # unknown await get_fact("test::Fact[agent1,key=key5]", 503) # broken await agent.stop() LogSequence(caplog, allow_errors=False, ignore=[ "tornado.access" ]).contains("inmanta.agent.agent.agent1", logging.ERROR, "Unable to retrieve fact").contains( "inmanta.agent.agent.agent1", logging.ERROR, "Unable to retrieve fact").contains( "inmanta.agent.agent.agent1", logging.ERROR, "Unable to retrieve fact").contains( "inmanta.agent.agent.agent1", logging.ERROR, "Unable to retrieve fact").contains( "inmanta.agent.agent.agent1", logging.ERROR, "Unable to retrieve fact").no_more_errors()