mirror of
https://github.com/hanzoai/ingress.git
synced 2026-10-26 02:47:15 +00:00
* feat(cloud-mount): port ingress to HIP-0106 Mount(*zip.App, cloud.Deps)
Add pkg/ingress/mount.go (build tag: cloud) exposing the canonical
HIP-0106 contract. Hanzo Ingress is k8s-native: the full reverse-proxy
/ TLS / providers machinery stays in cmd/traefik (standalone
hanzo-ingress at the cluster edge). The unified cloud binary
co-resident with Ingress only needs:
- /_/ingress/healthz — native zip endpoint so liveness probes survive
even when the edge proxy is reloading
- /_/ingress/config — read-only projection of the deployment's
expected entrypoints / providers / acme state. Sourced from env
(INGRESS_ENTRYPOINTS, INGRESS_PROVIDERS, INGRESS_ACME_ENABLED).
Nothing else mounts: cloud-mode does NOT import pkg/config/static
(would pull in the entire provider tree: Kubernetes, Docker, Consul,
AWS, Azure, GCP, Cloudflare, Akamai, etc. — every provider stays in
the standalone binary).
Build tag isolation: the standalone hanzo-ingress binary must not pull
hanzoai/cloud + hanzoai/zip. The `//go:build cloud` constraint on
mount.go + mount_test.go keeps the default build path clean. Build the
cloud variant with `-tags=cloud`.
Wiring:
- init() registers ("ingress", order=90) in cloud.Registry — runs
after gateway(80) so identity headers are already injected.
- go.mod gains the hanzoai/cloud + hanzoai/zip requires (gated by
tag at the import sites), pinned via local ../ replace.
Tests:
- TestMount_RegistersHealthAndConfig boots a fresh zip.App, mounts
ingress with sample env, asserts /_/ingress/healthz and
/_/ingress/config respond with the expected JSON.
- cmd/traefik (the standalone hanzo-ingress binary) still builds
clean in the default mode.
Schema: schema/ingress.zap describes Health + Config services for the
zapc codegen path.
* refactor: collapse pkg/ingress/ → root for clean import path
Subsystem code lives in package ingress at repo root. Importers now use
`github.com/hanzoai/ingress` (no /pkg/ingress/ nesting). Standalone shim moved
to cmd/ingress/ where applicable.
Per Hanzo Go-stdlib pattern: repo IS the package.
* refactor: flatten import path — github.com/hanzoai/cloud (drop /pkg/cloud)
84 lines
1.8 KiB
Go
84 lines
1.8 KiB
Go
// Copyright © 2026 Hanzo AI. MIT License.
|
|
|
|
//go:build cloud
|
|
// +build cloud
|
|
|
|
package ingress
|
|
|
|
import (
|
|
"io"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/hanzoai/cloud"
|
|
luxlog "github.com/luxfi/log"
|
|
|
|
"github.com/hanzoai/zip"
|
|
)
|
|
|
|
func TestMount_RegistersHealthAndConfig(t *testing.T) {
|
|
if !registryContains("ingress") {
|
|
t.Fatalf("cloud.Registry missing 'ingress'; Names=%v", registryNames())
|
|
}
|
|
|
|
t.Setenv("INGRESS_ENTRYPOINTS", "web,websecure")
|
|
t.Setenv("INGRESS_PROVIDERS", "kubernetes,file")
|
|
t.Setenv("INGRESS_ACME_ENABLED", "true")
|
|
|
|
app := zip.New(zip.Config{Logger: luxlog.New("test")})
|
|
deps := cloud.Deps{
|
|
Logger: luxlog.New("test"),
|
|
Brand: "hanzo",
|
|
Domain: "api.hanzo.ai",
|
|
DataDir: t.TempDir(),
|
|
}
|
|
if err := Mount(app, deps); err != nil {
|
|
t.Fatalf("Mount: %v", err)
|
|
}
|
|
|
|
for _, tc := range []struct {
|
|
path string
|
|
want string
|
|
status int
|
|
}{
|
|
{"/_/ingress/healthz", `"service":"ingress"`, 200},
|
|
{"/_/ingress/config", `"brand":"hanzo"`, 200},
|
|
} {
|
|
t.Run(tc.path, func(t *testing.T) {
|
|
req := httptest.NewRequest("GET", tc.path, nil)
|
|
resp, err := app.Fiber().Test(req)
|
|
if err != nil {
|
|
t.Fatalf("Fiber Test: %v", err)
|
|
}
|
|
if resp.StatusCode != tc.status {
|
|
t.Fatalf("status: got %d want %d", resp.StatusCode, tc.status)
|
|
}
|
|
raw, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatalf("read body: %v", err)
|
|
}
|
|
if !strings.Contains(string(raw), tc.want) {
|
|
t.Fatalf("body: got %q, want substring %q", string(raw), tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func registryContains(name string) bool {
|
|
for _, s := range cloud.Registry {
|
|
if s.Name == name {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func registryNames() []string {
|
|
out := make([]string, 0, len(cloud.Registry))
|
|
for _, s := range cloud.Registry {
|
|
out = append(out, s.Name)
|
|
}
|
|
return out
|
|
}
|