Skip to content

Commit

Permalink
Revert "black"
Browse files Browse the repository at this point in the history
This reverts commit 8de7963.
  • Loading branch information
mathleur committed Jan 21, 2025
1 parent 0a6893f commit 953aff5
Show file tree
Hide file tree
Showing 61 changed files with 153 additions and 1 deletion.
3 changes: 3 additions & 0 deletions admin/polytope-admin/tests/unit/auth_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@


class TestAuth:

# def __init__(self):
# self.address = None
# self.port = None
# self.admin_username = None
# self.admin_password = None

def setup_method(self, method):

# Cache environment variables and remove them so they are not used to authenticate
os.environ["POLYTOPE_USER_KEY"] = ""
os.environ["POLYTOPE_USER_EMAIL"] = ""
Expand All @@ -49,6 +51,7 @@ def setup_method(self, method):
self.c.ping()

def teardown_method(self, method):

# Log in and delete old test data
self.c.set_config("username", ValueStorage.admin_username)
self.c.set_config("password", ValueStorage.admin_password)
Expand Down
2 changes: 2 additions & 0 deletions polytope_server/basic_object_store/basic_object_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,15 @@ def do_DELETE(self):

class BasicObjectStore:
def __init__(self, config):

staging_config = config.get("staging", {})
object_store_config = staging_config.get("polytope", {})
self.host = object_store_config.get("host", "0.0.0.0")
self.port = object_store_config.get("port", "8000")
self.root_dir = object_store_config.get("root_dir", "/data")

def run(self):

if not os.path.isdir(self.root_dir):
try:
os.mkdir(self.root_dir)
Expand Down
6 changes: 6 additions & 0 deletions polytope_server/broker/broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

class Broker:
def __init__(self, config):

queue_config = config.get("queue")
self.queue = queue.create_queue(queue_config)

Expand All @@ -40,13 +41,15 @@ def __init__(self, config):
self.collections = collection.create_collections(config.get("collections"))

def run(self):

logging.info("Starting broker...")
logging.info("Maximum Queue Size: {}".format(self.max_queue_size))

while not time.sleep(self.scheduling_interval):
self.check_requests()

def check_requests(self):

self.queue.keep_alive()

# Don't queue if full. We don't need to query request_store.
Expand All @@ -69,6 +72,7 @@ def check_requests(self):

# Loop through requests queuing anything that meets QoS requirements
for wr in waiting_requests: # should break if queue full

if self.check_limits(active_requests, wr):
assert wr.status == Status.WAITING
active_requests.add(wr)
Expand All @@ -79,6 +83,7 @@ def check_requests(self):
return

def check_limits(self, active_requests, request):

logging.debug(f"Checking limits for request {request.id}")

# Get collection limits and calculate active requests
Expand Down Expand Up @@ -121,6 +126,7 @@ def check_limits(self, active_requests, request):
return True

def enqueue(self, request):

logging.info("Queuing request", extra={"request_id": request.id})

try:
Expand Down
1 change: 1 addition & 0 deletions polytope_server/common/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def __init__(self, config):
self.authorizers = []

for realm in config.get("authentication", {}):

logging.debug("Loading authenticators and authorizers for realm {}".format(realm))

for name, authentication_config in config["authentication"][realm].get("authenticators", {}).items():
Expand Down
1 change: 1 addition & 0 deletions polytope_server/common/authentication/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ def name(self) -> str:


def create_authentication(name, realm, config):

# Find the class matching config.type
type = config.get("type")
assert type is not None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def authentication_info(self):

@cache(lifetime=120)
def authenticate(self, credentials: str) -> User:

# credentials should be of the form '<email>:<API_key>'
try:
auth_email, auth_key = credentials.split(":", 1)
Expand Down Expand Up @@ -78,6 +79,7 @@ def collect_metric_info(self):


def retrieve_ecmwfapi_user(key, url, status_url, proxy=""):

url = url.rstrip("/")
proxies = {"http": proxy, "https": proxy}
response = requests.get(url + "/who-am-i?token=" + key, proxies=proxies)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def authentication_info(self):

@cache(lifetime=120)
def authenticate(self, credentials: str) -> User:

# credentials should be of the form 'Federation <secret>:<username>:<realm>'

try:
Expand All @@ -69,6 +70,7 @@ def collect_metric_info(self):


