Пример #1
0
    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
Пример #2
0
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
Пример #3
0
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
Пример #4
0
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
Пример #5
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
Пример #6
0
 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
Пример #7
0
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
Пример #8
0
    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
Пример #9
0
 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
Пример #10
0
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
Пример #11
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
Пример #12
0
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()
Пример #14
0
    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"])
Пример #15
0
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"
Пример #16
0
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()
Пример #17
0
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()
Пример #18
0
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)
Пример #19
0
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
Пример #20
0
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()
Пример #21
0
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"
Пример #22
0
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()
Пример #24
0
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
Пример #27
0
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()