async def check_rename_directory_on_storage(self, path_from: str,
                                             path_to: str) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         await client.storage.mv(URL(f"{self.tmpstorage}{path_from}"),
                                 URL(f"{self.tmpstorage}{path_to}"))
Example #2
0
 async def check_blob_size(self, bucket_name: str, key: str,
                           size: int) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         blob = await client.blob_storage.head_blob(bucket_name, key)
         assert blob.size == size
 async def kill_job(self, id_or_name: str) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         id = await resolve_job(id_or_name, client=client)
         with suppress(ResourceNotFound, IllegalArgumentError):
             await client.jobs.kill(id)
async def test_port_forward(nmrc_path: Path, nginx_job_async: Tuple[str, str]) -> None:
    loop_sleep = 1
    service_wait_time = 10 * 60

    async def get_(url: str) -> int:
        status = 999
        start_time = time()
        async with aiohttp.ClientSession() as session:
            while status != 200 and (int(time() - start_time) < service_wait_time):
                try:
                    async with session.get(url) as resp:
                        status = resp.status
                        text = await resp.text()
                        assert text == nginx_job_async[1], (
                            f"Secret not found "
                            f"via {url}. Like as it's not our test server."
                        )
                except aiohttp.ClientConnectionError:
                    status = 599
                if status != 200:
                    await asyncio.sleep(loop_sleep)
        return status

    async with api_get(path=nmrc_path, timeout=CLIENT_TIMEOUT) as client:
        port = unused_port()
        # We test client instead of run_cli as asyncio subprocesses do
        # not work if run from thread other than main.
        async with client.jobs.port_forward(
            nginx_job_async[0], port, 80, no_key_check=True
        ):
            await asyncio.sleep(loop_sleep)
            url = f"http://127.0.0.1:{port}/secret.txt"
            probe = await get_(url)
            assert probe == 200
async def nginx_job_async(
    nmrc_path: Path, loop: asyncio.AbstractEventLoop
) -> AsyncIterator[Tuple[str, str]]:
    async with api_get(path=nmrc_path) as client:
        secret = uuid4()
        command = (
            f"bash -c \"echo -n '{secret}' > /usr/share/nginx/html/secret.txt; "
            f"timeout 15m /usr/sbin/nginx -g 'daemon off;'\""
        )
        container = Container(
            image=RemoteImage.new_external_image(name="nginx", tag="latest"),
            command=command,
            resources=Resources(20, 0.1, None, None, True, None, None),
        )

        job = await client.jobs.run(
            container, is_preemptible=False, description="test NGINX job"
        )
        try:
            for i in range(60):
                status = await client.jobs.status(job.id)
                if status.status == JobStatus.RUNNING:
                    break
                await asyncio.sleep(1)
            else:
                raise AssertionError("Cannot start NGINX job")
            yield job.id, str(secret)
        finally:
            with suppress(Exception):
                await client.jobs.kill(job.id)
Example #6
0
 async def check_file_absent_on_storage(self, name: str, path: str) -> None:
     __tracebackhide__ = True
     url = URL(self.tmpstorage + path)
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         async for file in client.storage.ls(url):
             if file.type == FileStatusType.FILE and file.path == name:
                 raise AssertionError(f"File {name} found in {url}")
Example #7
0
 async def upload_blob(self, bucket_name: str, key: str,
                       file: Path) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         await client.blob_storage.upload_file(
             URL("file:" + str(file)),
             client.blob_storage.make_url(bucket_name, key))
 async def check_dir_absent_on_storage(self, name: str, path: str) -> None:
     __tracebackhide__ = True
     url = URL(self.tmpstorage + path)
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         files = await client.storage.ls(url)
         for file in files:
             if file.type == FileStatusType.DIRECTORY and file.path == name:
                 raise AssertionError(f"Dir {name} found in {url}")
 async def check_rm_file_on_storage(self,
                                    name: str,
                                    path: str,
                                    *,
                                    fromhome: bool = False) -> None:
     __tracebackhide__ = True
     url = self.make_uri(path, fromhome=fromhome)
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         await client.storage.rm(url / name)
Example #10
0
 async def check_blob_checksum(self, bucket_name: str, key: str,
                               checksum: str, tmp_path: Path) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         await client.blob_storage.download_file(
             client.blob_storage.make_url(bucket_name, key),
             URL("file:" + str(tmp_path)),
         )
         assert self.hash_hex(
             tmp_path) == checksum, "checksum test failed for {url}"
async def _get_storage_cookie(nmrc_path: Optional[Path]) -> None:
    async with api_get(timeout=CLIENT_TIMEOUT, path=nmrc_path) as client:
        await client.storage.ls(URL("storage:/"))
        cookie = client._get_session_cookie()
        if cookie is not None:
            new_config = dataclasses.replace(
                client._config,
                cookie_session=_CookieSession(cookie=cookie.value,
                                              timestamp=int(time())),
            )
            Factory(nmrc_path)._save(new_config)
