| local kube = import "../../../kube/hscloud.libsonnet"; |
| |
| { |
| local wow = self, |
| local cfg = wow.cfg, |
| local ns = wow.ns, |
| cfg:: { |
| namespace: error "namespace must be set", |
| prefix: "", |
| images: { |
| acore: "registry.k0.hswaw.net/q3k/azerothcore-wowtlk:1606950998", |
| panel: "registry.k0.hswaw.net/q3k/panel:1607075221-54d0e977e57cc2c8d949c3a7ecf2ff21abd9d143", |
| }, |
| db: { |
| local mkConfig = function(name) { |
| host: error ("db.%s.host must be set" % [name]), |
| port: error ("db.%s.prt must be set" % [name]), |
| user: error ("db.%s.user must be set" % [name]), |
| password: error ("db.%s.password must be set" % [name]), |
| database: "acore_%s" % [name], |
| }, |
| auth: mkConfig("auth"), |
| world: mkConfig("world"), |
| characters: mkConfig("characters"), |
| }, |
| panel: { |
| domain: error "panel.domain must be set", |
| soap: { |
| username: error "panel.soap.username must be set", |
| password: error "panel.soap.password must be set", |
| }, |
| secret: error "panel.secret must be set", |
| oauth: { |
| clientID: error "panel.oauth.clientID must set", |
| clientSecret: error "panel.oauth.clientSecret must set", |
| redirectURL: "https://%s/callback" % [cfg.panel.domain], |
| }, |
| motd: "", |
| }, |
| overrides: { |
| authserver: {}, |
| worldserver: {}, |
| ahbot: {}, |
| }, |
| }, |
| |
| ns: kube.Namespace(cfg.namespace), |
| |
| data: ns.Contain(kube.PersistentVolumeClaim(cfg.prefix + "data")) { |
| spec+: { |
| storageClassName: "waw-hdd-redundant-3", |
| accessModes: ["ReadWriteOnce"], |
| resources: { |
| requests: { |
| storage: "50Gi", |
| }, |
| }, |
| }, |
| }, |
| |
| // Make a *DatabaseInfo string for use by acore config. These are not any real |
| // standardized DSN format, just some semicolon-delimited proprietary format. |
| local mkDbString = function(config) ( |
| "%s;%d;%s;%s;%s" % [ |
| config.host, |
| config.port, |
| config.user, |
| config.password, |
| config.database, |
| ] |
| ), |
| |
| etc: ns.Contain(kube.Secret(cfg.prefix + "etc")) { |
| data: { |
| "worldserver.conf": std.base64(std.manifestIni({ |
| sections: { |
| worldserver: { |
| RealmID: 1, |
| DataDir: "/data/current", |
| LoginDatabaseInfo: mkDbString(cfg.db.auth), |
| WorldDatabaseInfo: mkDbString(cfg.db.world), |
| CharacterDatabaseInfo: mkDbString(cfg.db.characters), |
| LogLevel: 2, |
| |
| "Console.Enable": 0, |
| "Ra.Enable": 1, |
| "Ra.IP": "127.0.0.1", |
| "SOAP.Enabled": 1, |
| "SOAP.IP": "0.0.0.0", |
| |
| } + cfg.overrides.worldserver, |
| |
| }, |
| })), |
| "mod_ahbot.conf": std.base64(std.manifestIni({ |
| sections: { |
| worldserver: cfg.overrides.ahbot, |
| }, |
| })), |
| "authserver.conf": std.base64(std.manifestIni({ |
| sections: { |
| authserver: { |
| LoginDatabaseInfo: mkDbString(cfg.db.auth), |
| } + cfg.overrides.authserver, |
| }, |
| })), |
| }, |
| }, |
| |
| worldserverDeploy: ns.Contain(kube.Deployment(cfg.prefix + "worldserver")) { |
| spec+: { |
| template+: { |
| spec+: { |
| containers_: { |
| default: kube.Container("default") { |
| image: cfg.images.acore, |
| volumeMounts: [ |
| { name: "data", mountPath: "/data" }, |
| { name: "etc", mountPath: "/azeroth-server/etc/worldserver.conf", subPath: "worldserver.conf", }, |
| { name: "etc", mountPath: "/azeroth-server/etc/mod_ahbot.conf", subPath: "mod_ahbot.conf", }, |
| ], |
| command: [ |
| "/entrypoint.sh", |
| "/azeroth-server/bin/worldserver", |
| ], |
| }, |
| }, |
| securityContext: { |
| runAsUser: 999, |
| runAsGroup: 999, |
| fsGroup: 999, |
| }, |
| volumes_: { |
| data: kube.PersistentVolumeClaimVolume(wow.data), |
| etc: kube.SecretVolume(wow.etc), |
| }, |
| }, |
| }, |
| }, |
| }, |
| |
| authserverDeploy: ns.Contain(kube.Deployment(cfg.prefix + "authserver")) { |
| spec+: { |
| template+: { |
| spec+: { |
| containers_: { |
| default: kube.Container("default") { |
| image: cfg.images.acore, |
| volumeMounts_: { |
| etc: { mountPath: "/azeroth-server/etc/authserver.conf", subPath: "authserver.conf", }, |
| }, |
| command: [ |
| "/azeroth-server/bin/authserver", |
| ], |
| }, |
| }, |
| securityContext: { |
| runAsUser: 999, |
| runAsGroup: 999, |
| }, |
| volumes_: { |
| etc: kube.SecretVolume(wow.etc), |
| }, |
| }, |
| }, |
| }, |
| }, |
| |
| soapSvc: ns.Contain(kube.Service(cfg.prefix + "worldserver-soap")) { |
| target_pod:: wow.worldserverDeploy.spec.template, |
| spec+: { |
| ports: [ |
| { name: "soap", port: 7878, targetPort: 7878, protocol: "TCP" }, |
| ], |
| }, |
| }, |
| worldserverSvc: ns.Contain(kube.Service(cfg.prefix + "worldserver")) { |
| target_pod:: wow.worldserverDeploy.spec.template, |
| metadata+: { |
| annotations+: { |
| "metallb.universe.tf/allow-shared-ip": "%s/%ssvc" % [cfg.namespace, cfg.prefix], |
| }, |
| }, |
| spec+: { |
| ports: [ |
| { name: "worldserver", port: 8085, targetPort: 8085, protocol: "TCP" }, |
| ], |
| type: "LoadBalancer", |
| externalTrafficPolicy: "Cluster", |
| loadBalancerIP: cfg.address, |
| }, |
| }, |
| authserverSvc: ns.Contain(kube.Service(cfg.prefix + "authserver")) { |
| target_pod:: wow.authserverDeploy.spec.template, |
| metadata+: { |
| annotations+: { |
| "metallb.universe.tf/allow-shared-ip": "%s/%ssvc" % [cfg.namespace, cfg.prefix], |
| }, |
| }, |
| spec+: { |
| ports: [ |
| { name: "authserver", port: 3724, targetPort: 3724, protocol: "TCP" }, |
| ], |
| type: "LoadBalancer", |
| externalTrafficPolicy: "Cluster", |
| loadBalancerIP: cfg.address, |
| }, |
| }, |
| |
| panelSecret: ns.Contain(kube.Secret(cfg.prefix + "panel-secret")) { |
| data+: { |
| soapPassword: std.base64(cfg.panel.soap.password), |
| secret: std.base64(cfg.panel.secret), |
| oauthSecret: std.base64(cfg.panel.oauth.clientSecret), |
| "motd.txt": std.base64(cfg.panel.motd), |
| }, |
| }, |
| panelData: ns.Contain(kube.PersistentVolumeClaim(cfg.prefix + "panel-data")) { |
| spec+: { |
| storageClassName: "waw-hdd-redundant-3", |
| accessModes: ["ReadWriteOnce"], |
| resources: { |
| requests: { |
| storage: "128Mi", |
| }, |
| }, |
| }, |
| }, |
| panelDeploy: ns.Contain(kube.Deployment(cfg.prefix + "panel")) { |
| spec+: { |
| template+: { |
| spec+: { |
| containers_: { |
| default: kube.Container("default") { |
| image: cfg.images.panel, |
| env_: { |
| SOAP_PASSWORD: kube.SecretKeyRef(wow.panelSecret, "soapPassword"), |
| SECRET: kube.SecretKeyRef(wow.panelSecret, "secret"), |
| OAUTH_SECRET: kube.SecretKeyRef(wow.panelSecret, "oauthSecret"), |
| }, |
| command: [ |
| "/personal/q3k/wow/panel/panel", |
| "-listen", "0.0.0.0:8080", |
| "-db", "/data/panel.db", |
| "-soap_address", "http://%s" % [wow.soapSvc.host_colon_port], |
| "-soap_password", "$(SOAP_PASSWORD)", |
| "-secret", "$(SECRET)", |
| "-oauth_client_id", cfg.panel.oauth.clientID, |
| "-oauth_client_secret", "$(OAUTH_SECRET)", |
| "-oauth_redirect_url", cfg.panel.oauth.redirectURL, |
| "-motd", "/secret/motd.txt", |
| ], |
| volumeMounts_: { |
| data: { mountPath: "/data" }, |
| secret: { mountPath: "/secret" }, |
| }, |
| }, |
| }, |
| volumes_: { |
| data: kube.PersistentVolumeClaimVolume(wow.panelData), |
| secret: kube.SecretVolume(wow.panelSecret), |
| }, |
| }, |
| }, |
| }, |
| }, |
| panelSvc: ns.Contain(kube.Service(cfg.prefix + "panel")) { |
| target_pod:: wow.panelDeploy.spec.template, |
| spec+: { |
| ports: [ |
| { name: "web", port: 8080, targetPort: 8080, protocol: "TCP" }, |
| ], |
| }, |
| }, |
| panelIngress: ns.Contain(kube.SimpleIngress(cfg.prefix + "panel")) { |
| hosts:: [cfg.panel.domain], |
| target_service:: wow.panelSvc, |
| }, |
| } |