Skip to content

Commit 8434091

Browse files
authored
Revert "Tech Debt: Upgrading boto to boto3 for api & ingester"
1 parent 43af5f9 commit 8434091

File tree

16 files changed

+219
-259
lines changed

16 files changed

+219
-259
lines changed

.github/workflows/actions.yml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@ on: [push, pull_request]
33

44
jobs:
55
test-client:
6-
runs-on: ubuntu-latest
7-
timeout-minutes: 30
6+
runs-on: ubuntu-20.04
87
strategy:
98
matrix:
109
python: [3.8, 3.9, "3.10", 3.12]
1110
extras: ["test", "test,queuable,sentry"]
1211
steps:
1312
- name: Setup Python
14-
uses: actions/setup-python@v5
13+
uses: actions/setup-python@v2.2.2
1514
with:
1615
python-version: ${{ matrix.python }}
1716
- name: Check out repository code
@@ -21,14 +20,13 @@ jobs:
2120
- name: Test
2221
working-directory: ./client
2322
run: |
24-
pip --version
25-
pip install --verbose .[${{ matrix.extras }}]
26-
python -m pytest --import-mode=importlib ./datalake/tests/
23+
pip install -e .[${{ matrix.extras }}]
24+
py.test
2725
test-docker:
2826
runs-on: ubuntu-latest
2927
steps:
3028
- name: Check out repository code
31-
uses: actions/checkout@v4
29+
uses: actions/checkout@v2
3230
with:
3331
fetch-depth: 0
3432
- name: Test

.gitignore

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,4 @@ target/
5858

5959
# build artifacts
6060
version.txt
61-
62-
# Claude Code
63-
.claude/
61+
.claude/settings.local.json

Dockerfile

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,29 @@ ENV LC_ALL C.UTF-8
77

88
# TODO: keep requirements in one place
99
RUN pip install \
10-
'blinker>=1.4' \
11-
'boto3==1.35.41' \
12-
'botocore==1.35.64' \
13-
'click>=5.1' \
14-
'datalake<2' \
15-
'Flask>=0.10.1' \
16-
'flask-swagger>=0.2.14' \
17-
'memoized_property>=1.0.1' \
18-
'pyinotify>=0.9.4' \
19-
'python-dateutil>=2.4.2' \
20-
'python-dotenv>=0.1.3' \
21-
'pytz>=2015.4' \
22-
'raven>=5.0.0' \
23-
'requests>=2.5' \
24-
'sentry-sdk[flask]>=0.19.5' \
25-
'simplejson>=3.3.1' \
26-
'six>=1.10.0' \
10+
blinker>=1.4 \
11+
boto3>=1.1.3 \
12+
click>=5.1 \
13+
Flask>=0.10.1 \
14+
flask-swagger>=0.2.14 \
15+
memoized_property>=1.0.1 \
16+
python-dateutil>=2.4.2 \
17+
python-dotenv>=0.1.3 \
18+
pytz>=2015.4 \
19+
sentry-sdk[flask]>=0.19.5 \
20+
requests>=2.5 \
21+
simplejson>=3.3.1 \
22+
six>=1.10.0 \
2723
# test requirements
2824
'flake8>=2.5.0,<4.1' \
2925
'freezegun<1' \
30-
'moto>=5,<6' \
26+
'moto<3' \
3127
'pytest<8' \
32-
'pytest-cov>=2.5.1,<4' \
33-
'pytest-xdist' \
3428
'responses<0.22.0' \
35-
'tox>4,<5'
36-
29+
pyinotify>=0.9.4, \
30+
raven>=5.0.0 \
31+
'tox>4,<5' \
32+
'datalake<2'
3733

3834
RUN mkdir -p /opt/
3935
COPY . /opt/

Makefile

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,13 @@ dev: docker
1212
docker run --rm -it -v $$PWD:/opt --entrypoint /bin/bash $(IMAGE)
1313

1414
test-client: docker
15-
docker run --rm -t --entrypoint tox $(IMAGE) -c /opt/client/tox.ini
15+
docker run --rm --entrypoint tox $(IMAGE) -c /opt/client/tox.ini
1616

1717
test-ingester: docker
18-
docker run --rm -t --entrypoint pytest $(IMAGE) /opt/ingester -svvx
18+
docker run --rm --entrypoint py.test $(IMAGE) ingester
1919

