Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ func (a *variableResolverAdapter) LoadCandidates(ctx context.Context, workspaceI
return a.getter.LoadCandidates(ctx, workspaceID, entityType)
}

func (a *variableResolverAdapter) GetEntityByID(ctx context.Context, entityID uuid.UUID, entityType string) (*eval.EntityData, error) {
return a.getter.GetEntityByID(ctx, entityID, entityType)
}

func buildRelease(rt *ReleaseTarget, version *oapi.DeploymentVersion, variables map[string]oapi.LiteralValue) *oapi.Release {
return &oapi.Release{
ReleaseTarget: oapi.ReleaseTarget{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ type Getter interface {
// Realtime relationship resolution
GetRelationshipRules(ctx context.Context, workspaceID uuid.UUID) ([]eval.Rule, error)
LoadCandidates(ctx context.Context, workspaceID uuid.UUID, entityType string) ([]eval.EntityData, error)
GetEntityByID(ctx context.Context, entityID uuid.UUID, entityType string) (*eval.EntityData, error)
}
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,80 @@ FROM environment
WHERE workspace_id = $1
`

const getResourceByIDSQL = `
SELECT id, workspace_id, name, kind, version, identifier,
provider_id, config, metadata, created_at, updated_at
FROM resource
WHERE id = $1 AND deleted_at IS NULL
`

const getDeploymentByIDSQL = `
SELECT id, workspace_id, name, description, job_agent_id, job_agent_config, metadata
FROM deployment
WHERE id = $1
`

const getEnvironmentByIDSQL = `
SELECT id, workspace_id, name, description, metadata, created_at
FROM environment
WHERE id = $1
`

func (g *PostgresGetter) GetEntityByID(ctx context.Context, entityID uuid.UUID, entityType string) (*eval.EntityData, error) {
pool := db.GetPool(ctx)

var query string
var buildMap func(values []any) map[string]any
switch entityType {
case "resource":
query = getResourceByIDSQL
buildMap = rowToResourceMap
case "deployment":
query = getDeploymentByIDSQL
buildMap = rowToDeploymentMap
case "environment":
query = getEnvironmentByIDSQL
buildMap = rowToEnvironmentMap
default:
return nil, fmt.Errorf("unknown entity type: %s", entityType)
}

rows, err := pool.Query(ctx, query, entityID)
if err != nil {
return nil, fmt.Errorf("query %s by id %s: %w", entityType, entityID, err)
}
defer rows.Close()

if !rows.Next() {
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate %s row: %w", entityType, err)
}
return nil, fmt.Errorf("%s with id %s not found", entityType, entityID)
}

values, err := rows.Values()
if err != nil {
return nil, fmt.Errorf("scan %s row: %w", entityType, err)
}

id, ok := values[0].([16]byte)
if !ok {
return nil, fmt.Errorf("invalid id type for %s %s", entityType, entityID)
}

wsID, ok := values[1].([16]byte)
if !ok {
return nil, fmt.Errorf("invalid workspace_id type for %s %s", entityType, entityID)
}

return &eval.EntityData{
ID: uuid.UUID(id),
WorkspaceID: uuid.UUID(wsID),
EntityType: entityType,
Raw: buildMap(values),
}, nil
}

func rowToResourceMap(values []any) map[string]any {
m := map[string]any{"type": "resource"}
if len(values) > 0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type Getter interface {
GetResourceVariables(ctx context.Context, resourceID string) (map[string]oapi.ResourceVariable, error)
GetRelationshipRules(ctx context.Context, workspaceID uuid.UUID) ([]eval.Rule, error)
LoadCandidates(ctx context.Context, workspaceID uuid.UUID, entityType string) ([]eval.EntityData, error)
GetEntityByID(ctx context.Context, entityID uuid.UUID, entityType string) (*eval.EntityData, error)
}

// Scope carries the already-resolved entities for the release target so the
Expand Down Expand Up @@ -183,21 +184,16 @@ func (r *realtimeResolver) ResolveRelated(ctx context.Context, reference string)
relatedType = m.FromEntityType
}

candidates, err := r.getter.LoadCandidates(ctx, r.workspaceID, relatedType)
entity, err := r.getter.GetEntityByID(ctx, relatedID, relatedType)
if err != nil {
return nil, fmt.Errorf("load candidate for matched entity %s: %w", relatedID, err)
return nil, fmt.Errorf("get matched entity %s: %w", relatedID, err)
}

for i := range candidates {
if candidates[i].ID == relatedID {
re, err := entityDataToRelatableEntity(&candidates[i])
if err != nil {
return nil, fmt.Errorf("convert matched entity: %w", err)
}
result = append(result, re)
break
}
re, err := entityDataToRelatableEntity(entity)
if err != nil {
return nil, fmt.Errorf("convert matched entity: %w", err)
}
result = append(result, re)
}

return result, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package variableresolver

import (
"context"
"fmt"
"testing"

"workspace-engine/pkg/oapi"
Expand Down Expand Up @@ -47,6 +48,14 @@ func (m *mockGetter) GetRelationshipRules(_ context.Context, _ uuid.UUID) ([]eva
func (m *mockGetter) LoadCandidates(_ context.Context, _ uuid.UUID, entityType string) ([]eval.EntityData, error) {
return m.candidates[entityType], nil
}
func (m *mockGetter) GetEntityByID(_ context.Context, entityID uuid.UUID, entityType string) (*eval.EntityData, error) {
for i := range m.candidates[entityType] {
if m.candidates[entityType][i].ID == entityID {
return &m.candidates[entityType][i], nil
}
}
return nil, fmt.Errorf("%s with id %s not found", entityType, entityID)
}

// ---------------------------------------------------------------------------
// helpers
Expand Down
11 changes: 11 additions & 0 deletions apps/workspace-engine/test/controllers/harness/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ func (g *DesiredReleaseGetter) LoadCandidates(_ context.Context, _ uuid.UUID, en
return nil, nil
}

func (g *DesiredReleaseGetter) GetEntityByID(_ context.Context, entityID uuid.UUID, entityType string) (*eval.EntityData, error) {
if g.Candidates != nil {
for i := range g.Candidates[entityType] {
if g.Candidates[entityType][i].ID == entityID {
return &g.Candidates[entityType][i], nil
}
}
}
return nil, fmt.Errorf("%s with id %s not found", entityType, entityID)
}

// DesiredReleaseSetter implements desiredrelease.Setter.
// When JobDispatchQueue is set, it also enqueues a job-dispatch item for
// each release that is set, bridging the desired-release and job-dispatch
Expand Down
Loading