Example #12
0
 async def drop_stale_buckets(self, bucket_prefix: str) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         buckets = await client.blob_storage.list_buckets()
         for bucket in buckets:
             if (bucket.name.startswith(bucket_prefix)
                     and bucket.creation_time < time() - 3600 * 4 and
                     bucket.permission in (Action.WRITE, Action.MANAGE)):
                 await self.acleanup_bucket(bucket.name)
                 await self.adelete_bucket(bucket.name)
 async def check_upload_file_to_storage(self, name: str, path: str,
                                        local_file: str) -> None:
     __tracebackhide__ = True
     url = URL(self.tmpstorage + path)
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         if name is None:
             await client.storage.upload_file(URL("file:" + local_file),
                                              url)
         else:
             await client.storage.upload_file(URL("file:" + local_file),
                                              URL(f"{url}/{name}"))
Example #14
0
 async def resolve_job_name_to_id(self, job_name: str) -> str:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         return await resolve_job(
             job_name,
             client=client,
             status={
                 JobStatus.PENDING,
                 JobStatus.RUNNING,
                 JobStatus.SUCCEEDED,
                 JobStatus.FAILED,
             },
         )
Example #15
0
 async def drop_stale_buckets(self, bucket_prefix: str) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         buckets = await client.blob_storage.list_buckets()
         for bucket in buckets:
             if (bucket.name.startswith(bucket_prefix)
                     and bucket.creation_time < time() - 3600 * 4 and
                     bucket.permission in (Action.WRITE, Action.MANAGE)):
                 with suppress(ResourceNotFound):
                     # bucket can be deleted by another parallel test run,
                     # ignore ResourceNotFound errors
                     await self.acleanup_bucket(bucket.name)
                     await self.adelete_bucket(bucket.name)
 async def job_info(self,
                    job_id: str,
                    wait_start: bool = False) -> JobDescription:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         job = await client.jobs.status(job_id)
         start_time = time()
         while (wait_start and job.status == JobStatus.PENDING
                and time() - start_time < JOB_TIMEOUT):
             job = await client.jobs.status(job_id)
         if int(time() - start_time) > JOB_TIMEOUT:
             raise AssertionError(
                 f"timeout exceeded, last output: '{job.status}'")
         return job
Example #17
0
 async def check_file_exists_on_storage(self,
                                        name: str,
                                        path: str,
                                        size: int,
                                        *,
                                        fromhome: bool = False) -> None:
     __tracebackhide__ = True
     url = self.make_uri(path, fromhome=fromhome)
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         async for file in client.storage.ls(url):
             if (file.type == FileStatusType.FILE and file.name == name
                     and file.size == size):
                 return
     raise AssertionError(
         f"File {name} with size {size} not found in {url}")
Example #18
0
 async def akill_job(self, id_or_name: str, *, wait: bool = True) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         id = await resolve_job(
             id_or_name,
             client=client,
             status={JobStatus.PENDING, JobStatus.RUNNING})
         with suppress(ResourceNotFound, IllegalArgumentError):
             await client.jobs.kill(id)
             if wait:
                 while True:
                     stat = await client.jobs.status(id)
                     if stat.status not in (JobStatus.PENDING,
                                            JobStatus.RUNNING):
                         break
Example #19
0
 async def acreate_bucket(self, name: str, *, wait: bool = False) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         await client.blob_storage.create_bucket(name)
         if wait:
             t0 = time()
             delay = 1
             while time() - t0 < 30:
                 try:
                     await client.blob_storage.list_blobs(name, max_keys=10)
                     return
                 except ResourceNotFound:
                     delay = min(delay * 2, 15)
                     await asyncio.sleep(delay)
             raise RuntimeError(
                 f"Bucket {name} doesn't exist after the creation")
 async def wait_job_change_state_from(
         self,
         job_id: str,
         wait_state: JobStatus,
         stop_state: Optional[JobStatus] = None) -> None:
     __tracebackhide__ = True
     start_time = time()
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         job = await client.jobs.status(job_id)
         while job.status == wait_state and (int(time() - start_time) <
                                             JOB_TIMEOUT):
             if stop_state == job.status:
                 raise JobWaitStateStopReached(
                     f"failed running job {job_id}: {stop_state}")
             await asyncio.sleep(JOB_WAIT_SLEEP_SECONDS)
             job = await client.jobs.status(job_id)
 async def check_file_on_storage_checksum(self, name: str, path: str,
                                          checksum: str, tmpdir: str,
                                          tmpname: str) -> None:
     __tracebackhide__ = True
     url = URL(self.tmpstorage + path)
     if tmpname:
         target = join(tmpdir, tmpname)
         target_file = target
     else:
         target = tmpdir
         target_file = join(tmpdir, name)
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         await client.storage.download_file(url / name,
                                            URL("file:" + target))
         assert (self.hash_hex(target_file) == checksum
                 ), "checksum test failed for {url}"
    async def check_rename_file_on_storage(self, name_from: str,
                                           path_from: str, name_to: str,
                                           path_to: str) -> None:
        __tracebackhide__ = True
        async with api_get(timeout=CLIENT_TIMEOUT,
                           path=self._nmrc_path) as client:
            await client.storage.mv(
                URL(f"{self.tmpstorage}{path_from}/{name_from}"),
                URL(f"{self.tmpstorage}{path_to}/{name_to}"),
            )
            files1 = await client.storage.ls(
                URL(f"{self.tmpstorage}{path_from}"))
            names1 = {f.name for f in files1}
            assert name_from not in names1

            files2 = await client.storage.ls(URL(f"{self.tmpstorage}{path_to}")
                                             )
            names2 = {f.name for f in files2}
            assert name_to in names2
