Skip to content

Commit 7823b55

Browse files
authored
Merge pull request #25 from ecmwf/develop
Release 0.8.1
2 parents 1a881ec + cea8d9d commit 7823b55

File tree

4 files changed

+195
-102
lines changed

4 files changed

+195
-102
lines changed

polytope_server/common/datasource/polytope.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
# does it submit to any jurisdiction.
1919
#
2020

21+
import copy
2122
import json
2223
import logging
2324
import os
24-
import copy
2525

2626
import yaml
2727
from polytope.utility.exceptions import PolytopeError
@@ -61,7 +61,7 @@ def retrieve(self, request):
6161

6262
# Set the "pre-path" for this request
6363
pre_path = {}
64-
for k,v in r.items():
64+
for k, v in r.items():
6565
if k in self.req_single_keys:
6666
if isinstance(v, list):
6767
v = v[0]
@@ -70,14 +70,23 @@ def retrieve(self, request):
7070
polytope_mars_config = copy.deepcopy(self.config)
7171
polytope_mars_config["options"]["pre_path"] = pre_path
7272

73+
transforms = []
74+
for transform in polytope_mars_config["options"]["axis_config"]:
75+
if transform["axis_name"] in r.keys():
76+
logging.info("Found axis {} in request".format(transform["axis_name"]))
77+
transforms.append(transform)
78+
if transform["axis_name"] in ("latitude", "longitude", "values"):
79+
transforms.append(transform)
80+
81+
polytope_mars_config["options"]["axis_config"] = transforms
7382

7483
polytope_mars = PolytopeMars(
7584
polytope_mars_config,
76-
log_context= {
77-
"user": request.user.realm + ':' + request.user.username,
85+
log_context={
86+
"user": request.user.realm + ":" + request.user.username,
7887
"id": request.id,
79-
})
80-
88+
},
89+
)
8190

8291
try:
8392
self.output = polytope_mars.extract(r)
@@ -111,7 +120,7 @@ def match(self, request):
111120
raise Exception("got {} : {}, but expected one of {}".format(k, r[k], v))
112121

113122
# Check that there is only one value if required
114-
for k, v in r.items():
123+
for k, v in r.items():
115124
if k in self.req_single_keys:
116125
v = [v] if isinstance(v, str) else v
117126
if len(v) > 1:

polytope_server/common/staging/s3_boto3_staging.py

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020

2121
import json
2222
import logging
23-
import random
2423
import time
2524
from concurrent.futures import Future, ThreadPoolExecutor
2625

@@ -59,7 +58,6 @@ def submit(self, fn, /, *args, **kwargs):
5958

6059
class S3Staging_boto3(staging.Staging):
6160
def __init__(self, config):
62-
6361
self.bucket = config.get("bucket", "default")
6462
self.url = config.get("url", None)
6563

@@ -76,17 +74,9 @@ def __init__(self, config):
7674
for name in ["boto", "urllib3", "s3transfer", "boto3", "botocore", "nose"]:
7775
logging.getLogger(name).setLevel(logging.WARNING)
7876

79-
prefix = "https" if self.use_ssl else "http"
80-
81-
if config.get("random_host", False):
82-
self.host = config.get("random_host", {}).get("host", self.host)
83-
index = random.randint(0, config.get("random_host", {}).get("max", 1) - 1)
84-
# replace %%ID%% in the host with the index
85-
self.host = self.host.replace("%%ID%%", str(index))
86-
self.url = self.url + "/" + str(index)
87-
logging.info(f"Using random host: {self.host}")
77+
self.prefix = "https" if self.use_ssl else "http"
8878

89-
self._internal_url = f"{prefix}://{self.host}:{self.port}"
79+
self._internal_url = f"http://{self.host}:{self.port}"
9080

9181
# Setup Boto3 client
9282
self.s3_client = boto3.client(
@@ -125,7 +115,10 @@ def create(self, name, data, content_type):
125115
# else using content-disposition header
126116
try:
127117
multipart_upload = self.s3_client.create_multipart_upload(
128-
Bucket=self.bucket, Key=name, ContentType=content_type, ContentDisposition="attachment"
118+
Bucket=self.bucket,
119+
Key=name,
120+
ContentType=content_type,
121+
ContentDisposition="attachment",
129122
)
130123
upload_id = multipart_upload["UploadId"]
131124

@@ -140,7 +133,15 @@ def create(self, name, data, content_type):
140133
else:
141134
for part_data in self.iterator_buffer(data, self.buffer_size):
142135
if part_data:
143-
futures.append(executor.submit(self.upload_part, name, part_number, part_data, upload_id))
136+
futures.append(
137+
executor.submit(
138+
self.upload_part,
139+
name,
140+
part_number,
141+
part_data,
142+
upload_id,
143+
)
144+
)
144145
part_number += 1
145146

146147
for future in futures:
@@ -153,7 +154,10 @@ def create(self, name, data, content_type):
153154
raise ValueError("No data retrieved")
154155

155156
self.s3_client.complete_multipart_upload(
156-
Bucket=self.bucket, Key=name, UploadId=upload_id, MultipartUpload={"Parts": parts}
157+
Bucket=self.bucket,
158+
Key=name,
159+
UploadId=upload_id,
160+
MultipartUpload={"Parts": parts},
157161
)
158162

159163
logging.info(f"Successfully uploaded {name} in {len(parts)} parts.")
@@ -168,7 +172,11 @@ def create(self, name, data, content_type):
168172
def upload_part(self, name, part_number, data, upload_id):
169173
logging.debug(f"Uploading part {part_number} of {name}, {len(data)} bytes")
170174
response = self.s3_client.upload_part(
171-
Bucket=self.bucket, Key=name, PartNumber=part_number, UploadId=upload_id, Body=data
175+
Bucket=self.bucket,
176+
Key=name,
177+
PartNumber=part_number,
178+
UploadId=upload_id,
179+
Body=data,
172180
)
173181
return {"PartNumber": part_number, "ETag": response["ETag"]}
174182

@@ -190,14 +198,14 @@ def set_bucket_policy(self):
190198
},
191199
{
192200
"Sid": "AllowListBucket",
193-
"Effect": "Allow",
201+
"Effect": "Deny",
194202
"Principal": "*",
195203
"Action": "s3:ListBucket",
196204
"Resource": f"arn:aws:s3:::{self.bucket}",
197205
},
198206
{
199207
"Sid": "AllowGetBucketLocation",
200-
"Effect": "Allow",
208+
"Effect": "Deny",
201209
"Principal": "*",
202210
"Action": "s3:GetBucketLocation",
203211
"Resource": f"arn:aws:s3:::{self.bucket}",
@@ -239,7 +247,11 @@ def stat(self, name):
239247

240248
def get_url(self, name):
241249
if self.url:
242-
return f"{self.url}/{self.bucket}/{name}"
250+
if self.url.startswith("http"):
251+
# This covers both http and https
252+
return f"{self.url}/{self.bucket}/{name}"
253+
else:
254+
return f"{self.prefix}://{self.url}/{self.bucket}/{name}"
243255
return None
244256

245257
def get_internal_url(self, name):

0 commit comments

Comments
 (0)