node

package
v1.6.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 23, 2026 License: AGPL-3.0 Imports: 18 Imported by: 0

Documentation

Overview

Package node manages Docker host (server) records and their reachability.

Index

Constants

View Source
const IngressOverlay = "miabi-ingress"

IngressOverlay is the single shared, attachable Swarm overlay the central Goma gateway joins to reach every clustered app's service VIP for public (north- south) ingress. Cluster (service) apps attach to it in addition to their per-workspace east-west overlay. Because it carries only gateway↔VIP traffic (each service registers just its globally-unique upstream alias here, not its tenant-scoped name), east-west isolation between workspaces is unaffected.

Variables

View Source
var (
	ErrNodeNotFound = errors.New("node not found")
	ErrNameRequired = errors.New("node name is required")
	ErrLocalNode    = errors.New("the local node cannot be modified this way")
	ErrBadToken     = errors.New("invalid agent token")
	ErrNodeCordoned = errors.New("node is cordoned and cannot accept new placements")
	// ErrConnectivityAckRequired is returned when an update changes the node's
	// reachability settings without the caller acknowledging the impact.
	ErrConnectivityAckRequired = &connectivityAckError{}
)
View Source
var AppNetwork = "miabi"

AppNetwork is the shared Docker network Goma Gateway and managed app containers join (the proxy gateway network). Configurable via MIABI_PROXY_NETWORK; set once at startup with SetAppNetwork.

Functions

func AppAlias

func AppAlias(app *models.Application) string

AppAlias is the stable network DNS alias for an application's active container, used as the reverse-proxy upstream so it survives redeploys. It is the app's stored Alias ("mb-app-<token>-<id>"); legacy apps with no stored alias fall back to "mb-app-<id>".

func CanaryAlias

func CanaryAlias(app *models.Application) string

CanaryAlias is the network DNS alias for an application's canary container, run alongside the stable release during a canary deployment. Only the stable release answers AppAlias, so the proxy can split weighted traffic between the two distinct aliases.

func NewAppAlias

func NewAppAlias(token string, appID uint) string

NewAppAlias builds a fresh stable alias for a newly created app.

func SetAppNetwork

func SetAppNetwork(name string)

SetAppNetwork overrides the gateway network name (call once at startup, before Bootstrap or any deploy).

Types

type NodeInput

type NodeInput struct {
	Name           string
	Address        string
	PublicIP       string
	PublicHostname string
	Connectivity   models.ServerConnectivity
	AccessMode     models.ServerAccessMode
	// DockerEndpoint is the host for non-agent modes (unix://… / tcp://host:2376).
	DockerEndpoint string
	TLSCACert      string // api, optional (PEM)
	TLSCert        string // api, optional (PEM)
	TLSKey         string // api, optional (PEM; stored encrypted)
	// Acknowledge confirms the caller accepts that a reachability change may
	// briefly interrupt the workloads running on the node. Required whenever the
	// update actually changes connectivity/access mode/endpoint/address/TLS.
	Acknowledge bool
}

NodeInput is the create/update payload for a remote node. The TLS key is plaintext on input and encrypted at rest.

type NodeLimitError

type NodeLimitError struct{ Limit int }

NodeLimitError is returned when registering a node would exceed the edition's node cap. It exposes a stable Code() and a curated Message() so the API envelope surfaces NODE_LIMIT_REACHED with an upgrade-oriented message rather than the generic status word.

func (*NodeLimitError) Code

func (e *NodeLimitError) Code() string

func (*NodeLimitError) Error

func (e *NodeLimitError) Error() string

func (*NodeLimitError) Message

func (e *NodeLimitError) Message() string

type Service

type Service struct {
	// contains filtered or unexported fields
}

func NewService

func NewService(repo *repositories.ServerRepository, dockerClient docker.Client) *Service

func (*Service) AdoptGateway

func (s *Service) AdoptGateway(id uint, container, image, configYAML string) (*models.Server, error)

AdoptGateway tracks a pre-existing gateway container as this node's gateway (import). It records the container name + image, optionally copies the gateway's existing config into the node's stored config, switches the node to edge-gateway connectivity, and stamps the deploy time — without recreating anything, so the running gateway is untouched.

