Пример #1
0
    def result_filename(self, content_type):
        dname = (Path(random.choice(self.result_dirs)) /
                 "{:02x}".format(random.randint(0, 0xFF)) /
                 "{:02x}".format(random.randint(0, 0xFF)))
        dname.mkdir(parents=True, exist_ok=True)

        fd, ret = tempfile.mkstemp(
            dir=str(dname),
            prefix="{}-".format(uuid.uuid4().hex),
            suffix=extension_for(content_type),
        )
        os.close(fd)
        return Path(ret)
Пример #2
0
    def __init__(self, uwsgi_ini_file, servicelib_ini_file, pid_file, log_file,
                 scratch_dir):
        self.servicelib_ini_file = servicelib_ini_file
        self.pid_file = pid_file
        self.log_file = log_file
        self.host = "127.0.0.1"
        self.port = utils.available_port()

        servicelib_dir = Path(__file__, "..", "..").resolve()
        services_dir = servicelib_dir / "samples"

        self.uwsgi_ini = UWSGI_INI_TEMPLATE.format(
            host=self.host,
            log_file=log_file,
            pid_file=pid_file,
            port=self.port,
            services_dir=services_dir,
        )
        with open(uwsgi_ini_file, "wt") as f:
            f.write(self.uwsgi_ini)

        self.servicelib_ini = SERVICELIB_INI_TEMPLATE.format(
            host=self.host,
            port=self.port,
            scratch_dir=scratch_dir,
            services_dir=services_dir,
            uwsgi_config_file=uwsgi_ini_file,
        )
        with open(servicelib_ini_file, "wt") as f:
            f.write(self.servicelib_ini)

        scratch_dir.mkdir(parents=True, exist_ok=True)
Пример #3
0
def test_downloadable_result_as_argument(worker):
    this_dir = str(Path(__file__, "..").resolve())
    tar_file = worker.http_post("/services/tar-create",
                                data=json.dumps([this_dir]))

    res = worker.http_post("/services/tar-list", data=json.dumps([tar_file]))
    assert this_dir[1:] in res
Пример #4
0
def test_errors_in_service_loading(worker_cmd, services_dir, expected_error):
    services_dir = Path(__file__, "..", "..", "samples", "invalid-services",
                        services_dir).resolve()
    w = worker_cmd("--worker-services-dir={}".format(services_dir), )
    with pytest.raises(Exception) as exc:
        with w:
            pass
    assert expected_error in str(exc.value)
Пример #5
0
    def create_temp_file(self):
        dname = (Path(self.strategy.download_dir(self.scratch_dirs)) /
                 "{:02x}".format(random.randint(0, 0xFF)) /
                 "{:02x}".format(random.randint(0, 0xFF)))
        dname.mkdir(parents=True, exist_ok=True)

        fd, ret = tempfile.mkstemp(dir=str(dname),
                                   prefix="{}-".format(uuid.uuid4().hex))
        os.close(fd)
        return ret
Пример #6
0
    def as_local_file(self, result):
        h = hashlib.sha256()
        h.update(result["location"].encode("utf-8"))
        # TODO: Update hash object with byte range fields, too, once they are
        # implemented.
        fname = h.hexdigest()

        for dname in self.scratch_dirs:
            path = os.path.join(dname, fname[0:2], fname[2:4], fname)
            if os.access(path, os.F_OK):
                self.log.debug("%s already downloaded, returning", path)
                return Path(path)

        dname = Path(random.choice(
            self.scratch_dirs)) / fname[0:2] / fname[2:4]
        dname.mkdir(parents=True, exist_ok=True)
        path = dname / fname

        self.log.debug("Downloading %s into %s", result, path)
        download(result, path)
        return path
Пример #7
0
def worker():
    tmp_path = Path(tempfile.mkdtemp())
    try:
        with Worker(
                tmp_path / "uwsgi.ini",
                tmp_path / "servicelib.ini",
                tmp_path / "uwsgi.pid",
                tmp_path / "uwsgi.log",
                tmp_path / "scratch",
        ) as s:
            yield s
    finally:
        shutil.rmtree(str(tmp_path), ignore_errors=True)
