blob: 7906463921fdaaf54bf43eae6d2d53e6c347c0d5 [file] [log] [blame]
local kube = import "../../../kube/kube.libsonnet";
{
AppServiceIrc(name):: {
local bridge = self,
local cfg = bridge.cfg,
cfg:: {
metadata: {},
// Whether the bootstrap job should be created/updated. Kubernetes
// doesn't like changing the configuration of jobs, so once this
// appservice has been set up, this flag should be flipped to
// false.
bootstrapJob: true,
config: std.native("parseYaml")(importstr "appservice/appservice-irc.yaml")[0] {
local appservicecfg = self,
ircService+: {
[if cfg.passwordEncryptionKeySecret != null then "passwordEncryptionKeyPath"]: "/key/key.pem",
debugApi+: {
# Unfortunately, we have to enable the debugApi if any
# configured server wants to use
# ignoreIdleUsersOnStartup. This is seemingly an
# appservice-irc bug:
# https://github.com/matrix-org/matrix-appservice-irc/issues/1240
enabled: std.length(std.filter(
function (k) (
local v = appservicecfg.ircService.servers[k];
v.membershipLists.ignoreIdleUsersOnStartup.enabled == true
),
std.objectFields(appservicecfg.ircService.servers)
)) > 0,
},
},
},
image: error "image must be set",
storageClassName: error "storageClassName must be set",
# RSA encryption private key secret name containing "key.pem" key
# Create using:
# kubectl -n matrix create secret generic appservice-irc-password-encryption-key --from-file=key.pem=<(openssl genpkey -out - -outform PEM -algorithm RSA -pkeyopt rsa_keygen_bits:2048)
passwordEncryptionKeySecret: null,
},
config: kube.Secret("appservice-irc-%s" % [name]) {
metadata+: cfg.metadata,
data_: {
"config.yaml": std.manifestJsonEx(cfg.config, ""),
},
},
dataVolume: kube.PersistentVolumeClaim("appservice-irc-%s" % [name]) {
metadata+: cfg.metadata,
spec+: {
storageClassName: cfg.storageClassName,
accessModes: [ "ReadWriteOnce" ],
resources: {
requests: {
storage: "10Gi",
},
},
},
},
bootstrapJob: if cfg.bootstrapJob then (kube.Job("appservice-irc-%s-bootstrap" % [name]) {
metadata+: cfg.metadata {
labels: {
"job-name": "appservice-irc-%s-bootstrap" % [name],
},
},
spec+: {
template+: {
spec+: {
volumes_: {
config: kube.SecretVolume(bridge.config),
},
containers_: {
bootstrap: kube.Container("appservice-irc-%s-bootstrap" % [name]) {
image: cfg.image,
command: ["sh", "-c", "node app.js -r -u http://appservice-irc-%s:9999 -c /config/config.yaml -f /tmp/registration.yaml && cat /tmp/registration.yaml" % [name]],
volumeMounts_: {
config: { mountPath: "/config" },
},
},
},
},
},
},
}) else {},
deployment: kube.Deployment("appservice-irc-%s" % [name]) {
metadata+: cfg.metadata,
spec+: {
replicas: 1,
template+: {
spec+: {
volumes_: {
config: kube.SecretVolume(bridge.config),
data: kube.PersistentVolumeClaimVolume(bridge.dataVolume),
registration: { secret: { secretName: "appservice-irc-%s-registration" % [name] } },
} + (if cfg.passwordEncryptionKeySecret != null then {
key: { secret: { secretName: cfg.passwordEncryptionKeySecret } },
} else {}),
nodeSelector: cfg.nodeSelector,
containers_: {
appserviceIrc: kube.Container("appservice-irc-%s" % [name]) {
image: cfg.image,
command: ["node", "app.js", "-c", "/config/config.yaml", "-f", "/registration/registration.yaml", "-p", "9999"],
ports_: {
http: { containerPort: 9999 },
},
volumeMounts_: {
registration: { mountPath: "/registration", },
config: { mountPath: "/config", },
data: { mountPath: "/data" },
} + (if cfg.passwordEncryptionKeySecret != null then {
key: { mountPath: "/key" },
} else {}),
},
},
},
},
},
},
svc: kube.Service("appservice-irc-%s" % [name]) {
metadata+: cfg.metadata,
target_pod:: bridge.deployment.spec.template,
},
},
}