def retrieve_ecmwfapi_user(key, url="https://api.ecmwf.int/v1", proxy=""):

url = url.rstrip("/")
proxies = {"http": proxy, "https": proxy}
response = requests.get(url + "/who-am-i?token=" + key, proxies=proxies)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def get_certs(self):

@cache(lifetime=120)
def authenticate(self, credentials: str) -> User:

try:
certs = self.get_certs()
decoded_token = jwt.decode(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def authentication_info(self):

@cache(lifetime=120)
def authenticate(self, credentials: str) -> User:

# credentials should be of the form 'base64(<username>:<API_key>)'
try:
decoded = base64.b64decode(credentials).decode("utf-8")
Expand All @@ -80,6 +81,7 @@ def authenticate(self, credentials: str) -> User:
logging.debug("Setting HTTPS_PROXY to {}".format(os.environ["https_proxy"]))

try:

# Open a session as a registered client
client = KeycloakOpenID(
server_url=self.url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ def check_offline_access_token(self, token: str) -> bool:

@cache(lifetime=120)
def authenticate(self, credentials: str) -> User:

try:

# Check if this is a valid offline_access token
if not self.check_offline_access_token(credentials):
raise ForbiddenRequest("Not a valid offline_access token")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def authentication_info(self):
return "Authenticate with username and password"

def authenticate(self, credentials: str) -> User:

# credentials should be of the form 'base64(<username>:<API_key>)'
try:
decoded = base64.b64decode(credentials).decode("utf-8")
Expand Down
1 change: 1 addition & 0 deletions polytope_server/common/authorization/authorization.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def name(self) -> str:


def create_authorization(name, realm, config):

# Find the class matching config.type
type = config.get("type")
module = import_module("polytope_server.common.authorization." + type + "_authorization")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def __init__(self, name, realm, config):
super().__init__(name, realm, config)

def get_roles(self, user: User) -> list:

if user.realm != self.realm():
raise ValueError(
"Trying to authorize a user in the wrong realm, expected {}, got {}".format(self.realm, user.realm)
Expand Down
1 change: 1 addition & 0 deletions polytope_server/common/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

class Collection:
def __init__(self, name, config):

self.config = config
self.name = name
self.roles = config.get("roles")
Expand Down
5 changes: 5 additions & 0 deletions polytope_server/common/datasource/coercion.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class CoercionError(Exception):


class Coercion:

allow_ranges = [
"number",
"step",
Expand All @@ -32,6 +33,7 @@ def coerce_value(key: str, value: Any):
coerced_values = [Coercion.coerce_value(key, v) for v in value]
return coerced_values
elif isinstance(value, str):

if "/to/" in value and key in Coercion.allow_ranges:
# Handle ranges with possible "/by/" suffix
start_value, rest = value.split("/to/", 1)
Expand Down Expand Up @@ -106,6 +108,7 @@ def coerce_date(value: Any) -> str:

@staticmethod
def coerce_step(value: Any) -> str:

if isinstance(value, int):
if value < 0:
raise CoercionError("Step must be greater than or equal to 0.")
Expand All @@ -120,6 +123,7 @@ def coerce_step(value: Any) -> str:

@staticmethod
def coerce_number(value: Any) -> str:

if isinstance(value, int):
if value <= 0:
raise CoercionError("Number must be a positive value.")
Expand Down Expand Up @@ -213,6 +217,7 @@ def coerce_time(value: Any) -> str:

@staticmethod
def coerce_expver(value: Any) -> str:

# Integers accepted, converted to 4-length strings
if isinstance(value, int):
if 0 <= value <= 9999:
Expand Down
1 change: 1 addition & 0 deletions polytope_server/common/datasource/datasource.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ def dispatch(self, request, input_data) -> bool:


def create_datasource(config):

# Allows passing in just the name as config
if isinstance(config, str):
config = {"name": config}
Expand Down
10 changes: 10 additions & 0 deletions polytope_server/common/datasource/fdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ def __init__(self, config):
os.makedirs(root["path"], exist_ok=True)

def check_schema(self):

schema = self.fdb_config.get("schema", None)

# If schema is empty, leave it empty
Expand All @@ -71,6 +72,7 @@ def check_schema(self):

# pull schema from git
if "git" in schema:

git_config = schema["git"]
git_path = Path(git_config["path"])

Expand Down Expand Up @@ -108,6 +110,7 @@ def get_type(self):
return self.type

def archive(self, request):

# could add a check that the request is a singular object (does not contain)

# r = yaml.safe_load(request.user_request)
Expand All @@ -117,6 +120,7 @@ def archive(self, request):
return True

def retrieve(self, request):

r = yaml.safe_load(request.user_request)
logging.info(r)
self.output = self.fdb.retrieve(r)
Expand All @@ -126,6 +130,7 @@ def repr(self):
return self.config.get("repr", "fdb")

def result(self, request):

if not self.output:
return

Expand All @@ -140,9 +145,11 @@ def result(self, request):
return

def match(self, request):

r = yaml.safe_load(request.user_request) or {}

for k, v in self.match_rules.items():

# An empty match rule means that the key must not be present
if v is None or len(v) == 0:
if k in r:
Expand Down Expand Up @@ -199,6 +206,7 @@ def convert_to_mars_request(self, loaded_request):
return request_str[:-1]

def check_single_date(self, date, offset, offset_fmted):

# Date is relative (0 = now, -1 = one day ago)
if str(date)[0] == "0" or str(date)[0] == "-":
date_offset = int(date)
Expand Down Expand Up @@ -242,7 +250,9 @@ def date_check(self, date, offsets):
# YYYYMMDD/to/YYYYMMDD -- check end and start date
# YYYYMMDD/to/YYYYMMDD/by/N -- check end and start date
if len(split) == 3 or len(split) == 5:

if split[1].casefold() == "to".casefold():

if len(split) == 5 and split[3].casefold() != "by".casefold():
raise Exception("Invalid date range")

Expand Down
3 changes: 3 additions & 0 deletions polytope_server/common/datasource/federated.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def repr(self):
return self.config.get("repr", "federated")

def archive(self, request):

url = "/".join(
[
self.url + ":" + str(self.port),
Expand Down Expand Up @@ -130,6 +131,7 @@ def archive(self, request):
return True

def retrieve(self, request):

url = "/".join(
[
self.url + ":" + str(self.port),
Expand Down Expand Up @@ -191,6 +193,7 @@ def retrieve(self, request):
return True

def result(self, request):

response = requests.get(self.result_url, stream=True)

self.mime_type_result = response.headers["Content-Type"]
Expand Down
8 changes: 8 additions & 0 deletions polytope_server/common/datasource/mars.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ def repr(self):
return self.config.get("repr", "mars")

def match(self, request):

r = yaml.safe_load(request.user_request) or {}

for k, v in self.match_rules.items():

# An empty match rule means that the key must not be present
if v is None or len(v) == 0:
if k in r:
Expand Down Expand Up @@ -122,6 +124,7 @@ def archive(self, request):
raise NotImplementedError("Archiving not implemented for MARS data source")

def retrieve(self, request):

# Open a FIFO for MARS output
self.fifo = FIFO("MARS-FIFO-" + request.id)

Expand Down Expand Up @@ -160,6 +163,7 @@ def retrieve(self, request):
return True

def result(self, request):

# The FIFO will get EOF if MARS exits unexpectedly, so we will break out of this loop automatically
for x in self.fifo.data():
yield x
Expand Down Expand Up @@ -234,6 +238,7 @@ def convert_to_mars_request(self, verb, user_request):
return request_str

def check_single_date(self, date, offset, offset_fmted, after=False):

# Date is relative (0 = now, -1 = one day ago)
if str(date)[0] == "0" or str(date)[0] == "-":
date_offset = int(date)
Expand All @@ -259,6 +264,7 @@ def check_single_date(self, date, offset, offset_fmted, after=False):
return

def parse_relativedelta(self, time_str):

pattern = r"(\d+)([dhm])"
time_dict = {"d": 0, "h": 0, "m": 0}
matches = re.findall(pattern, time_str)
Expand Down Expand Up @@ -296,7 +302,9 @@ def date_check(self, date, offset, after=False):
# YYYYMMDD/to/YYYYMMDD -- check end and start date
# YYYYMMDD/to/YYYYMMDD/by/N -- check end and start date
if len(split) == 3 or len(split) == 5:

if split[1].casefold() == "to".casefold():

if len(split) == 5 and split[3].casefold() != "by".casefold():
raise Exception("Invalid date range")

Expand Down
Loading

0 comments on commit 953aff5

Please sign in to comment.