blob: 8828b49424125d23a7c0981ac51d49b2129fb960 [file] [log] [blame]
Serge Bazanski1572e522020-12-03 23:19:28 +01001local kube = import "../../../kube/kube.libsonnet";
2
3{
4 local wow = self,
5 local cfg = wow.cfg,
6 local ns = wow.ns,
7 cfg:: {
8 namespace: error "namespace must be set",
9 prefix: "",
10 images: {
11 acore: "registry.k0.hswaw.net/q3k/azerothcore-wowtlk:1606950998",
Serge Bazanski7ea8e472020-12-04 10:48:37 +010012 panel: "registry.k0.hswaw.net/q3k/panel:1607075221-54d0e977e57cc2c8d949c3a7ecf2ff21abd9d143",
Serge Bazanski1572e522020-12-03 23:19:28 +010013 },
14 db: {
15 local mkConfig = function(name) {
16 host: error ("db.%s.host must be set" % [name]),
17 port: error ("db.%s.prt must be set" % [name]),
18 user: error ("db.%s.user must be set" % [name]),
19 password: error ("db.%s.password must be set" % [name]),
20 database: "acore_%s" % [name],
21 },
22 auth: mkConfig("auth"),
23 world: mkConfig("world"),
24 characters: mkConfig("characters"),
25 },
26 panel: {
27 domain: error "panel.domain must be set",
28 soap: {
29 username: error "panel.soap.username must be set",
30 password: error "panel.soap.password must be set",
31 },
32 secret: error "panel.secret must be set",
33 oauth: {
34 clientID: error "panel.oauth.clientID must set",
35 clientSecret: error "panel.oauth.clientSecret must set",
36 redirectURL: "https://%s/callback" % [cfg.panel.domain],
37 },
38 motd: "",
39 },
40 overrides: {
41 authserver: {},
42 worldserver: {},
43 ahbot: {},
44 },
45 },
46
47 ns: kube.Namespace(cfg.namespace),
48
49 data: ns.Contain(kube.PersistentVolumeClaim(cfg.prefix + "data")) {
50 spec+: {
51 storageClassName: "waw-hdd-redundant-3",
52 accessModes: ["ReadWriteOnce"],
53 resources: {
54 requests: {
55 storage: "50Gi",
56 },
57 },
58 },
59 },
60
61 // Make a *DatabaseInfo string for use by acore config. These are not any real
62 // standardized DSN format, just some semicolon-delimited proprietary format.
63 local mkDbString = function(config) (
64 "%s;%d;%s;%s;%s" % [
65 config.host,
66 config.port,
67 config.user,
68 config.password,
69 config.database,
70 ]
71 ),
72
73 etc: ns.Contain(kube.Secret(cfg.prefix + "etc")) {
74 data: {
75 "worldserver.conf": std.base64(std.manifestIni({
76 sections: {
77 worldserver: {
78 RealmID: 1,
79 DataDir: "/data/current",
80 LoginDatabaseInfo: mkDbString(cfg.db.auth),
81 WorldDatabaseInfo: mkDbString(cfg.db.world),
82 CharacterDatabaseInfo: mkDbString(cfg.db.characters),
83 LogLevel: 2,
84
85 "Console.Enable": 0,
86 "Ra.Enable": 1,
87 "Ra.IP": "127.0.0.1",
88 "SOAP.Enabled": 1,
89 "SOAP.IP": "0.0.0.0",
90
91 } + cfg.overrides.worldserver,
92
93 },
94 })),
95 "mod_ahbot.conf": std.base64(std.manifestIni({
96 sections: {
97 worldserver: cfg.overrides.ahbot,
98 },
99 })),
100 "authserver.conf": std.base64(std.manifestIni({
101 sections: {
102 authserver: {
103 LoginDatabaseInfo: mkDbString(cfg.db.auth),
104 } + cfg.overrides.authserver,
105 },
106 })),
107 },
108 },
109
110 worldserverDeploy: ns.Contain(kube.Deployment(cfg.prefix + "worldserver")) {
111 spec+: {
112 template+: {
113 spec+: {
114 containers_: {
115 default: kube.Container("default") {
116 image: cfg.images.acore,
117 volumeMounts: [
118 { name: "data", mountPath: "/data" },
119 { name: "etc", mountPath: "/azeroth-server/etc/worldserver.conf", subPath: "worldserver.conf", },
120 { name: "etc", mountPath: "/azeroth-server/etc/mod_ahbot.conf", subPath: "mod_ahbot.conf", },
121 ],
122 command: [
123 "/entrypoint.sh",
124 "/azeroth-server/bin/worldserver",
125 ],
126 },
127 },
128 securityContext: {
129 runAsUser: 999,
130 runAsGroup: 999,
131 fsGroup: 999,
132 },
133 volumes_: {
134 data: kube.PersistentVolumeClaimVolume(wow.data),
135 etc: kube.SecretVolume(wow.etc),
136 },
137 },
138 },
139 },
140 },
141
142 authserverDeploy: ns.Contain(kube.Deployment(cfg.prefix + "authserver")) {
143 spec+: {
144 template+: {
145 spec+: {
146 containers_: {
147 default: kube.Container("default") {
148 image: cfg.images.acore,
149 volumeMounts_: {
150 etc: { mountPath: "/azeroth-server/etc/authserver.conf", subPath: "authserver.conf", },
151 },
152 command: [
153 "/azeroth-server/bin/authserver",
154 ],
155 },
156 },
157 securityContext: {
158 runAsUser: 999,
159 runAsGroup: 999,
160 },
161 volumes_: {
162 etc: kube.SecretVolume(wow.etc),
163 },
164 },
165 },
166 },
167 },
168
169 soapSvc: ns.Contain(kube.Service(cfg.prefix + "worldserver-soap")) {
170 target_pod:: wow.worldserverDeploy.spec.template,
171 spec+: {
172 ports: [
173 { name: "soap", port: 7878, targetPort: 7878, protocol: "TCP" },
174 ],
175 },
176 },
177 worldserverSvc: ns.Contain(kube.Service(cfg.prefix + "worldserver")) {
178 target_pod:: wow.worldserverDeploy.spec.template,
179 metadata+: {
180 annotations+: {
181 "metallb.universe.tf/allow-shared-ip": "%s/%ssvc" % [cfg.namespace, cfg.prefix],
182 },
183 },
184 spec+: {
185 ports: [
186 { name: "worldserver", port: 8085, targetPort: 8085, protocol: "TCP" },
187 ],
188 type: "LoadBalancer",
189 externalTrafficPolicy: "Cluster",
190 loadBalancerIP: cfg.address,
191 },
192 },
193 authserverSvc: ns.Contain(kube.Service(cfg.prefix + "authserver")) {
194 target_pod:: wow.authserverDeploy.spec.template,
195 metadata+: {
196 annotations+: {
197 "metallb.universe.tf/allow-shared-ip": "%s/%ssvc" % [cfg.namespace, cfg.prefix],
198 },
199 },
200 spec+: {
201 ports: [
202 { name: "authserver", port: 3724, targetPort: 3724, protocol: "TCP" },
203 ],
204 type: "LoadBalancer",
205 externalTrafficPolicy: "Cluster",
206 loadBalancerIP: cfg.address,
207 },
208 },
209
210 panelSecret: ns.Contain(kube.Secret(cfg.prefix + "panel-secret")) {
211 data+: {
212 soapPassword: std.base64(cfg.panel.soap.password),
213 secret: std.base64(cfg.panel.secret),
214 oauthSecret: std.base64(cfg.panel.oauth.clientSecret),
215 "motd.txt": std.base64(cfg.panel.motd),
216 },
217 },
218 panelData: ns.Contain(kube.PersistentVolumeClaim(cfg.prefix + "panel-data")) {
219 spec+: {
220 storageClassName: "waw-hdd-redundant-3",
221 accessModes: ["ReadWriteOnce"],
222 resources: {
223 requests: {
224 storage: "128Mi",
225 },
226 },
227 },
228 },
229 panelDeploy: ns.Contain(kube.Deployment(cfg.prefix + "panel")) {
230 spec+: {
231 template+: {
232 spec+: {
233 containers_: {
234 default: kube.Container("default") {
235 image: cfg.images.panel,
236 env_: {
237 SOAP_PASSWORD: kube.SecretKeyRef(wow.panelSecret, "soapPassword"),
238 SECRET: kube.SecretKeyRef(wow.panelSecret, "secret"),
239 OAUTH_SECRET: kube.SecretKeyRef(wow.panelSecret, "oauthSecret"),
240 },
241 command: [
242 "/personal/q3k/wow/panel/panel",
243 "-listen", "0.0.0.0:8080",
244 "-db", "/data/panel.db",
245 "-soap_address", "http://%s" % [wow.soapSvc.host_colon_port],
246 "-soap_password", "$(SOAP_PASSWORD)",
247 "-secret", "$(SECRET)",
248 "-oauth_client_id", cfg.panel.oauth.clientID,
249 "-oauth_client_secret", "$(OAUTH_SECRET)",
250 "-oauth_redirect_url", cfg.panel.oauth.redirectURL,
251 "-motd", "/secret/motd.txt",
252 ],
253 volumeMounts_: {
254 data: { mountPath: "/data" },
255 secret: { mountPath: "/secret" },
256 },
257 },
258 },
259 volumes_: {
260 data: kube.PersistentVolumeClaimVolume(wow.panelData),
261 secret: kube.SecretVolume(wow.panelSecret),
262 },
263 },
264 },
265 },
266 },
267 panelSvc: ns.Contain(kube.Service(cfg.prefix + "panel")) {
268 target_pod:: wow.panelDeploy.spec.template,
269 spec+: {
270 ports: [
271 { name: "web", port: 8080, targetPort: 8080, protocol: "TCP" },
272 ],
273 },
274 },
275 panelIngress: ns.Contain(kube.Ingress(cfg.prefix + "panel")) {
276 metadata+: {
277 annotations+: {
278 "kubernetes.io/tls-acme": "true",
279 "certmanager.k8s.io/cluster-issuer": "letsencrypt-prod",
280 },
281 },
282 spec+: {
283 tls: [
284 {
285 hosts: [cfg.panel.domain],
286 secretName: cfg.prefix + "panel-tls",
287 },
288 ],
289 rules: [
290 {
291 host: cfg.panel.domain,
292 http: {
293 paths: [
294 { path: "/", backend: wow.panelSvc.name_port },
295 ],
296 },
297 }
298 ],
299 },
300 },
301}