serve: --ops, so a standalone iam is probeable again
The graft moved /healthz, /readyz and /metrics off the public listener onto zip's ops listener, which is right: a host owns liveness for what it composes, and a child registering /healthz silently takes over the shared binary's. But nothing brought that listener up. Standalone, iam answered 8000 with no /healthz on it, both probes took 404, the pod never went Ready, its Service kept zero endpoints, and every caller resolving identity through iam.hanzo.svc got connection refused. The ops listener is now stated the way the other two already were — an address, in the same grammar, on the same line: iam serve --zap :9653 --http http://:8000 --ops http://:9090 Default on, because this binary's deployment is standalone. --ops "" is the grafted case, where the host owns the ops port (HIP-0106 §1.3(f)). Needs zip v1.18.23: OPS_PORT built a bare address, a bare address is ZAP, and a kubelet cannot probe a ZAP socket. Verified: --ops http://:9090 gives three listeners, ops on http, /healthz 200 "ok" /readyz 200 "ready" /metrics 200, and 8000 404s all three. --ops "" gives two listeners and nothing on 9090. gofmt also reordered a pre-existing import; main.go was unformatted at HEAD. Co-authored-by: Hanzo Dev <dev@hanzo.ai>
This commit is contained in:
@@ -19,7 +19,7 @@ retract [v1.0.0, v1.31.37] // Casdoor lineage; moved to github.com/hanzoai/iam-v
|
||||
require (
|
||||
github.com/hanzoai/orm v0.6.16
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/zap-proto/zip v1.18.22
|
||||
github.com/zap-proto/zip v1.18.23
|
||||
golang.org/x/crypto v0.53.0
|
||||
)
|
||||
|
||||
|
||||
@@ -211,6 +211,8 @@ github.com/zap-proto/zip v1.18.21 h1:h90f1DReRU2yAigoAPjSM6BFX0gRbata2TDVNmaeKbM
|
||||
github.com/zap-proto/zip v1.18.21/go.mod h1:EKMmUX9wCPvpkhpMBQRqa17YVXNXRYEjj7X+65Y+J9E=
|
||||
github.com/zap-proto/zip v1.18.22 h1:lTQeI1+uIiZpCCWkV2N3ti6mPTfO1CI2oTj2b4DFLtk=
|
||||
github.com/zap-proto/zip v1.18.22/go.mod h1:EKMmUX9wCPvpkhpMBQRqa17YVXNXRYEjj7X+65Y+J9E=
|
||||
github.com/zap-proto/zip v1.18.23 h1:bcJbDYxXa78OGVwF/+YWKd77rXfOil6txVwrGsW/2ko=
|
||||
github.com/zap-proto/zip v1.18.23/go.mod h1:EKMmUX9wCPvpkhpMBQRqa17YVXNXRYEjj7X+65Y+J9E=
|
||||
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
|
||||
@@ -37,8 +37,8 @@ import (
|
||||
"github.com/hanzoai/iam/internal/oidc"
|
||||
"github.com/hanzoai/iam/internal/provision"
|
||||
"github.com/hanzoai/iam/internal/routes"
|
||||
_ "github.com/hanzoai/iam/pkg/schema" // registers the v2 entity kinds
|
||||
"github.com/hanzoai/iam/internal/seed"
|
||||
_ "github.com/hanzoai/iam/pkg/schema" // registers the v2 entity kinds
|
||||
"github.com/hanzoai/iam/pkg/store"
|
||||
)
|
||||
|
||||
@@ -66,12 +66,12 @@ func main() {
|
||||
}
|
||||
|
||||
func serveCmd() *cobra.Command {
|
||||
var storeBackend, dbPath, zapAddr, httpAddr, initData string
|
||||
var storeBackend, dbPath, zapAddr, httpAddr, opsAddr, initData string
|
||||
cmd := &cobra.Command{
|
||||
Use: "serve",
|
||||
Short: "Open the entity store and serve the IAM API",
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
return serve(cmd.Context(), storeBackend, dbPath, zapAddr, httpAddr, initData)
|
||||
return serve(cmd.Context(), storeBackend, dbPath, zapAddr, httpAddr, opsAddr, initData)
|
||||
},
|
||||
}
|
||||
f := cmd.Flags()
|
||||
@@ -79,11 +79,17 @@ func serveCmd() *cobra.Command {
|
||||
f.StringVar(&dbPath, "db", "data/iam.db", "SQLite database path (store=sqlite)")
|
||||
f.StringVar(&zapAddr, "zap", ":9653", "ZAP primary listen address")
|
||||
f.StringVar(&httpAddr, "http", "http://:8080", "HTTP edge listen address")
|
||||
// The third listener, said the same way as the other two. /healthz, /readyz
|
||||
// and /metrics live here and never on the public port, so a probe does not
|
||||
// queue behind public traffic (HIP-0119 §1). Empty means this process owns no
|
||||
// ops listener — right for a grafted iam, where the HOST owns liveness
|
||||
// (HIP-0106 §1.3(f)); wrong for a standalone one, which is why it defaults on.
|
||||
f.StringVar(&opsAddr, "ops", zip.DefaultOpsAddr, "ops listen address for /healthz, /readyz and /metrics (empty: none)")
|
||||
f.StringVar(&initData, "init-data", "", "path to init_data.json to seed on boot (new-only; ${VAR} from env)")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func serve(ctx context.Context, storeBackend, dbPath, zapAddr, httpAddr, initData string) error {
|
||||
func serve(ctx context.Context, storeBackend, dbPath, zapAddr, httpAddr, opsAddr, initData string) error {
|
||||
db, err := openStore(storeBackend, dbPath)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -115,7 +121,7 @@ func serve(ctx context.Context, storeBackend, dbPath, zapAddr, httpAddr, initDat
|
||||
// endpoint. The authz Guard gates it like any other route (fail-closed), but
|
||||
// an identity service has no need to expose its admin CRUD as an agent tool
|
||||
// surface, so it is disabled outright — one fewer surface to defend.
|
||||
app := zip.New(zip.Config{AppName: "iam", MCP: zip.MCPConfig{Disabled: true}})
|
||||
app := zip.New(zip.Config{AppName: "iam", MCP: zip.MCPConfig{Disabled: true}, OpsAddr: opsAddr})
|
||||
routes.Route(app, db)
|
||||
app.OnShutdown(func(context.Context) error { return db.Close() })
|
||||
|
||||
|
||||
Reference in New Issue
Block a user