2020
test-api: docker
21-
docker run --rm -t --entrypoint pytest $(IMAGE) /opt/api -svvx
22-
23-
testp-client: docker
24-
docker run --rm -t --entrypoint /bin/bash $(IMAGE) -c "cd /opt/client && pytest -svvx -n auto"
25-
26-
testp-ingester: docker
27-
docker run --rm -t --entrypoint pytest $(IMAGE) /opt/ingester -svvx -n auto
28-
29-
testp-api: docker
30-
docker run --rm -t --entrypoint pytest $(IMAGE) /opt/api -svvx -n auto
21+
docker run --rm --entrypoint py.test $(IMAGE) api
3122

3223
.PHONY: test # Run the tests
3324
test:
@@ -36,18 +27,6 @@ test:
3627
$(MAKE) test-ingester
3728
$(MAKE) test-api
3829

39-
.PHONY: testp # Run all tests in parallel with pytest-xdist
40-
testp: docker
41-
docker run --rm -t --entrypoint /bin/bash $(IMAGE) -c "\
42-
set -e && \
43-
echo '==> Running client tests...' && \
44-
cd /opt/client && pytest -svvx -n auto && \
45-
echo '==> Running ingester tests...' && \
46-
cd /opt/ingester && pytest -svvx -n auto && \
47-
echo '==> Running API tests...' && \
48-
cd /opt/api && pytest -svvx -n auto && \
49-
echo '==> All tests passed!'"
50-
5130
.PHONY: push
5231
push:
5332
docker push $(IMAGE)

api/tests/conftest.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
ClientError as BotoClientError,
1919
NoCredentialsError
2020
)
21-
from moto import mock_aws
21+
from moto import mock_dynamodb2
2222

2323
from datalake_api import app as datalake_api
2424
from datalake.tests import * # noqa
@@ -33,27 +33,30 @@
3333
# This will cause moto to fail
3434
# But more critically, may impact production systems
3535
# So we test for real credentials and fail hard if they exist
36-
# Session fixture runs in pytest setup rather than at import time
37-
@pytest.fixture(scope='session', autouse=True)
38-
def verify_no_aws_credentials():
39-
sts = boto3.client('sts')
40-
try:
41-
sts.get_caller_identity()
42-
pytest.exit("Real AWS credentials detected, aborting", 3)
43-
except NoCredentialsError:
44-
pass
36+
sts = boto3.client('sts')
37+
try:
38+
sts.get_caller_identity()
39+
pytest.exit("Real AWS credentials detected, aborting", 3)
40+
except NoCredentialsError:
41+
pass # no credentials are good
4542

4643

4744
def get_client():
4845
from datalake_api import settings
4946
datalake_api.app.config.from_object(settings)
5047

5148
datalake_api.app.config['TESTING'] = True
52-
datalake_api.app.config['AWS_REGION'] = 'us-east-1'
5349
datalake_api.app.config['AWS_ACCESS_KEY_ID'] = 'abc'
5450
datalake_api.app.config['AWS_SECRET_ACCESS_KEY'] = '123'
5551

56-
for a in ('archive_fetcher', 's3_bucket', 'dynamodb'):
52+
# TODO: Sigh. The api caches the archive_fetcher and s3_bucket, which is
53+
# the right thing. However, because moto<3 still uses httpretty, and
54+
# because httpretty wreaks havoc on the python socket code, these cached
55+
# parts end up in a bad state after their first use. The right thing to do
56+
# here is to upgrade moto. But for that we will also have to move
57+
# everything from boto to boto3. This is a near-term goal. But first lets
58+
# get everything off of python2.
59+
for a in ('archive_fetcher', 's3_bucket'):
5760
try:
5861
delattr(datalake_api.app, a)
5962
except AttributeError:
@@ -68,15 +71,15 @@ def client():
6871

6972
@pytest.fixture
7073
def dynamodb(request):
71-
mock = mock_aws()
74+
mock = mock_dynamodb2()
7275
mock.start()
7376

7477
def tear_down():
7578
mock.stop()
7679
request.addfinalizer(tear_down)
7780

7881
return boto3.resource('dynamodb',
79-
region_name='us-east-1',
82+
region_name='us-west-2',
8083
aws_secret_access_key='123',
8184
aws_access_key_id='abc')
8285

client/datalake/tests/conftest.py

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

2121

2222
try:
23-
from moto import mock_aws
23+
from moto import mock_s3
2424
import boto3
2525
from six.moves.urllib.parse import urlparse
2626
import json
@@ -125,8 +125,24 @@ def get_tmpfile(content):
125125

126126

127127
@pytest.fixture
128-
def s3_connection():
129-
with mock_aws():
128+
def aws_connector(request):
129+
130+
def create_connection(mocker, connector):
131+
mock = mocker()
132+
mock.start()
133+
134+
def tear_down():
135+
mock.stop()
136+
request.addfinalizer(tear_down)
137+
138+
return connector()
139+
140+
return create_connection
141+
142+
143+
@pytest.fixture
144+
def s3_connection(aws_connector):
145+
with mock_s3():
130146
yield boto3.resource('s3')
131147

