예제 #1
0
def ui_edit_environment(name):
    conda_store = get_conda_store()
    environment = api.get_environment(conda_store.db, name)
    specification = api.get_specification(conda_store.db,
                                          environment.specification.sha256)
    return render_template("create.html",
                           specification=yaml.dump(specification.spec))
예제 #2
0
def api_get_environment(
    namespace: str,
    environment_name: str,
    request: Request,
    conda_store=Depends(dependencies.get_conda_store),
    auth=Depends(dependencies.get_auth),
):
    auth.authorize_request(
        request,
        f"{namespace}/{environment_name}",
        {Permissions.ENVIRONMENT_READ},
        require=True,
    )

    environment = api.get_environment(
        conda_store.db, namespace=namespace, name=environment_name
    )
    if environment is None:
        raise HTTPException(status_code=404, detail="environment does not exist")

    return {
        "status": "ok",
        "data": schema.Environment.from_orm(environment).dict(
            exclude={"current_build"}
        ),
    }
예제 #3
0
def dynamic_conda_store_environment(conda_store, packages):
    def replace_words(s, words):
        for k, v in words.items():
            s = s.replace(k, v)
        return s

    constraint_mapper = {
        ".gt.": ">",
        ".ge.": ">=",
        ".lt.": "<",
        ".le.": "<=",
        ".eq.": "==",
    }

    # TODO: should really be doing checking on package names to
    # validate user input
    packages = [replace_words(_, constraint_mapper) for _ in sorted(packages)]
    environment_name = "|".join(packages)
    environment = api.get_environment(conda_store.db,
                                      environment_name,
                                      namespace="conda-store-dynamic")

    if environment is None:
        environment_specification = {
            "name": environment_name,
            "channels": ["conda-forge"],
            "dependencies": packages,
        }
        conda_store.register_environment(environment_specification,
                                         namespace="conda-store-dynamic")
    return environment_name
예제 #4
0
    def update_environment_build(self, namespace, name, build_id):
        build = api.get_build(self.db, build_id)
        if build is None:
            raise utils.CondaStoreError(f"build id={build_id} does not exist")

        environment = api.get_environment(self.db,
                                          namespace=namespace,
                                          name=name)
        if environment is None:
            raise utils.CondaStoreError(
                f"environment namespace={namespace} name={name} does not exist"
            )

        if build.status != schema.BuildStatus.COMPLETED:
            raise utils.CondaStoreError(
                "cannot update environment to build id since not completed")

        if build.specification.name != name:
            raise utils.CondaStoreError(
                "cannot update environment to build id since specification does not match environment name"
            )

        environment.current_build_id = build.id
        self.db.commit()

        self.celery_app
        # must import tasks after a celery app has been initialized
        from conda_store_server.worker import tasks

        tasks.task_update_environment_build.si(environment.id).apply_async()
예제 #5
0
def ui_get_environment(name):
    conda_store = get_conda_store()
    return render_template(
        "environment.html",
        environment=api.get_environment(conda_store.db, name),
        environment_builds=api.get_environment_builds(conda_store.db, name),
    )
예제 #6
0
def task_update_environment_build(self, environment_id):
    conda_store = self.worker.conda_store
    environment = api.get_environment(conda_store.db, id=environment_id)

    conda_prefix = environment.current_build.build_path(conda_store)
    environment_prefix = environment.current_build.environment_path(
        conda_store)

    utils.symlink(conda_prefix, environment_prefix)
예제 #7
0
def get_docker_image_manifest(conda_store, image, tag, timeout=10 * 60):
    namespace, *image_name = image.split("/")

    # /v2/<image-name>/manifest/<tag>
    if len(image_name) == 0:
        return docker_error_message(schema.DockerRegistryError.NAME_UNKNOWN)

    if namespace == "conda-store-dynamic":
        environment_name = dynamic_conda_store_environment(
            conda_store, image_name)
    elif len(image_name) > 1:
        return docker_error_message(schema.DockerRegistryError.NAME_UNKNOWN)
    else:
        environment_name = image_name[0]

    # check that namespace/environment_name exist
    environment = api.get_environment(conda_store.db,
                                      namespace=namespace,
                                      name=environment_name)
    if environment is None:
        return docker_error_message(schema.DockerRegistryError.NAME_UNKNOWN)

    if tag == "latest":
        build_key = environment.current_build.build_key
    elif tag.startswith("sha256:"):
        # looking for sha256 of docker manifest
        manifests_key = f"docker/manifest/{tag}"
        return RedirectResponse(conda_store.storage.get_url(manifests_key))
    else:
        build_key = tag

    build_id = orm.Build.parse_build_key(build_key)
    if build_id is None:
        return docker_error_message(
            schema.DockerRegistryError.MANIFEST_UNKNOWN)

    build = api.get_build(conda_store.db, build_id)
    if build is None:
        return docker_error_message(
            schema.DockerRegistryError.MANIFEST_UNKNOWN)

    # waiting for image to be built by conda-store
    start_time = time.time()
    while not build.has_docker_manifest:
        conda_store.db.refresh(build)
        time.sleep(10)
        if time.time() - start_time > timeout:
            return docker_error_message(
                schema.DockerRegistryError.MANIFEST_UNKNOWN)

    manifests_key = f"docker/manifest/{build_key}"
    return RedirectResponse(conda_store.storage.get_url(manifests_key))
