Files
zeekay 6de27ba73b feat: nchain — composable blockchain node infrastructure operator
7 CRDs (nchain.hanzo.ai/v1alpha1):
  - NodeCluster: protocol-agnostic blockchain node cluster
  - Chain: blockchain/subnet/L2 definition
  - Indexer: blockchain data indexer
  - Explorer: block explorer UI+API
  - Bridge: cross-chain bridge
  - Gateway: RPC/API gateway with routing + rate limiting
  - Network: top-level composer (creates all child CRDs)

Protocol driver architecture:
  - LuxDriver: full luxd flag generation, snow consensus, staking keys,
    snapshot restore, chain tracking, startup scripting (487 lines)
  - EthereumDriver: reth command generation, standard EVM ports
  - GenericDriver: passthrough for any containerized node

Key design principles:
  - Composable: each CRD stands alone or composes via Network
  - Orthogonal: validators, indexers, explorers, bridges, gateways
    are independent concerns with independent CRDs
  - Complete: covers the full lifecycle from bootstrap to production
  - Protocol-agnostic: driver pattern isolates blockchain-specific logic
  - Do everything exactly once: one way to manage any blockchain

Replaces both HanzoNetwork (hanzo-operator) and LuxNetwork (lux-operator)
with a unified, deeper, protocol-agnostic alternative.

6,215 lines Go | go build + go vet clean
2026-03-03 06:43:22 -08:00

56 lines
1.5 KiB
Go

package controller
import (
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/predicate"
)
// specChangePred triggers reconciliation on create events or when the
// spec changes (generation bump). It ignores status-only updates and
// delete events.
func specChangePred() predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(_ event.CreateEvent) bool {
return true
},
UpdateFunc: func(e event.UpdateEvent) bool {
if e.ObjectOld == nil || e.ObjectNew == nil {
return false
}
return e.ObjectNew.GetGeneration() != e.ObjectOld.GetGeneration()
},
DeleteFunc: func(_ event.DeleteEvent) bool {
return false
},
GenericFunc: func(_ event.GenericEvent) bool {
return false
},
}
}
// ownedResourcePred triggers reconciliation on status changes to owned
// resources (Deployments, StatefulSets). It detects status changes by
// comparing resource versions when generation is unchanged.
func ownedResourcePred() predicate.Predicate {
return predicate.Funcs{
CreateFunc: func(_ event.CreateEvent) bool {
return false
},
UpdateFunc: func(e event.UpdateEvent) bool {
if e.ObjectOld == nil || e.ObjectNew == nil {
return false
}
if e.ObjectNew.GetGeneration() == e.ObjectOld.GetGeneration() {
return e.ObjectNew.GetResourceVersion() != e.ObjectOld.GetResourceVersion()
}
return false
},
DeleteFunc: func(_ event.DeleteEvent) bool {
return true
},
GenericFunc: func(_ event.GenericEvent) bool {
return false
},
}
}