Skip to content

Commit

Permalink
fix bugs with frontend charm
Browse files Browse the repository at this point in the history
  • Loading branch information
omar-selo committed Jul 20, 2023
1 parent bce3ea3 commit ff3dac3
Showing 1 changed file with 79 additions and 25 deletions.
104 changes: 79 additions & 25 deletions frontend/charm/src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
"""Test Observer frontend charm."""

import logging
import sys
from typing import Tuple

import ops
from charms.nginx_ingress_integrator.v0.nginx_route import require_nginx_route
from ops.framework import StoredState
from ops.model import (
ActiveStatus,
BlockedStatus,
Expand All @@ -26,8 +26,6 @@
class TestObserverFrontendCharm(ops.CharmBase):
"""The frontend charm operates serving the frontend through nginx."""

_stored = StoredState()

def __init__(self, *args):
super().__init__(*args)
self.pebble_service_name = "test-observer-frontend"
Expand All @@ -48,8 +46,6 @@ def __init__(self, *args):
self._on_rest_api_relation_broken,
)

self._stored.set_default(backend_hostname=None, backend_port=None)

self._setup_ingress()

def _setup_ingress(self):
Expand Down Expand Up @@ -94,20 +90,12 @@ def _config_is_valid(self, config) -> Tuple[bool, str]:
def _on_rest_api_relation_update(self, event):
api_hostname = event.relation.data[event.app].get("hostname")
api_port = event.relation.data[event.app].get("port")
logger.debug(f"API hostname: {api_hostname} (app: {event.app})")

if self.unit.is_leader():
self._stored.backend_hostname = api_hostname
self._stored.backend_port = api_port

logger.debug(f"API hostname: {api_hostname}, port: {api_port} (app: {event.app})")
self._update_layer_and_restart(event)

def _on_rest_api_relation_broken(self, event):
logger.debug("REST API relation broken -> removing backend hostname")

if self.unit.is_leader():
self._stored.backend_hostname = None
self._stored.backend_port = None
logger.debug("REST API relation broken")
self._update_layer_and_restart(event)

def nginx_config(self, base_uri: str) -> str:
"""Return a config where the backend port `base_uri` is adjusted."""
Expand All @@ -132,30 +120,96 @@ def nginx_config(self, base_uri: str) -> str:
}}
"""

def nginx_503_config(self) -> str:
"""Return a config for the situation when the backend is not yet available."""
return """
server {
listen 80 default_server;
server_name _;
return 503;
error_page 503 @maintenance;
location @maintenance {
rewrite ^(.*)$ /503.html break;
root /usr/share/nginx/html;
}
}
"""

def html_503(self) -> str:
"""Return a 503 response page."""
return """
<html>
<head>
<title>503 Service Unavailable</title>
</head>
<body>
<h1>503 Service Unavailable</h1>
<p>Backend not yet configured.</p>
</body>
</html>
"""

def _update_layer_and_restart(self, event):
self.unit.status = MaintenanceStatus(f"Updating {self.pebble_service_name} layer")

api_relation = next(iter(self.model.relations["test-observer-rest-api"]), None)

if api_relation is None:
if self.container.can_connect():
self.container.add_layer(
self.pebble_service_name, self._pebble_layer, combine=True
)
self.container.push(
"/etc/nginx/sites-available/test-observer-frontend",
self.nginx_503_config(),
make_dirs=True,
)
self.container.push(
"/usr/share/nginx/html/503.html",
self.html_503(),
make_dirs=True,
)
self.container.restart(self.pebble_service_name)
self.unit.status = MaintenanceStatus(
"test-observer-rest-api relation not connected."
)
else:
self.unit.status = WaitingStatus(
"Waiting for Pebble for API to set maintenance state"
)

return

relation_data = api_relation.data[api_relation.app]
if not relation_data:
self.unit.status = WaitingStatus("Waiting for test observer api relation data")
sys.exit()

hostname = api_relation.data[api_relation.app]["hostname"]
port = api_relation.data[api_relation.app]["port"]

scheme = self.config["test-observer-api-scheme"]
hostname = self._stored.backend_hostname
port = self._stored.backend_port

logger.info(f"Hostname: {hostname} (from relation: {hostname})")
logger.info(f"Port: {port} (from relation: {port})")

if int(port) == 80 or int(port) == 443:
base_uri = f"{scheme}{hostname}"
else:
base_uri = f"{scheme}{hostname}:{port}"

self.container.push(
"/etc/nginx/sites-available/test-observer-frontend",
self.nginx_config(base_uri=base_uri),
make_dirs=True,
)

if self.container.can_connect():
self.container.add_layer(self.pebble_service_name, self._pebble_layer, combine=True)
self.container.push(
"/etc/nginx/sites-available/test-observer-frontend",
self.nginx_config(base_uri=base_uri),
make_dirs=True,
)
self.container.restart(self.pebble_service_name)
self.unit.status = ActiveStatus()
else:
self.unit.status = WaitingStatus("Waiting for Pebble for API")
self.unit.status = WaitingStatus("Waiting for Pebble for API to set available state")

@property
def _pebble_layer(self):
Expand Down

0 comments on commit ff3dac3

Please sign in to comment.