Пример #8
0
def main():
    logutils.configure_logging()

    cmd = ["uwsgi"]

    autoreload = int(config.get("worker_autoreload", "0"))
    if autoreload > 0:
        cmd.extend(["--py-autoreload", "{}".format(autoreload)])

    serve_results = config.get("worker_serve_results", default=None)
    if serve_results is not None:
        for dname in serve_results.split(":"):
            cmd.extend(["--static-map", "{}={}".format(dname, dname)])

    swagger_yaml = Path(
        config.get("worker_services_dir", default="/code/services"), "swagger.yaml"
    )
    if swagger_yaml.exists():
        cmd.extend(["--static-map", "/services/swagger.yaml={}".format(swagger_yaml)])

    swagger_ui = Path(
        config.get("worker_swagger_ui_path", default="/usr/share/nginx/html")
    )
    if swagger_yaml.exists():
        cmd.extend(["--static-map", "/docs={}".format(swagger_ui)])
        cmd.extend(["--static-index", "index.html"])

    try:
        static_assets = config.get("worker_static_map")
    except Exception:
        pass
    else:
        cmd.extend(["--static-map", static_assets])

    cmd.append(
        config.get(
            "worker_uwsgi_config_file",
            default=str(Path(config.__file__, "..", "uwsgi.ini").resolve()),
        )
    )

    os.environ.setdefault(
        "SERVICELIB_WORKER_NUM_PROCESSES",
        config.get("worker_num_processes", str(psutil.cpu_count())),
    )
    os.environ.setdefault(
        "SERVICELIB_WORKER_NUM_THREADS", config.get("worker_num_threads", "1")
    )
    os.environ.setdefault("SERVICELIB_WORKER_PORT", config.get("worker_port", "8000"))

    log = logutils.get_logger("servicelib-worker")
    log.info("Running: %s", " ".join(cmd))
    os.execlp(cmd[0], *cmd[0:])
Пример #9
0
 def as_local_file(self, result):
     ret = Path(urlparse(result["location"]).path)
     for d in self.result_dirs:
         try:
             d = Path(d)
             ret.relative_to(d)
             st_size = ret.stat().st_size
             if st_size == result["contentLength"]:
                 return ret
             self.log.debug(
                 "as_local_file(%s): size %s does not match contentLength",
                 result,
                 st_size,
             )
         except Exception as exc:
             self.log.info("as_local_file(%s): Not in %s: %s", result, d,
                           exc)
Пример #10
0
def test_result_as_local_file(local_results):
    r = local_results.create("text/plain")
    assert local_results.as_local_file(r.as_dict()) == Path(r.path)
Пример #11
0
def test_downloadable_result(worker):
    this_dir = str(Path(__file__, "..").resolve())
    res = worker.http_post("/services/tar-create", data=json.dumps([this_dir]))
    tar_file = requests.get(res["location"])
    assert len(tar_file.content) == res["contentLength"]
Пример #12
0
def servicelib_yaml(request, monkeypatch):
    monkeypatch.setenv(*env_var(
        "SERVICELIB_CONFIG_URL",
        Path(__file__, "..", "sample-servicelib.yaml").resolve().as_uri(),
    ))
