Skip to content

Commit

Permalink
Merge pull request #38 from mozilla/34-heartbeat-views
Browse files Browse the repository at this point in the history
Add heartbeat and lbheartbeat endpoints.
  • Loading branch information
Natim committed Aug 8, 2017
2 parents bd848f6 + d8c7c70 commit 320624b
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 5 deletions.
12 changes: 11 additions & 1 deletion pollbot/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,20 @@ def get_app(loop=None):
)
})

# Home
cors.add(app.router.add_get('/', home.redirect)) # Redirects to /v1/
cors.add(app.router.add_get('/v1', home.redirect)) # Redirects to /v1/
cors.add(app.router.add_get('/contribute.json', utilities.contribute_json))
cors.add(app.router.add_get('/v1/', home.index))

# Utilities
cors.add(app.router.add_get('/contribute.json', utilities.contribute_json))
cors.add(app.router.add_get('/v1/__api__', utilities.oas_spec))

# Heartbeat
cors.add(app.router.add_get('/v1/__heartbeat__', utilities.heartbeat))
cors.add(app.router.add_get('/v1/__lbheartbeat__', utilities.lbheartbeat))

# Statuses
cors.add(app.router.add_get('/v1/{product}/{version}/archive', release.archive))
cors.add(app.router.add_get('/v1/{product}/{version}/bedrock/release-notes',
release.bedrock_release_notes))
Expand All @@ -40,6 +49,7 @@ def get_app(loop=None):
cors.add(app.router.add_get('/v1/{product}/{version}/product-details',
release.product_details))

# Swagger UI and documentation
setup_swagger(app,
swagger_url="/v1/api/doc",
swagger_from_file=os.path.join(HERE, "api.yaml"))
Expand Down
1 change: 1 addition & 0 deletions pollbot/middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async def handle_404(request, response):


async def handle_500(request, response=None, error=None):
logger.error(error)
return web.json_response({
"status": 503,
"message": "Service currently unavailable"
Expand Down
10 changes: 10 additions & 0 deletions pollbot/tasks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,13 @@ def get_session():
"User-Agent": "PollBot/{} aiohttp/{} python/{}".format(
pollbot_version, aiohttp_version, python_version)
})


def heartbeat_factory(url):
async def heartbeat():
with get_session() as session:
async with session.get(url, timeout=10) as resp:
if resp.status == 200:
return True
return False
return heartbeat
5 changes: 4 additions & 1 deletion pollbot/tasks/archives.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from . import get_session
from . import get_session, heartbeat_factory


async def archives(product, version):
with get_session() as session:
url = 'https://archive.mozilla.org/pub/{}/releases/{}/'.format(product, version)
async with session.get(url) as resp:
return resp.status != 404


heartbeat = heartbeat_factory('https://archive.mozilla.org/pub/firefox/releases/')
5 changes: 4 additions & 1 deletion pollbot/tasks/bedrock.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pyquery import PyQuery as pq
from pollbot.exceptions import TaskError
from pollbot.utils import build_version_id
from . import get_session
from . import get_session, heartbeat_factory


async def release_notes(product, version):
Expand Down Expand Up @@ -37,3 +37,6 @@ async def download_links(product, version):
d = pq(body)
last_release = d("html").attr('data-latest-firefox')
return build_version_id(last_release) >= build_version_id(version)


heartbeat = heartbeat_factory('https://www.mozilla.org/en-US/firefox/all/')
5 changes: 4 additions & 1 deletion pollbot/tasks/product_details.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pollbot.exceptions import TaskError

from . import get_session
from . import get_session, heartbeat_factory


async def product_details(product, version):
Expand All @@ -12,3 +12,6 @@ async def product_details(product, version):
raise TaskError(msg)
body = await resp.json()
return '{}-{}'.format(product, version) in body['releases']


heartbeat = heartbeat_factory('https://product-details.mozilla.org/1.0/firefox.json')
21 changes: 20 additions & 1 deletion pollbot/views/utilities.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import asyncio
import os.path

from aiohttp import web
import ruamel.yaml as yaml
from aiohttp import web

from pollbot.tasks import archives, bedrock, product_details


HERE = os.path.dirname(__file__)

Expand All @@ -18,3 +22,18 @@ async def oas_spec(request):

async def contribute_json(request):
return render_yaml_file("contribute.yaml")


async def lbheartbeat(request):
return web.json_response({"status": "running"})


async def heartbeat(request):
info = await asyncio.gather(archives.heartbeat(),
bedrock.heartbeat(),
product_details.heartbeat())
status = all(info) and 200 or 503
return web.json_response({"archive": info[0],
"bedrock": info[1],
"product-details": info[2]},
status=status)
22 changes: 22 additions & 0 deletions tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pollbot.tasks.archives import archives
from pollbot.tasks.bedrock import release_notes, security_advisories, download_links
from pollbot.tasks.product_details import product_details
from pollbot.views.utilities import heartbeat


class DeliveryTasksTest(asynctest.TestCase):
Expand Down Expand Up @@ -134,3 +135,24 @@ async def test_product_details_tasks_returns_error_if_error(self):
with pytest.raises(TaskError) as excinfo:
await product_details('firefox', '54.0')
assert str(excinfo.value) == 'Product Details info not available (404)'

async def test_failing_heartbeat(self):
# Archive
url = 'https://archive.mozilla.org/pub/firefox/releases/'
self.mocked.get(url, status=404)

# Bedrock
url = 'https://www.mozilla.org/en-US/firefox/all/'
self.mocked.get(url, status=404)

# Product Details
url = 'https://product-details.mozilla.org/1.0/firefox.json'
self.mocked.get(url, status=404)

resp = await heartbeat(None)
assert json.loads(resp.body.decode()) == {
"archive": False,
"bedrock": False,
"product-details": False
}
assert resp.status == 503
17 changes: 17 additions & 0 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,20 @@ async def test_release_product_details(cli):
body={
"status": "exists"
})


# Utilities
async def test_lbheartbeat(cli):
await check_response(cli, "/v1/__lbheartbeat__",
body={
"status": "running"
})


async def test_heartbeat(cli):
await check_response(cli, "/v1/__heartbeat__",
body={
"archive": True,
"bedrock": True,
"product-details": True,
})

0 comments on commit 320624b

Please sign in to comment.