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))
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"} ), }
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
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()
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), )
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)
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))
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()
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()
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)
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))
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)
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