Files
zeekay 2a40ec664c ingress is a subsystem, so it imports zip and nothing of its host
Mount took a cloud.Deps in order to read two fields out of it, Brand and
Domain, and handed both straight back on /_/ingress/config. Nothing else in
that struct was ever touched, and carrying it cost the whole dependency:
hanzoai/cloud ships two editions under one module path, so cloud.Deps is a
different type in each and a package that names it can be composed by exactly
one of them. This repo has already been on both sides of that. Days ago its
go.mod pinned cloud v1.801.293, where Deps has no Logger field and there is no
package-level Register at all; today it pins v0.1.1, where both exist. One file,
two truths, depending on which edition happened to be pinned. So ingress takes
the two strings now and cloud is out of go.mod.

The other half of the coupling was direction. An init() pushed ingress into
cloud.Registry, so the host had to be imported for the subsystem to announce
itself, and the graph closed on itself. App builds and returns its own *zip.App
instead: a host holds what it gets back and mounts it where it likes, and
ingress no longer knows a registry exists. The logger came out of the same
struct and is the process default now, which cannot be nil and so needs no
check.

None of this was ever compiled. It sat behind a `cloud` build tag that no make
target, no CI job and no Dockerfile passed, which is how a file gets to be
valid against one edition of its dependency and dead against the other without
anyone noticing. The tag protected nothing either -- cmd/ingress does not
import this package, and `go list -deps ./cmd/ingress` still shows no zip -- so
it is gone, and `.` joins test-unit and the hanzo.yml test list. A surface that
nothing builds is how this rotted the first time.
2026-08-10 12:59:57 -07:00

55 lines
1.2 KiB
Go

// Copyright © 2026 Hanzo AI. MIT License.
package ingress
import (
"io"
"net/http/httptest"
"strings"
"testing"
)
func TestApp_ServesHealthAndConfig(t *testing.T) {
t.Setenv("INGRESS_ENTRYPOINTS", "web,websecure")
t.Setenv("INGRESS_PROVIDERS", "kubernetes,file")
t.Setenv("INGRESS_ACME_ENABLED", "true")
app, err := App("hanzo", "api.hanzo.ai")
if err != nil {
t.Fatalf("App: %v", err)
}
for _, tc := range []struct {
path string
want []string
}{
{"/_/ingress/healthz", []string{`"service":"ingress"`}},
{"/_/ingress/config", []string{
`"brand":"hanzo"`,
`"domain":"api.hanzo.ai"`,
`"entrypoints":["web","websecure"]`,
`"providers":["kubernetes","file"]`,
`"acme_enabled":true`,
}},
} {
t.Run(tc.path, func(t *testing.T) {
resp, err := app.Fiber().Test(httptest.NewRequest("GET", tc.path, nil))
if err != nil {
t.Fatalf("Test: %v", err)
}
if resp.StatusCode != 200 {
t.Fatalf("status: got %d want 200", resp.StatusCode)
}
raw, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("read body: %v", err)
}
for _, want := range tc.want {
if !strings.Contains(string(raw), want) {
t.Fatalf("body: got %q, want substring %q", string(raw), want)
}
}
})
}
}