diff --git a/binderhub/repoproviders.py b/binderhub/repoproviders.py index be9dd75f4..a72cc9387 100644 --- a/binderhub/repoproviders.py +++ b/binderhub/repoproviders.py @@ -67,11 +67,29 @@ class RepoProvider(LoggingConfigurable): """ ) + allowed_specs = List( + help=""" + List of specs to allow building. + + Should be a list of regexes (not regex objects) that match specs which + should be allowed. + + A spec is allowed if: + 1. it matches allowed_specs and does not match banned_specs or + 2. allowed_specs is unspecified and the spec does not match banned_specs. + """, + config=True, + ) + banned_specs = List( help=""" List of specs to blacklist building. Should be a list of regexes (not regex objects) that match specs which should be blacklisted + + A spec is allowed if: + 1. it matches allowed_specs and does not match banned_specs or + 2. allowed_specs is unspecified and the spec does not match banned_specs. """, config=True, ) @@ -112,13 +130,22 @@ class RepoProvider(LoggingConfigurable): def is_banned(self): """ - Return true if the given spec has been banned + Return true if the given spec has been banned or explicitly + not allowed. """ for banned in self.banned_specs: # Ignore case, because most git providers do not # count DS-100/textbook as different from ds-100/textbook if re.match(banned, self.spec, re.IGNORECASE): return True + if self.allowed_specs and len(self.allowed_specs): + for allowed in self.allowed_specs: + if re.match(allowed, self.spec, re.IGNORECASE): + return False + # allowed_specs is not empty but spec is not in it: banned. + return True + # allowed_specs unspecified or empty and spec does not match + # banned_specs: not banned. return False def has_higher_quota(self): diff --git a/binderhub/tests/test_repoproviders.py b/binderhub/tests/test_repoproviders.py index df5f63e0e..87c6a3727 100644 --- a/binderhub/tests/test_repoproviders.py +++ b/binderhub/tests/test_repoproviders.py @@ -264,6 +264,29 @@ def test_banned(): assert provider.is_banned() +def test_allowed(): + provider = GitHubRepoProvider( + spec="jupyterhub/zero-to-jupyterhub-k8s/v0.4", allowed_specs=["^jupyterhub.*"] + ) + assert not provider.is_banned() + + +def test_not_allowed(): + provider = GitHubRepoProvider( + spec="jupyterhub/zero-to-jupyterhub-k8s/v0.4", allowed_specs=["^yuvipanda.*"] + ) + assert provider.is_banned() + + +def test_allowed_but_banned(): + provider = GitHubRepoProvider( + spec="jupyterhub/zero-to-jupyterhub-k8s/v0.4", + allowed_specs=["^jupyterhub.*"], + banned_specs=[".*zero-to-.*"], + ) + assert provider.is_banned() + + def test_higher_quota(): provider = GitHubRepoProvider( spec="jupyterhub/zero-to-jupyterhub-k8s/v0.4", high_quota_specs=["^yuvipanda.*"]