Example #23
0
    async def acleanup_bucket(self, bucket_name: str) -> None:
        __tracebackhide__ = True
        # Each test needs a clean bucket state and we can't delete bucket until it's
        # cleaned
        async with api_get(timeout=CLIENT_TIMEOUT,
                           path=self._nmrc_path) as client:
            blobs, _ = await client.blob_storage.list_blobs(bucket_name,
                                                            recursive=True)
            if not blobs:
                return

            # XXX: We do assume we will not have tests that run 10000 of objects. If we
            # do, please add a semaphore here.
            tasks = []
            for blob in blobs:
                log.info("Removing %s %s", bucket_name, blob.key)
                tasks.append(
                    client.blob_storage.delete_blob(bucket_name, key=blob.key))
            await asyncio.gather(*tasks)
 async def wait_job_change_state_to(
     self,
     job_id: str,
     target_state: JobStatus,
     stop_state: Optional[JobStatus] = None,
 ) -> None:
     __tracebackhide__ = True
     start_time = time()
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         job = await client.jobs.status(job_id)
         while target_state != job.status:
             if stop_state and stop_state == job.status:
                 raise JobWaitStateStopReached(
                     f"failed running job {job_id}: '{stop_state}'")
             if int(time() - start_time) > JOB_TIMEOUT:
                 raise AssertionError(
                     f"timeout exceeded, last output: '{job.status}'")
             await asyncio.sleep(JOB_WAIT_SLEEP_SECONDS)
             job = await client.jobs.status(job_id)
Example #25
0
    async def arun_job_and_wait_state(
        self,
        image: str,
        command: str = "",
        *,
        description: Optional[str] = None,
        name: Optional[str] = None,
        tty: bool = False,
        wait_state: JobStatus = JobStatus.RUNNING,
        stop_state: JobStatus = JobStatus.FAILED,
    ) -> str:
        __tracebackhide__ = True
        async with api_get(timeout=CLIENT_TIMEOUT,
                           path=self._nmrc_path) as client:
            preset = client.presets["cpu-micro"]
            resources = Resources(memory_mb=preset.memory_mb, cpu=preset.cpu)
            container = Container(
                image=client.parse.remote_image(image),
                command=command,
                resources=resources,
                tty=tty,
            )
            job = await client.jobs.run(
                container,
                is_preemptible=preset.is_preemptible,
                description=description,
                name=name,
            )

            start_time = time()
            while job.status != wait_state:
                if stop_state == job.status:
                    raise JobWaitStateStopReached(
                        f"failed running job {job.id}: {stop_state}")
                if int(time() - start_time) > JOB_TIMEOUT:
                    raise AssertionError(
                        f"timeout exceeded, last output: '{job.status}'")
                await asyncio.sleep(JOB_WAIT_SLEEP_SECONDS)
                job = await client.jobs.status(job.id)

            return job.id
 async def _check_job_output() -> AsyncIterator[bytes]:
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         async for chunk in client.jobs.monitor(job_id):
             yield chunk
 async def assert_job_state(self, job_id: str, state: JobStatus) -> None:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         job = await client.jobs.status(job_id)
         assert job.status == state
 async def mkdir(self, path: str, **kwargs: bool) -> None:
     __tracebackhide__ = True
     url = URL(self.tmpstorage + path)
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         await client.storage.mkdir(url, **kwargs)
 async def rm(self, path: str, *, recursive: bool = False) -> None:
     __tracebackhide__ = True
     url = URL(self.tmpstorage + path)
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         await client.storage.rm(url, recursive=recursive)
 async def resolve_job_name_to_id(self, job_name: str) -> str:
     __tracebackhide__ = True
     async with api_get(timeout=CLIENT_TIMEOUT,
                        path=self._nmrc_path) as client:
         return await resolve_job(job_name, client=client)