hswaw/kube: refactor

This breaks up hswaw.jsonnet into a component-per-file pattern.

Change-Id: I1b83d44146ae6c3d3f7c5d02abc2c9b764cc0e8e
diff --git a/hswaw/kube/hswaw.jsonnet b/hswaw/kube/hswaw.jsonnet
index e0b5432..905d964 100644
--- a/hswaw/kube/hswaw.jsonnet
+++ b/hswaw/kube/hswaw.jsonnet
@@ -1,191 +1,22 @@
 local mirko = import "../../kube/mirko.libsonnet";
 local kube = import "../../kube/kube.libsonnet";
 
+local smsgw = import "smsgw.libsonnet";
+local ldapweb = import "ldapweb.libsonnet";
+
 {
     hswaw(name):: mirko.Environment(name) {
         local env = self,
         local cfg = self.cfg,
 
         cfg+: {
-            smsgw: {
-                secret: {
-                    twilio_token: error "twilio_token must be set",
-                },
-                image: "registry.k0.hswaw.net/q3k/smsgs:1570049853-05c5b491c45de6d960979d4aee8635768f3178e9",
-                webhookFQDN: error "webhookFQDN must be set",
-            },
-            ldapweb: {
-                # Manually built from code.hackerspace.pl/q3k/ldap-web-public.
-                image: "registry.k0.hswaw.net/q3k/ldap-web:1571402374",
-
-                webFQDN: error "webFQDN must be set",
-            },
+            smsgw: smsgw.cfg,
+            ldapweb: ldapweb.cfg,
         },
 
         components: {
-            smsgw: mirko.Component(env, "smsgw") {
-                local smsgw = self,
-                cfg+: {
-                    image: cfg.smsgw.image,
-                    container: smsgw.GoContainer("main", "/smsgw/smsgw") {
-                        env_: {
-                            TWILIO_TOKEN: kube.SecretKeyRef(smsgw.secret, "twilio_token"),
-                        },
-                        command+: [
-                            "-twilio_friendly_phone", "48732168371",
-                            "-twilio_sid", "AC806ed4bf4b6c80c8f8ea686379b69518",
-                            "-twilio_token", "$(TWILIO_TOKEN)",
-                            "-webhook_listen", "0.0.0.0:5000",
-                            "-webhook_public", "https://%s/" % [ env.cfg.smsgw.webhookFQDN ],
-                        ],
-                    },
-                    ports+: {
-                        publicHTTP: {
-                            webhook: {
-                                port: 5000,
-                                dns: env.cfg.smsgw.webhookFQDN,
-                            }
-                        },
-                    },
-                },
-
-                secret: kube.Secret("smsgw") {
-                    metadata+: smsgw.metadata,
-                    data: env.cfg.smsgw.secret,
-                },
-
-                // Temporary machinery to access gRPC from outsite.
-                // In the future, this will be handled by a proxy/API gateway.
-                // For now, we need this running.
-                // TODO(q3k): remove this when we have an API GW or proxy.
-                stopgap: {
-                    local stopgap = self,
-
-                    rpcLB: kube.Service("smsgw-tcp-rpc") {
-                        metadata+: smsgw.metadata,
-                        target_pod: smsgw.deployment.spec.template,
-                        spec+: {
-                            type: "LoadBalancer",
-                            ports: [
-                                { name: "grpc-external", port: 443, targetPort: 4200 },
-                            ],
-                        },
-                    },
-
-                    mkClientCert(name, cn):: kube.Certificate(name) {
-                        metadata+: smsgw.metadata,
-                        spec: {
-                            secretName: name,
-                            duration: "35040h0m0s", // 4 years
-                            issuerRef: {
-                                // Contract with cluster/lib/pki.libsonnet.
-                                // Copied over.
-                                name: "pki-ca",
-                                kind: "ClusterIssuer",
-                            },
-                            commonName: cn,
-                        },
-                    },
-
-                    kasownikCert: stopgap.mkClientCert("smsgw-tcp-rpc-consumer", "kasownik.external.hswaw.net"),
-                    piorekfCert: stopgap.mkClientCert("smsgw-tcp-rpc-piorekf", "piorekf.person.hswaw.net"),
-                }
-            },
-
-            ldapweb: mirko.Component(env, "ldapweb") {
-                local ldapweb = self,
-                cfg+: {
-                    image: cfg.ldapweb.image,
-                    volumes+: {
-                        config: kube.ConfigMapVolume(ldapweb.configmap),
-                    },
-                    container: ldapweb.Container("main") {
-                        # Starts by default on port 8000.
-                        volumeMounts_+: {
-                            config: { mountPath: "/app/webapp/config.py", subPath: "config.py", },
-                        },
-                    },
-                    ports+: {
-                        publicHTTP: {
-                            web: {
-                                port: 8000,
-                                dns: env.cfg.ldapweb.webFQDN,
-                            },
-                        },
-                    },
-                },
-
-                configmap: kube.ConfigMap(ldapweb.makeName("config")) {
-                    metadata+: ldapweb.metadata,
-                    data: {
-                        "config.py": |||
-                            # -*- coding: utf-8 -*-
-                            import flask_wtf
-                            import wtforms
-                            ldap_url = 'ldap://ldap.hackerspace.pl'
-                            dn_format = "uid=%s,ou=people,dc=hackerspace,dc=pl" 
-                            
-                            admin_dn = 'cn=ldapweb,ou=Services,dc=hackerspace,dc=pl'
-                            admin_pw = 'unused'
-                            
-                            hackerspace_name = 'Warsaw Hackerspace'
-                            
-                            readable_names = {
-                                'commonname': u'Common Name',
-                                'givenname': u'Given Name',
-                                'gecos': u'GECOS (public name)',
-                                'surname': u'Surname',
-                                'loginshell': u'Shell',
-                                'telephonenumber': 'Phone Number',
-                                'mobiletelephonenumber': 'Mobile Number',
-                                'sshpublickey': 'SSH Public Key',
-                            }
-                            
-                            full_name = {
-                                'cn': 'commonname',
-                                'gecos': 'gecos',
-                                'sn': 'surname',
-                                'mobile': 'mobiletelephonenumber',
-                                'l': 'locality',
-                            }
-                            
-                            can_add = set([
-                                'telephonenumber',
-                                'mobiletelephonenumber',
-                                'sshpublickey',
-                            ])
-                            can_delete = can_add 
-                            can_modify = can_add | set([
-                                'givenname', 'surname', 'commonname', 'gecos',
-                            ])
-                            can = { 'add':can_add, 'mod':can_modify, 'del':can_delete }
-                            admin_required = set()
-                            
-                            
-                            perm_errors = {
-                                    'add': 'You cannot add this attribute!',
-                                    'mod': 'You cannot change this attribute!',
-                                    'del': 'You cannot delete this attribute!',
-                                    }
-                            std_templates = {
-                                    'add': 'ops/add.html',
-                                    'mod': 'ops/mod.html',
-                                    'del': 'ops/del.html',
-                                    }
-                            
-                            
-                            
-                            default_field = (wtforms.fields.StringField, {})
-                            fields = { 'telephonenumber': (wtforms.fields.StringField, {'validators': [wtforms.validators.Regexp(r'[+0-9 ]+')]})}
-                            
-                            kadmin_passwd = True
-                            kadmin_principal_map = "{}@HACKERSPACE.PL"
-                            
-                            TOKEN_LENGTH = 32
-                        |||,
-                    },
-                },
-            },
+            smsgw: smsgw.component(cfg.smsgw, env),
+            ldapweb: ldapweb.component(cfg.ldapweb, env),
         },
     },
 
diff --git a/hswaw/kube/ldapweb.libsonnet b/hswaw/kube/ldapweb.libsonnet
new file mode 100644
index 0000000..af6320b
--- /dev/null
+++ b/hswaw/kube/ldapweb.libsonnet
@@ -0,0 +1,105 @@
+local mirko = import "../../kube/mirko.libsonnet";
+local kube = import "../../kube/kube.libsonnet";
+
+{
+    cfg:: {
+        # Manually built from code.hackerspace.pl/q3k/ldap-web-public.
+        image: "registry.k0.hswaw.net/q3k/ldap-web:1571402374",
+        webFQDN: error "webFQDN must be set!",
+    },
+
+    component(cfg, env): mirko.Component(env, "ldapweb") {
+        local ldapweb = self,
+        cfg+: {
+            image: cfg.image,
+            volumes+: {
+                config: kube.ConfigMapVolume(ldapweb.configmap),
+            },
+            container: ldapweb.Container("main") {
+                # Starts by default on port 8000.
+                volumeMounts_+: {
+                    config: { mountPath: "/app/webapp/config.py", subPath: "config.py", },
+                },
+            },
+            ports+: {
+                publicHTTP: {
+                    web: {
+                        port: 8000,
+                        dns: cfg.webFQDN,
+                    },
+                },
+            },
+        },
+
+        configmap: kube.ConfigMap(ldapweb.makeName("config")) {
+            metadata+: ldapweb.metadata,
+            data: {
+                "config.py": |||
+                    # -*- coding: utf-8 -*-
+                    import flask_wtf
+                    import wtforms
+                    ldap_url = 'ldap://ldap.hackerspace.pl'
+                    dn_format = "uid=%s,ou=people,dc=hackerspace,dc=pl" 
+                    
+                    admin_dn = 'cn=ldapweb,ou=Services,dc=hackerspace,dc=pl'
+                    admin_pw = 'unused'
+                    
+                    hackerspace_name = 'Warsaw Hackerspace'
+                    
+                    readable_names = {
+                        'commonname': u'Common Name',
+                        'givenname': u'Given Name',
+                        'gecos': u'GECOS (public name)',
+                        'surname': u'Surname',
+                        'loginshell': u'Shell',
+                        'telephonenumber': 'Phone Number',
+                        'mobiletelephonenumber': 'Mobile Number',
+                        'sshpublickey': 'SSH Public Key',
+                    }
+                    
+                    full_name = {
+                        'cn': 'commonname',
+                        'gecos': 'gecos',
+                        'sn': 'surname',
+                        'mobile': 'mobiletelephonenumber',
+                        'l': 'locality',
+                    }
+                    
+                    can_add = set([
+                        'telephonenumber',
+                        'mobiletelephonenumber',
+                        'sshpublickey',
+                    ])
+                    can_delete = can_add 
+                    can_modify = can_add | set([
+                        'givenname', 'surname', 'commonname', 'gecos',
+                    ])
+                    can = { 'add':can_add, 'mod':can_modify, 'del':can_delete }
+                    admin_required = set()
+                    
+                    
+                    perm_errors = {
+                            'add': 'You cannot add this attribute!',
+                            'mod': 'You cannot change this attribute!',
+                            'del': 'You cannot delete this attribute!',
+                            }
+                    std_templates = {
+                            'add': 'ops/add.html',
+                            'mod': 'ops/mod.html',
+                            'del': 'ops/del.html',
+                            }
+                    
+                    
+                    
+                    default_field = (wtforms.fields.StringField, {})
+                    fields = { 'telephonenumber': (wtforms.fields.StringField, {'validators': [wtforms.validators.Regexp(r'[+0-9 ]+')]})}
+                    
+                    kadmin_passwd = True
+                    kadmin_principal_map = "{}@HACKERSPACE.PL"
+                    
+                    TOKEN_LENGTH = 32
+                |||,
+            },
+        },
+    },
+}
diff --git a/hswaw/kube/smsgw.libsonnet b/hswaw/kube/smsgw.libsonnet
new file mode 100644
index 0000000..a35b892
--- /dev/null
+++ b/hswaw/kube/smsgw.libsonnet
@@ -0,0 +1,81 @@
+local mirko = import "../../kube/mirko.libsonnet";
+local kube = import "../../kube/kube.libsonnet";
+
+{
+    cfg:: {
+        secret: {
+            twilio_token: error "twilio_token must be set",
+        },
+        image: "registry.k0.hswaw.net/q3k/smsgs:1570049853-05c5b491c45de6d960979d4aee8635768f3178e9",
+        webhookFQDN: error "webhookFQDN must be set",
+    },
+
+    component(cfg, env):: mirko.Component(env, "smsgw") {
+        local smsgw = self,
+        cfg+: {
+            image: cfg.image,
+            container: smsgw.GoContainer("main", "/smsgw/smsgw") {
+                env_: {
+                    TWILIO_TOKEN: kube.SecretKeyRef(smsgw.secret, "twilio_token"),
+                },
+                command+: [
+                    "-twilio_friendly_phone", "48732168371",
+                    "-twilio_sid", "AC806ed4bf4b6c80c8f8ea686379b69518",
+                    "-twilio_token", "$(TWILIO_TOKEN)",
+                    "-webhook_listen", "0.0.0.0:5000",
+                    "-webhook_public", "https://%s/" % [ cfg.webhookFQDN ],
+                ],
+            },
+            ports+: {
+                publicHTTP: {
+                    webhook: {
+                        port: 5000,
+                        dns: cfg.webhookFQDN,
+                    }
+                },
+            },
+        },
+
+        secret: kube.Secret("smsgw") {
+            metadata+: smsgw.metadata,
+            data: cfg.secret,
+        },
+
+        // Temporary machinery to access gRPC from outsite.
+        // In the future, this will be handled by a proxy/API gateway.
+        // For now, we need this running.
+        // TODO(q3k): remove this when we have an API GW or proxy.
+        stopgap: {
+            local stopgap = self,
+
+            rpcLB: kube.Service("smsgw-tcp-rpc") {
+                metadata+: smsgw.metadata,
+                target_pod: smsgw.deployment.spec.template,
+                spec+: {
+                    type: "LoadBalancer",
+                    ports: [
+                        { name: "grpc-external", port: 443, targetPort: 4200 },
+                    ],
+                },
+            },
+
+            mkClientCert(name, cn):: kube.Certificate(name) {
+                metadata+: smsgw.metadata,
+                spec: {
+                    secretName: name,
+                    duration: "35040h0m0s", // 4 years
+                    issuerRef: {
+                        // Contract with cluster/lib/pki.libsonnet.
+                        // Copied over.
+                        name: "pki-ca",
+                        kind: "ClusterIssuer",
+                    },
+                    commonName: cn,
+                },
+            },
+
+            kasownikCert: stopgap.mkClientCert("smsgw-tcp-rpc-consumer", "kasownik.external.hswaw.net"),
+            piorekfCert: stopgap.mkClientCert("smsgw-tcp-rpc-piorekf", "piorekf.person.hswaw.net"),
+        }
+    },
+}