Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProxyRepoProvider which routes requests to existing repoprovider based on external api #1511

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions binderhub/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
HydroshareProvider,
RepoProvider,
ZenodoProvider,
ProxyRepoProvider
)
from .utils import ByteSpecification, url_path_join

Expand Down Expand Up @@ -517,6 +518,7 @@ def _default_build_namespace(self):
"figshare": FigshareProvider,
"hydroshare": HydroshareProvider,
"dataverse": DataverseProvider,
"proxy": ProxyRepoProvider,
},
config=True,
help="""
Expand Down
3 changes: 2 additions & 1 deletion binderhub/event-schemas/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"Zenodo",
"Figshare",
"Hydroshare",
"Dataverse"
"Dataverse",
"Proxy"
],
"description": "Provider for the repository being launched"
},
Expand Down
1 change: 1 addition & 0 deletions binderhub/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"figshare": "Figshare",
"hydroshare": "Hydroshare",
"dataverse": "Dataverse",
"proxy": "Proxy"
}


Expand Down
70 changes: 70 additions & 0 deletions binderhub/repoproviders.py
Original file line number Diff line number Diff line change
Expand Up @@ -1036,3 +1036,73 @@ async def get_resolved_spec(self):

def get_build_slug(self):
return self.gist_id

class ProxyRepoProvider(RepoProvider):
"""RepoProvider that acts as a proxy for another provider

Uses an external API to determine desired provider and spec given
an input spec that acts as a repo id in the external API."""

name = Unicode("Proxy")

display_name = "Proxy"

api_url = Unicode(
config=True,
help="""The path to the external API
Requests to api_url/spec should return a json with a spec
field and a provider field that maps to one of the predefined
repoproviders.
"""
)

labels = {
"text": "URL to API endpoint returning project's spec and provider",
"tag_text": "Git ref (branch, tag, or commit)",
"ref_prop_disabled": True,
"label_prop_disabled": True,
}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.provider, kwargs = self.resolve_provider(kwargs)
import inspect
for name, value in inspect.getmembers(self.provider(*args, **kwargs)):
if name in ["__dict__", "labels"]:
continue
try:
setattr(self, name, value)
except Exception as e:
self.log.debug(f"Error copying {e}")
self.log.debug(f"Copied attributes from {self.provider} instance")

def resolve_provider(self, kwargs):
import requests
spec = kwargs["spec"]
# remove auto generated commit
spec = spec.split("/")[0]
project_url = f"{self.api_url}/{spec}"
self.log.debug(f"Fetching {project_url}")
project_metadata = requests.get(project_url).json()
try:
provider = project_metadata["provider"]
spec = project_metadata["spec"]
except AttributeError as e:
msg = f"""API endpoint {project_url} must return json with
'provider' and 'spec' attributes"""
raise ValueError(msg)
providers = {
'gh': GitHubRepoProvider,
'gist': GistRepoProvider,
'git': GitRepoProvider,
'gl': GitLabRepoProvider,
'zenodo': ZenodoProvider,
'figshare': FigshareProvider,
'hydroshare': HydroshareProvider,
'dataverse': DataverseProvider,
}
provider_class = providers[provider]
self.log.debug(f"Using {provider} provider with spec {spec}")
kwargs["spec"] = spec

return provider_class, kwargs
2 changes: 1 addition & 1 deletion binderhub/static/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ function getBuildFormValues() {

let ref = $('#ref').val().trim() || $("#ref").attr("placeholder");
if (providerPrefix === 'zenodo' || providerPrefix === 'figshare' || providerPrefix === 'dataverse' ||
providerPrefix === 'hydroshare') {
providerPrefix === 'hydroshare' || providerPrefix === 'proxy') {
ref = "";
}
const path = $('#filepath').val().trim();
Expand Down