mcpgateway

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Nov 6, 2026 License: MIT Imports: 43 Imported by: 0

Documentation

Overview

Package mcpgateway aggregates upstream MCP servers behind GoModel's authenticated /mcp endpoints. The gateway terminates the MCP protocol on both legs: it is an MCP server to clients and an MCP client to upstreams. It is also the credential boundary — client bearer tokens never reach an upstream; upstream credentials come only from server configuration.

Index

Constants

View Source
const ScopeHeader = "X-MCP-Servers"

ScopeHeader restricts a request's visible servers to a comma-separated subset, so one gateway key can serve differently-scoped clients without extra endpoints. Unknown names are ignored; an empty header means all.

View Source
const ServerSecretEntity = "mcp_servers"

ServerSecretEntity is the SecretKey.Entity of admin-managed MCP servers and the first segment of their secret field paths, for example "mcp_servers.github.headers.Authorization" (ADR-0014 §4). Header values are the secret fields: admin-managed servers have no stdio environment.

View Source
const ToolDiscoveryHeader = "X-MCP-Tool-Discovery"

ToolDiscoveryHeader overrides mcp.tool_discovery for one session ("off" or "search"), so a client without its own tool search can opt in while other clients of the same gateway keep the full tool list. Read at initialize; unknown values fall back to the configured default.

Variables

View Source
var ErrInvalidVirtualServer = errors.New("invalid virtual MCP server")

ErrInvalidVirtualServer marks a virtual server the admin API refuses: invalid fields, unknown or nested members, or a name a server holds.

View Source
var ErrNotFound = errors.New("mcp server not found")

ErrNotFound indicates a requested managed MCP server was not found.

View Source
var ErrServerNotVisible = errors.New("server is not available for this user path")

ErrServerNotVisible rejects a call from a session whose user path may no longer use the server.

View Source
var ErrToolExcluded = errors.New("tool is excluded by the gateway tool filters")

ErrToolExcluded rejects a call to a tool the operator filters hide.

View Source
var ErrVirtualNameTaken = errors.New("slug is used by a virtual MCP server")

ErrVirtualNameTaken marks a new admin-managed server whose slug a virtual server already serves at /mcp/{name}.

Functions

func NamespacedName

func NamespacedName(server, name string) string

NamespacedName is the aggregated-endpoint name for one upstream feature.

func Reencrypt added in v0.1.100

func Reencrypt(ctx context.Context, shared storage.Storage, box *encryption.Box) (encryption.Report, error)

Reencrypt seals every managed server header that is in plaintext or sealed with a data key other than box's active one.

func VirtualNameTakenError added in v0.1.100

func VirtualNameTakenError(name string) error

VirtualNameTakenError explains ErrVirtualNameTaken for one slug; it matches ErrVirtualNameTaken under errors.Is.

Types

type CatalogFeature

type CatalogFeature struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	ReadOnly    bool   `json:"read_only,omitempty"`
	Destructive bool   `json:"destructive,omitempty"`
}

CatalogFeature is one listed tool or prompt in a catalog view, using the upstream's original (un-prefixed) name. ReadOnly and Destructive relay the upstream's tool annotations only when it set them explicitly; they are hints for operators choosing tools to exclude, not guarantees.

type CatalogResource

type CatalogResource struct {
	URI         string `json:"uri"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
}

CatalogResource is one listed resource in a catalog view.

type CatalogTemplate

type CatalogTemplate struct {
	URITemplate string `json:"uri_template"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
}

CatalogTemplate is one listed resource template in a catalog view.

type CatalogView

type CatalogView struct {
	Server        string            `json:"server"`
	Status        ServerStatus      `json:"status"`
	Instructions  string            `json:"instructions,omitempty"`
	Tools         []CatalogFeature  `json:"tools"`
	ExcludedTools []CatalogFeature  `json:"excluded_tools"`
	Prompts       []CatalogFeature  `json:"prompts"`
	Resources     []CatalogResource `json:"resources"`
	Templates     []CatalogTemplate `json:"templates"`
}

CatalogView is the admin-facing snapshot of what one upstream currently exposes through the gateway. Tools are the ones the operator tool filters expose; ExcludedTools are discovered upstream but hidden by those filters.

type ManagedServer