예제 #8
0
def task_delete_environment(self, environment_id):
    conda_store = self.worker.conda_store
    environment = api.get_environment(conda_store.db, id=environment_id)

    for build in environment.builds:
        conda_store.log.info(f"deleting artifacts for build={build.id}")
        for build_artifact in api.list_build_artifacts(
                conda_store.db,
                build_id=build.id,
        ).all():
            delete_build_artifact(conda_store, build_artifact)

    conda_store.db.delete(environment)
    conda_store.db.commit()
예제 #9
0
    def delete_environment(self, namespace, name):
        environment = api.get_environment(self.db,
                                          namespace=namespace,
                                          name=name)
        if environment is None:
            raise utils.CondaStoreError(
                f"environment namespace={namespace} name={name} does not exist"
            )

        utcnow = datetime.datetime.utcnow()
        environment.deleted_on = utcnow
        for build in environment.builds:
            build.deleted_on = utcnow
        self.db.commit()

        self.celery_app

        # must import tasks after a celery app has been initialized
        from conda_store_server.worker import tasks

        tasks.task_delete_environment.si(environment.id).apply_async()
예제 #10
0
파일: ui.py 프로젝트: Quansight/conda-store
def ui_edit_environment(
    namespace: str,
    environment_name: str,
    request: Request,
    templates=Depends(dependencies.get_templates),
    conda_store=Depends(dependencies.get_conda_store),
    auth=Depends(dependencies.get_auth),
    entity=Depends(dependencies.get_entity),
):
    auth.authorize_request(
        request,
        f"{namespace}/{environment_name}",
        {Permissions.ENVIRONMENT_CREATE},
        require=True,
    )

    environment = api.get_environment(
        conda_store.db, namespace=namespace, name=environment_name
    )
    if environment is None:
        return templates.TemplateResponse(
            "404.html",
            {
                "request": request,
                "message": f"environment namespace={namespace} name={environment_name} not found",
            },
            status_code=404,
        )

    context = {
        "request": request,
        "environment": environment,
        "entity": entity,
        "specification": yaml.dump(environment.current_build.specification.spec),
        "namespaces": [environment.namespace],
    }

    return templates.TemplateResponse("create.html", context)
예제 #11
0
def get_docker_image_manifest(conda_store, image, tag, timeout=10 * 60):
    namespace, *image_name = image.split("/")

    # /v2/<image-name>/manifest/<tag>
    if len(image_name) == 0:
        return docker_error_message(schema.DockerRegistryError.NAME_UNKNOWN)

    if namespace == "conda-store-dynamic":
        environment_name = dynamic_conda_store_environment(
            conda_store, image_name)
    elif len(image_name) > 1:
        return docker_error_message(schema.DockerRegistryError.NAME_UNKNOWN)
    else:
        environment_name = image_name[0]

    # check that namespace/environment_name exist
    environment = api.get_environment(conda_store.db,
                                      environment_name,
                                      namespace=namespace)
    if environment is None:
        return docker_error_message(schema.DockerRegistryError.NAME_UNKNOWN)

    if tag == "latest":
        # waiting for image to be built by conda-store
        start_time = time.time()
        while environment.specification is None:
            conda_store.db.refresh(environment)
            time.sleep(10)
            if time.time() - start_time > timeout:
                return docker_error_message(
                    schema.DockerRegistryError.MANIFEST_UNKNOWN)

        specification_sha256 = environment.specification.sha256
    else:
        specification_sha256 = tag

    manifests_key = f"docker/manifest/{environment_name}/{specification_sha256}"
    return redirect(conda_store.storage.get_url(manifests_key))
예제 #12
0
def api_get_environment(name):
    conda_store = get_conda_store()
    environment = schema.Environment.from_orm(
        api.get_environment(conda_store.db, name)).dict()
    return jsonify(environment)
예제 #13
0
    def register_environment(self,
                             specification: dict,
                             namespace: str = None,
                             force_build=False):
        """Register a given specification to conda store with given namespace/name.

        If force_build is True a build will be triggered even if
        specification already exists.

        """
        namespace = namespace or self.default_namespace

        # Create Namespace if namespace if it does not exist
        namespace_model = api.get_namespace(self.db, name=namespace)
        if namespace_model is None:
            namespace = api.create_namespace(self.db, name=namespace)
            self.db.commit()
        else:
            namespace = namespace_model

        specification_model = self.validate_specification(
            conda_store=self,
            namespace=namespace.name,
            specification=schema.CondaSpecification.parse_obj(specification),
        )
        specification_sha256 = utils.datastructure_hash(
            specification_model.dict())

        specification = api.get_specification(self.db,
                                              sha256=specification_sha256)
        if specification is None:
            self.log.info(
                f"specification name={specification_model.name} sha256={specification_sha256} registered"
            )
            specification = orm.Specification(specification_model.dict())
            self.db.add(specification)
            self.db.commit()
        else:
            self.log.debug(
                f"specification name={specification_model.name} sha256={specification_sha256} already registered"
            )
            if not force_build:
                return

        # Create Environment if specification of given namespace/name
        # does not exist yet
        environment = api.get_environment(self.db,
                                          namespace_id=namespace.id,
                                          name=specification.name)
        environment_was_empty = environment is None
        if environment_was_empty:
            environment = orm.Environment(
                name=specification.name,
                namespace_id=namespace.id,
            )
            self.db.add(environment)
            self.db.commit()

        build = self.create_build(environment.id, specification.sha256)

        if environment_was_empty:
            environment.current_build = build
            self.db.commit()

        return build.id