cloud/{apigw,lib/component}: add cockroachdb client, sample schema
This sets up some boilerplate to connect to CockroachDB servers,
including test in-memory servers.
We also add a first pass apigw user table schema, as the first user of
this new functionality. We exercise that, in turn, in a test.
We also rename component.Configuration to component.ComponentConfig.
There's a stutter in there, but it makes sense with
component.CockroachConfig alongside.
Change-Id: I76691146b87ce135d60db179b3f51eee16525df7
Reviewed-on: https://review.monogon.dev/c/monogon/+/912
Reviewed-by: Leopold Schabel <leo@monogon.tech>
Vouch-Run-CI: Leopold Schabel <leo@monogon.tech>
Tested-by: Jenkins CI
diff --git a/cloud/apigw/server/server_test.go b/cloud/apigw/server/server_test.go
index 16cdc07..704de36 100644
--- a/cloud/apigw/server/server_test.go
+++ b/cloud/apigw/server/server_test.go
@@ -13,22 +13,29 @@
"google.golang.org/protobuf/proto"
apb "source.monogon.dev/cloud/api"
+ "source.monogon.dev/cloud/apigw/model"
"source.monogon.dev/cloud/lib/component"
)
-// TestPublicSimple ensures the public grpc-web listener is working.
-func TestPublicSimple(t *testing.T) {
- s := Server{
+func dut() *Server {
+ return &Server{
Config: Config{
- Configuration: component.Configuration{
+ Component: component.ComponentConfig{
GRPCListenAddress: ":0",
DevCerts: true,
DevCertsPath: "/tmp/foo",
},
+ Database: component.CockroachConfig{
+ InMemory: true,
+ },
PublicListenAddress: ":0",
},
}
+}
+// TestPublicSimple ensures the public grpc-web listener is working.
+func TestPublicSimple(t *testing.T) {
+ s := dut()
ctx := context.Background()
s.Start(ctx)
@@ -72,3 +79,48 @@
t.Errorf("Wanted message %q, got %q", want, got)
}
}
+
+// TestUserSimple makes sure we can add and retrieve users. This is a low-level
+// test which mostly exercises the machinery to bring up a working database in
+// tests.
+func TestUserSimple(t *testing.T) {
+ s := dut()
+ ctx := context.Background()
+ s.Start(ctx)
+
+ db, err := s.Config.Database.Connect()
+ if err != nil {
+ t.Fatalf("Connecting to the database failed: %v", err)
+ }
+ q := model.New(db)
+
+ // Start out with no account by sub 'test'.
+ accounts, err := q.GetAccountByOIDC(ctx, "test")
+ if err != nil {
+ t.Fatalf("Retrieving accounts failed: %v", err)
+ }
+ if want, got := 0, len(accounts); want != got {
+ t.Fatalf("Expected no accounts at first, got %d", got)
+ }
+
+ // Create a new test account for sub 'test'.
+ _, err = q.InitializeAccountFromOIDC(ctx, model.InitializeAccountFromOIDCParams{
+ AccountOidcSub: "test",
+ AccountDisplayName: "Test User",
+ })
+ if err != nil {
+ t.Fatalf("Creating new account failed: %v", err)
+ }
+
+ // Expect this account to be available now.
+ accounts, err = q.GetAccountByOIDC(ctx, "test")
+ if err != nil {
+ t.Fatalf("Retrieving accounts failed: %v", err)
+ }
+ if want, got := 1, len(accounts); want != got {
+ t.Fatalf("Expected exactly one account after creation, got %d", got)
+ }
+ if want, got := "Test User", accounts[0].AccountDisplayName; want != got {
+ t.Fatalf("Expected to read back display name %q, got %q", want, got)
+ }
+}