type ManagedServer struct {
	// Name is the immutable ASCII slug and remains the storage primary key.
	Name        string `json:"slug"`
	DisplayName string `json:"name"`

	URL                 string            `json:"url"`
	Transport           string            `json:"transport"`
	Headers             map[string]string `json:"headers,omitempty"`
	Description         string            `json:"description,omitempty"`
	Enabled             bool              `json:"enabled"`
	AllowedTools        []string          `json:"allowed_tools,omitempty"`
	DisallowedTools     []string          `json:"disallowed_tools,omitempty"`
	UserPaths           []string          `json:"user_paths,omitempty"`
	DisallowedUserPaths []string          `json:"disallowed_user_paths,omitempty"`
	ToolTimeoutSeconds  int               `json:"tool_timeout_seconds,omitempty"`
	CreatedAt           time.Time         `json:"created_at"`
	UpdatedAt           time.Time         `json:"updated_at"`
}

ManagedServer is one admin-managed upstream server row. Stdio fields are deliberately absent: runtime-registered subprocesses are a remote code execution vector (see the gateway spec), so stdio servers exist only as declarative config.

func (ManagedServer) Spec

func (m ManagedServer) Spec() ServerSpec

Spec converts the row into a runtime spec.

func (*ManagedServer) Validate

func (m *ManagedServer) Validate() error

Validate checks the row against the same rules as declarative config, additionally rejecting the stdio transport. The receiver is only mutated (normalized transport/URL) once every check has passed.

type ManagedVirtualServer added in v0.1.104