132148

client/pyproject.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ classifiers = [
2121
"Programming Language :: Python :: 3",
2222
]
2323
dependencies = [
24-
'boto3==1.35.41',
25-
'botocore==1.35.64',
24+
'boto3>=1.9.68',
2625
'memoized_property>=1.0.1',
2726
'pyblake2>=0.9.3; python_version<"3.6"',
2827
'click>=4.1',
@@ -38,7 +37,7 @@ dynamic = ["version"]
3837
test = [
3938
'pytest<8.0.0',
4039
'pytest-cov>=2.5.1,<4',
41-
'moto[s3]>5,<6',
40+
'moto[s3]>4,<5',
4241
'twine<4.0.0',
4342
'pip>=20.0.0,<22.0.0',
4443
'wheel<0.38.0',
@@ -74,7 +73,7 @@ distance-dirty = "{base_version}+{distance}.{vcs}{rev}.dirty"
7473
# Example formatted version: 1.2.3+42.ge174a1f.dirty
7574

7675
[tool.pytest.ini_options]
77-
addopts = "--cov=datalake --cov-config .coveragerc"
76+
addopts = "--cov=planet.mc_client --cov-config .coveragerc"
7877
markers = [
7978
"slow: marks tests as slow (deselect with '-m \"not slow\"')"
8079
]

ingester/datalake_ingester/queue.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# the License.
1414

1515
from memoized_property import memoized_property
16-
import boto3
16+
import boto.sqs
1717
import simplejson as json
1818
import logging
1919
import os
@@ -39,13 +39,16 @@ def set_handler(self, h):
3939
self.handler = h
4040

4141
@memoized_property
42-
def _connection(self):
43-
region = os.environ.get('AWS_REGION', 'us-east-1')
44-
return boto3.resource('sqs', region_name=region)
42+
def _queue(self):
43+
return self._connection.get_queue(self.queue_name)
4544

4645
@memoized_property
47-
def _queue(self):
48-
return self._connection.get_queue_by_name(QueueName=self.queue_name)
46+
def _connection(self):
47+
region = os.environ.get('AWS_REGION')
48+
if region:
49+
return boto.sqs.connect_to_region(region)
50+
else:
51+
return boto.connect_sqs()
4952

5053
_LONG_POLL_TIMEOUT = 20
5154

@@ -54,19 +57,17 @@ def drain(self, timeout=None):
5457
'''
5558
long_poll_timeout = timeout or self._LONG_POLL_TIMEOUT
5659
while True:
57-
messages = self._queue.receive_messages(
58-
MaxNumberOfMessages=1,
59-
WaitTimeSeconds=long_poll_timeout
60-
)
61-
if not messages:
60+
raw_msg = self._queue.read(wait_time_seconds=long_poll_timeout)
61+
if raw_msg is None:
6262
if timeout:
6363
return
6464
else:
6565
continue
66-
self._handle_raw_message(messages[0])
66+
self._handle_raw_message(raw_msg)
6767

6868
def _handle_raw_message(self, raw_msg):
69-
raw = raw_msg.body.replace('\n', ' ')
69+
# eliminate newlines in raw message so it all logs to one line
70+
raw = raw_msg.get_body().replace('\n', ' ')
7071
if not self.handler:
7172
self.logger.error('NO HANDLER CONFIGURED: %s', raw)
7273
return
@@ -75,4 +76,4 @@ def _handle_raw_message(self, raw_msg):
7576
msg = json.loads(raw)
7677

7778
self.handler(msg)
78-
raw_msg.delete()
79+
self._queue.delete_message(raw_msg)

ingester/datalake_ingester/reporter.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import boto3
1+
import boto.sns
22
import simplejson as json
33
import logging
44
from memoized_property import memoized_property
@@ -25,10 +25,13 @@ def _log_name(self):
2525

2626
@memoized_property
2727
def _connection(self):
28-
region = os.environ.get('AWS_REGION', 'us-east-1')
29-
return boto3.client('sns', region_name=region)
28+
region = os.environ.get('AWS_REGION')
29+
if region:
30+
return boto.sns.connect_to_region(region)
31+
else:
32+
return boto.connect_sns()
3033

3134
def report(self, ingestion_report):
3235
message = json.dumps(ingestion_report)
3336
self.logger.info('REPORTING: %s', message)
34-
self._connection.publish(TopicArn=self.report_key, Message=message)
37+
self._connection.publish(topic=self.report_key, message=message)

0 commit comments

Comments
 (0)