Files
bri-sandbox-development-pla…/control-plane/internal/store/store_test.go
T
Achmad 55d7705c63 Slice 2: real auth, agent-mediated repo/branch listing, deployment list from SQLite
- protocol: add RepoInfo, RouteOverride; add HostPort, SandboxID to DeployRequest.
- ws hub: add CallAgent for sync request/response RPCs over the agent WS,
  and DeliverAgentReply to route {op:reply} frames back to the caller.
  UnregisterAgent now also fails any pending RPCs so callers don't hang.
- agent-micro: new op handlers list_repos, list_branches, probe.
  Wire protocol.Event frames use json.RawMessage so each op decodes
  its own data shape.
- agent-gateway: same op handlers (list_repos/list_branches/probe) plus
  push_routes, which the gateway uses to rewrite the api-gateway
  config.php. Detailed in a later commit.
- control-plane login: validateViaAgent now calls CallAgent('probe')
  against the gateway agent (git ls-remote), replacing the
  accept-any-creds stub.
- control-plane repos: handleListRepos and handleListBranches forward
  to the agents via list_repos / list_branches RPCs, replacing the
  hardcoded fixtures.
- control-plane deployments: split into its own file. handleListDeployments
  reads from SQLite (was hardcoded []). handleCreateDeployment now
  supports sandbox-scoped deploys with a host port + env merge.
  handleStopDeployment looks up the node from the deployment row.
- store: split into store.go + deployments.go. The Deployment type
  adds sandboxId, containerId, hostPort. StartDeploymentInSandbox,
  SetContainerID, ListDeployments, GetDeployment, LatestDeploymentBySandboxService
  are new.
- store_test.go: round-trips every Slice-2 path (env, sandbox,
  template, clone, routes, deployment).
- .gitignore: track bin/ — the build runs on a separate Linux box
  with the golang:1.24 toolchain, and the binaries are SCPed from
  there to the company VMs (92 / 186). The VMs have no internet.
- Tracked bin/{control-plane,agent-micro,agent-gateway}.
2026-06-24 03:58:53 +00:00

115 lines
3.1 KiB
Go

package store_test
import (
"os"
"testing"
"github.com/sdp/control-plane/internal/store"
)
// TestSandboxRoundTrip exercises the Slice-2 CRUD path against a
// throwaway data directory. The build pipeline runs this; the
// real deployment uses the control plane's HTTP layer.
func TestSandboxRoundTrip(t *testing.T) {
dir, err := os.MkdirTemp("", "sdp-store-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
st, err := store.Open(dir)
if err != nil {
t.Fatalf("open: %v", err)
}
defer st.Close()
// env
e := store.Environment{ID: "e1", Name: "dev", Values: map[string]string{"FOO": "bar"}}
if err := st.CreateEnvironment(e); err != nil {
t.Fatalf("env create: %v", err)
}
got, err := st.GetEnvironment("e1")
if err != nil {
t.Fatalf("env get: %v", err)
}
if got.Values["FOO"] != "bar" {
t.Fatalf("env values: got %v", got.Values)
}
// sandbox
sb := store.Sandbox{ID: "s1", Name: "qa", GatewayBranch: "develop", GatewayHostPort: 8080,
Services: []store.SandboxService{
{ID: "s1-haven", SandboxID: "s1", Repo: "haven", Branch: "main", HostPort: 9001, UseOCP: false, EnvID: "e1"},
}}
if err := st.CreateSandbox(sb); err != nil {
t.Fatalf("sandbox create: %v", err)
}
gotsb, err := st.GetSandbox("s1")
if err != nil {
t.Fatalf("sandbox get: %v", err)
}
if len(gotsb.Services) != 1 || gotsb.Services[0].Repo != "haven" {
t.Fatalf("sandbox services: %+v", gotsb.Services)
}
// template + clone
t1 := store.Template{ID: "t1", Name: "acct", GatewayBranch: "develop",
Services: []store.TemplateService{
{ID: "t1-haven", TemplateID: "t1", Repo: "haven", Branch: "feature/x", HostPort: 9001, UseOCP: false},
}}
if err := st.CreateTemplate(t1); err != nil {
t.Fatalf("tpl create: %v", err)
}
if err := st.CloneTemplateIntoSandbox("t1", store.Sandbox{ID: "s2", Name: "qa2"}); err != nil {
t.Fatalf("clone: %v", err)
}
cs, err := st.GetSandbox("s2")
if err != nil {
t.Fatalf("cloned get: %v", err)
}
if cs.GatewayBranch != "develop" || len(cs.Services) != 1 {
t.Fatalf("cloned content: %+v", cs)
}
// routes
if err := st.SetRoutes("s1", []store.Route{
{ID: "r1", SandboxID: "s1", Key: "haven", Value: "http://172.18.136.92:9001"},
{ID: "r2", SandboxID: "s1", Key: "eredar", Value: "", TargetOCP: true},
}); err != nil {
t.Fatalf("routes: %v", err)
}
rs, err := st.ListRoutes("s1")
if err != nil {
t.Fatalf("routes list: %v", err)
}
if len(rs) != 2 {
t.Fatalf("routes count: %d", len(rs))
}
// deployment
if err := st.StartDeploymentInSandbox("d1", "s1", "haven", "main", "achmad", 9001); err != nil {
t.Fatalf("dep start: %v", err)
}
d, err := st.GetDeployment("d1")
if err != nil {
t.Fatalf("dep get: %v", err)
}
if d.HostPort != 9001 || d.SandboxID != "s1" {
t.Fatalf("dep content: %+v", d)
}
if err := st.SetContainerID("d1", "container-abc"); err != nil {
t.Fatalf("container id: %v", err)
}
d, _ = st.GetDeployment("d1")
if d.ContainerID != "container-abc" {
t.Fatalf("container id roundtrip: %q", d.ContainerID)
}
deps, err := st.ListDeployments("s1", 10)
if err != nil {
t.Fatalf("deps list: %v", err)
}
if len(deps) != 1 {
t.Fatalf("deps count: %d", len(deps))
}
}