blob: 295cc3d42d8642e9c4695d1ab976a8ad9790c4a6 [file] [log] [blame]
local kube = import "../../../kube/hscloud.libsonnet";
{
IX: {
local ix = self,
local cfg = ix.cfg,
cfg:: {
image: "registry.k0.hswaw.net/bgpwtf/cccampix:1566584484-a2960f526c36de0dbcd911f05ee9db587e63eb9b",
octorpki: {
image: cfg.image,
storageClassName: "waw-hdd-redundant-2",
resources: {
requests: { cpu: "200m", memory: "1Gi" },
limits: { cpu: "1", memory: "2Gi" },
},
},
verifier: {
image: cfg.image,
domain: "ix-grpc.bgp.wtf",
db: {
host: "public.crdb-waw1.svc.cluster.local",
port: 26257,
username: "cccampix",
name: "cccampix",
tlsSecret: "client-cccampix-certificate",
},
},
pgpencryptor: {
image: cfg.image,
db: {
host: "public.crdb-waw1.svc.cluster.local",
port: 26257,
username: "cccampix",
name: "cccampix-pgpencryptor",
tlsSecret: "client-cccampix-certificate",
},
},
irr: {
image: cfg.image,
},
peeringdb: {
image: cfg.image,
},
frontend: {
domain: "ix-status.bgp.wtf",
image: cfg.image,
},
alice: {
domain: "ix-lg.bgp.wtf",
image: "registry.k0.hswaw.net/q3k/alice-lg:20190823-1557",
},
appName: "ix",
namespace: error "namespace must be defined",
prefix: "",
},
local ns = kube.Namespace(cfg.namespace),
name(component):: cfg.prefix + component,
metadata(component):: {
namespace: cfg.namespace,
labels: {
"app.kubernetes.io/name": cfg.appName,
"app.kubernetes.io/managed-by": "kubecfg",
"app.kubernetes.io/component": component,
},
},
octorpki: {
address:: "%s.%s.svc.cluster.local:%d" % [
"octorpki",
ix.cfg.namespace,
8080,
],
cache: kube.PersistentVolumeClaim(ix.name("octorpki")) {
metadata+: ix.metadata("octorpki"),
storage:: "2Gi",
storageClass:: cfg.octorpki.storageClassName,
},
deployment: kube.Deployment(ix.name("octorpki")) {
metadata+: ix.metadata("octorpki"),
spec+: {
template+: {
spec+: {
volumes_: {
cache: ix.octorpki.cache.volume,
},
containers_: {
octorpki: kube.Container(ix.name("octorpki")){
image: cfg.octorpki.image,
args: [
"/octorpki/entrypoint.sh",
],
ports_: {
client: { containerPort: 8080 },
},
volumeMounts_: {
cache: { mountPath: "/cache" },
},
resources: cfg.octorpki.resources,
},
},
},
},
},
},
svc: kube.Service(ix.name("octorpki")) {
metadata+: ix.metadata("octorpki"),
target:: ix.octorpki.deployment,
},
},
component(name):: {
local component = self,
args:: error "args must be set",
name:: name,
port:: 4200,
volumes:: {},
volumeMounts:: {},
deployment: kube.Deployment(ix.name(name)) {
metadata+: ix.metadata(name),
spec+: {
template+: {
spec+: {
volumes_: component.volumes,
containers_: {
[name]: kube.Container(ix.name(name)) {
image: cfg[name].image,
args: component.args,
volumeMounts_: component.volumeMounts,
},
},
},
},
},
},
svc: kube.Service(ix.name(name)) {
metadata+: ix.metadata(name),
target:: component.deployment,
spec+: {
ports: [
{ name: "client", port: component.port, targetPort: component.port, protocol: "TCP" },
],
},
},
address:: "%s.%s.svc.cluster.local:%d" % [
component.name,
ix.cfg.namespace,
component.port,
],
},
irr: ix.component("irr") {
args: [
"/ix/irr",
"-hspki_disable",
"-listen_address=0.0.0.0:4200",
],
},
peeringdb: ix.component("peeringdb") {
args: [
"/ix/peeringdb",
"-hspki_disable",
"-listen_address=0.0.0.0:4200",
],
},
crdb:: {
volumes: {
tls: {
secret: {
secretName: cfg.verifier.db.tlsSecret,
defaultMode: kube.parseOctal("0400"),
},
},
},
volumeMounts: {
tls: {
mountPath: "/tls",
},
},
args(dbconf): [
"-dsn", "postgres://%s@%s:%d/%s?sslmode=require&sslrootcert=%s&sslcert=%s&sslkey=%s" % [
dbconf.username,
dbconf.host,
dbconf.port,
dbconf.name,
"/tls/ca.crt",
"/tls/tls.crt",
"/tls/tls.key",
],
]
},
verifier: ix.component("verifier") {
volumes: ix.crdb.volumes,
volumeMounts: ix.crdb.volumeMounts,
args: [
"/ix/verifier",
"-hspki_disable",
"-listen_address=0.0.0.0:4200",
"-peeringdb=" + ix.peeringdb.address,
"-irr=" + ix.irr.address,
"-octorpki=" + ix.octorpki.address,
"-pgpencryptor=" + ix.pgpencryptor.address,
] + ix.crdb.args(cfg.verifier.db),
},
pgpencryptor: ix.component("pgpencryptor") {
volumes: ix.crdb.volumes,
volumeMounts: ix.crdb.volumeMounts,
args: [
"/ix/pgpencryptor",
"-hspki_disable",
"-listen_address=0.0.0.0:4200",
] + ix.crdb.args(cfg.pgpencryptor.db),
},
frontend: ix.component("frontend") {
port: 8080,
args: [
"/ix/frontend.par",
"--flask_secret=dupa",
"--listen=0.0.0.0:8080",
"--verifier=" + ix.verifier.address,
],
},
alice: ix.component("alice") {
port: 7340,
volumes: {
config: ix.alice.configMap.volume,
theme: ix.alice.themeMap.volume,
},
volumeMounts: {
config: {
mountPath: "/etc/alice",
},
theme: {
mountPath: "/etc/alice-theme",
},
},
args: [
"/usr/bin/alice-lg",
"-config", "/etc/alice/alice",
],
themeMap: kube.ConfigMap(ix.name("alice-theme")) {
metadata+: ix.metadata("alice-theme"),
data: {
"content.js": |||
Alice.updateContent({
header: {
title: "CCCampIX Looking Glass",
tagline: "powered by alice-lg"
},
welcome: {
title: "CCCampIX Looking Glass",
tagline: "BGP to the tent."
}
});
|||,
},
},
configMap: kube.ConfigMap(ix.name("alice")) {
metadata+: ix.metadata("alice"),
data: {
config: |||
[server]
listen_http = 0.0.0.0:7340
enable_neighbors_status_refresh = false
asn = 208521
[housekeeping]
interval = 5
force_release_memory = true
[theme]
path = /etc/alice-theme
[pagination]
routes_filtered_page_size = 250
routes_accepted_page_size = 250
routes_not_exported_page_size = 250
[rejection_reasons]
208521:65666:1 = An IP Bogon was detected
208521:65666:2 = Prefix is longer than 64
208521:65666:3 = Prefix is longer than 24
208521:65666:4 = AS path contains a bogon AS
208521:65666:5 = AS path length is longer than 64
208521:65666:6 = BGP Path invalid (must be only peer)
208521:65666:9 = Prefix not found in RPKI for Origin AS
[neighbours_columns]
Description = Description
address = Neighbour
asn = ASN
state = State
Uptime = Uptime
routes_received = Routes Received
routes_filtered = Filtered
[routes_columns]
network = Network
gateway = Gateway
interface = Interface
metric = Metric
bgp.as_path = AS Path
[lookup_columns]
network = Network
gateway = Gateway
neighbour.asn = ASN
neighbour.description = Description
bgp.as_path = AS Path
routeserver.name = RS
[source.rs1-camp-v4]
name = rs1.camp.bgp.wtf (IPv4)
group = Camp
[source.rs1-camp-v4.birdwatcher]
timezone = UTC
api = http://isw01.camp.bgp.wtf:3000/
type = single_table
neighbors_refresh_timeout = 2
servertime = 2006-01-02T15:04:05Z
servertime_short = 2006-01-02 15:04:05
servertime_ext = 2006-01-02 15:04:05
[source.rs1-camp-v6]
name = rs1.camp.bgp.wtf (IPv6)
group = Camp
[source.rs1-camp-v6.birdwatcher]
timezone = UTC
api = http://isw01.camp.bgp.wtf:3001/
type = single_table
neighbors_refresh_timeout = 2
servertime = 2006-01-02T15:04:05Z
servertime_short = 2006-01-02 15:04:05
servertime_ext = 2006-01-02 15:04:05
[source.rs2-camp-v4]
name = rs2.camp.bgp.wtf (IPv4)
group = Camp
[source.rs2-camp-v4.birdwatcher]
timezone = UTC
api = http://isw01.camp.bgp.wtf:3002/
type = single_table
neighbors_refresh_timeout = 2
servertime = 2006-01-02T15:04:05Z
servertime_short = 2006-01-02 15:04:05
servertime_ext = 2006-01-02 15:04:05
[source.rs2-camp-v6]
name = rs2.camp.bgp.wtf (IPv6)
group = Camp
[source.rs2-camp-v6.birdwatcher]
timezone = UTC
api = http://isw01.camp.bgp.wtf:3003/
type = single_table
neighbors_refresh_timeout = 2
servertime = 2006-01-02T15:04:05Z
servertime_short = 2006-01-02 15:04:05
servertime_ext = 2006-01-02 15:04:05
|||,
},
},
},
ripeSync: kube.CronJob(ix.name("ripe-sync")) {
metadata+: ix.metadata("ripe-sync"),
spec+: {
schedule: "*/5 * * * *",
jobTemplate+: {
spec+: {
selector:: null,
template+: {
spec+: {
containers_: {
"ripe-sync": kube.Container(ix.name("ripe-sync")) {
image: cfg.image,
args: [
"/ix/ripe-sync.par",
"$(PASSWORD)",
ix.verifier.address,
],
env_: {
PASSWORD: {
secretKeyRef: {
name: ix.name("ripe-sync"),
key: "password",
},
},
},
},
},
},
},
},
},
},
},
ingress: kube.SimpleIngress("ingress") {
hosts:: [cfg.frontend.domain],
target:: ix.frontend.svc,
metadata+: ix.metadata("public"),
},
aliceIngress: kube.SimpleIngress("alice") {
hosts:: [cfg.alice.domain],
target:: ix.alice.svc,
metadata+: ix.metadata("alice"),
},
grpcIngress: kube.SimpleIngress("grpc") {
hosts:: [cfg.verifier.domain],
target:: ix.verifier.svc,
metadata+: ix.metadata("alice") {
annotations+: {
"kubernetes.io/ingress.class": "nginx",
"nginx.ingress.kubernetes.io/ssl-redirect": "true",
"nginx.ingress.kubernetes.io/backend-protocol": "GRPC",
},
},
},
},
}