Skip to content

Commit 58f706a

Browse files
chore: fix db selector read/writes (#685)
1 parent 6a80bd5 commit 58f706a

File tree

7 files changed

+282
-372
lines changed

7 files changed

+282
-372
lines changed

apps/workspace-engine/pkg/db/common.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package db
22

33
import (
44
"encoding/json"
5+
6+
"workspace-engine/pkg/oapi"
57
)
68

79
func parseJSONToStruct(jsonData []byte) map[string]interface{} {
@@ -16,3 +18,40 @@ func parseJSONToStruct(jsonData []byte) map[string]interface{} {
1618

1719
return dataMap
1820
}
21+
22+
// wrapSelectorFromDB wraps a db selector in oapi JsonSelector format
23+
func wrapSelectorFromDB(rawMap map[string]interface{}) (*oapi.Selector, error) {
24+
if rawMap == nil {
25+
return nil, nil
26+
}
27+
28+
// Wrap the raw map in JsonSelector format
29+
selector := &oapi.Selector{}
30+
err := selector.FromJsonSelector(oapi.JsonSelector{
31+
Json: rawMap,
32+
})
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
return selector, nil
38+
}
39+
40+
// unwrapSelectorForDB unwraps a selector for database storage (database stores unwrapped selector format)
41+
// NOTE: CEL selectors are not currently supported - they will be written as NULL to the database.
42+
func unwrapSelectorForDB(selector *oapi.Selector) (map[string]interface{}, error) {
43+
if selector == nil {
44+
return nil, nil
45+
}
46+
47+
// Try as JsonSelector
48+
jsonSelector, err := selector.AsJsonSelector()
49+
if err == nil && jsonSelector.Json != nil {
50+
// Return the unwrapped map directly - pgx can handle it
51+
return jsonSelector.Json, nil
52+
}
53+
54+
// CEL selectors are not supported - return nil to store NULL in database
55+
// TODO: Add support for CEL selectors in the future
56+
return nil, nil
57+
}

apps/workspace-engine/pkg/db/deployments.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ func getDeployments(ctx context.Context, workspaceID string) ([]*oapi.Deployment
3939
deployments := make([]*oapi.Deployment, 0)
4040
for rows.Next() {
4141
var deployment oapi.Deployment
42+
var rawSelector map[string]interface{}
43+
4244
err := rows.Scan(
4345
&deployment.Id,
4446
&deployment.Name,
@@ -47,11 +49,18 @@ func getDeployments(ctx context.Context, workspaceID string) ([]*oapi.Deployment
4749
&deployment.SystemId,
4850
&deployment.JobAgentId,
4951
&deployment.JobAgentConfig,
50-
&deployment.ResourceSelector,
52+
&rawSelector,
5153
)
5254
if err != nil {
5355
return nil, err
5456
}
57+
58+
// Wrap selector from unwrapped database format to JsonSelector format
59+
deployment.ResourceSelector, err = wrapSelectorFromDB(rawSelector)
60+
if err != nil {
61+
return nil, err
62+
}
63+
5564
deployments = append(deployments, &deployment)
5665
}
5766
if err := rows.Err(); err != nil {
@@ -74,6 +83,12 @@ const DEPLOYMENT_UPSERT_QUERY = `
7483
`
7584

7685
func writeDeployment(ctx context.Context, deployment *oapi.Deployment, tx pgx.Tx) error {
86+
// Unwrap selector for database storage (database stores unwrapped ResourceCondition format)
87+
selectorToStore, err := unwrapSelectorForDB(deployment.ResourceSelector)
88+
if err != nil {
89+
return err
90+
}
91+
7792
if _, err := tx.Exec(
7893
ctx,
7994
DEPLOYMENT_UPSERT_QUERY,
@@ -84,7 +99,7 @@ func writeDeployment(ctx context.Context, deployment *oapi.Deployment, tx pgx.Tx
8499
deployment.SystemId,
85100
deployment.JobAgentId,
86101
deployment.JobAgentConfig,
87-
deployment.ResourceSelector,
102+
selectorToStore,
88103
); err != nil {
89104
return err
90105
}

apps/workspace-engine/pkg/db/deployments_test.go

Lines changed: 18 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -464,88 +464,8 @@ func TestDBDeployments_WithJsonResourceSelector(t *testing.T) {
464464
}
465465
}
466466

467-
func TestDBDeployments_WithCelResourceSelector(t *testing.T) {
468-
workspaceID, conn := setupTestWithWorkspace(t)
469-
470-
tx, err := conn.Begin(t.Context())
471-
if err != nil {
472-
t.Fatalf("failed to begin tx: %v", err)
473-
}
474-
defer tx.Rollback(t.Context())
475-
476-
// Create a system first
477-
systemID := uuid.New().String()
478-
systemDescription := fmt.Sprintf("desc-%s", systemID[:8])
479-
sys := &oapi.System{
480-
Id: systemID,
481-
WorkspaceId: workspaceID,
482-
Name: fmt.Sprintf("test-system-%s", systemID[:8]),
483-
Description: &systemDescription,
484-
}
485-
err = writeSystem(t.Context(), sys, tx)
486-
if err != nil {
487-
t.Fatalf("failed to create system: %v", err)
488-
}
489-
490-
// Create deployment with CEL resource selector
491-
deploymentID := uuid.New().String()
492-
description := "test deployment with CEL selector"
493-
494-
// Create a CEL selector
495-
resourceSelector := &oapi.Selector{}
496-
celExpression := "resource.metadata.environment == 'production'"
497-
err = resourceSelector.FromCelSelector(oapi.CelSelector{
498-
Cel: celExpression,
499-
})
500-
if err != nil {
501-
t.Fatalf("failed to create CEL selector: %v", err)
502-
}
503-
504-
deployment := &oapi.Deployment{
505-
Id: deploymentID,
506-
Name: fmt.Sprintf("test-deployment-%s", deploymentID[:8]),
507-
Slug: fmt.Sprintf("test-deployment-%s", deploymentID[:8]),
508-
SystemId: systemID,
509-
Description: &description,
510-
JobAgentConfig: map[string]interface{}{},
511-
ResourceSelector: resourceSelector,
512-
}
513-
514-
err = writeDeployment(t.Context(), deployment, tx)
515-
if err != nil {
516-
t.Fatalf("expected no errors, got %v", err)
517-
}
518-
519-
err = tx.Commit(t.Context())
520-
if err != nil {
521-
t.Fatalf("failed to commit: %v", err)
522-
}
523-
524-
// Read back and validate
525-
actualDeployments, err := getDeployments(t.Context(), workspaceID)
526-
if err != nil {
527-
t.Fatalf("expected no errors, got %v", err)
528-
}
529-
530-
if len(actualDeployments) != 1 {
531-
t.Fatalf("expected 1 deployment, got %d", len(actualDeployments))
532-
}
533-
534-
actualDeployment := actualDeployments[0]
535-
if actualDeployment.ResourceSelector == nil {
536-
t.Fatalf("expected resource selector to be non-nil")
537-
}
538-
539-
// Validate the selector content
540-
celSelector, err := actualDeployment.ResourceSelector.AsCelSelector()
541-
if err != nil {
542-
t.Fatalf("expected CEL selector, got error: %v", err)
543-
}
544-
545-
if celSelector.Cel != celExpression {
546-
t.Fatalf("expected CEL expression %s, got %s", celExpression, celSelector.Cel)
547-
}
548-
}
467+
// TODO: Add CEL selector tests when CEL support is implemented
468+
// func TestDBDeployments_WithCelResourceSelector(t *testing.T) { ... }
549469

550470
func TestDBDeployments_UpdateResourceSelector(t *testing.T) {
551471
workspaceID, conn := setupTestWithWorkspace(t)
@@ -605,20 +525,23 @@ func TestDBDeployments_UpdateResourceSelector(t *testing.T) {
605525
t.Fatalf("failed to commit: %v", err)
606526
}
607527

608-
// Update with CEL selector
528+
// Update with a different JSON selector
609529
tx, err = conn.Begin(t.Context())
610530
if err != nil {
611531
t.Fatalf("failed to begin tx: %v", err)
612532
}
613533
defer tx.Rollback(t.Context())
614534

615535
updatedSelector := &oapi.Selector{}
616-
celExpression := "resource.kind == 'pod'"
617-
err = updatedSelector.FromCelSelector(oapi.CelSelector{
618-
Cel: celExpression,
536+
err = updatedSelector.FromJsonSelector(oapi.JsonSelector{
537+
Json: map[string]interface{}{
538+
"type": "kind",
539+
"value": "pod",
540+
"operator": "equals",
541+
},
619542
})
620543
if err != nil {
621-
t.Fatalf("failed to create CEL selector: %v", err)
544+
t.Fatalf("failed to create updated JSON selector: %v", err)
622545
}
623546

624547
deployment.ResourceSelector = updatedSelector
@@ -648,13 +571,16 @@ func TestDBDeployments_UpdateResourceSelector(t *testing.T) {
648571
t.Fatalf("expected resource selector to be non-nil")
649572
}
650573

651-
// Validate it's now a CEL selector
652-
celSelector, err := actualDeployment.ResourceSelector.AsCelSelector()
574+
// Validate it's the updated JSON selector
575+
jsonSelector, err := actualDeployment.ResourceSelector.AsJsonSelector()
653576
if err != nil {
654-
t.Fatalf("expected CEL selector, got error: %v", err)
577+
t.Fatalf("expected JSON selector, got error: %v", err)
655578
}
656579

657-
if celSelector.Cel != celExpression {
658-
t.Fatalf("expected CEL expression %s, got %s", celExpression, celSelector.Cel)
580+
if jsonSelector.Json["type"] != "kind" {
581+
t.Fatalf("expected type 'kind', got %v", jsonSelector.Json["type"])
582+
}
583+
if jsonSelector.Json["value"] != "pod" {
584+
t.Fatalf("expected value 'pod', got %v", jsonSelector.Json["value"])
659585
}
660586
}

apps/workspace-engine/pkg/db/environments.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,27 @@ func getEnvironments(ctx context.Context, workspaceID string) ([]*oapi.Environme
3939
for rows.Next() {
4040
var environment oapi.Environment
4141
var createdAt time.Time
42+
var rawSelector map[string]interface{}
43+
4244
err := rows.Scan(
4345
&environment.Id,
4446
&environment.Name,
4547
&environment.SystemId,
4648
&createdAt,
4749
&environment.Description,
48-
&environment.ResourceSelector,
50+
&rawSelector,
4951
)
5052
if err != nil {
5153
return nil, err
5254
}
5355
environment.CreatedAt = createdAt.Format(time.RFC3339)
56+
57+
// Wrap selector from unwrapped database format to JsonSelector format
58+
environment.ResourceSelector, err = wrapSelectorFromDB(rawSelector)
59+
if err != nil {
60+
return nil, err
61+
}
62+
5463
environments = append(environments, &environment)
5564
}
5665
if err := rows.Err(); err != nil {
@@ -70,14 +79,20 @@ const ENVIRONMENT_UPSERT_QUERY = `
7079
`
7180

7281
func writeEnvironment(ctx context.Context, environment *oapi.Environment, tx pgx.Tx) error {
82+
// Unwrap selector for database storage (database stores unwrapped ResourceCondition format)
83+
selectorToStore, err := unwrapSelectorForDB(environment.ResourceSelector)
84+
if err != nil {
85+
return err
86+
}
87+
7388
if _, err := tx.Exec(
7489
ctx,
7590
ENVIRONMENT_UPSERT_QUERY,
7691
environment.Id,
7792
environment.Name,
7893
environment.SystemId,
7994
environment.Description,
80-
environment.ResourceSelector,
95+
selectorToStore,
8196
); err != nil {
8297
return err
8398
}

0 commit comments

Comments
 (0)