func (*Service) Authenticate

func (s *Service) Authenticate(token string) (*models.Server, error)

Authenticate resolves the node an agent token belongs to (constant-time-ish via hash lookup).

func (*Service) AuthenticateProvider

func (s *Service) AuthenticateProvider(slug, token string) (*models.Server, error)

AuthenticateProvider resolves the node a Goma HTTP-provider request belongs to, accepting either the agent join token or the node's gateway token. The slug in the URL must match the resolved node.

func (*Service) Bootstrap

func (s *Service) Bootstrap(ctx context.Context, endpoint string)

Bootstrap registers the local node, pings the daemon to set its status, and ensures the managed Docker network exists. Non-fatal: logs and continues if Docker is unreachable so the API can still serve.

func (*Service) CreateNode

func (s *Service) CreateNode(in NodeInput) (*models.Server, string, error)

CreateNode registers a remote node. For agent mode it returns a one-time join token (only its hash is stored); other modes return an empty token.

func (*Service) DeleteNode

func (s *Service) DeleteNode(id uint) error

DeleteNode removes a remote node record.

func (*Service) FindBySwarmNodeID added in v1.3.0

func (s *Service) FindBySwarmNodeID(swarmNodeID string) (*models.Server, error)

FindBySwarmNodeID resolves the node backing a swarm node id.

func (*Service) GatewayRedisPassword

func (s *Service) GatewayRedisPassword(id uint) (string, error)

GatewayRedisPassword returns the per-node edge-gateway Redis password (decrypted), minting and persisting one (encrypted) on first use. Stable across redeploys so the gateway and its Redis keep matching credentials.

func (*Service) GatewayToken

func (s *Service) GatewayToken(id uint) (string, error)

GatewayToken returns the node's edge-gateway provider token (decrypted), minting and persisting one (encrypted) on first use. Unlike the join token it is recoverable, so the gateway can be (re)deployed on demand.

func (*Service) Get

func (s *Service) Get(id uint) (*models.Server, error)

Get returns a node by id.

func (*Service) IDByUID

func (s *Service) IDByUID(uid string) (uint, error)

IDByUID resolves a node's portable uid to its numeric id.

func (*Service) LearnEndpoint

func (s *Service) LearnEndpoint(id uint, ip, hostname string)

LearnEndpoint fills a node's public IP and/or hostname discovered from its agent connection, so an admin doesn't have to know them when adding the node: ip is the agent's source address as seen by the control plane, hostname is self-reported (X-Agent-Hostname). Non-destructive — it only fills fields the admin left blank, so an explicit value is never overwritten. Only a routable public IP is adopted (a private/NAT/loopback source would be misleading).

func (*Service) LearnSwarmNodeID added in v1.3.0

func (s *Service) LearnSwarmNodeID(id uint, swarmNodeID string)

LearnSwarmNodeID records the swarm node id the agent read from its own Docker engine at connect (X-Agent-Swarm-Node-ID).

This is how a Miabi node gets mapped to its swarm node in every case, not just the one where Miabi did the joining. The control plane can only fill SwarmNodeID itself when it ran the `swarm join` (see cluster.JoinNode); a host joined with `docker swarm join`, or one that was already a member when Miabi met it, stayed unmapped forever. That is not cosmetic — an unmapped node cannot be resolved from a service's task, which is precisely what makes a replica's logs and metrics unreachable. The node is the authority on which node it is, so let it say.

Unlike LearnEndpoint this OVERWRITES: a node can leave one swarm and join another, and its own report is always more current than ours. An empty value is ignored rather than treated as "left the swarm" — an older agent sends nothing at all, and we must not wipe a good id because of it. The leave paths clear it explicitly (cluster.LeaveNode).

func (*Service) List

func (s *Service) List(ctx context.Context) ([]models.Server, error)

List returns all servers, refreshing the local node's live status.

func (*Service) MarkConnected

func (s *Service) MarkConnected(id uint, agentVersion string)

