launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #29797
[Merge] ~cjwatson/launchpad-layers:cron-support into launchpad-layers:main
Colin Watson has proposed merging ~cjwatson/launchpad-layers:cron-support into launchpad-layers:main.
Commit message:
Support crontab handling
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/launchpad-layers/+git/launchpad-layers/+merge/439398
Add a `configure_cron` function that sets up a crontab from a template.
Launchpad's crontabs generally include a call to `oops-datedir2amqp` to catch up with publishing OOPSes that were temporarily spooled to disk. This needs a bit of extra support in building the config dictionary, since it needs RabbitMQ credentials in a different form.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/launchpad-layers:cron-support into launchpad-layers:main.
diff --git a/launchpad-base/config.yaml b/launchpad-base/config.yaml
index 868c93b..3fa13a5 100644
--- a/launchpad-base/config.yaml
+++ b/launchpad-base/config.yaml
@@ -43,6 +43,10 @@ options:
type: string
description: URL of file used to control whether cron scripts run.
default: "file:cronscripts.ini"
+ cron_mailto:
+ type: string
+ description: Email address for output from cron jobs.
+ default: "error-reports@xxxxxxxxxxxxxx"
databases:
type: string
description: >
diff --git a/launchpad-base/lib/charms/launchpad/base.py b/launchpad-base/lib/charms/launchpad/base.py
index 2a182fe..1fb2815 100644
--- a/launchpad-base/lib/charms/launchpad/base.py
+++ b/launchpad-base/lib/charms/launchpad/base.py
@@ -5,10 +5,13 @@ import grp
import os.path
import pwd
import re
+import subprocess
from dataclasses import dataclass
from email.utils import parseaddr
+from urllib.parse import urlparse
from charmhelpers.core import hookenv, host, templating
+from charms.reactive import endpoint_from_flag
from ols import base
from psycopg2.extensions import make_dsn, parse_dsn
@@ -36,6 +39,15 @@ def ensure_lp_directories():
host.mkdir(home_dir(), owner=base.user(), group=base.user(), perms=0o755)
+def _get_first_rabbitmq_hostname(rabbitmq):
+ for conversation in rabbitmq.conversations():
+ for relation_id in conversation.relation_ids:
+ for unit in hookenv.related_units(relation_id):
+ return hookenv.relation_get(
+ "private-address", unit, relation_id
+ )
+
+
def get_service_config():
config = dict(hookenv.config())
config.update(
@@ -51,6 +63,34 @@ def get_service_config():
"var_dir": var_dir(),
}
)
+
+ # oops-datedir2amqp is used in crontabs and needs broken-out RabbitMQ
+ # credentials. This isn't ideal because it doesn't support high
+ # availability, but we can tolerate that for fallback OOPS publishing
+ # for now.
+ if config["rabbitmq_broker_urls"]:
+ rabbitmq_url = urlparse(config["rabbitmq_broker_urls"].split()[0])
+ config.update(
+ {
+ "rabbitmq_host": rabbitmq_url.hostname,
+ "rabbitmq_password": rabbitmq_url.password,
+ "rabbitmq_username": rabbitmq_url.username,
+ "rabbitmq_vhost": rabbitmq_url.path.lstrip("/"),
+ }
+ )
+ else:
+ rabbitmq = endpoint_from_flag("rabbitmq.available")
+ hostname = _get_first_rabbitmq_hostname(rabbitmq)
+ if hostname is not None:
+ config.update(
+ {
+ "rabbitmq_host": hostname,
+ "rabbitmq_password": rabbitmq.password(),
+ "rabbitmq_username": rabbitmq.username(),
+ "rabbitmq_vhost": rabbitmq.vhost(),
+ }
+ )
+
return config
@@ -192,3 +232,19 @@ def strip_dsn_authentication(dsn):
parsed_dsn = parse_dsn(dsn)
parsed_dsn.pop("password", None)
return make_dsn(**parsed_dsn)
+
+
+def configure_cron(config, template):
+ hookenv.log("Writing crontab.")
+ crontab_path = os.path.join(home_dir(), "crontab")
+ templating.render(
+ template,
+ crontab_path,
+ config,
+ owner=base.user(),
+ group=base.user(),
+ perms=0o600,
+ )
+ subprocess.run(
+ ["sudo", "-H", "-u", base.user(), "crontab", crontab_path], check=True
+ )
Follow ups