Merge changes Ic71cbdce,I097b58ef
* changes:
app/matrix: cleanup irc bridge registration oneliner
app/matrix: add wellKnown server integration
diff --git a/app/matrix/matrix.hackerspace.pl.jsonnet b/app/matrix/matrix.hackerspace.pl.jsonnet
index d71dd84..6488fbb 100644
--- a/app/matrix/matrix.hackerspace.pl.jsonnet
+++ b/app/matrix/matrix.hackerspace.pl.jsonnet
@@ -26,8 +26,7 @@
"irc-freenode": irc.AppServiceIrc("freenode") {
cfg+: {
image: cfg.images.appserviceIRC,
- // TODO(q3k): move this appservice to waw-hdd-redundant-3
- storageClassName: "waw-hdd-paranoid-2",
+ storageClassName: "waw-hdd-redundant-3",
metadata: app.metadata("appservice-irc-freenode"),
// TODO(q3k): add labels to blessed nodes
nodeSelector: {
diff --git a/app/matrix/wellknown/BUILD b/app/matrix/wellknown/BUILD
index 1cf4138..b44ac52 100644
--- a/app/matrix/wellknown/BUILD
+++ b/app/matrix/wellknown/BUILD
@@ -1,3 +1,4 @@
+load("@io_bazel_rules_docker//container:container.bzl", "container_image", "container_layer", "container_push")
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
go_library(
@@ -23,3 +24,28 @@
embed = [":go_default_library"],
deps = ["@com_github_go_test_deep//:go_default_library"],
)
+
+container_layer(
+ name = "layer_bin",
+ files = [
+ ":wellknown",
+ ],
+ directory = "/app/matrix/",
+)
+
+container_image(
+ name = "runtime",
+ base = "@prodimage-bionic//image",
+ layers = [
+ ":layer_bin",
+ ],
+)
+
+container_push(
+ name = "push",
+ image = ":runtime",
+ format = "Docker",
+ registry = "registry.k0.hswaw.net",
+ repository = "q3k/wellknown",
+ tag = "{BUILD_TIMESTAMP}-{STABLE_GIT_COMMIT}",
+)
diff --git a/app/matrix/wellknown/README.me b/app/matrix/wellknown/README.md
similarity index 100%
rename from app/matrix/wellknown/README.me
rename to app/matrix/wellknown/README.md
diff --git a/bgpwtf/invoice/BUILD.bazel b/bgpwtf/invoice/BUILD.bazel
index 900f0b3..950474e 100644
--- a/bgpwtf/invoice/BUILD.bazel
+++ b/bgpwtf/invoice/BUILD.bazel
@@ -1,4 +1,4 @@
-load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
+load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
go_library(
name = "go_default_library",
@@ -31,3 +31,9 @@
embed = [":go_default_library"],
visibility = ["//visibility:public"],
)
+
+go_test(
+ name = "go_default_test",
+ srcs = ["calc_test.go"],
+ embed = [":go_default_library"],
+)
diff --git a/bgpwtf/invoice/calc.go b/bgpwtf/invoice/calc.go
index 9c411da..72933d3 100644
--- a/bgpwtf/invoice/calc.go
+++ b/bgpwtf/invoice/calc.go
@@ -1,17 +1,23 @@
package main
import (
+ "sort"
"time"
pb "code.hackerspace.pl/hscloud/bgpwtf/invoice/proto"
)
+// calculateInvoiceData applies all business logic to populate an Invoice's
+// denormalized fields from its InvoiceData.
func calculateInvoiceData(p *pb.Invoice) {
+ // Populate default unit.
+ // TODO(q3k): this really should be done on invoice submit instead.
p.Unit = p.Data.Unit
if p.Unit == "" {
p.Unit = "€"
}
+ // Calculate totals.
p.TotalNet = 0
p.Total = 0
for _, i := range p.Data.Item {
@@ -24,6 +30,21 @@
i.Total = rowTotal
}
+ // Calculate due date.
due := int64(time.Hour*24) * p.Data.DaysDue
p.DueDate = time.Unix(0, p.Date).Add(time.Duration(due)).UnixNano()
+
+ // Denormalize Items' GTUCodes into the Invoice's summary GTU codes.
+ codeSet := make(map[pb.GTUCode]bool)
+ for _, item := range p.Data.Item {
+ for _, code := range item.GtuCode {
+ codeSet[code] = true
+ }
+ }
+ var codes []pb.GTUCode
+ for c, _ := range codeSet {
+ codes = append(codes, c)
+ }
+ sort.Slice(codes, func(i, j int) bool { return codes[i] < codes[j] })
+ p.GtuCode = codes
}
diff --git a/bgpwtf/invoice/calc_test.go b/bgpwtf/invoice/calc_test.go
new file mode 100644
index 0000000..e8607c9
--- /dev/null
+++ b/bgpwtf/invoice/calc_test.go
@@ -0,0 +1,129 @@
+package main
+
+import (
+ "testing"
+ "time"
+
+ pb "code.hackerspace.pl/hscloud/bgpwtf/invoice/proto"
+)
+
+// Fake test data for test in this file.
+var (
+ itemInternet1 = &pb.Item{
+ Title: "Dostęp do Internetu - Umowa FOOBAR/10 - Opłata Abonentowa 2020/08",
+ Count: 1,
+ UnitPrice: 4200,
+ Vat: 23000,
+ }
+ itemInternet2 = &pb.Item{
+ Title: "Dostęp do Internetu - Umowa FOOBAR/10 - Opłata Abonentowa 2020/09",
+ Count: 1,
+ UnitPrice: 4200,
+ Vat: 23000,
+ }
+ itemHardware = &pb.Item{
+ Title: "Thinkpad x230, i7, 16GB RAM, Refurbished",
+ Count: 1,
+ UnitPrice: 10000,
+ Vat: 23000,
+ GtuCode: []pb.GTUCode{pb.GTUCode_GTU_05},
+ }
+ billing1 = []string{
+ "Wykop Sp. z o. o.",
+ "Zakręt 8",
+ "60-351 Poznań",
+ }
+ billing2 = []string{
+ "TEH Adam Karolczak",
+ "Zgoda 18/2",
+ "95-200 Pabianice",
+ }
+ vatID1 = "PL8086133742"
+ vatID2 = "DE133742429"
+ iban = "PL 59 1090 2402 9746 7956 2256 2375"
+ swift = "WLPPZLPAXXX"
+)
+
+func TestCalculate(t *testing.T) {
+ now := time.Now()
+ for _, te := range []struct {
+ description string
+ data *pb.InvoiceData
+ want *pb.Invoice
+ }{
+ {
+ description: "Invoice without JPK_V7 codes",
+ data: &pb.InvoiceData{
+ Item: []*pb.Item{itemInternet1, itemInternet2},
+ InvoicerBilling: billing1,
+ CustomerBilling: billing2,
+ InvoicerVatId: vatID1,
+ CustomerVatId: vatID2,
+ Date: now.UnixNano(),
+ DaysDue: 21,
+ Iban: iban,
+ Swift: swift,
+ Unit: "PLN",
+ },
+ want: &pb.Invoice{
+ TotalNet: 8400,
+ Total: 10332,
+ Unit: "PLN",
+ },
+ },
+ {
+ description: "Invoice with JPK_V7 codes",
+ data: &pb.InvoiceData{
+ // Repeated item with GTU code GTU_5, to ensure result doesn't
+ // have repeated codes.
+ Item: []*pb.Item{itemInternet1, itemHardware, itemHardware},
+ InvoicerBilling: billing1,
+ CustomerBilling: billing2,
+ InvoicerVatId: vatID1,
+ CustomerVatId: vatID2,
+ Date: now.UnixNano(),
+ DaysDue: 21,
+ Iban: iban,
+ Swift: swift,
+ Unit: "PLN",
+ },
+ want: &pb.Invoice{
+ TotalNet: 24200,
+ Total: 29766,
+ Unit: "PLN",
+ GtuCode: []pb.GTUCode{pb.GTUCode_GTU_05},
+ },
+ },
+ } {
+ t.Run(te.description, func(t *testing.T) {
+ invoice := &pb.Invoice{
+ Data: te.data,
+ Date: te.data.Date,
+ }
+ calculateInvoiceData(invoice)
+ if want, got := te.want.TotalNet, invoice.TotalNet; want != got {
+ t.Errorf("got TotalNet %d, wanted %d", got, want)
+ }
+ if want, got := te.want.Total, invoice.Total; want != got {
+ t.Errorf("got Total %d, wanted %d", got, want)
+ }
+ if want, got := te.want.Unit, invoice.Unit; want != got {
+ t.Errorf("got Unit %q, wanted %q", got, want)
+ }
+ due := time.Duration(int64(time.Hour*24) * te.data.DaysDue)
+ if want, got := now.Add(due).UnixNano(), invoice.DueDate; want != got {
+ t.Errorf("got DueDate %d, wanted %d", got, want)
+ }
+ if want, got := len(te.want.GtuCode), len(invoice.GtuCode); want != got {
+ t.Errorf("got %d GTU codes, wanted %d", got, want)
+ } else {
+ for i, want := range te.want.GtuCode {
+ got := invoice.GtuCode[i]
+ if want != got {
+ t.Errorf("GTU code %d: wanted %s, got %s", i, want.String(), got.String())
+ }
+ }
+ }
+ })
+ }
+}
diff --git a/bgpwtf/invoice/main.go b/bgpwtf/invoice/main.go
index 5133010..ae17dbb 100644
--- a/bgpwtf/invoice/main.go
+++ b/bgpwtf/invoice/main.go
@@ -130,6 +130,10 @@
return &pb.SealInvoiceResponse{}, nil
}
+func (s *service) GetInvoices(req *pb.GetInvoicesRequest, srv pb.Invoicer_GetInvoicesServer) error {
+ return status.Error(codes.Unimplemented, "unimplemented")
+}
+
func init() {
flag.Set("logtostderr", "true")
}
diff --git a/bgpwtf/invoice/model.go b/bgpwtf/invoice/model.go
index fcf4aba..548d8ff 100644
--- a/bgpwtf/invoice/model.go
+++ b/bgpwtf/invoice/model.go
@@ -75,7 +75,7 @@
invoice_id, final_uid, sealed_time
) values (
?,
- ( select printf("%04d", ifnull( (select final_uid as v from invoice_seal order by final_uid desc limit 1), 20000) + 1 )),
+ ( select printf("%04d", ifnull( (select final_uid as v from invoice_seal order by final_uid desc limit 1), 21000) + 1 )),
?
)
`
diff --git a/bgpwtf/invoice/proto/BUILD.bazel b/bgpwtf/invoice/proto/BUILD.bazel
index 51f85fe..2eeae64 100644
--- a/bgpwtf/invoice/proto/BUILD.bazel
+++ b/bgpwtf/invoice/proto/BUILD.bazel
@@ -1,3 +1,4 @@
+load("@rules_proto//proto:defs.bzl", "proto_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
diff --git a/bgpwtf/invoice/proto/invoice.proto b/bgpwtf/invoice/proto/invoice.proto
index ee2b9d8..70e6923 100644
--- a/bgpwtf/invoice/proto/invoice.proto
+++ b/bgpwtf/invoice/proto/invoice.proto
@@ -264,12 +264,12 @@
// If sealed, otherwise 'proforma'.
string final_uid = 3;
int64 date = 4;
- int64 due_date = 5;
// Denormalized fields follow.
+ int64 due_date = 5;
uint64 total_net = 6;
uint64 total = 7;
string unit = 8;
- repeated GTUCode gtu_codes = 10;
+ repeated GTUCode gtu_code = 10;
// Next tag: 11;
}
@@ -312,9 +312,48 @@
message SealInvoiceResponse {
}
+message GetInvoicesRequest {
+ // Return all invoices issued in a given year.
+ message ForYear {
+ int32 year = 1;
+ }
+ // Return all invoices issued in a given month of a year.
+ message ForMonth {
+ int32 year = 1;
+ int32 month = 2;
+ }
+
+ oneof range {
+ ForYear for_year = 1;
+ ForMonth for_month = 2;
+ }
+}
+
+message GetInvoicesResponse {
+ // Each chunk may contain an arbitrary amount of invoices, and each
+ // GetInvoices request may return an arbitrary amount of
+ // GetInvoicesResponses in a stream.
+ repeated Invoice invoice = 1;
+}
+
service Invoicer {
+ // Create an invoice with given data, returning UID. The newly created
+ // invoice is created as a proforma invoice and not yet sealed, ie. not
+ // given a unique, sequential ID.
rpc CreateInvoice(CreateInvoiceRequest) returns (CreateInvoiceResponse);
+
+ // Get invoice details for a given UID.
rpc GetInvoice(GetInvoiceRequest) returns (GetInvoiceResponse);
+
+ // Return chunks of a rendered PDF for a given UID. If the invoice is
+ // sealed, the stored PDF will be returned, otherwise a PDF will be
+ // rendered on the fly.
rpc RenderInvoice(RenderInvoiceRequest) returns (stream RenderInvoiceResponse);
+
+ // Seal invoice, ie. assign it a sequential ID and render it to an
+ // immutable PDF for audit purposes.
rpc SealInvoice(SealInvoiceRequest) returns (SealInvoiceResponse);
+
+ // Return a summarized detail of invoice data for a given filter.
+ rpc GetInvoices(GetInvoicesRequest) returns (stream GetInvoicesResponse);
}
diff --git a/bgpwtf/machines/secrets/cipher/edge01.waw.bgp.wtf-private.nix b/bgpwtf/machines/secrets/cipher/edge01.waw.bgp.wtf-private.nix
index f97f1eb..aea2b80 100644
--- a/bgpwtf/machines/secrets/cipher/edge01.waw.bgp.wtf-private.nix
+++ b/bgpwtf/machines/secrets/cipher/edge01.waw.bgp.wtf-private.nix
@@ -1,50 +1,51 @@
-----BEGIN PGP MESSAGE-----
-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
-=1q6K
+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
+=nGiW
-----END PGP MESSAGE-----
diff --git a/cluster/kube/k0-cockroach.jsonnet b/cluster/kube/k0-cockroach.jsonnet
new file mode 100644
index 0000000..faf0f14
--- /dev/null
+++ b/cluster/kube/k0-cockroach.jsonnet
@@ -0,0 +1,7 @@
+// Only the CockroachDB cluster - nodes, clients etc.
+
+local k0 = (import "k0.libsonnet").k0;
+
+{
+ cockroach: k0.cockroach,
+}
diff --git a/cluster/kube/k0.libsonnet b/cluster/kube/k0.libsonnet
index ad6b735..44f83d0 100644
--- a/cluster/kube/k0.libsonnet
+++ b/cluster/kube/k0.libsonnet
@@ -65,7 +65,7 @@
topology: [
{ name: "bc01n01", node: "bc01n01.hswaw.net" },
{ name: "bc01n02", node: "bc01n02.hswaw.net" },
- { name: "bc01n03", node: "bc01n03.hswaw.net" },
+ { name: "dcr01s22", node: "dcr01s22.hswaw.net" },
],
// Host path on SSD.
hostPath: "/var/db/crdb-waw1",
@@ -80,112 +80,19 @@
buglessDev: k0.cockroach.waw2.Client("bugless-dev"),
sso: k0.cockroach.waw2.Client("sso"),
herpDev: k0.cockroach.waw2.Client("herp-dev"),
+ gitea: k0.cockroach.waw2.Client("gitea"),
},
},
ceph: {
// waw1 cluster - dead as of 2019/08/06, data corruption
- // waw2 cluster: shitty 7200RPM 2.5" HDDs
- waw2: rook.Cluster(k0.cluster.rook, "ceph-waw2") {
- spec: {
- mon: {
- count: 3,
- allowMultiplePerNode: false,
- },
- storage: {
- useAllNodes: false,
- useAllDevices: false,
- config: {
- databaseSizeMB: "1024",
- journalSizeMB: "1024",
- },
- nodes: [
- {
- name: "bc01n01.hswaw.net",
- location: "rack=dcr01 chassis=bc01 host=bc01n01",
- devices: [ { name: "sda" } ],
- },
- {
- name: "bc01n02.hswaw.net",
- location: "rack=dcr01 chassis=bc01 host=bc01n02",
- devices: [ { name: "sda" } ],
- },
- {
- name: "bc01n03.hswaw.net",
- location: "rack=dcr01 chassis=bc01 host=bc01n03",
- devices: [ { name: "sda" } ],
- },
- ],
- },
- benji:: {
- metadataStorageClass: "waw-hdd-paranoid-2",
- encryptionPassword: std.split((importstr "../secrets/plain/k0-benji-encryption-password"), '\n')[0],
- pools: [
- "waw-hdd-redundant-2",
- "waw-hdd-redundant-2-metadata",
- "waw-hdd-paranoid-2",
- "waw-hdd-yolo-2",
- ],
- s3Configuration: {
- awsAccessKeyId: "RPYZIROFXNLQVU2WJ4R3",
- awsSecretAccessKey: std.split((importstr "../secrets/plain/k0-benji-secret-access-key"), '\n')[0],
- bucketName: "benji-k0-backups",
- endpointUrl: "https://s3.eu-central-1.wasabisys.com/",
- },
- }
- },
- },
- waw2Pools: {
- // redundant block storage
- blockRedundant: rook.ECBlockPool(k0.ceph.waw2, "waw-hdd-redundant-2") {
- spec: {
- failureDomain: "host",
- erasureCoded: {
- dataChunks: 2,
- codingChunks: 1,
- },
- },
- },
- // paranoid block storage (3 replicas)
- blockParanoid: rook.ReplicatedBlockPool(k0.ceph.waw2, "waw-hdd-paranoid-2") {
- spec: {
- failureDomain: "host",
- replicated: {
- size: 3,
- },
- },
- },
- // yolo block storage (no replicas!)
- blockYolo: rook.ReplicatedBlockPool(k0.ceph.waw2, "waw-hdd-yolo-2") {
- spec: {
- failureDomain: "host",
- replicated: {
- size: 1,
- },
- },
- },
- objectRedundant: rook.S3ObjectStore(k0.ceph.waw2, "waw-hdd-redundant-2-object") {
- spec: {
- metadataPool: {
- failureDomain: "host",
- replicated: { size: 3 },
- },
- dataPool: {
- failureDomain: "host",
- erasureCoded: {
- dataChunks: 2,
- codingChunks: 1,
- },
- },
- },
- },
- },
+ // waw2 cluster - dead as of 2021/01/22, torn down (horrible M610 RAID controllers are horrible)
// waw3: 6TB SAS 3.5" HDDs
waw3: rook.Cluster(k0.cluster.rook, "ceph-waw3") {
spec: {
mon: {
- count: 3,
+ count: 1,
allowMultiplePerNode: false,
},
storage: {
@@ -267,8 +174,8 @@
spec: {
failureDomain: "osd",
erasureCoded: {
- dataChunks: 12,
- codingChunks: 4,
+ dataChunks: 2,
+ codingChunks: 1,
},
},
},
@@ -383,7 +290,6 @@
# bits they use, whatever those might be.
# TODO(q3k): fix this?
unnecessarilyInsecureNamespaces: [
- policies.AllowNamespaceInsecure("ceph-waw2"),
policies.AllowNamespaceInsecure("ceph-waw3"),
policies.AllowNamespaceInsecure("matrix"),
policies.AllowNamespaceInsecure("registry"),
diff --git a/cluster/kube/lib/cockroachdb.libsonnet b/cluster/kube/lib/cockroachdb.libsonnet
index 8ebad52..9f206f0 100644
--- a/cluster/kube/lib/cockroachdb.libsonnet
+++ b/cluster/kube/lib/cockroachdb.libsonnet
@@ -42,7 +42,7 @@
local cluster = self,
cfg:: {
- image: "cockroachdb/cockroach:v19.1.0",
+ image: "cockroachdb/cockroach:v20.2.4",
# Must be unique per cluster.
portServe: 26257,
diff --git a/cluster/kube/lib/rook.libsonnet b/cluster/kube/lib/rook.libsonnet
index 8f83d2d..c8e38a8 100644
--- a/cluster/kube/lib/rook.libsonnet
+++ b/cluster/kube/lib/rook.libsonnet
@@ -10,7 +10,7 @@
local env = self,
local cfg = env.cfg,
cfg:: {
- image: "rook/ceph:v1.1.9",
+ image: "rook/ceph:v1.2.7",
namespace: "rook-ceph-system",
},
@@ -54,6 +54,7 @@
},
dataDirHostPath: oa.String { pattern: "^/(\\S+)" },
skipUpgradeChecks: oa.Boolean,
+ continueUpgradeAfterChecksEvenIfNotHealthy: oa.Boolean,
mon: oa.Dict {
allowMultiplePerNode: oa.Boolean,
count: oa.Integer { minimum: 0, maximum: 9 },
@@ -236,6 +237,15 @@
subresources: { status: {} },
},
},
+ cephclients: kube.CustomResourceDefinition("ceph.rook.io", "v1", "CephClient") {
+ spec+: {
+ validation: oa.Validation(oa.Dict {
+ spec: oa.Dict {
+ caps: oa.Any,
+ },
+ }),
+ },
+ },
},
sa: {
@@ -307,9 +317,24 @@
},
{
apiGroups: ["policy", "apps"],
- resources: ["poddisruptionbudgets", "deployments"],
+ resources: ["poddisruptionbudgets", "deployments", "replicasets"],
verbs: ["*"],
},
+ {
+ apiGroups: ["healthchecking.openshift.io"],
+ resources: ["machinedisruptionbudgets"],
+ verbs: ["get", "list", "watch", "create", "update", "delete"],
+ },
+ {
+ apiGroups: ["machine.openshift.io"],
+ resources: ["machines"],
+ verbs: ["get", "list", "watch", "create", "update", "delete"],
+ },
+ {
+ apiGroups: ["storage.k8s.io"],
+ resources: ["csidrivers"],
+ verbs: ["create"],
+ },
],
},
@@ -733,7 +758,17 @@
apiGroups: [""],
resources: ["configmaps"],
verbs: ["get", "list", "watch", "create", "update", "delete"],
- }
+ },
+ ],
+ },
+ osdCluster: kube.ClusterRole(cluster.name("osd-cluster")) {
+ metadata+: cluster.metadata { namespace:: null },
+ rules: [
+ {
+ apiGroups: [""],
+ resources: ["nodes"],
+ verbs: ["get", "list"],
+ },
],
},
mgr: kube.Role(cluster.name("mgr")) {
@@ -802,13 +837,21 @@
subjects_: [cluster.sa.mgr],
},
+ osdClusterRB: kube.ClusterRoleBinding(cluster.name("osd-cluster")) {
+ metadata+: {
+ namespace:: null,
+ },
+ roleRef_: cluster.roles.osdCluster,
+ subjects_: [cluster.sa.osd],
+ },
+
+
cluster: kube._Object("ceph.rook.io/v1", "CephCluster", name) {
metadata+: cluster.metadata,
spec: {
cephVersion: {
# https://github.com/rook/rook/issues/2945#issuecomment-483964014
- #image: "ceph/ceph:v13.2.5-20190319",
- image: "ceph/ceph:v14.2.2-20190830",
+ image: "ceph/ceph:v14.2.16",
allowUnsupported: true,
},
dataDirHostPath: if name == "ceph-waw2" then "/var/lib/rook" else "/var/lib/rook-%s" % [name],
diff --git a/cluster/nix/defs-machines.nix b/cluster/nix/defs-machines.nix
index 4c50f67..da9150c 100644
--- a/cluster/nix/defs-machines.nix
+++ b/cluster/nix/defs-machines.nix
@@ -25,19 +25,10 @@
mgmtIf = "eno1";
stateVersion = "18.09";
}
- rec {
- name = "bc01n03";
- threads = 16;
- fqdn = "${name}.hswaw.net";
- ipAddr = "185.236.240.37";
- ipAddrBits = 28;
- gw = "185.236.240.33";
- podNet = "10.10.18.0/24";
- diskBoot = "/dev/disk/by-id/scsi-360024e8078a8fa0023b1787e0605a3e0";
- fsRoot = "/dev/disk/by-uuid/afc05836-c9b3-4d7e-b0a2-3ebfe2336d4f";
- mgmtIf = "eno1";
- stateVersion = "18.09";
- }
+ # Tombstone - bc01n03 suffered from hardware failure on 2021/01/10.
+ # rec {
+ # name = "bc01n03";
+ # }
rec {
name = "dcr01s22";
threads = 48;
diff --git a/devtools/gerrit/kube/prod.jsonnet b/devtools/gerrit/kube/prod.jsonnet
index 68f68cc..5f47210 100644
--- a/devtools/gerrit/kube/prod.jsonnet
+++ b/devtools/gerrit/kube/prod.jsonnet
@@ -11,7 +11,7 @@
domain: "gerrit.hackerspace.pl",
identity: "7b6244cf-e30b-42c5-ba91-c329ef4e6cf1",
- storageClassName: "waw-hdd-paranoid-2",
+ storageClassName: "waw-hdd-redundant-3",
secureSecret: "gerrit",
},
diff --git a/devtools/kube/depotview.libsonnet b/devtools/kube/depotview.libsonnet
index 019542c..f82ff84 100644
--- a/devtools/kube/depotview.libsonnet
+++ b/devtools/kube/depotview.libsonnet
@@ -10,7 +10,12 @@
local depotview = self,
cfg+: {
image: cfg.image,
- container: depotview.GoContainer("main", "/devtools/depotview") {}
+ container: depotview.GoContainer("main", "/devtools/depotview") {
+ resources: {
+ requests: { cpu: "25m", memory: "256Mi" },
+ limits: { cpu: "500m", memory: "512Mi" },
+ },
+ }
},
}
}