MarkConnected records that a node's agent connected.

func (*Service) MarkDisconnected

func (s *Service) MarkDisconnected(id uint)

MarkDisconnected records that a node's agent dropped.

func (*Service) MarkGatewayDeployed

func (s *Service) MarkGatewayDeployed(id uint)

MarkGatewayDeployed stamps the node's last successful gateway deploy time and clears any imported-gateway tracking (a fresh install supersedes an import).

func (*Service) NameBySwarmNodeID

func (s *Service) NameBySwarmNodeID(swarmNodeID string) string

NameBySwarmNodeID resolves a swarm node id to a node's Miabi display name, so a cluster app's real replica placement can be shown by name. Returns "" when no node record carries that swarm id (the caller then falls back to a short id).

func (*Service) Placeable

func (s *Service) Placeable(serverID uint) error

Placeable validates that a node can accept a new resource (app/db/volume). The local node (0) is always placeable; a remote node must exist and not be cordoned. (Reachability is enforced separately when the operation runs.)

func (*Service) RegenerateToken

func (s *Service) RegenerateToken(id uint) (string, error)

RegenerateToken issues a fresh join token for a node, invalidating the old one.

func (*Service) RegisterClusterNode added in v1.3.0

func (s *Service) RegisterClusterNode(swarmNodeID, hostname string) (*models.Server, error)

RegisterClusterNode creates the record for a swarm worker that registered itself through the global agent service.

The caller (cluster.AuthenticateAgent) has already verified the swarm node id is a member of THIS swarm, so this is not an open registration endpoint — the machine is one the swarm already trusts.

The node is marked AutoJoined: the cluster brought it in, an admin did not. It has no join token of its own (it authenticates with the cluster token), and it defaults to port-forward connectivity like any other node — which in cluster mode is moot, since ingress reaches it over the overlay.

func (*Service) ReleaseGateway

func (s *Service) ReleaseGateway(id uint) (*models.Server, error)

ReleaseGateway stops tracking an imported gateway without touching the container (the inverse of AdoptGateway).

func (*Service) SetCordoned

func (s *Service) SetCordoned(id uint, cordoned bool) error

SetCordoned toggles a node's drain flag (no new placements when cordoned).

func (*Service) SetGatewayConfig

func (s *Service) SetGatewayConfig(id uint, config string) (*models.Server, error)

SetGatewayConfig stores a node's custom edge-gateway config (empty resets to the rendered default). Returns the updated node.

func (*Service) SetGatewayImage

func (s *Service) SetGatewayImage(id uint, image string) (*models.Server, error)

SetGatewayImage stores a node's edge-gateway image override (empty resets to the resolved default). Returns the updated node.

func (*Service) SetGatewayUpdate

func (s *Service) SetGatewayUpdate(id uint, p *models.GatewayUpdateProgress) error

SetGatewayUpdate persists the node's in-flight gateway update progress (nil clears it). Used by the safe-update flow so progress survives a reconnect.

func (*Service) SetNodeLimit

func (s *Service) SetNodeLimit(fn func() int)

SetNodeLimit wires the resolved edition node cap (manager + remotes). The closure is re-evaluated on every node registration so a license install or lapse takes effect without a restart. A nil closure or a negative return means unlimited.

func (*Service) SetSwarmNodeID

func (s *Service) SetSwarmNodeID(id uint, swarmNodeID string) error

SetSwarmNodeID records (or clears) the Docker Swarm node ID a node maps to, so the Nodes page can correlate it to `docker node ls`. Idempotent: a no-op when the value is unchanged, to avoid write churn on every cluster refresh.

func (*Service) UpdateNode

func (s *Service) UpdateNode(id uint, in NodeInput) (*models.Server, error)

UpdateNode edits a remote node's reachability settings. Credential fields are only replaced when non-empty (so an unchanged form keeps existing secrets).

func (*Service) WorkloadImpact

func (s *Service) WorkloadImpact(id uint) (apps int64, databases int64, err error)

WorkloadImpact reports how many applications and database instances are placed on the node, so the UI can warn what a connectivity change would affect.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL