#! /usr/bin/env python3 # -*- coding: utf-8 -*- # vim:fenc=utf-8 # Copyright © 2020 Dominik Fleischmann dominik.fleischmann@canonical.com """Operator Charm main library.""" # Load modules from lib directory import logging import setuppath # noqa:F401 from ops.charm import CharmBase from ops.framework import StoredState from ops.main import main from ops.model import ActiveStatus, MaintenanceStatus import subprocess class SquidK8SCharm(CharmBase): """Class reprisenting this Operator charm.""" state = StoredState() def __init__(self, *args): """Initialize charm and configure states and events to observe.""" super().__init__(*args) # -- standard hook observation self.framework.observe(self.on.install, self.on_install) self.framework.observe(self.on.start, self.on_start) self.framework.observe(self.on.config_changed, self.on_config_changed) self.framework.observe(self.on.deleteurl_action, self.on_deleteurl_action) # -- initialize states -- self.state.set_default(installed=False) self.state.set_default(configured=False) self.state.set_default(started=False) def make_pod_spec(self): config = self.framework.model.config ports = [{"name": "squid", "containerPort": config["port"], "protocol": "TCP"}] spec = { "containers": [{ "name": self.framework.model.app.name, "image": config["image"], "ports": ports, }], } return spec def _apply_spec(self, spec): # Only apply the spec if this unit is a leader if self.framework.model.unit.is_leader(): self.framework.model.pod.set_spec(spec) self.state.spec = spec def on_install(self, event): """Handle install state.""" self.unit.status = MaintenanceStatus("Installing charm software") # Perform install tasks self.unit.status = MaintenanceStatus("Install complete") logging.info("Install of software complete") self.state.installed = True def on_config_changed(self, event): """Handle config changed.""" if not self.state.installed: logging.warning("Config changed called before install complete, deferring event: {}.".format(event.handle)) return if self.state.started: # Stop if necessary for reconfig logging.info("Stopping for configuration, event handle: {}".format(event.handle)) # Configure the software logging.info("Configuring") self.state.configured = True def on_start(self, event): """Handle start state.""" if not self.state.configured: logging.warning("Start called before configuration complete, deferring event: {}".format(event.handle)) return self.unit.status = MaintenanceStatus("Applying pod spec") # Start software new_pod_spec = self.make_pod_spec() self._apply_spec(new_pod_spec) self.unit.status = ActiveStatus("Unit is ready") self.state.started = True logging.info("Started") def on_deleteurl_action(self, event): """Handle the deleteurl action.""" url = event.params["url"] line_to_delete = "acl allowedurls dstdomain .{}".format(url) line_deleted = False with open("/etc/squid/squid.conf", "r") as f: lines = f.readlines() with open("/etc/squid/squid.conf", "w") as f: for line in lines: if line_to_delete not in line: f.write(line) else: line_deleted = True if line_deleted: event.set_results({"output": "URL deleted succesfully"}) subprocess.check_output("kill -HUP `cat /var/run/squid.pid`", shell=True) else: event.fail("No URL was deleted") if __name__ == "__main__": from ops.main import main main(SquidK8SCharm)