Files
moby/daemon/extensions_default.go
T
Paweł Gronowski be285dcad8 daemon: Create the extension API socket on first use
Every daemon with an extension host opened an extra full-access API
socket at startup, even when no extension used the API.

The socket is now created when an extension first connects to the API.
The daemonapi client looks up the endpoint on its first connection, so
NewClient no longer takes a context.

The socket is served separately from the configured hosts, returns 503
until the daemon is ready, and closes after extensions shut down.
It is accessible only to the daemon user, or to Administrators and
LocalSystem on Windows.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-11-04 19:48:07 +01:00

105 lines
3.6 KiB
Go

package daemon
import (
"fmt"
"maps"
"slices"
"strings"
"github.com/moby/extensions"
"github.com/moby/extensions/clientpoint"
"github.com/moby/extensions/serverpoint"
"github.com/moby/moby/v2/daemon/config"
"github.com/moby/moby/v2/daemon/internal/extensionapi"
"github.com/moby/moby/v2/daemon/internal/extensionconfig"
"github.com/moby/moby/v2/daemon/internal/extensionstorage/bbolt"
containernamegeneratorpb "github.com/moby/moby/v2/extpoints/containernamegenerator/v0/protogen"
containerstatepb "github.com/moby/moby/v2/extpoints/containerstate/v0/protogen"
daemonapipb "github.com/moby/moby/v2/extpoints/daemonapi/v0/protogen"
daemonconfigpb "github.com/moby/moby/v2/extpoints/daemonconfig/v0/protogen"
servicenamegeneratorpb "github.com/moby/moby/v2/extpoints/servicenamegenerator/v0/protogen"
storagepb "github.com/moby/moby/v2/extpoints/storage/kv/v0/protogen"
namesgeneratorlegacy "github.com/moby/moby/v2/internal/namesgenerator/legacy"
)
// builtinExtensions lists in-tree extensions that should be available in the
// engine by default.
var builtinExtensions = []extensions.Extension{
namesgeneratorlegacy.Extension,
bbolt.Extension,
}
// optionalExtensions lists built-ins that remain inactive until explicitly
// enabled through extensions.enable.
func (daemon *Daemon) optionalExtensions() []extensions.Extension {
return []extensions.Extension{}
}
// daemonExtensions declares extensions that need daemon-owned state.
// Ordinary builtin definitions obtain their bootstrap settings through points.
func (daemon *Daemon) daemonExtensions() []extensions.Extension {
cfg := daemon.Config()
return []extensions.Extension{
extensionconfig.New(&cfg),
newMonolithExtension(daemon),
extensionapi.New(daemon.extensionAPIEndpoint),
}
}
// selectBuiltinExtensions applies activation settings to whole extensions.
// Provider conflicts and required dependencies are validated by the host.
func selectBuiltinExtensions(cfg config.ExtensionsConfig, defaults, optional []extensions.Extension) ([]extensions.Extension, error) {
if err := cfg.Validate(); err != nil {
return nil, err
}
all := slices.Concat(defaults, optional)
enabled := make(map[string]bool, len(all))
for _, ext := range optional {
enabled[string(ext.Declaration().ID)] = false
}
for _, ext := range defaults {
enabled[string(ext.Declaration().ID)] = true
}
for _, id := range slices.Concat(cfg.Enable, cfg.Disable) {
if _, known := enabled[id]; !known {
return nil, fmt.Errorf("extensions: unknown built-in extension %q (available: %s)", id, strings.Join(slices.Sorted(maps.Keys(enabled)), ", "))
}
}
for _, id := range cfg.Enable {
enabled[id] = true
}
for _, id := range cfg.Disable {
enabled[id] = false
}
return slices.DeleteFunc(all, func(ext extensions.Extension) bool {
return !enabled[string(ext.Declaration().ID)]
}), nil
}
// clientProviders lists generated client wiring for points that launched
// extensions may provide.
//
// A point that's simply exposed as a service by an extension DOES NOT need to
// be in this list.
// This list only contains points that the daemon calls directly.
func clientProviders() []clientpoint.Registration {
return []clientpoint.Registration{
containernamegeneratorpb.ClientPoint,
servicenamegeneratorpb.ClientPoint,
}
}
// dependencyProviders lists points that external extensions may call back
// into.
// Points not in this list will not be able to used as dependencies.
func dependencyProviders() []serverpoint.Registration {
return []serverpoint.Registration{
storagepb.ServerPoint,
daemonconfigpb.ServerPoint,
containerstatepb.ServerPoint,
daemonapipb.ServerPoint,
}
}