diff --git a/internal/server/converter.go b/internal/server/converter.go index f42f872..2c364a4 100644 --- a/internal/server/converter.go +++ b/internal/server/converter.go @@ -2,6 +2,7 @@ package server import ( "fmt" + "strings" exposev1 "github.com/agynio/expose/.gen/go/agynio/api/expose/v1" "github.com/agynio/expose/internal/store" @@ -21,6 +22,9 @@ func parseUUID(value string, field string) (uuid.UUID, error) { } func toProtoExposure(exposure store.Exposure) *exposev1.Exposure { + if exposure.Status == store.ExposureStatusActive && !exposureResourcesComplete(exposure) { + panic(fmt.Sprintf("active exposure %s has incomplete OpenZiti resources", exposure.ID)) + } return &exposev1.Exposure{ Meta: &exposev1.EntityMeta{ Id: exposure.ID.String(), @@ -38,6 +42,13 @@ func toProtoExposure(exposure store.Exposure) *exposev1.Exposure { } } +func exposureResourcesComplete(exposure store.Exposure) bool { + return strings.TrimSpace(exposure.OpenZitiServiceID) != "" && + strings.TrimSpace(exposure.OpenZitiBindPolicyID) != "" && + strings.TrimSpace(exposure.OpenZitiDialPolicyID) != "" && + strings.TrimSpace(exposure.URL) != "" +} + func toProtoExposureStatus(status store.ExposureStatus) exposev1.ExposureStatus { switch status { case store.ExposureStatusProvisioning: diff --git a/internal/server/converter_test.go b/internal/server/converter_test.go index 44e71c3..60e3b98 100644 --- a/internal/server/converter_test.go +++ b/internal/server/converter_test.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "strings" "testing" @@ -61,6 +62,29 @@ func TestParseUUID(t *testing.T) { } } +func TestToProtoExposurePanicsForActiveWithoutResources(t *testing.T) { + exposure := store.Exposure{ + ID: uuid.New(), + WorkloadID: uuid.New(), + AgentID: uuid.New(), + Port: 8080, + Status: store.ExposureStatusActive, + } + + defer func() { + recovered := recover() + if recovered == nil { + t.Fatal("expected panic for active exposure with incomplete resources") + } + message := fmt.Sprint(recovered) + if !strings.Contains(message, "incomplete OpenZiti resources") { + t.Fatalf("unexpected panic: %v", recovered) + } + }() + + _ = toProtoExposure(exposure) +} + func TestToProtoExposureStatus(t *testing.T) { tests := []struct { name string diff --git a/internal/server/server_test.go b/internal/server/server_test.go index fbb2a72..fd04635 100644 --- a/internal/server/server_test.go +++ b/internal/server/server_test.go @@ -695,18 +695,24 @@ func TestAddExposureExplicitClusterAdmin(t *testing.T) { created = exposure return nil } - storeMock.updateExposureProvisioned = func(context.Context, uuid.UUID, store.ExposureResourceIDs) error { + var provisioned store.ExposureResourceIDs + storeMock.updateExposureProvisioned = func(_ context.Context, _ uuid.UUID, resources store.ExposureResourceIDs) error { + provisioned = resources return nil } storeMock.getExposure = func(_ context.Context, id uuid.UUID) (store.Exposure, error) { return store.Exposure{ - ID: id, - WorkloadID: workloadID, - AgentID: agentID, - Port: 8080, - Status: store.ExposureStatusActive, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), + ID: id, + WorkloadID: workloadID, + AgentID: agentID, + Port: 8080, + OpenZitiServiceID: provisioned.OpenZitiServiceID, + OpenZitiBindPolicyID: provisioned.OpenZitiBindPolicyID, + OpenZitiDialPolicyID: provisioned.OpenZitiDialPolicyID, + URL: provisioned.URL, + Status: store.ExposureStatusActive, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), }, nil } @@ -1229,13 +1235,17 @@ func TestListExposuresSuccess(t *testing.T) { listExposuresByWorkload: func(_ context.Context, id uuid.UUID, size int32, cursor *store.PageCursor) (store.ListResult, error) { return store.ListResult{ Exposures: []store.Exposure{{ - ID: workloadID, - WorkloadID: workloadID, - AgentID: uuid.New(), - Port: 8080, - Status: store.ExposureStatusActive, - CreatedAt: time.Now(), - UpdatedAt: time.Now(), + ID: workloadID, + WorkloadID: workloadID, + AgentID: uuid.New(), + Port: 8080, + OpenZitiServiceID: "svc-id", + OpenZitiBindPolicyID: "bind-id", + OpenZitiDialPolicyID: "dial-id", + URL: "http://exposed.ziti:8080", + Status: store.ExposureStatusActive, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), }}, NextCursor: &store.PageCursor{AfterID: nextID}, }, nil