Пример #13
0
    def __init__(self, uwsgi_ini_file, servicelib_yaml_file, pid_file,
                 log_file, scratch_dir, *cmdline_args):
        self.servicelib_yaml_file = servicelib_yaml_file
        self.pid_file = pid_file
        self.log_file = log_file
        self.host = "127.0.0.1"
        self.port = utils.available_port()

        # Some tests in `tests/test_client.py` call service `proxy`, which
        # calls other services. We need several uWSGI processes to be ready
        # to accept requests.
        self.num_processes = 4

        # Set to 1 because we're assuming `servicelib` (and the services built
        # upon it) are not thread-safe.
        #
        # We do want to set it explicitly to 1, so that Python's threading
        # machinery gets initialised.
        self.num_threads = 1

        scratch_dir.mkdir(parents=True, exist_ok=True)

        servicelib_dir = Path(__file__, "..", "..").resolve()
        scratch_dir = str(scratch_dir)
        uwsgi_ini_file = str(uwsgi_ini_file)

        for a in cmdline_args:
            if a.startswith("--worker-services-dir="):
                services_dir = a[len("--worker-services-dir="):]
                break
        else:
            services_dir = str(servicelib_dir / "samples")

        self.uwsgi_ini = UWSGI_INI_TEMPLATE.format(
            host=self.host,
            log_file=log_file,
            num_processes=self.num_processes,
            num_threads=self.num_threads,
            pid_file=pid_file,
            port=self.port,
            services_dir=services_dir,
        )
        with open(uwsgi_ini_file, "wt") as f:
            f.write(self.uwsgi_ini)

        self.servicelib_conf = {
            "worker": {
                "hostname": self.host,
                "port": self.port,
                "serve_results": scratch_dir,
                "services_dir": services_dir,
                "static_map": "/services-source-code={}".format(services_dir),
                "swagger_ui_path": "{}/swagger-ui".format(services_dir),
                "uwsgi_config_file": uwsgi_ini_file,
            },
            "inventory": {
                "class": "default",
            },
            "registry": {
                "class": "redis",
                "url": "redis://localhost/0",
            },
            "cache": {
                "class": "memcached",
                "memcached_addresses": ["localhost:11211"],
            },
            "log": {
                "level": "debug",
                "type": "text",
            },
            "results": {
                "class": "http-files",
                "dirs": [scratch_dir],
                "http_hostname": self.host,
            },
            "scratch": {
                "strategy": "random",
                "dirs": [scratch_dir],
            },
        }
        with open(servicelib_yaml_file, "wb") as f:
            yaml.safe_dump(self.servicelib_conf,
                           f,
                           encoding="utf-8",
                           allow_unicode=True)

        self.cmdline_args = cmdline_args
Пример #14
0
def main():
    logutils.configure_logging()

    cmdline_config = cmdline.parse_args(
        "worker.autoreload",
        "worker.hostname",
        "worker.load_workers",
        "worker.num_processes",
        "worker.num_threads",
        "worker.port",
        "worker.services_dir",
    )
    for k, v in cmdline_config.items():
        if isinstance(v, list):
            v = json.dumps(v)
        else:
            v = str(v)
        os.environ[env_var(k)] = v

    cmd = ["uwsgi", "--req-logger", "file:/dev/null"]

    autoreload = int(config.get("worker.autoreload", "0"))
    if autoreload > 0:
        cmd.extend(["--py-autoreload",
                    "{}".format(autoreload)])  # pragma: no cover

    serve_results = config.get("worker.serve_results", default=None)
    if serve_results is not None:
        for dname in serve_results.split(":"):
            cmd.extend(["--static-map", "{}={}".format(dname, dname)])

    swagger_yaml = Path(
        config.get("worker.services_dir", default="/code/services"),
        "swagger.yaml")
    if swagger_yaml.exists():
        cmd.extend(
            ["--static-map", "/services/swagger.yaml={}".format(swagger_yaml)])

    swagger_ui = Path(
        config.get("worker.swagger_ui_path", default="/usr/share/nginx/html"))
    if swagger_yaml.exists():
        cmd.extend(["--static-map", "/docs={}".format(swagger_ui)])
        cmd.extend(["--static-index", "index.html"])

    static_assets = config.get("worker.static_map", default=None)
    if static_assets is not None:
        cmd.extend(["--static-map", static_assets])

    cmd.append(
        config.get(
            "worker.uwsgi_config_file",
            default=str(Path(logutils.__file__, "..", "uwsgi.ini").resolve()),
        ))

    os.environ.setdefault(
        env_var("worker.num_processes"),
        config.get("worker.num_processes", str(psutil.cpu_count())),
    )
    os.environ.setdefault(env_var("worker.num_threads"),
                          str(config.get("worker.num_threads", 1)))
    os.environ.setdefault(env_var("worker.port"),
                          str(config.get("worker.port", 8000)))

    log = logutils.get_logger("servicelib-worker")
    log.info("Environment: %s", os.environ)
    log.info("Running: %s", " ".join(cmd))

    # If we're running under `pytest-cov`, call `pytest_cov.embed.cleanup()`
    # before exec of uWSGI, so that we do not lose coverage info for this
    # Python module.
    if os.environ.get("COV_CORE_DATAFILE"):
        from pytest_cov.embed import cleanup

        cleanup()

    os.execlp(cmd[0], *cmd[0:])