type ManagedVirtualServer struct {
	Name          string    `json:"name"`
	Description   string    `json:"description,omitempty"`
	Servers       []string  `json:"servers"`
	ToolDiscovery string    `json:"tool_discovery,omitempty"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
	// Generation is a random token the store sets when it creates the row
	// and keeps across edits, so it tells one creation of a name from the
	// next. Rows created before it have none; see incarnation.
	Generation string `json:"-"`
}

ManagedVirtualServer is one admin-managed virtual server row.

func (ManagedVirtualServer) Spec added in v0.1.104

Spec converts the row into a runtime spec.

func (*ManagedVirtualServer) Validate added in v0.1.104

func (v *ManagedVirtualServer) Validate() error

Validate applies the declarative-config rules and normalizes the row in place. Member existence and name clashes depend on the running gateway, so Service.UpsertVirtual checks them.

type Manager

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

Manager owns the set of upstream connections and their catalogs.

func NewManager

func NewManager(httpClient *http.Client) *Manager

NewManager creates an empty manager. Apply installs the initial specs.

func (*Manager) Apply

func (m *Manager) Apply(specs []ServerSpec)

Apply reconciles the running upstreams with the desired specs: removed servers are closed, new servers are added, changed servers are redialed. Unchanged servers keep their live session and catalog; servers whose only change is the access policy (tool filters, user-path scopes) keep their session and apply the new policy in place. Initial connects run asynchronously so startup and admin edits never block on upstream IO.

func (*Manager) CallTool

func (m *Manager) CallTool(ctx context.Context, server, tool string, args json.RawMessage) (*mcp.CallToolResult, error)

CallTool forwards one tool call to the named server using the original (un-prefixed) tool name.

func (*Manager) Close

func (m *Manager) Close()

Close terminates the maintenance loop and every upstream session.

func (*Manager) GetPrompt

func (m *Manager) GetPrompt(ctx context.Context, server string, params *mcp.GetPromptParams) (*mcp.GetPromptResult, error)

GetPrompt forwards one prompts/get to the named server.

func (*Manager) ReadResource

func (m *Manager) ReadResource(ctx context.Context, server string, params *mcp.ReadResourceParams) (*mcp.ReadResourceResult, error)

ReadResource forwards one resources/read to the named server.

func (*Manager) Reconnect

func (m *Manager) Reconnect(ctx context.Context, name string) (ServerView, error)

Reconnect force-redials one server and relists its catalog synchronously.

func (*Manager) Views

func (m *Manager) Views() []ServerView

Views returns admin snapshots of every upstream, sorted by name.

type MongoDBStore

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

MongoDBStore stores managed MCP servers and virtual servers in MongoDB.

func NewMongoDBStore

func NewMongoDBStore(database *mongo.Database) (*MongoDBStore, error)

NewMongoDBStore creates collection indexes if needed.

func (*MongoDBStore) Close

func (s *MongoDBStore) Close() error

func (*MongoDBStore) Delete

func (s *MongoDBStore) Delete(ctx context.Context, name string) error

func (*MongoDBStore) DeleteVirtual added in v0.1.104

func (s *MongoDBStore) DeleteVirtual(ctx context.Context, name string) (*ManagedVirtualServer, error)

func (*MongoDBStore) Get

func (s *MongoDBStore) Get(ctx context.Context, name string) (*ManagedServer, error)

func (*MongoDBStore) GetVirtual added in v0.1.104

func (s *MongoDBStore) GetVirtual(ctx context.Context, name string) (*ManagedVirtualServer, error)

func (*MongoDBStore) List

func (s *MongoDBStore) List(ctx context.Context) ([]ManagedServer, error)

func (*MongoDBStore) ListVirtual added in v0.1.104

func (s *MongoDBStore) ListVirtual(ctx context.Context) ([]ManagedVirtualServer, error)

func (*MongoDBStore) Update added in v0.1.100

func (s *MongoDBStore) Update(ctx context.Context, server ManagedServer) error

func (*MongoDBStore) UpdateVirtual added in v0.1.104

func (s *MongoDBStore) UpdateVirtual(ctx context.Context, virtual ManagedVirtualServer) error

func (*MongoDBStore) Upsert

func (s *MongoDBStore) Upsert(ctx context.Context, server ManagedServer) error

func (*MongoDBStore) UpsertVirtual added in v0.1.104

func (s *MongoDBStore) UpsertVirtual(ctx context.Context, virtual ManagedVirtualServer) error

type Options

type Options struct {
	// ConfigServers are the declarative servers from config.yaml / MCP_SERVERS.
	ConfigServers map[string]ServerSpec
	// VirtualServers are the declarative virtual servers, keyed by name.
	VirtualServers map[string]VirtualServerSpec
	// VirtualStore persists admin-managed virtual servers. Optional.
	VirtualStore VirtualStore
	// RefreshInterval re-reads the stores in the background, so admin edits
	// made on another gateway instance sharing the database reach this one.
	// Zero disables it.
	RefreshInterval time.Duration
	// Store persists admin-managed servers. Optional.
	Store Store
	// HTTPClient is the shared outbound HTTP client for http/sse upstreams.
	HTTPClient *http.Client
	// UsageLogger records one usage entry per tool call. Optional.
	UsageLogger usage.LoggerInterface
	// UserPathHeader is the configured user-path header name.
	UserPathHeader string
	// AllowedOrigins are the browser origins permitted to reach the endpoint.
	// Empty trusts none, which is the default; see originGuard.
	AllowedOrigins []string
	// ToolDiscovery is the default discovery mode, config.MCPToolDiscoveryOff
	// or config.MCPToolDiscoverySearch.
	ToolDiscovery string
	// Secrets resolves secret references in admin-managed header values.
	// Nil resolves the built-in env and file schemes only.
	Secrets *config.Secrets
	// SharedStore shares downstream session bindings between the replicas on
	// one database, so a session continues on whichever replica a request
	// reaches. Nil keeps every session on the instance that opened it.
	SharedStore ext.SharedStore
}

Options configures NewService.

type Result

type Result struct {
	Service *Service
	Store   Store
	// contains filtered or unexported fields
}

Result holds the initialized MCP gateway and any owned resources.

func New

func New(ctx context.Context, cfg *config.Config, shared storage.Storage, box *encryption.Box, httpClient *http.Client, usageLogger usage.LoggerInterface, secrets *config.Secrets, providerServers map[string]config.MCPServerConfig, sessions ext.SharedStore) (*Result, error)

New creates the MCP gateway subsystem using an existing storage connection. Header values of managed servers are sealed with box; a nil box stores them in plaintext. secrets resolves the secret references admin-managed servers hold. providerServers are the provider-hosted servers mcp.provider_servers enables; a server in cfg.MCP.Servers with the same slug replaces one. sessions shares downstream sessions between replicas; nil keeps them on this instance.

func (*Result) Close

func (r *Result) Close() error

Close releases resources held by the MCP gateway subsystem.

type SQLStore added in v0.1.60

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

SQLStore stores managed MCP servers in a SQL database.

func NewSQLStore added in v0.1.60

func NewSQLStore(ctx context.Context, db sqlx.DB) (*SQLStore, error)

NewSQLStore creates the mcp_servers table and indexes if needed.

func (*SQLStore) Close added in v0.1.60

func (s *SQLStore) Close() error

func (*SQLStore) Delete added in v0.1.60

func (s *SQLStore) Delete(ctx context.Context, name string) error

func (*SQLStore) DeleteVirtual added in v0.1.104

func (s *SQLStore) DeleteVirtual(ctx context.Context, name string) (*ManagedVirtualServer, error)

func (*SQLStore) Get added in v0.1.60

func (s *SQLStore) Get(ctx context.Context, name string) (*ManagedServer, error)

func (*SQLStore) GetVirtual added in v0.1.104

func (s *SQLStore) GetVirtual(ctx context.Context, name string) (*ManagedVirtualServer, error)

func (*SQLStore) List added in v0.1.60

func (s *SQLStore) List(ctx context.Context) ([]ManagedServer, error)

func (*SQLStore) ListVirtual added in v0.1.104

func (s *SQLStore) ListVirtual(ctx context.Context) ([]ManagedVirtualServer, error)

func (*SQLStore) Update added in v0.1.100

func (s *SQLStore) Update(ctx context.Context, server ManagedServer) error

func (*SQLStore) UpdateVirtual added in v0.1.104

func (s *SQLStore) UpdateVirtual(ctx context.Context, virtual ManagedVirtualServer) error

func (*SQLStore) Upsert added in v0.1.60

func (s *SQLStore) Upsert(ctx context.Context, server ManagedServer) error

func (*SQLStore) UpsertVirtual added in v0.1.104

func (s *SQLStore) UpsertVirtual(ctx context.Context, virtual ManagedVirtualServer) error

type ServerSpec

type ServerSpec struct {
	// Name is the stable ASCII slug used for routing and namespacing.
	Name        string
	DisplayName string

	URL       string
	Transport string
	// Headers are sent to the upstream, secret references resolved.
	Headers map[string]string
	// HeaderReferences holds the stored value of each header of an
	// admin-managed server that holds a secret reference, so the admin API
	// can show the reference instead of masking the header.
	HeaderReferences map[string]string
	Command          string
	Args             []string
	Env              map[string]string
	Description      string
	Enabled          bool
	AllowedTools     []string
	DisallowedTools  []string
	UserPaths        []string
	// DisallowedUserPaths hides the server from these subtrees; it wins over
	// UserPaths.
	DisallowedUserPaths []string
	ToolTimeout         time.Duration

	// Managed marks specs declared in config.yaml / MCP_SERVERS. They override
	// admin-store rows with the same name and are read-only in the dashboard.
	Managed bool
}

ServerSpec is the runtime-normalized definition of one upstream server, merged from declarative config (Managed=true) and the admin store.

func SpecFromConfig

func SpecFromConfig(name string, cfg config.MCPServerConfig) ServerSpec

SpecFromConfig converts one declarative config entry into a runtime spec.

type ServerStatus

type ServerStatus string

ServerStatus describes the runtime connection state of one upstream server.

const (
	// StatusDisabled means the server is declared but switched off.
	StatusDisabled ServerStatus = "disabled"
	// StatusConnecting means no session has been established yet.
	StatusConnecting ServerStatus = "connecting"
	// StatusConnected means the session is live and the catalog is fresh.
	StatusConnected ServerStatus = "connected"
	// StatusDegraded means the last connect or listing failed; any previous
	// catalog is kept (stale carry-forward) and the server is re-probed.
	StatusDegraded ServerStatus = "degraded"
)

type ServerView

type ServerView struct {
	Spec      ServerSpec
	Status    ServerStatus
	LastError string
	ToolCount int
	// ExcludedToolCount counts discovered tools hidden by the tool filters.
	ExcludedToolCount int
	PromptCount       int
	// ResourceCount includes resource templates.
	ResourceCount int
	ConnectedAt   time.Time
}

ServerView is a point-in-time snapshot of one upstream for admin and dashboard consumption.

type Service

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

Service is the MCP gateway: it merges declarative and admin-store server specs into the upstream manager and serves the downstream MCP endpoints.

func NewService

func NewService(ctx context.Context, opts Options) (*Service, error)

NewService builds the gateway service and starts connecting to the merged server set. Upstream connects are asynchronous; construction never blocks.

func (*Service) Catalog

func (s *Service) Catalog(name string) (CatalogView, bool)

Catalog returns the current catalog snapshot for one server, for the admin API and dashboard inspector. ok is false for unknown server names; a known server that has never listed successfully returns empty (non-nil) lists.

func (*Service) Close

func (s *Service) Close()

Close stops background work, terminates upstream sessions, and cancels downstream HTTP exchanges. Streamable HTTP clients keep a GET request open for server events, so those request contexts must be ended before the HTTP server can complete its graceful drain.

func (*Service) Delete

func (s *Service) Delete(ctx context.Context, name string) error

Delete removes one admin-managed server, then reconciles.

func (*Service) DeleteVirtual added in v0.1.104

func (s *Service) DeleteVirtual(ctx context.Context, name string) error

DeleteVirtual removes one admin-managed virtual server, then reconciles.

func (*Service) GetManaged

func (s *Service) GetManaged(ctx context.Context, name string) (*ManagedServer, error)

GetManaged returns one admin-managed server row from the store. Config- declared servers are not store rows, so they (and a missing store) report ErrNotFound.

func (*Service) IsManaged

func (s *Service) IsManaged(name string) bool

IsManaged reports whether name is declared in config/env (read-only).

func (*Service) IsManagedVirtual added in v0.1.104

func (s *Service) IsManagedVirtual(name string) bool

IsManagedVirtual reports whether name is a virtual server declared in config/env, which is read-only.

func (*Service) IsVirtual added in v0.1.100

func (s *Service) IsVirtual(name string) bool

IsVirtual reports whether name is a virtual server, from config or the admin store, which reserves /mcp/{name} for it.

func (*Service) Reconnect

func (s *Service) Reconnect(ctx context.Context, name string) (ServerView, error)

Reconnect force-redials one server and returns its fresh state.

func (*Service) Refresh added in v0.1.104

func (s *Service) Refresh(ctx context.Context) error

Refresh re-reads the stores and reconciles, like Reload, but also reports the stored servers whose references did not resolve, so the admin runtime refresh shows them and the cluster sync poller retries them.

func (*Service) Reload

func (s *Service) Reload(ctx context.Context) error

Reload re-merges declarative and store specs and reconciles the upstream set. Declarative entries shadow store rows with the same name, mirroring the tagging/virtual-models source precedence.

Secret references in stored headers are resolved here. A row whose references do not resolve is logged and left out at startup; once its server runs, it keeps its current headers instead, so a secret backend outage never disconnects a working upstream.

func (*Service) RotateSecrets added in v0.1.101

func (s *Service) RotateSecrets(ctx context.Context, fields []string) error

RotateSecrets re-resolves the admin-managed servers owning fields, as reported by a secret recheck, and redials each one whose resolved headers changed (ADR-0014 §5). Every other server keeps its session untouched. A server whose references cannot be re-resolved keeps its current headers.

func (*Service) Running added in v0.1.101

func (s *Service) Running(name string) bool

Running reports whether the server name is enabled in the running upstream set. A disabled server is kept there for the admin view but serves nothing.

func (*Service) ServeHTTP

func (s *Service) ServeHTTP(w http.ResponseWriter, r *http.Request, pinnedServer string) error

ServeHTTP handles one downstream MCP HTTP exchange. pinnedServer is the /mcp/{server} path segment ("" for the aggregated endpoint): a server slug or a virtual server name; a server wins over a virtual server. Gateway authentication has already run; this layer enforces session-to-principal binding and stamps the internal identity headers tool handlers read.

func (*Service) SetChangeNotifier added in v0.1.109

func (s *Service) SetChangeNotifier(fn func(context.Context))

SetChangeNotifier installs fn, called after every successful write of a server or virtual server so other gateway instances reload them. Call it before serving.

func (*Service) Skipped added in v0.1.101

func (s *Service) Skipped() map[string]error

Skipped returns, by name, why the last full reload left out stored servers whose secret references did not resolve.

func (*Service) ToolCallLabel added in v0.1.99

func (s *Service) ToolCallLabel(sessionID, name, target string) string

ToolCallLabel names the tool a session's tools/call runs, matching its usage entry. name is the called tool and target the call's arguments.name. In a discovery session call_tool resolves to its target, and a bare name the session accepts resolves to its namespaced name. Only the session knows whether call_tool is the meta-tool: on a pinned endpoint without discovery it can be an upstream tool of that name.

func (*Service) Upsert

func (s *Service) Upsert(ctx context.Context, server ManagedServer) error

Upsert validates and persists one admin-managed server, then reconciles. Config-declared names are read-only; stdio definitions are rejected at the store boundary (declarative-only by design — see the gateway spec).

func (*Service) UpsertVirtual added in v0.1.104

func (s *Service) UpsertVirtual(ctx context.Context, virtual ManagedVirtualServer) (VirtualServerView, error)

UpsertVirtual validates and persists one admin-managed virtual server, then reconciles. Members must be existing servers. A new virtual server may not take a server's slug; one stored before the server appeared stays editable, and its edit fails rather than recreating it if a delete wins the race. It returns the saved definition's admin view.

func (*Service) Views

func (s *Service) Views() []ServerView

Views returns the current admin snapshot of all servers.

func (*Service) VirtualViews added in v0.1.100

func (s *Service) VirtualViews() []VirtualServerView

VirtualViews returns every virtual server sorted by name.

type Store

type Store interface {
	List(ctx context.Context) ([]ManagedServer, error)
	Get(ctx context.Context, name string) (*ManagedServer, error)
	Upsert(ctx context.Context, server ManagedServer) error
	// Update rewrites an existing row and returns ErrNotFound when the row is
	// gone, so an edit racing a delete cannot recreate the server.
	Update(ctx context.Context, server ManagedServer) error
	Delete(ctx context.Context, name string) error
	Close() error
}

Store defines persistence operations for admin-managed MCP servers.

type VirtualServerSpec added in v0.1.100

type VirtualServerSpec struct {
	Name        string
	Description string
	// Servers are the member server slugs, in declaration order.
	Servers []string
	// ToolDiscovery is the session default for this endpoint: "off",
	// "search", or "" to inherit the gateway default.
	ToolDiscovery string
	// Managed marks virtual servers declared in config.yaml or
	// MCP_VIRTUAL_SERVERS. They override admin-store rows with the same name
	// and are read-only in the dashboard.
	Managed bool
	// Incarnation identifies one creation of an admin store row (see
	// ManagedVirtualServer.incarnation); empty for a managed one. Every
	// replica reads the same value, so it tells a virtual server from one
	// recreated under its name without comparing replica clocks.
	Incarnation string
}

VirtualServerSpec is one virtual MCP server: a named subset of the upstream servers served at /mcp/{name}. It filters, never grants — every member keeps its own user-path scope and tool filters.

func VirtualFromConfig added in v0.1.100

func VirtualFromConfig(name string, cfg config.MCPVirtualServerConfig) VirtualServerSpec

VirtualFromConfig converts one declarative entry into a runtime spec.

type VirtualServerView added in v0.1.100

type VirtualServerView struct {
	Spec VirtualServerSpec
	// ToolDiscovery is the effective default mode, "off" or "search".
	ToolDiscovery string
	// MissingServers lists members no configured server matches.
	MissingServers []string
	// Conflict explains why the virtual server is not served; empty when it is.
	Conflict string
}

VirtualServerView is the admin snapshot of one virtual server.

type VirtualStore added in v0.1.104

type VirtualStore interface {
	ListVirtual(ctx context.Context) ([]ManagedVirtualServer, error)
	GetVirtual(ctx context.Context, name string) (*ManagedVirtualServer, error)
	UpsertVirtual(ctx context.Context, virtual ManagedVirtualServer) error
	// UpdateVirtual rewrites an existing row and returns ErrNotFound when the
	// row is gone, so an edit racing a delete cannot recreate it.
	UpdateVirtual(ctx context.Context, virtual ManagedVirtualServer) error
	// DeleteVirtual removes a row and returns it as it was deleted, in the
	// same operation, so a caller learns which incarnation it removed even
	// when another instance replaced the row just before.
	DeleteVirtual(ctx context.Context, name string) (*ManagedVirtualServer, error)
}

VirtualStore persists admin-managed virtual servers. The SQL and MongoDB stores implement it next to Store.

Jump to

Keyboard shortcuts

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