mirror of
https://github.com/siderolabs/talos.git
synced 2026-05-08 22:06:18 +02:00
feat: implement time and resolvers multi-doc configuration
Fixes #10954 Fixes #10955 Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
This commit is contained in:
parent
399240be3a
commit
5e1de00359
@ -187,6 +187,13 @@ When `volumeType = "disk"`:
|
||||
When using UEFI boot with systemd-boot as bootloader (on new installs of Talos from 1.10+ onwards), Talos will now not touch the UEFI boot order.
|
||||
Talos 1.11 made a fix to create UEFI boot entry and set the boot order as first entry, but this behavior caused issues on some systems.
|
||||
To avoid further issues, Talos will now only create the UEFI boot entry if it does not exist, but will not modify the boot order.
|
||||
"""
|
||||
|
||||
[notes.network-configuration]
|
||||
title = "Network Configuration"
|
||||
description = """\
|
||||
The network configuration under `.machine.network` (with the exception of KubeSpan) has been deprecated, but it is still supported for backwards compatibility.
|
||||
New configuration documents were created to replace it, they will be documented in the future.
|
||||
"""
|
||||
|
||||
[make_deps]
|
||||
|
||||
@ -39,7 +39,11 @@ func (r *TimeServer) Register(s *grpc.Server) {
|
||||
|
||||
// Time issues a query to the configured ntp server and displays the results.
|
||||
func (r *TimeServer) Time(ctx context.Context, in *emptypb.Empty) (reply *timeapi.TimeResponse, err error) {
|
||||
timeServers := r.ConfigProvider.Config().Machine().Time().Servers()
|
||||
var timeServers []string
|
||||
|
||||
if cfg := r.ConfigProvider.Config().NetworkTimeSyncConfig(); cfg != nil {
|
||||
timeServers = cfg.Servers()
|
||||
}
|
||||
|
||||
if len(timeServers) == 0 {
|
||||
timeServers = []string{constants.DefaultNTPServer}
|
||||
|
||||
@ -82,7 +82,7 @@ func (ctrl *ResolverConfigController) Run(ctx context.Context, r controller.Runt
|
||||
if !state.IsNotFoundError(err) {
|
||||
return fmt.Errorf("error getting config: %w", err)
|
||||
}
|
||||
} else if cfg.Config().Machine() != nil {
|
||||
} else {
|
||||
cfgProvider = cfg.Config()
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ func (ctrl *ResolverConfigController) Run(ctx context.Context, r controller.Runt
|
||||
|
||||
// parse machine configuration for specs
|
||||
if cfgProvider != nil {
|
||||
if configServers, ok := ctrl.parseMachineConfiguration(logger, cfgProvider); ok {
|
||||
if configServers, ok := ctrl.parseMachineConfiguration(cfgProvider); ok {
|
||||
specs = append(specs, configServers)
|
||||
}
|
||||
}
|
||||
@ -181,8 +181,8 @@ func (ctrl *ResolverConfigController) getDefault(cfg talosconfig.Config, hostnam
|
||||
spec.ConfigLayer = network.ConfigDefault
|
||||
|
||||
if cfg == nil ||
|
||||
cfg.Machine() == nil ||
|
||||
cfg.Machine().Network().DisableSearchDomain() ||
|
||||
cfg.NetworkResolverConfig() == nil ||
|
||||
cfg.NetworkResolverConfig().DisableSearchDomain() ||
|
||||
hostnameStatus == nil ||
|
||||
hostnameStatus.Domainname == "" {
|
||||
return spec
|
||||
@ -215,27 +215,21 @@ func (ctrl *ResolverConfigController) parseCmdline(logger *zap.Logger) (spec net
|
||||
return spec
|
||||
}
|
||||
|
||||
func (ctrl *ResolverConfigController) parseMachineConfiguration(logger *zap.Logger, cfgProvider talosconfig.Config) (network.ResolverSpecSpec, bool) {
|
||||
func (ctrl *ResolverConfigController) parseMachineConfiguration(cfgProvider talosconfig.Config) (network.ResolverSpecSpec, bool) {
|
||||
var spec network.ResolverSpecSpec
|
||||
|
||||
resolvers := cfgProvider.Machine().Network().Resolvers()
|
||||
searchDomains := cfgProvider.Machine().Network().SearchDomains()
|
||||
if cfgProvider.NetworkResolverConfig() == nil {
|
||||
return spec, false
|
||||
}
|
||||
|
||||
resolvers := cfgProvider.NetworkResolverConfig().Resolvers()
|
||||
searchDomains := cfgProvider.NetworkResolverConfig().SearchDomains()
|
||||
|
||||
if len(resolvers) == 0 && len(searchDomains) == 0 {
|
||||
return spec, false
|
||||
}
|
||||
|
||||
for _, resolver := range resolvers {
|
||||
server, err := netip.ParseAddr(resolver)
|
||||
if err != nil {
|
||||
logger.Warn("failed to parse DNS server", zap.String("server", resolver), zap.Error(err))
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
spec.DNSServers = append(spec.DNSServers, server)
|
||||
}
|
||||
|
||||
spec.DNSServers = slices.Clone(resolvers)
|
||||
spec.SearchDomains = slices.Clone(searchDomains)
|
||||
spec.ConfigLayer = network.ConfigMachineConfiguration
|
||||
|
||||
|
||||
@ -5,29 +5,21 @@
|
||||
package network_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/controller/runtime"
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"github.com/cosi-project/runtime/pkg/state/impl/inmem"
|
||||
"github.com/cosi-project/runtime/pkg/state/impl/namespaced"
|
||||
"github.com/siderolabs/go-pointer"
|
||||
"github.com/siderolabs/go-procfs/procfs"
|
||||
"github.com/siderolabs/go-retry/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest"
|
||||
netctrl "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/network"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/container"
|
||||
networkcfg "github.com/siderolabs/talos/pkg/machinery/config/types/network"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/config"
|
||||
@ -35,70 +27,14 @@ import (
|
||||
)
|
||||
|
||||
type ResolverConfigSuite struct {
|
||||
suite.Suite
|
||||
|
||||
state state.State
|
||||
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) State() state.State { return suite.state }
|
||||
|
||||
func (suite *ResolverConfigSuite) Ctx() context.Context { return suite.ctx }
|
||||
|
||||
func (suite *ResolverConfigSuite) SetupTest() {
|
||||
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 3*time.Minute)
|
||||
|
||||
suite.state = state.WrapCore(namespaced.NewState(inmem.Build))
|
||||
|
||||
var err error
|
||||
|
||||
suite.runtime, err = runtime.NewRuntime(suite.state, zaptest.NewLogger(suite.T()))
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) startRuntime() {
|
||||
suite.wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer suite.wg.Done()
|
||||
|
||||
suite.Assert().NoError(suite.runtime.Run(suite.ctx))
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) assertResolvers(requiredIDs []string, check func(*network.ResolverSpec, *assert.Assertions)) {
|
||||
assertResources(suite.ctx, suite.T(), suite.state, requiredIDs, check, rtestutils.WithNamespace(network.ConfigNamespaceName))
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) assertNoResolver(id string) error {
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.ResolverSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, res := range resources.Items {
|
||||
if res.Metadata().ID() == id {
|
||||
return retry.ExpectedErrorf("spec %q is still there", id)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
ctest.DefaultSuite
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) TestDefaults() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.ResolverConfigController{}))
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.ResolverConfigController{}))
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.assertResolvers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"default/resolvers",
|
||||
}, func(r *network.ResolverSpec, asrt *assert.Assertions) {
|
||||
@ -111,16 +47,17 @@ func (suite *ResolverConfigSuite) TestDefaults() {
|
||||
asrt.Empty(r.TypedSpec().SearchDomains)
|
||||
asrt.Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) TestWithHostnameStatus() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.ResolverConfigController{}))
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.ResolverConfigController{}))
|
||||
|
||||
hostnameStatus := network.NewHostnameStatus(network.NamespaceName, network.HostnameID)
|
||||
hostnameStatus.TypedSpec().Hostname = "irrelevant"
|
||||
hostnameStatus.TypedSpec().Domainname = "example.org"
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||
suite.Create(hostnameStatus)
|
||||
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
@ -143,11 +80,10 @@ func (suite *ResolverConfigSuite) TestWithHostnameStatus() {
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
suite.Create(cfg)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.assertResolvers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"default/resolvers",
|
||||
}, func(r *network.ResolverSpec, asrt *assert.Assertions) {
|
||||
@ -160,48 +96,52 @@ func (suite *ResolverConfigSuite) TestWithHostnameStatus() {
|
||||
asrt.Equal([]string{"example.org"}, r.TypedSpec().SearchDomains)
|
||||
asrt.Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
|
||||
// make domain name empty
|
||||
hostnameStatus.TypedSpec().Domainname = ""
|
||||
suite.Require().NoError(suite.state.Update(suite.ctx, hostnameStatus))
|
||||
suite.Update(hostnameStatus)
|
||||
|
||||
suite.assertResolvers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"default/resolvers",
|
||||
}, func(r *network.ResolverSpec, asrt *assert.Assertions) {
|
||||
asrt.Empty(r.TypedSpec().SearchDomains)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
|
||||
// bring back domain name, but disable via machine config
|
||||
hostnameStatus.TypedSpec().Domainname = "example.org"
|
||||
suite.Require().NoError(suite.state.Update(suite.ctx, hostnameStatus))
|
||||
suite.Update(hostnameStatus)
|
||||
|
||||
cfg.Container().RawV1Alpha1().MachineConfig.MachineNetwork.NetworkDisableSearchDomain = pointer.To(true)
|
||||
suite.Require().NoError(suite.state.Update(suite.ctx, cfg))
|
||||
cfg.Container().RawV1Alpha1().MachineConfig.MachineNetwork.NetworkDisableSearchDomain = pointer.To(true) //nolint:staticcheck
|
||||
suite.Update(cfg)
|
||||
|
||||
suite.assertResolvers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"default/resolvers",
|
||||
}, func(r *network.ResolverSpec, asrt *assert.Assertions) {
|
||||
asrt.Empty(r.TypedSpec().SearchDomains)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) TestCmdline() {
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
suite.Runtime().RegisterController(
|
||||
&netctrl.ResolverConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2:172.21.0.1:172.20.0.1:255.255.255.0:master1:eth1::10.0.0.1:10.0.0.2:10.0.0.1"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.assertResolvers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"cmdline/resolvers",
|
||||
}, func(r *network.ResolverSpec, asrt *assert.Assertions) {
|
||||
@ -213,13 +153,12 @@ func (suite *ResolverConfigSuite) TestCmdline() {
|
||||
)
|
||||
asrt.Empty(r.TypedSpec().SearchDomains)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) TestMachineConfiguration() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.ResolverConfigController{}))
|
||||
|
||||
suite.startRuntime()
|
||||
func (suite *ResolverConfigSuite) TestMachineConfigurationLegacy() {
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.ResolverConfigController{}))
|
||||
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
@ -245,9 +184,10 @@ func (suite *ResolverConfigSuite) TestMachineConfiguration() {
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
suite.Create(cfg)
|
||||
|
||||
suite.assertResolvers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"configuration/resolvers",
|
||||
}, func(r *network.ResolverSpec, asrt *assert.Assertions) {
|
||||
@ -263,32 +203,72 @@ func (suite *ResolverConfigSuite) TestMachineConfiguration() {
|
||||
r.TypedSpec().SearchDomains,
|
||||
)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
|
||||
ctest.UpdateWithConflicts(suite, cfg, func(r *config.MachineConfig) error {
|
||||
r.Container().RawV1Alpha1().MachineConfig.MachineNetwork.NameServers = nil
|
||||
r.Container().RawV1Alpha1().MachineConfig.MachineNetwork.Searches = nil
|
||||
r.Container().RawV1Alpha1().MachineConfig.MachineNetwork.NameServers = nil //nolint:staticcheck
|
||||
r.Container().RawV1Alpha1().MachineConfig.MachineNetwork.Searches = nil //nolint:staticcheck
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoResolver("configuration/resolvers")
|
||||
},
|
||||
),
|
||||
)
|
||||
ctest.AssertNoResource[*network.ResolverSpec](suite, "configuration/resolvers", rtestutils.WithNamespace(network.ConfigNamespaceName))
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) TearDownTest() {
|
||||
suite.T().Log("tear down")
|
||||
func (suite *ResolverConfigSuite) TestMachineConfigurationNewStyle() {
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.ResolverConfigController{}))
|
||||
|
||||
suite.ctxCancel()
|
||||
rc := networkcfg.NewResolverConfigV1Alpha1()
|
||||
rc.ResolverNameservers = []networkcfg.NameserverConfig{
|
||||
{
|
||||
Address: networkcfg.Addr{Addr: netip.MustParseAddr("2.2.2.2")},
|
||||
},
|
||||
{
|
||||
Address: networkcfg.Addr{Addr: netip.MustParseAddr("3.3.3.3")},
|
||||
},
|
||||
}
|
||||
rc.ResolverSearchDomains = networkcfg.SearchDomainsConfig{
|
||||
SearchDomains: []string{"example.com", "example.org"},
|
||||
}
|
||||
|
||||
suite.wg.Wait()
|
||||
ctr, err := container.New(rc)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(ctr)
|
||||
suite.Create(cfg)
|
||||
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"configuration/resolvers",
|
||||
}, func(r *network.ResolverSpec, asrt *assert.Assertions) {
|
||||
asrt.Equal(
|
||||
[]netip.Addr{
|
||||
netip.MustParseAddr("2.2.2.2"),
|
||||
netip.MustParseAddr("3.3.3.3"),
|
||||
}, r.TypedSpec().DNSServers,
|
||||
)
|
||||
|
||||
asrt.Equal(
|
||||
[]string{"example.com", "example.org"},
|
||||
r.TypedSpec().SearchDomains,
|
||||
)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
|
||||
suite.Destroy(cfg)
|
||||
|
||||
ctest.AssertNoResource[*network.ResolverSpec](suite, "configuration/resolvers", rtestutils.WithNamespace(network.ConfigNamespaceName))
|
||||
}
|
||||
|
||||
func TestResolverConfigSuite(t *testing.T) {
|
||||
suite.Run(t, new(ResolverConfigSuite))
|
||||
t.Parallel()
|
||||
|
||||
suite.Run(t, &ResolverConfigSuite{
|
||||
DefaultSuite: ctest.DefaultSuite{
|
||||
Timeout: 10 * time.Second,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ func (ctrl *TimeServerConfigController) Run(ctx context.Context, r controller.Ru
|
||||
if !state.IsNotFoundError(err) {
|
||||
return fmt.Errorf("error getting config: %w", err)
|
||||
}
|
||||
} else if cfg.Config().Machine() != nil {
|
||||
} else {
|
||||
cfgProvider = cfg.Config()
|
||||
}
|
||||
|
||||
@ -193,11 +193,11 @@ func (ctrl *TimeServerConfigController) parseCmdline(logger *zap.Logger) (spec n
|
||||
}
|
||||
|
||||
func (ctrl *TimeServerConfigController) parseMachineConfiguration(cfgProvider talosconfig.Config) (spec network.TimeServerSpecSpec) {
|
||||
if len(cfgProvider.Machine().Time().Servers()) == 0 {
|
||||
if cfgProvider.NetworkTimeSyncConfig() == nil {
|
||||
return spec
|
||||
}
|
||||
|
||||
spec.NTPServers = slices.Clone(cfgProvider.Machine().Time().Servers())
|
||||
spec.NTPServers = slices.Clone(cfgProvider.NetworkTimeSyncConfig().Servers())
|
||||
spec.ConfigLayer = network.ConfigMachineConfiguration
|
||||
|
||||
return spec
|
||||
|
||||
@ -5,27 +5,19 @@
|
||||
package network_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/controller/runtime"
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"github.com/cosi-project/runtime/pkg/state/impl/inmem"
|
||||
"github.com/cosi-project/runtime/pkg/state/impl/namespaced"
|
||||
"github.com/siderolabs/go-procfs/procfs"
|
||||
"github.com/siderolabs/go-retry/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest"
|
||||
netctrl "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/network"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/container"
|
||||
networkcfg "github.com/siderolabs/talos/pkg/machinery/config/types/network"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/config"
|
||||
@ -33,106 +25,46 @@ import (
|
||||
)
|
||||
|
||||
type TimeServerConfigSuite struct {
|
||||
suite.Suite
|
||||
|
||||
state state.State
|
||||
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) State() state.State { return suite.state }
|
||||
|
||||
func (suite *TimeServerConfigSuite) Ctx() context.Context { return suite.ctx }
|
||||
|
||||
func (suite *TimeServerConfigSuite) SetupTest() {
|
||||
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 3*time.Minute)
|
||||
|
||||
suite.state = state.WrapCore(namespaced.NewState(inmem.Build))
|
||||
|
||||
var err error
|
||||
|
||||
suite.runtime, err = runtime.NewRuntime(suite.state, zaptest.NewLogger(suite.T()))
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) startRuntime() {
|
||||
suite.wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer suite.wg.Done()
|
||||
|
||||
suite.Assert().NoError(suite.runtime.Run(suite.ctx))
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) assertTimeServers(
|
||||
requiredIDs []string,
|
||||
check func(*network.TimeServerSpec, *assert.Assertions),
|
||||
) {
|
||||
assertResources(suite.ctx, suite.T(), suite.state, requiredIDs, check, rtestutils.WithNamespace(network.ConfigNamespaceName))
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) assertNoTimeServer(id string) error {
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.TimeServerSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, res := range resources.Items {
|
||||
if res.Metadata().ID() == id {
|
||||
return retry.ExpectedErrorf("spec %q is still there", id)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
ctest.DefaultSuite
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) TestDefaults() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.TimeServerConfigController{}))
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.TimeServerConfigController{}))
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.assertTimeServers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"default/timeservers",
|
||||
}, func(r *network.TimeServerSpec, asrt *assert.Assertions) {
|
||||
asrt.Equal([]string{constants.DefaultNTPServer}, r.TypedSpec().NTPServers)
|
||||
asrt.Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) TestCmdline() {
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
suite.Runtime().RegisterController(
|
||||
&netctrl.TimeServerConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2:172.21.0.1:172.20.0.1:255.255.255.0:master1:eth1::10.0.0.1:10.0.0.2:10.0.0.1"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.assertTimeServers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"cmdline/timeservers",
|
||||
}, func(r *network.TimeServerSpec, asrt *assert.Assertions) {
|
||||
asrt.Equal([]string{"10.0.0.1"}, r.TypedSpec().NTPServers)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) TestMachineConfiguration() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.TimeServerConfigController{}))
|
||||
|
||||
suite.startRuntime()
|
||||
func (suite *TimeServerConfigSuite) TestMachineConfigurationLegacy() {
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.TimeServerConfigController{}))
|
||||
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
@ -157,39 +89,62 @@ func (suite *TimeServerConfigSuite) TestMachineConfiguration() {
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
suite.Create(cfg)
|
||||
|
||||
suite.assertTimeServers(
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"configuration/timeservers",
|
||||
}, func(r *network.TimeServerSpec, asrt *assert.Assertions) {
|
||||
asrt.Equal([]string{"za.pool.ntp.org", "pool.ntp.org"}, r.TypedSpec().NTPServers)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
|
||||
ctest.UpdateWithConflicts(suite, cfg, func(r *config.MachineConfig) error {
|
||||
r.Container().RawV1Alpha1().MachineConfig.MachineTime = nil
|
||||
r.Container().RawV1Alpha1().MachineConfig.MachineTime = nil //nolint:staticcheck
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoTimeServer("configuration/timeservers")
|
||||
},
|
||||
),
|
||||
)
|
||||
ctest.AssertNoResource[*network.TimeServerSpec](suite, "configuration/timeservers", rtestutils.WithNamespace(network.ConfigNamespaceName))
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) TearDownTest() {
|
||||
suite.T().Log("tear down")
|
||||
func (suite *TimeServerConfigSuite) TestMachineConfigurationNewStyle() {
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.TimeServerConfigController{}))
|
||||
|
||||
suite.ctxCancel()
|
||||
tsc := networkcfg.NewTimeSyncConfigV1Alpha1()
|
||||
tsc.TimeNTP = &networkcfg.NTPConfig{
|
||||
Servers: []string{"za.pool.ntp.org", "pool.ntp.org"},
|
||||
}
|
||||
|
||||
suite.wg.Wait()
|
||||
ctr, err := container.New(tsc)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(ctr)
|
||||
suite.Create(cfg)
|
||||
|
||||
ctest.AssertResources(
|
||||
suite,
|
||||
[]string{
|
||||
"configuration/timeservers",
|
||||
}, func(r *network.TimeServerSpec, asrt *assert.Assertions) {
|
||||
asrt.Equal([]string{"za.pool.ntp.org", "pool.ntp.org"}, r.TypedSpec().NTPServers)
|
||||
},
|
||||
rtestutils.WithNamespace(network.ConfigNamespaceName),
|
||||
)
|
||||
|
||||
suite.Destroy(cfg)
|
||||
|
||||
ctest.AssertNoResource[*network.TimeServerSpec](suite, "configuration/timeservers", rtestutils.WithNamespace(network.ConfigNamespaceName))
|
||||
}
|
||||
|
||||
func TestTimeServerConfigSuite(t *testing.T) {
|
||||
suite.Run(t, new(TimeServerConfigSuite))
|
||||
t.Parallel()
|
||||
|
||||
suite.Run(t, &TimeServerConfigSuite{
|
||||
DefaultSuite: ctest.DefaultSuite{
|
||||
Timeout: 10 * time.Second,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -6,83 +6,20 @@
|
||||
package network_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"slices"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/controller/runtime"
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"github.com/cosi-project/runtime/pkg/state/impl/inmem"
|
||||
"github.com/cosi-project/runtime/pkg/state/impl/namespaced"
|
||||
"github.com/siderolabs/go-retry/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"go.uber.org/zap/zaptest"
|
||||
|
||||
"github.com/siderolabs/talos/internal/app/machined/pkg/controllers/ctest"
|
||||
netctrl "github.com/siderolabs/talos/internal/app/machined/pkg/controllers/network"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
||||
)
|
||||
|
||||
type TimeServerSpecSuite struct {
|
||||
suite.Suite
|
||||
|
||||
state state.State
|
||||
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (suite *TimeServerSpecSuite) SetupTest() {
|
||||
suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 3*time.Minute)
|
||||
|
||||
suite.state = state.WrapCore(namespaced.NewState(inmem.Build))
|
||||
|
||||
var err error
|
||||
|
||||
suite.runtime, err = runtime.NewRuntime(suite.state, zaptest.NewLogger(suite.T()))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.TimeServerSpecController{}))
|
||||
|
||||
suite.startRuntime()
|
||||
}
|
||||
|
||||
func (suite *TimeServerSpecSuite) startRuntime() {
|
||||
suite.wg.Add(1)
|
||||
|
||||
go func() {
|
||||
defer suite.wg.Done()
|
||||
|
||||
suite.Assert().NoError(suite.runtime.Run(suite.ctx))
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *TimeServerSpecSuite) assertStatus(id string, servers ...string) error {
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.TimeServerStatusType, id, resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
status := r.(*network.TimeServerStatus) //nolint:forcetypeassert
|
||||
|
||||
if !slices.Equal(status.TypedSpec().NTPServers, servers) {
|
||||
return retry.ExpectedErrorf("server list mismatch: %q != %q", status.TypedSpec().NTPServers, servers)
|
||||
}
|
||||
|
||||
return nil
|
||||
ctest.DefaultSuite
|
||||
}
|
||||
|
||||
func (suite *TimeServerSpecSuite) TestSpec() {
|
||||
@ -92,27 +29,26 @@ func (suite *TimeServerSpecSuite) TestSpec() {
|
||||
ConfigLayer: network.ConfigDefault,
|
||||
}
|
||||
|
||||
for _, res := range []resource.Resource{spec} {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
suite.Create(spec)
|
||||
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus("timeservers", constants.DefaultNTPServer)
|
||||
},
|
||||
),
|
||||
ctest.AssertResource(
|
||||
suite,
|
||||
"timeservers",
|
||||
func(status *network.TimeServerStatus, asrt *assert.Assertions) {
|
||||
asrt.Equal([]string{constants.DefaultNTPServer}, status.TypedSpec().NTPServers)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *TimeServerSpecSuite) TearDownTest() {
|
||||
suite.T().Log("tear down")
|
||||
|
||||
suite.ctxCancel()
|
||||
|
||||
suite.wg.Wait()
|
||||
}
|
||||
|
||||
func TestTimeServerSpecSuite(t *testing.T) {
|
||||
suite.Run(t, new(TimeServerSpecSuite))
|
||||
t.Parallel()
|
||||
|
||||
suite.Run(t, &TimeServerSpecSuite{
|
||||
DefaultSuite: ctest.DefaultSuite{
|
||||
Timeout: 5 * time.Second,
|
||||
AfterSetup: func(suite *ctest.DefaultSuite) {
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.TimeServerSpecController{}))
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -171,12 +171,12 @@ func (ctrl *SyncController) Run(ctx context.Context, r controller.Runtime, logge
|
||||
syncDisabled = true
|
||||
}
|
||||
|
||||
if cfg != nil && cfg.Config().Machine() != nil {
|
||||
if cfg.Config().Machine().Time().Disabled() {
|
||||
if cfg != nil && cfg.Config().NetworkTimeSyncConfig() != nil {
|
||||
if cfg.Config().NetworkTimeSyncConfig().Disabled() {
|
||||
syncDisabled = true
|
||||
}
|
||||
|
||||
syncTimeout = cfg.Config().Machine().Time().BootTimeout()
|
||||
syncTimeout = cfg.Config().NetworkTimeSyncConfig().BootTimeout()
|
||||
}
|
||||
|
||||
if !timeSynced {
|
||||
|
||||
@ -367,7 +367,7 @@ func (suite *SyncSuite) TestReconcileSyncChangeConfig() {
|
||||
)
|
||||
|
||||
ctest.UpdateWithConflicts(suite, cfg, func(r *config.MachineConfig) error {
|
||||
r.Container().RawV1Alpha1().MachineConfig.MachineTime = &v1alpha1.TimeConfig{
|
||||
r.Container().RawV1Alpha1().MachineConfig.MachineTime = &v1alpha1.TimeConfig{ //nolint:staticcheck
|
||||
TimeDisabled: pointer.To(true),
|
||||
}
|
||||
|
||||
|
||||
@ -167,7 +167,7 @@ func (r *Runtime) CanApplyImmediate(cfg config.Provider) error {
|
||||
if newConfig.MachineConfig != nil && currentConfig.MachineConfig != nil {
|
||||
newConfig.MachineConfig.MachineCA = currentConfig.MachineConfig.MachineCA
|
||||
newConfig.MachineConfig.MachineAcceptedCAs = currentConfig.MachineConfig.MachineAcceptedCAs
|
||||
newConfig.MachineConfig.MachineTime = currentConfig.MachineConfig.MachineTime
|
||||
newConfig.MachineConfig.MachineTime = currentConfig.MachineConfig.MachineTime //nolint:staticcheck
|
||||
newConfig.MachineConfig.MachineCertSANs = currentConfig.MachineConfig.MachineCertSANs
|
||||
newConfig.MachineConfig.MachineInstall = currentConfig.MachineConfig.MachineInstall
|
||||
newConfig.MachineConfig.MachineNetwork = currentConfig.MachineConfig.MachineNetwork
|
||||
|
||||
@ -21,6 +21,8 @@ type Config interface { //nolint:interfacebloat
|
||||
RunDefaultDHCPOperators() bool
|
||||
NetworkStaticHostConfig() []NetworkStaticHostConfig
|
||||
NetworkHostnameConfig() NetworkHostnameConfig
|
||||
NetworkResolverConfig() NetworkResolverConfig
|
||||
NetworkTimeSyncConfig() NetworkTimeSyncConfig
|
||||
NetworkCommonLinkConfigs() []NetworkCommonLinkConfig
|
||||
NetworkLinkAliasConfigs() []NetworkLinkAliasConfig
|
||||
NetworkDHCPConfigs() []NetworkDHCPConfig
|
||||
|
||||
@ -27,7 +27,6 @@ type MachineConfig interface {
|
||||
Security() Security
|
||||
Network() MachineNetwork
|
||||
Disks() []Disk
|
||||
Time() Time
|
||||
Env() Env
|
||||
Files() ([]File, error)
|
||||
Type() machine.Type
|
||||
@ -143,11 +142,8 @@ type MachineScheduler interface {
|
||||
//
|
||||
// This is a legacy interface which is going to be decomposed and removed in the future.
|
||||
type MachineNetwork interface {
|
||||
Resolvers() []string
|
||||
SearchDomains() []string
|
||||
Devices() []Device
|
||||
KubeSpan() KubeSpan
|
||||
DisableSearchDomain() bool
|
||||
}
|
||||
|
||||
// Device represents a network interface.
|
||||
@ -321,14 +317,6 @@ type NetworkDeviceSelector interface {
|
||||
Physical() *bool
|
||||
}
|
||||
|
||||
// Time defines the requirements for a config that pertains to time related
|
||||
// options.
|
||||
type Time interface {
|
||||
Disabled() bool
|
||||
Servers() []string
|
||||
BootTimeout() time.Duration
|
||||
}
|
||||
|
||||
// Kubelet defines the requirements for a config that pertains to kubelet
|
||||
// related options.
|
||||
//
|
||||
|
||||
@ -112,6 +112,21 @@ type NetworkHostnameConfig interface {
|
||||
AutoHostname() nethelpers.AutoHostnameKind
|
||||
}
|
||||
|
||||
// NetworkResolverConfig defines a resolver configuration.
|
||||
type NetworkResolverConfig interface {
|
||||
Resolvers() []netip.Addr
|
||||
SearchDomains() []string
|
||||
DisableSearchDomain() bool
|
||||
}
|
||||
|
||||
// NetworkTimeSyncConfig defines the requirements for a config that pertains to time related
|
||||
// options.
|
||||
type NetworkTimeSyncConfig interface {
|
||||
Disabled() bool
|
||||
Servers() []string
|
||||
BootTimeout() time.Duration
|
||||
}
|
||||
|
||||
// NetworkPhysicalLinkConfig defines a physical network link configuration.
|
||||
type NetworkPhysicalLinkConfig interface {
|
||||
PhysicalLinkConfig()
|
||||
|
||||
@ -64,7 +64,7 @@ func TestSchemaValidation(t *testing.T) {
|
||||
{
|
||||
name: "v1alpha1_invalid-duration",
|
||||
config: newV1Alpha1Config(t, nil, func(rawConfig map[string]any) {
|
||||
setNestedField(t, rawConfig, "100y", "machine", "time", "bootTimeout")
|
||||
setNestedField(t, rawConfig, "100y", "cluster", "adminKubeconfig", "certLifetime")
|
||||
}),
|
||||
expectedErrorContains: `does not match pattern`,
|
||||
},
|
||||
|
||||
@ -302,6 +302,38 @@ func (container *Container) NetworkHostnameConfig() config.NetworkHostnameConfig
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetworkResolverConfig implements config.Config interface.
|
||||
func (container *Container) NetworkResolverConfig() config.NetworkResolverConfig {
|
||||
// first check if we have a dedicated document
|
||||
matching := findMatchingDocs[config.NetworkResolverConfig](container.documents)
|
||||
if len(matching) > 0 {
|
||||
return matching[0]
|
||||
}
|
||||
|
||||
// fallback to v1alpha1
|
||||
if container.v1alpha1Config != nil {
|
||||
return container.v1alpha1Config
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetworkTimeSyncConfig implements config.Config interface.
|
||||
func (container *Container) NetworkTimeSyncConfig() config.NetworkTimeSyncConfig {
|
||||
// first check if we have a dedicated document
|
||||
matching := findMatchingDocs[config.NetworkTimeSyncConfig](container.documents)
|
||||
if len(matching) > 0 {
|
||||
return matching[0]
|
||||
}
|
||||
|
||||
// fallback to v1alpha1
|
||||
if container.v1alpha1Config != nil {
|
||||
return container.v1alpha1Config.NetworkTimeSyncConfig()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NetworkCommonLinkConfigs implements config.Config interface.
|
||||
func (container *Container) NetworkCommonLinkConfigs() []config.NetworkCommonLinkConfig {
|
||||
return findMatchingDocs[config.NetworkCommonLinkConfig](container.documents)
|
||||
|
||||
@ -2249,6 +2249,101 @@
|
||||
"type": "object",
|
||||
"description": "LinkSelector selects a link to alias."
|
||||
},
|
||||
"network.NTPConfig": {
|
||||
"properties": {
|
||||
"servers": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "servers",
|
||||
"description": "Specifies time (NTP) servers to use for setting the system time.\nDefaults to time.cloudflare.com.\n",
|
||||
"markdownDescription": "Specifies time (NTP) servers to use for setting the system time.\nDefaults to `time.cloudflare.com`.",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecifies time (NTP) servers to use for setting the system time.\nDefaults to \u003ccode\u003etime.cloudflare.com\u003c/code\u003e.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "NTPConfig represents a NTP server configuration."
|
||||
},
|
||||
"network.NameserverConfig": {
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-f.:]+$",
|
||||
"title": "address",
|
||||
"description": "The IP address of the nameserver.\n",
|
||||
"markdownDescription": "The IP address of the nameserver.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe IP address of the nameserver.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "NameserverConfig represents a single nameserver configuration."
|
||||
},
|
||||
"network.PTPConfig": {
|
||||
"properties": {
|
||||
"devices": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "devices",
|
||||
"description": "description: |\n A list of PTP devices to sync with (e.g. provided by the hypervisor).\n\nA PTP device is typically represented as a character device file in the /dev directory,\n\n\nsuch as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time\n with an external time source that supports the Precision Time Protocol.\n",
|
||||
"markdownDescription": "description: |\n A list of PTP devices to sync with (e.g. provided by the hypervisor).\n\n A PTP device is typically represented as a character device file in the /dev directory,\n such as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time\n with an external time source that supports the Precision Time Protocol.",
|
||||
"x-intellij-html-description": "\u003cp\u003edescription: |\n A list of PTP devices to sync with (e.g. provided by the hypervisor).\u003c/p\u003e\n\n\u003cpre\u003e\u003ccode\u003eA PTP device is typically represented as a character device file in the /dev directory,\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003esuch as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time\n with an external time source that supports the Precision Time Protocol.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "PTPConfig represents a PTP (Precision Time Protocol) configuration."
|
||||
},
|
||||
"network.ResolverConfigV1Alpha1": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"enum": [
|
||||
"v1alpha1"
|
||||
],
|
||||
"title": "apiVersion",
|
||||
"description": "apiVersion is the API version of the resource.\n",
|
||||
"markdownDescription": "apiVersion is the API version of the resource.",
|
||||
"x-intellij-html-description": "\u003cp\u003eapiVersion is the API version of the resource.\u003c/p\u003e\n"
|
||||
},
|
||||
"kind": {
|
||||
"enum": [
|
||||
"ResolverConfig"
|
||||
],
|
||||
"title": "kind",
|
||||
"description": "kind is the kind of the resource.\n",
|
||||
"markdownDescription": "kind is the kind of the resource.",
|
||||
"x-intellij-html-description": "\u003cp\u003ekind is the kind of the resource.\u003c/p\u003e\n"
|
||||
},
|
||||
"nameservers": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/network.NameserverConfig"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "nameservers",
|
||||
"description": "A list of nameservers (DNS servers) to use for resolving domain names.\n\nNameservers are used to resolve domain names on the host, and they are also\npropagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.\n\nThis overrides any nameservers obtained via DHCP or platform configuration.\nDefault configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers.\n",
|
||||
"markdownDescription": "A list of nameservers (DNS servers) to use for resolving domain names.\n\nNameservers are used to resolve domain names on the host, and they are also\npropagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.\n\nThis overrides any nameservers obtained via DHCP or platform configuration.\nDefault configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers.",
|
||||
"x-intellij-html-description": "\u003cp\u003eA list of nameservers (DNS servers) to use for resolving domain names.\u003c/p\u003e\n\n\u003cp\u003eNameservers are used to resolve domain names on the host, and they are also\npropagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.\u003c/p\u003e\n\n\u003cp\u003eThis overrides any nameservers obtained via DHCP or platform configuration.\nDefault configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers.\u003c/p\u003e\n"
|
||||
},
|
||||
"searchDomains": {
|
||||
"$ref": "#/$defs/network.SearchDomainsConfig",
|
||||
"title": "searchDomains",
|
||||
"description": "Configuration for search domains (in /etc/resolv.conf).\n\nThe default is to derive search domains from the hostname FQDN.\n",
|
||||
"markdownDescription": "Configuration for search domains (in /etc/resolv.conf).\n\nThe default is to derive search domains from the hostname FQDN.",
|
||||
"x-intellij-html-description": "\u003cp\u003eConfiguration for search domains (in /etc/resolv.conf).\u003c/p\u003e\n\n\u003cp\u003eThe default is to derive search domains from the hostname FQDN.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"apiVersion",
|
||||
"kind"
|
||||
],
|
||||
"description": "ResolverConfig is a config document to configure DNS resolving."
|
||||
},
|
||||
"network.RouteConfig": {
|
||||
"properties": {
|
||||
"destination": {
|
||||
@ -2391,6 +2486,30 @@
|
||||
"type": "object",
|
||||
"description": "RulePortSelector is a port selector for the network rule."
|
||||
},
|
||||
"network.SearchDomainsConfig": {
|
||||
"properties": {
|
||||
"domains": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "domains",
|
||||
"description": "A list of search domains to be used for DNS resolution.\n\nSearch domains are appended to unqualified domain names during DNS resolution.\nFor example, if “example.com” is a search domain and a user tries to resolve\n“host”, the system will attempt to resolve “host.example.com”.\n\nThis overrides any search domains obtained via DHCP or platform configuration.\nThe default configuration derives the search domain from the hostname FQDN.\n",
|
||||
"markdownDescription": "A list of search domains to be used for DNS resolution.\n\nSearch domains are appended to unqualified domain names during DNS resolution.\nFor example, if \"example.com\" is a search domain and a user tries to resolve\n\"host\", the system will attempt to resolve \"host.example.com\".\n\nThis overrides any search domains obtained via DHCP or platform configuration.\nThe default configuration derives the search domain from the hostname FQDN.",
|
||||
"x-intellij-html-description": "\u003cp\u003eA list of search domains to be used for DNS resolution.\u003c/p\u003e\n\n\u003cp\u003eSearch domains are appended to unqualified domain names during DNS resolution.\nFor example, if \u0026ldquo;example.com\u0026rdquo; is a search domain and a user tries to resolve\n\u0026ldquo;host\u0026rdquo;, the system will attempt to resolve \u0026ldquo;host.example.com\u0026rdquo;.\u003c/p\u003e\n\n\u003cp\u003eThis overrides any search domains obtained via DHCP or platform configuration.\nThe default configuration derives the search domain from the hostname FQDN.\u003c/p\u003e\n"
|
||||
},
|
||||
"disableDefault": {
|
||||
"type": "boolean",
|
||||
"title": "disableDefault",
|
||||
"description": "Disable default search domain configuration from hostname FQDN.\n\nWhen set to true, the system will not derive search domains from the hostname FQDN.\nThis allows for a custom configuration of search domains without any defaults.\n",
|
||||
"markdownDescription": "Disable default search domain configuration from hostname FQDN.\n\nWhen set to true, the system will not derive search domains from the hostname FQDN.\nThis allows for a custom configuration of search domains without any defaults.",
|
||||
"x-intellij-html-description": "\u003cp\u003eDisable default search domain configuration from hostname FQDN.\u003c/p\u003e\n\n\u003cp\u003eWhen set to true, the system will not derive search domains from the hostname FQDN.\nThis allows for a custom configuration of search domains without any defaults.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "SearchDomainsConfig represents search domains configuration."
|
||||
},
|
||||
"network.StaticHostConfigV1Alpha1": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
@ -2438,6 +2557,64 @@
|
||||
],
|
||||
"description": "StaticHostConfig is a config document to set /etc/hosts entries."
|
||||
},
|
||||
"network.TimeSyncConfigV1Alpha1": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"enum": [
|
||||
"v1alpha1"
|
||||
],
|
||||
"title": "apiVersion",
|
||||
"description": "apiVersion is the API version of the resource.\n",
|
||||
"markdownDescription": "apiVersion is the API version of the resource.",
|
||||
"x-intellij-html-description": "\u003cp\u003eapiVersion is the API version of the resource.\u003c/p\u003e\n"
|
||||
},
|
||||
"kind": {
|
||||
"enum": [
|
||||
"TimeSyncConfig"
|
||||
],
|
||||
"title": "kind",
|
||||
"description": "kind is the kind of the resource.\n",
|
||||
"markdownDescription": "kind is the kind of the resource.",
|
||||
"x-intellij-html-description": "\u003cp\u003ekind is the kind of the resource.\u003c/p\u003e\n"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"title": "enabled",
|
||||
"description": "Indicates if the time synchronization is enabled for the machine.\nDefaults to true.\n",
|
||||
"markdownDescription": "Indicates if the time synchronization is enabled for the machine.\nDefaults to `true`.",
|
||||
"x-intellij-html-description": "\u003cp\u003eIndicates if the time synchronization is enabled for the machine.\nDefaults to \u003ccode\u003etrue\u003c/code\u003e.\u003c/p\u003e\n"
|
||||
},
|
||||
"bootTimeout": {
|
||||
"type": "string",
|
||||
"pattern": "^[-+]?(((\\d+(\\.\\d*)?|\\d*(\\.\\d+)+)([nuµm]?s|m|h))|0)+$",
|
||||
"title": "bootTimeout",
|
||||
"description": "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to “infinity” (waiting forever for time sync)\n",
|
||||
"markdownDescription": "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \"infinity\" (waiting forever for time sync)",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \u0026ldquo;infinity\u0026rdquo; (waiting forever for time sync)\u003c/p\u003e\n"
|
||||
},
|
||||
"ntp": {
|
||||
"$ref": "#/$defs/network.NTPConfig",
|
||||
"title": "ntp",
|
||||
"description": "Specifies NTP configuration to sync the time over network.\nMutually exclusive with PTP configuration.\n",
|
||||
"markdownDescription": "Specifies NTP configuration to sync the time over network.\nMutually exclusive with PTP configuration.",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecifies NTP configuration to sync the time over network.\nMutually exclusive with PTP configuration.\u003c/p\u003e\n"
|
||||
},
|
||||
"ptp": {
|
||||
"$ref": "#/$defs/network.PTPConfig",
|
||||
"title": "ptp",
|
||||
"description": "Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.\nMutually exclusive with NTP configuration.\n",
|
||||
"markdownDescription": "Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.\nMutually exclusive with NTP configuration.",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.\nMutually exclusive with NTP configuration.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"apiVersion",
|
||||
"kind"
|
||||
],
|
||||
"description": "TimeSyncConfig is a config document to configure time synchronization (NTP)."
|
||||
},
|
||||
"network.VLANConfigV1Alpha1": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
@ -4412,13 +4589,6 @@
|
||||
"markdownDescription": "The `env` field allows for the addition of environment variables.\nAll environment variables are set on PID 1 in addition to every service.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe \u003ccode\u003eenv\u003c/code\u003e field allows for the addition of environment variables.\nAll environment variables are set on PID 1 in addition to every service.\u003c/p\u003e\n"
|
||||
},
|
||||
"time": {
|
||||
"$ref": "#/$defs/v1alpha1.TimeConfig",
|
||||
"title": "time",
|
||||
"description": "Used to configure the machine’s time settings.\n",
|
||||
"markdownDescription": "Used to configure the machine's time settings.",
|
||||
"x-intellij-html-description": "\u003cp\u003eUsed to configure the machine\u0026rsquo;s time settings.\u003c/p\u003e\n"
|
||||
},
|
||||
"sysctls": {
|
||||
"patternProperties": {
|
||||
".*": {
|
||||
@ -4640,39 +4810,12 @@
|
||||
},
|
||||
"v1alpha1.NetworkConfig": {
|
||||
"properties": {
|
||||
"nameservers": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "nameservers",
|
||||
"description": "Used to statically set the nameservers for the machine.\nDefaults to 1.1.1.1 and 8.8.8.8\n",
|
||||
"markdownDescription": "Used to statically set the nameservers for the machine.\nDefaults to `1.1.1.1` and `8.8.8.8`",
|
||||
"x-intellij-html-description": "\u003cp\u003eUsed to statically set the nameservers for the machine.\nDefaults to \u003ccode\u003e1.1.1.1\u003c/code\u003e and \u003ccode\u003e8.8.8.8\u003c/code\u003e\u003c/p\u003e\n"
|
||||
},
|
||||
"searchDomains": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "searchDomains",
|
||||
"description": "Used to statically set arbitrary search domains.\n",
|
||||
"markdownDescription": "Used to statically set arbitrary search domains.",
|
||||
"x-intellij-html-description": "\u003cp\u003eUsed to statically set arbitrary search domains.\u003c/p\u003e\n"
|
||||
},
|
||||
"kubespan": {
|
||||
"$ref": "#/$defs/v1alpha1.NetworkKubeSpan",
|
||||
"title": "kubespan",
|
||||
"description": "Configures KubeSpan feature.\n",
|
||||
"markdownDescription": "Configures KubeSpan feature.",
|
||||
"x-intellij-html-description": "\u003cp\u003eConfigures KubeSpan feature.\u003c/p\u003e\n"
|
||||
},
|
||||
"disableSearchDomain": {
|
||||
"type": "boolean",
|
||||
"title": "disableSearchDomain",
|
||||
"description": "Disable generating a default search domain in /etc/resolv.conf\nbased on the machine hostname.\nDefaults to false.\n",
|
||||
"markdownDescription": "Disable generating a default search domain in /etc/resolv.conf\nbased on the machine hostname.\nDefaults to `false`.",
|
||||
"x-intellij-html-description": "\u003cp\u003eDisable generating a default search domain in /etc/resolv.conf\nbased on the machine hostname.\nDefaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@ -4886,38 +5029,6 @@
|
||||
"type": "object",
|
||||
"description": "SchedulerConfig represents the kube scheduler configuration options."
|
||||
},
|
||||
"v1alpha1.TimeConfig": {
|
||||
"properties": {
|
||||
"disabled": {
|
||||
"type": "boolean",
|
||||
"title": "disabled",
|
||||
"description": "Indicates if the time service is disabled for the machine.\nDefaults to false.\n",
|
||||
"markdownDescription": "Indicates if the time service is disabled for the machine.\nDefaults to `false`.",
|
||||
"x-intellij-html-description": "\u003cp\u003eIndicates if the time service is disabled for the machine.\nDefaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n"
|
||||
},
|
||||
"servers": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "servers",
|
||||
"description": "description: |\n Specifies time (NTP) servers to use for setting the system time.\n Defaults to time.cloudflare.com.\n\nTalos can also sync to the PTP time source (e.g provided by the hypervisor),\n provide the path to the PTP device as “/dev/ptp0” or “/dev/ptp_kvm”.\n",
|
||||
"markdownDescription": "description: |\n Specifies time (NTP) servers to use for setting the system time.\n Defaults to `time.cloudflare.com`.\n\n Talos can also sync to the PTP time source (e.g provided by the hypervisor),\n provide the path to the PTP device as \"/dev/ptp0\" or \"/dev/ptp_kvm\".",
|
||||
"x-intellij-html-description": "\u003cp\u003edescription: |\n Specifies time (NTP) servers to use for setting the system time.\n Defaults to \u003ccode\u003etime.cloudflare.com\u003c/code\u003e.\u003c/p\u003e\n\n\u003cp\u003eTalos can also sync to the PTP time source (e.g provided by the hypervisor),\n provide the path to the PTP device as \u0026ldquo;/dev/ptp0\u0026rdquo; or \u0026ldquo;/dev/ptp_kvm\u0026rdquo;.\u003c/p\u003e\n"
|
||||
},
|
||||
"bootTimeout": {
|
||||
"type": "string",
|
||||
"pattern": "^[-+]?(((\\d+(\\.\\d*)?|\\d*(\\.\\d+)+)([nuµm]?s|m|h))|0)+$",
|
||||
"title": "bootTimeout",
|
||||
"description": "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to “infinity” (waiting forever for time sync)\n",
|
||||
"markdownDescription": "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \"infinity\" (waiting forever for time sync)",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \u0026ldquo;infinity\u0026rdquo; (waiting forever for time sync)\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "TimeConfig represents the options for configuring time on a machine."
|
||||
},
|
||||
"v1alpha1.UdevConfig": {
|
||||
"properties": {
|
||||
"rules": {
|
||||
@ -5037,12 +5148,18 @@
|
||||
{
|
||||
"$ref": "#/$defs/network.LinkAliasConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.ResolverConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.RuleConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.StaticHostConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.TimeSyncConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.VLANConfigV1Alpha1"
|
||||
},
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Code generated by "deep-copy -type BondConfigV1Alpha1 -type BridgeConfigV1Alpha1 -type DefaultActionConfigV1Alpha1 -type DHCPv4ConfigV1Alpha1 -type DHCPv6ConfigV1Alpha1 -type DummyLinkConfigV1Alpha1 -type EthernetConfigV1Alpha1 -type HCloudVIPConfigV1Alpha1 -type HostnameConfigV1Alpha1 -type KubespanEndpointsConfigV1Alpha1 -type Layer2VIPConfigV1Alpha1 -type LinkConfigV1Alpha1 -type LinkAliasConfigV1Alpha1 -type RuleConfigV1Alpha1 -type StaticHostConfigV1Alpha1 -type VLANConfigV1Alpha1 -type WireguardConfigV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT.
|
||||
// Code generated by "deep-copy -type BondConfigV1Alpha1 -type BridgeConfigV1Alpha1 -type DefaultActionConfigV1Alpha1 -type DHCPv4ConfigV1Alpha1 -type DHCPv6ConfigV1Alpha1 -type DummyLinkConfigV1Alpha1 -type EthernetConfigV1Alpha1 -type HCloudVIPConfigV1Alpha1 -type HostnameConfigV1Alpha1 -type KubespanEndpointsConfigV1Alpha1 -type Layer2VIPConfigV1Alpha1 -type LinkConfigV1Alpha1 -type LinkAliasConfigV1Alpha1 -type ResolverConfigV1Alpha1 -type RuleConfigV1Alpha1 -type StaticHostConfigV1Alpha1 -type TimeSyncConfigV1Alpha1 -type VLANConfigV1Alpha1 -type WireguardConfigV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go ."; DO NOT EDIT.
|
||||
|
||||
package network
|
||||
|
||||
@ -404,6 +404,24 @@ func (o *LinkAliasConfigV1Alpha1) DeepCopy() *LinkAliasConfigV1Alpha1 {
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *ResolverConfigV1Alpha1.
|
||||
func (o *ResolverConfigV1Alpha1) DeepCopy() *ResolverConfigV1Alpha1 {
|
||||
var cp ResolverConfigV1Alpha1 = *o
|
||||
if o.ResolverNameservers != nil {
|
||||
cp.ResolverNameservers = make([]NameserverConfig, len(o.ResolverNameservers))
|
||||
copy(cp.ResolverNameservers, o.ResolverNameservers)
|
||||
}
|
||||
if o.ResolverSearchDomains.SearchDomains != nil {
|
||||
cp.ResolverSearchDomains.SearchDomains = make([]string, len(o.ResolverSearchDomains.SearchDomains))
|
||||
copy(cp.ResolverSearchDomains.SearchDomains, o.ResolverSearchDomains.SearchDomains)
|
||||
}
|
||||
if o.ResolverSearchDomains.SearchDisableDefault != nil {
|
||||
cp.ResolverSearchDomains.SearchDisableDefault = new(bool)
|
||||
*cp.ResolverSearchDomains.SearchDisableDefault = *o.ResolverSearchDomains.SearchDisableDefault
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *RuleConfigV1Alpha1.
|
||||
func (o *RuleConfigV1Alpha1) DeepCopy() *RuleConfigV1Alpha1 {
|
||||
var cp RuleConfigV1Alpha1 = *o
|
||||
@ -428,6 +446,32 @@ func (o *StaticHostConfigV1Alpha1) DeepCopy() *StaticHostConfigV1Alpha1 {
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *TimeSyncConfigV1Alpha1.
|
||||
func (o *TimeSyncConfigV1Alpha1) DeepCopy() *TimeSyncConfigV1Alpha1 {
|
||||
var cp TimeSyncConfigV1Alpha1 = *o
|
||||
if o.TimeEnabled != nil {
|
||||
cp.TimeEnabled = new(bool)
|
||||
*cp.TimeEnabled = *o.TimeEnabled
|
||||
}
|
||||
if o.TimeNTP != nil {
|
||||
cp.TimeNTP = new(NTPConfig)
|
||||
*cp.TimeNTP = *o.TimeNTP
|
||||
if o.TimeNTP.Servers != nil {
|
||||
cp.TimeNTP.Servers = make([]string, len(o.TimeNTP.Servers))
|
||||
copy(cp.TimeNTP.Servers, o.TimeNTP.Servers)
|
||||
}
|
||||
}
|
||||
if o.TimePTP != nil {
|
||||
cp.TimePTP = new(PTPConfig)
|
||||
*cp.TimePTP = *o.TimePTP
|
||||
if o.TimePTP.Devices != nil {
|
||||
cp.TimePTP.Devices = make([]string, len(o.TimePTP.Devices))
|
||||
copy(cp.TimePTP.Devices, o.TimePTP.Devices)
|
||||
}
|
||||
}
|
||||
return &cp
|
||||
}
|
||||
|
||||
// DeepCopy generates a deep copy of *VLANConfigV1Alpha1.
|
||||
func (o *VLANConfigV1Alpha1) DeepCopy() *VLANConfigV1Alpha1 {
|
||||
var cp VLANConfigV1Alpha1 = *o
|
||||
|
||||
@ -154,7 +154,7 @@ func TestHostnameConfigValidate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestV1Alpha1Validate(t *testing.T) {
|
||||
func TestHostnameV1Alpha1Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
|
||||
@ -5,6 +5,6 @@
|
||||
// Package network provides network machine configuration documents.
|
||||
package network
|
||||
|
||||
//go:generate go tool github.com/siderolabs/talos/tools/docgen -output network_doc.go network.go bond.go bridge.go default_action_config.go dhcp4.go dhcp6.go dummy.go ethernet.go hcloud_vip.go hostname.go kubespan_endpoints.go layer2_vip.go link.go link_alias.go port_range.go rule_config.go static_host.go vlan.go wireguard.go
|
||||
//go:generate go tool github.com/siderolabs/talos/tools/docgen -output network_doc.go network.go bond.go bridge.go default_action_config.go dhcp4.go dhcp6.go dummy.go ethernet.go hcloud_vip.go hostname.go kubespan_endpoints.go layer2_vip.go link.go link_alias.go port_range.go resolver.go rule_config.go static_host.go time_sync.go vlan.go wireguard.go
|
||||
|
||||
//go:generate go tool github.com/siderolabs/deep-copy -type BondConfigV1Alpha1 -type BridgeConfigV1Alpha1 -type DefaultActionConfigV1Alpha1 -type DHCPv4ConfigV1Alpha1 -type DHCPv6ConfigV1Alpha1 -type DummyLinkConfigV1Alpha1 -type EthernetConfigV1Alpha1 -type HCloudVIPConfigV1Alpha1 -type HostnameConfigV1Alpha1 -type KubespanEndpointsConfigV1Alpha1 -type Layer2VIPConfigV1Alpha1 -type LinkConfigV1Alpha1 -type LinkAliasConfigV1Alpha1 -type RuleConfigV1Alpha1 -type StaticHostConfigV1Alpha1 -type VLANConfigV1Alpha1 -type WireguardConfigV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go .
|
||||
//go:generate go tool github.com/siderolabs/deep-copy -type BondConfigV1Alpha1 -type BridgeConfigV1Alpha1 -type DefaultActionConfigV1Alpha1 -type DHCPv4ConfigV1Alpha1 -type DHCPv6ConfigV1Alpha1 -type DummyLinkConfigV1Alpha1 -type EthernetConfigV1Alpha1 -type HCloudVIPConfigV1Alpha1 -type HostnameConfigV1Alpha1 -type KubespanEndpointsConfigV1Alpha1 -type Layer2VIPConfigV1Alpha1 -type LinkConfigV1Alpha1 -type LinkAliasConfigV1Alpha1 -type ResolverConfigV1Alpha1 -type RuleConfigV1Alpha1 -type StaticHostConfigV1Alpha1 -type TimeSyncConfigV1Alpha1 -type VLANConfigV1Alpha1 -type WireguardConfigV1Alpha1 -pointer-receiver -header-file ../../../../../hack/boilerplate.txt -o deep_copy.generated.go .
|
||||
|
||||
@ -1227,6 +1227,99 @@ func (LinkSelector) Doc() *encoder.Doc {
|
||||
return doc
|
||||
}
|
||||
|
||||
func (ResolverConfigV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "ResolverConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "ResolverConfig is a config document to configure DNS resolving." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "ResolverConfig is a config document to configure DNS resolving.",
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Type: "Meta",
|
||||
Inline: true,
|
||||
},
|
||||
{
|
||||
Name: "nameservers",
|
||||
Type: "[]NameserverConfig",
|
||||
Note: "",
|
||||
Description: "A list of nameservers (DNS servers) to use for resolving domain names.\n\nNameservers are used to resolve domain names on the host, and they are also\npropagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.\n\nThis overrides any nameservers obtained via DHCP or platform configuration.\nDefault configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "A list of nameservers (DNS servers) to use for resolving domain names." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "searchDomains",
|
||||
Type: "SearchDomainsConfig",
|
||||
Note: "",
|
||||
Description: "Configuration for search domains (in /etc/resolv.conf).\n\nThe default is to derive search domains from the hostname FQDN.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Configuration for search domains (in /etc/resolv.conf)." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", exampleResolverConfigV1Alpha1())
|
||||
|
||||
doc.AddExample("", exampleResolverConfigV1Alpha2())
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (NameserverConfig) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "NameserverConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "NameserverConfig represents a single nameserver configuration." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "NameserverConfig represents a single nameserver configuration.",
|
||||
AppearsIn: []encoder.Appearance{
|
||||
{
|
||||
TypeName: "ResolverConfigV1Alpha1",
|
||||
FieldName: "nameservers",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "address",
|
||||
Type: "Addr",
|
||||
Note: "",
|
||||
Description: "The IP address of the nameserver.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "The IP address of the nameserver." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.Fields[0].AddExample("", Addr{netip.MustParseAddr("10.0.0.1")})
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (SearchDomainsConfig) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "SearchDomainsConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "SearchDomainsConfig represents search domains configuration." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "SearchDomainsConfig represents search domains configuration.",
|
||||
AppearsIn: []encoder.Appearance{
|
||||
{
|
||||
TypeName: "ResolverConfigV1Alpha1",
|
||||
FieldName: "searchDomains",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "domains",
|
||||
Type: "[]string",
|
||||
Note: "",
|
||||
Description: "A list of search domains to be used for DNS resolution.\n\nSearch domains are appended to unqualified domain names during DNS resolution.\nFor example, if \"example.com\" is a search domain and a user tries to resolve\n\"host\", the system will attempt to resolve \"host.example.com\".\n\nThis overrides any search domains obtained via DHCP or platform configuration.\nThe default configuration derives the search domain from the hostname FQDN.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "A list of search domains to be used for DNS resolution." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "disableDefault",
|
||||
Type: "bool",
|
||||
Note: "",
|
||||
Description: "Disable default search domain configuration from hostname FQDN.\n\nWhen set to true, the system will not derive search domains from the hostname FQDN.\nThis allows for a custom configuration of search domains without any defaults.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Disable default search domain configuration from hostname FQDN." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (RuleConfigV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "NetworkRuleConfig",
|
||||
@ -1375,6 +1468,104 @@ func (StaticHostConfigV1Alpha1) Doc() *encoder.Doc {
|
||||
return doc
|
||||
}
|
||||
|
||||
func (TimeSyncConfigV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "TimeSyncConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "TimeSyncConfig is a config document to configure time synchronization (NTP)." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "TimeSyncConfig is a config document to configure time synchronization (NTP).",
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Type: "Meta",
|
||||
Inline: true,
|
||||
},
|
||||
{
|
||||
Name: "enabled",
|
||||
Type: "bool",
|
||||
Note: "",
|
||||
Description: "Indicates if the time synchronization is enabled for the machine.\nDefaults to `true`.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Indicates if the time synchronization is enabled for the machine." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "bootTimeout",
|
||||
Type: "Duration",
|
||||
Note: "",
|
||||
Description: "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \"infinity\" (waiting forever for time sync)",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "ntp",
|
||||
Type: "NTPConfig",
|
||||
Note: "",
|
||||
Description: "Specifies NTP configuration to sync the time over network.\nMutually exclusive with PTP configuration.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Specifies NTP configuration to sync the time over network." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "ptp",
|
||||
Type: "PTPConfig",
|
||||
Note: "",
|
||||
Description: "Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.\nMutually exclusive with NTP configuration.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("", exampleTimeSyncConfigV1Alpha1())
|
||||
|
||||
doc.AddExample("", exampleTimeSyncConfigV1Alpha2())
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (NTPConfig) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "NTPConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "NTPConfig represents a NTP server configuration." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "NTPConfig represents a NTP server configuration.",
|
||||
AppearsIn: []encoder.Appearance{
|
||||
{
|
||||
TypeName: "TimeSyncConfigV1Alpha1",
|
||||
FieldName: "ntp",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "servers",
|
||||
Type: "[]string",
|
||||
Note: "",
|
||||
Description: "Specifies time (NTP) servers to use for setting the system time.\nDefaults to `time.cloudflare.com`.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Specifies time (NTP) servers to use for setting the system time." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (PTPConfig) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "PTPConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "PTPConfig represents a PTP (Precision Time Protocol) configuration." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "PTPConfig represents a PTP (Precision Time Protocol) configuration.",
|
||||
AppearsIn: []encoder.Appearance{
|
||||
{
|
||||
TypeName: "TimeSyncConfigV1Alpha1",
|
||||
FieldName: "ptp",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "devices",
|
||||
Type: "[]string",
|
||||
Note: "",
|
||||
Description: "description: |\n A list of PTP devices to sync with (e.g. provided by the hypervisor).\n\n A PTP device is typically represented as a character device file in the /dev directory,\n such as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time\n with an external time source that supports the Precision Time Protocol.\n",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "description: |" /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (VLANConfigV1Alpha1) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "VLANConfig",
|
||||
@ -1573,10 +1764,16 @@ func GetFileDoc() *encoder.FileDoc {
|
||||
RouteConfig{}.Doc(),
|
||||
LinkAliasConfigV1Alpha1{}.Doc(),
|
||||
LinkSelector{}.Doc(),
|
||||
ResolverConfigV1Alpha1{}.Doc(),
|
||||
NameserverConfig{}.Doc(),
|
||||
SearchDomainsConfig{}.Doc(),
|
||||
RuleConfigV1Alpha1{}.Doc(),
|
||||
RulePortSelector{}.Doc(),
|
||||
IngressRule{}.Doc(),
|
||||
StaticHostConfigV1Alpha1{}.Doc(),
|
||||
TimeSyncConfigV1Alpha1{}.Doc(),
|
||||
NTPConfig{}.Doc(),
|
||||
PTPConfig{}.Doc(),
|
||||
VLANConfigV1Alpha1{}.Doc(),
|
||||
WireguardConfigV1Alpha1{}.Doc(),
|
||||
WireguardPeer{}.Doc(),
|
||||
|
||||
177
pkg/machinery/config/types/network/resolver.go
Normal file
177
pkg/machinery/config/types/network/resolver.go
Normal file
@ -0,0 +1,177 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network
|
||||
|
||||
//docgen:jsonschema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/netip"
|
||||
"slices"
|
||||
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
"github.com/siderolabs/go-pointer"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/container"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/internal/registry"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/meta"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
// ResolverKind is a ResolverConfig document kind.
|
||||
const ResolverKind = "ResolverConfig"
|
||||
|
||||
func init() {
|
||||
registry.Register(ResolverKind, func(version string) config.Document {
|
||||
switch version {
|
||||
case "v1alpha1": //nolint:goconst
|
||||
return &ResolverConfigV1Alpha1{}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Check interfaces.
|
||||
var (
|
||||
_ config.NetworkResolverConfig = &ResolverConfigV1Alpha1{}
|
||||
_ container.V1Alpha1ConflictValidator = &ResolverConfigV1Alpha1{}
|
||||
)
|
||||
|
||||
// ResolverConfigV1Alpha1 is a config document to configure DNS resolving.
|
||||
//
|
||||
// examples:
|
||||
// - value: exampleResolverConfigV1Alpha1()
|
||||
// - value: exampleResolverConfigV1Alpha2()
|
||||
// alias: ResolverConfig
|
||||
// schemaRoot: true
|
||||
// schemaMeta: v1alpha1/ResolverConfig
|
||||
type ResolverConfigV1Alpha1 struct {
|
||||
meta.Meta `yaml:",inline"`
|
||||
|
||||
// description: |
|
||||
// A list of nameservers (DNS servers) to use for resolving domain names.
|
||||
//
|
||||
// Nameservers are used to resolve domain names on the host, and they are also
|
||||
// propagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.
|
||||
//
|
||||
// This overrides any nameservers obtained via DHCP or platform configuration.
|
||||
// Default configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers.
|
||||
ResolverNameservers []NameserverConfig `yaml:"nameservers,omitempty"`
|
||||
// description: |
|
||||
// Configuration for search domains (in /etc/resolv.conf).
|
||||
//
|
||||
// The default is to derive search domains from the hostname FQDN.
|
||||
ResolverSearchDomains SearchDomainsConfig `yaml:"searchDomains,omitempty"`
|
||||
}
|
||||
|
||||
// NameserverConfig represents a single nameserver configuration.
|
||||
type NameserverConfig struct {
|
||||
// description: |
|
||||
// The IP address of the nameserver.
|
||||
// examples:
|
||||
// - value: >
|
||||
// Addr{netip.MustParseAddr("10.0.0.1")}
|
||||
// schema:
|
||||
// type: string
|
||||
// pattern: ^[0-9a-f.:]+$
|
||||
Address Addr `yaml:"address"`
|
||||
}
|
||||
|
||||
// SearchDomainsConfig represents search domains configuration.
|
||||
type SearchDomainsConfig struct {
|
||||
// description: |
|
||||
// A list of search domains to be used for DNS resolution.
|
||||
//
|
||||
// Search domains are appended to unqualified domain names during DNS resolution.
|
||||
// For example, if "example.com" is a search domain and a user tries to resolve
|
||||
// "host", the system will attempt to resolve "host.example.com".
|
||||
//
|
||||
// This overrides any search domains obtained via DHCP or platform configuration.
|
||||
// The default configuration derives the search domain from the hostname FQDN.
|
||||
SearchDomains []string `yaml:"domains,omitempty"`
|
||||
// description: |
|
||||
// Disable default search domain configuration from hostname FQDN.
|
||||
//
|
||||
// When set to true, the system will not derive search domains from the hostname FQDN.
|
||||
// This allows for a custom configuration of search domains without any defaults.
|
||||
SearchDisableDefault *bool `yaml:"disableDefault,omitempty"`
|
||||
}
|
||||
|
||||
// NewResolverConfigV1Alpha1 creates a new ResolverConfig config document.
|
||||
func NewResolverConfigV1Alpha1() *ResolverConfigV1Alpha1 {
|
||||
return &ResolverConfigV1Alpha1{
|
||||
Meta: meta.Meta{
|
||||
MetaKind: ResolverKind,
|
||||
MetaAPIVersion: "v1alpha1",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func exampleResolverConfigV1Alpha1() *ResolverConfigV1Alpha1 {
|
||||
cfg := NewResolverConfigV1Alpha1()
|
||||
cfg.ResolverNameservers = []NameserverConfig{
|
||||
{
|
||||
Address: Addr{netip.MustParseAddr("1.1.1.1")},
|
||||
},
|
||||
{
|
||||
Address: Addr{netip.MustParseAddr("ff08::1")},
|
||||
},
|
||||
}
|
||||
cfg.ResolverSearchDomains = SearchDomainsConfig{
|
||||
SearchDomains: []string{"example.com"},
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func exampleResolverConfigV1Alpha2() *ResolverConfigV1Alpha1 {
|
||||
cfg := NewResolverConfigV1Alpha1()
|
||||
cfg.ResolverSearchDomains = SearchDomainsConfig{
|
||||
SearchDisableDefault: pointer.To(true),
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Clone implements config.Document interface.
|
||||
func (s *ResolverConfigV1Alpha1) Clone() config.Document {
|
||||
return s.DeepCopy()
|
||||
}
|
||||
|
||||
// V1Alpha1ConflictValidate implements container.V1Alpha1ConflictValidator interface.
|
||||
func (s *ResolverConfigV1Alpha1) V1Alpha1ConflictValidate(v1alpha1Cfg *v1alpha1.Config) error {
|
||||
if v1alpha1Cfg.SearchDomains() != nil {
|
||||
return errors.New(".machine.network.searchDomains is already set in v1alpha1 config")
|
||||
}
|
||||
|
||||
if v1alpha1Cfg.Resolvers() != nil {
|
||||
return errors.New(".machine.network.nameservers is already set in v1alpha1 config")
|
||||
}
|
||||
|
||||
if v1alpha1Cfg.DisableSearchDomain() {
|
||||
return errors.New(".machine.network.disableSearchDomain is already set in v1alpha1 config")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Resolvers implements NetworkResolverConfig interface.
|
||||
func (s *ResolverConfigV1Alpha1) Resolvers() []netip.Addr {
|
||||
return xslices.Map(s.ResolverNameservers, func(ns NameserverConfig) netip.Addr {
|
||||
return ns.Address.Addr
|
||||
})
|
||||
}
|
||||
|
||||
// SearchDomains implements NetworkResolverConfig interface.
|
||||
func (s *ResolverConfigV1Alpha1) SearchDomains() []string {
|
||||
return slices.Clone(s.ResolverSearchDomains.SearchDomains)
|
||||
}
|
||||
|
||||
// DisableSearchDomain implements NetworkResolverConfig interface.
|
||||
func (s *ResolverConfigV1Alpha1) DisableSearchDomain() bool {
|
||||
return pointer.SafeDeref(s.ResolverSearchDomains.SearchDisableDefault)
|
||||
}
|
||||
146
pkg/machinery/config/types/network/resolver_test.go
Normal file
146
pkg/machinery/config/types/network/resolver_test.go
Normal file
@ -0,0 +1,146 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network_test
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"github.com/siderolabs/go-pointer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/configloader"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/meta"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/network"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
//go:embed testdata/resolverconfig.yaml
|
||||
var expectedResolverConfigDocument []byte
|
||||
|
||||
func TestResolverConfigMarshalStability(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := network.NewResolverConfigV1Alpha1()
|
||||
cfg.ResolverNameservers = []network.NameserverConfig{
|
||||
{
|
||||
Address: network.Addr{Addr: netip.MustParseAddr("10.0.0.1")},
|
||||
},
|
||||
{
|
||||
Address: network.Addr{Addr: netip.MustParseAddr("2001:4860:4860::8888")},
|
||||
},
|
||||
}
|
||||
cfg.ResolverSearchDomains = network.SearchDomainsConfig{
|
||||
SearchDomains: []string{"example.org", "example.com"},
|
||||
SearchDisableDefault: pointer.To(false),
|
||||
}
|
||||
|
||||
marshaled, err := encoder.NewEncoder(cfg, encoder.WithComments(encoder.CommentsDisabled)).Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log(string(marshaled))
|
||||
|
||||
assert.Equal(t, expectedResolverConfigDocument, marshaled)
|
||||
}
|
||||
|
||||
func TestResolverConfigUnmarshal(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
provider, err := configloader.NewFromBytes(expectedResolverConfigDocument)
|
||||
require.NoError(t, err)
|
||||
|
||||
docs := provider.Documents()
|
||||
require.Len(t, docs, 1)
|
||||
|
||||
assert.Equal(t, &network.ResolverConfigV1Alpha1{
|
||||
Meta: meta.Meta{
|
||||
MetaAPIVersion: "v1alpha1",
|
||||
MetaKind: network.ResolverKind,
|
||||
},
|
||||
ResolverNameservers: []network.NameserverConfig{
|
||||
{
|
||||
Address: network.Addr{Addr: netip.MustParseAddr("10.0.0.1")},
|
||||
},
|
||||
{
|
||||
Address: network.Addr{Addr: netip.MustParseAddr("2001:4860:4860::8888")},
|
||||
},
|
||||
},
|
||||
ResolverSearchDomains: network.SearchDomainsConfig{
|
||||
SearchDomains: []string{"example.org", "example.com"},
|
||||
SearchDisableDefault: pointer.To(false),
|
||||
},
|
||||
}, docs[0])
|
||||
}
|
||||
|
||||
func TestResolverV1Alpha1Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
v1alpha1Cfg *v1alpha1.Config
|
||||
cfg func() *network.ResolverConfigV1Alpha1
|
||||
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
v1alpha1Cfg: &v1alpha1.Config{},
|
||||
cfg: network.NewResolverConfigV1Alpha1,
|
||||
},
|
||||
{
|
||||
name: "v1alpha1 nameservers set",
|
||||
v1alpha1Cfg: &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NameServers: []string{"1.1.1.1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
cfg: network.NewResolverConfigV1Alpha1,
|
||||
|
||||
expectedError: ".machine.network.nameservers is already set in v1alpha1 config",
|
||||
},
|
||||
{
|
||||
name: "v1alpha1 search domains set",
|
||||
v1alpha1Cfg: &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
Searches: []string{"cluster.org"},
|
||||
},
|
||||
},
|
||||
},
|
||||
cfg: network.NewResolverConfigV1Alpha1,
|
||||
|
||||
expectedError: ".machine.network.searchDomains is already set in v1alpha1 config",
|
||||
},
|
||||
{
|
||||
name: "v1alpha1 disable search domains set",
|
||||
v1alpha1Cfg: &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkDisableSearchDomain: pointer.To(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
cfg: network.NewResolverConfigV1Alpha1,
|
||||
|
||||
expectedError: ".machine.network.disableSearchDomain is already set in v1alpha1 config",
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
err := test.cfg().V1Alpha1ConflictValidate(test.v1alpha1Cfg)
|
||||
if test.expectedError != "" {
|
||||
assert.EqualError(t, err, test.expectedError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
10
pkg/machinery/config/types/network/testdata/resolverconfig.yaml
vendored
Normal file
10
pkg/machinery/config/types/network/testdata/resolverconfig.yaml
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
apiVersion: v1alpha1
|
||||
kind: ResolverConfig
|
||||
nameservers:
|
||||
- address: 10.0.0.1
|
||||
- address: 2001:4860:4860::8888
|
||||
searchDomains:
|
||||
domains:
|
||||
- example.org
|
||||
- example.com
|
||||
disableDefault: false
|
||||
7
pkg/machinery/config/types/network/testdata/timesyncconfig.yaml
vendored
Normal file
7
pkg/machinery/config/types/network/testdata/timesyncconfig.yaml
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
apiVersion: v1alpha1
|
||||
kind: TimeSyncConfig
|
||||
enabled: true
|
||||
bootTimeout: 1m0s
|
||||
ntp:
|
||||
servers:
|
||||
- time.cloudflare.com
|
||||
191
pkg/machinery/config/types/network/time_sync.go
Normal file
191
pkg/machinery/config/types/network/time_sync.go
Normal file
@ -0,0 +1,191 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network
|
||||
|
||||
//docgen:jsonschema
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/container"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/internal/registry"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/meta"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/validation"
|
||||
)
|
||||
|
||||
// TimeSyncKind is a TimeSyncConfig document kind.
|
||||
const TimeSyncKind = "TimeSyncConfig"
|
||||
|
||||
func init() {
|
||||
registry.Register(TimeSyncKind, func(version string) config.Document {
|
||||
switch version {
|
||||
case "v1alpha1": //nolint:goconst
|
||||
return &TimeSyncConfigV1Alpha1{}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Check interfaces.
|
||||
var (
|
||||
_ config.NetworkTimeSyncConfig = &TimeSyncConfigV1Alpha1{}
|
||||
_ config.Validator = &TimeSyncConfigV1Alpha1{}
|
||||
_ container.V1Alpha1ConflictValidator = &TimeSyncConfigV1Alpha1{}
|
||||
)
|
||||
|
||||
// TimeSyncConfigV1Alpha1 is a config document to configure time synchronization (NTP).
|
||||
//
|
||||
// examples:
|
||||
// - value: exampleTimeSyncConfigV1Alpha1()
|
||||
// - value: exampleTimeSyncConfigV1Alpha2()
|
||||
// alias: TimeSyncConfig
|
||||
// schemaRoot: true
|
||||
// schemaMeta: v1alpha1/TimeSyncConfig
|
||||
type TimeSyncConfigV1Alpha1 struct {
|
||||
meta.Meta `yaml:",inline"`
|
||||
|
||||
// description: |
|
||||
// Indicates if the time synchronization is enabled for the machine.
|
||||
// Defaults to `true`.
|
||||
TimeEnabled *bool `yaml:"enabled,omitempty"`
|
||||
// description: |
|
||||
// Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.
|
||||
// NTP sync will be still running in the background.
|
||||
// Defaults to "infinity" (waiting forever for time sync)
|
||||
// schema:
|
||||
// type: string
|
||||
// pattern: ^[-+]?(((\d+(\.\d*)?|\d*(\.\d+)+)([nuµm]?s|m|h))|0)+$
|
||||
TimeBootTimeout time.Duration `yaml:"bootTimeout,omitempty"`
|
||||
// description: |
|
||||
// Specifies NTP configuration to sync the time over network.
|
||||
// Mutually exclusive with PTP configuration.
|
||||
TimeNTP *NTPConfig `yaml:"ntp,omitempty"`
|
||||
// description: |
|
||||
// Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.
|
||||
// Mutually exclusive with NTP configuration.
|
||||
TimePTP *PTPConfig `yaml:"ptp,omitempty"`
|
||||
}
|
||||
|
||||
// NTPConfig represents a NTP server configuration.
|
||||
type NTPConfig struct {
|
||||
// description: |
|
||||
// Specifies time (NTP) servers to use for setting the system time.
|
||||
// Defaults to `time.cloudflare.com`.
|
||||
Servers []string `yaml:"servers,omitempty"`
|
||||
}
|
||||
|
||||
// PTPConfig represents a PTP (Precision Time Protocol) configuration.
|
||||
type PTPConfig struct {
|
||||
// description: |
|
||||
// A list of PTP devices to sync with (e.g. provided by the hypervisor).
|
||||
//
|
||||
// A PTP device is typically represented as a character device file in the /dev directory,
|
||||
// such as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time
|
||||
// with an external time source that supports the Precision Time Protocol.
|
||||
Devices []string `yaml:"devices,omitempty"`
|
||||
}
|
||||
|
||||
// NewTimeSyncConfigV1Alpha1 creates a new TimeSyncConfig config document.
|
||||
func NewTimeSyncConfigV1Alpha1() *TimeSyncConfigV1Alpha1 {
|
||||
return &TimeSyncConfigV1Alpha1{
|
||||
Meta: meta.Meta{
|
||||
MetaKind: TimeSyncKind,
|
||||
MetaAPIVersion: "v1alpha1",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func exampleTimeSyncConfigV1Alpha1() *TimeSyncConfigV1Alpha1 {
|
||||
cfg := NewTimeSyncConfigV1Alpha1()
|
||||
cfg.TimeNTP = &NTPConfig{
|
||||
Servers: []string{"pool.ntp.org"},
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
func exampleTimeSyncConfigV1Alpha2() *TimeSyncConfigV1Alpha1 {
|
||||
cfg := NewTimeSyncConfigV1Alpha1()
|
||||
cfg.TimePTP = &PTPConfig{
|
||||
Devices: []string{"/dev/ptp0"},
|
||||
}
|
||||
|
||||
return cfg
|
||||
}
|
||||
|
||||
// Clone implements config.Document interface.
|
||||
func (s *TimeSyncConfigV1Alpha1) Clone() config.Document {
|
||||
return s.DeepCopy()
|
||||
}
|
||||
|
||||
// Validate implements config.Validator interface.
|
||||
func (s *TimeSyncConfigV1Alpha1) Validate(validation.RuntimeMode, ...validation.Option) ([]string, error) {
|
||||
var errs error
|
||||
|
||||
if s.TimeBootTimeout < 0 {
|
||||
errs = errors.Join(errs, errors.New("bootTimeout cannot be negative"))
|
||||
}
|
||||
|
||||
if s.TimeNTP != nil && s.TimePTP != nil {
|
||||
errs = errors.Join(errs, errors.New("only one of ntp or ptp configuration can be specified"))
|
||||
}
|
||||
|
||||
return nil, errs
|
||||
}
|
||||
|
||||
// V1Alpha1ConflictValidate implements container.V1Alpha1ConflictValidator interface.
|
||||
func (s *TimeSyncConfigV1Alpha1) V1Alpha1ConflictValidate(v1alpha1Cfg *v1alpha1.Config) error {
|
||||
v1tsc := v1alpha1Cfg.NetworkTimeSyncConfig()
|
||||
|
||||
if v1tsc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if v1tsc.Disabled() {
|
||||
return errors.New("time sync cannot be disabled in both v1alpha1 and new-style configuration")
|
||||
}
|
||||
|
||||
if len(v1tsc.Servers()) > 0 {
|
||||
return errors.New("time servers cannot be specified in both v1alpha1 and new-style configuration")
|
||||
}
|
||||
|
||||
if v1tsc.BootTimeout() != 0 {
|
||||
return errors.New("boot timeout cannot be specified in both v1alpha1 and new-style configuration")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Disabled implements config.NetworkTimeSyncConfig interface.
|
||||
func (s *TimeSyncConfigV1Alpha1) Disabled() bool {
|
||||
if s.TimeEnabled == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return !*s.TimeEnabled
|
||||
}
|
||||
|
||||
// BootTimeout implements config.NetworkTimeSyncConfig interface.
|
||||
func (s *TimeSyncConfigV1Alpha1) BootTimeout() time.Duration {
|
||||
return s.TimeBootTimeout
|
||||
}
|
||||
|
||||
// Servers implements config.NetworkTimeSyncConfig interface.
|
||||
func (s *TimeSyncConfigV1Alpha1) Servers() []string {
|
||||
// The configuration validates that only one of the NTP or PTP is set.
|
||||
if s.TimeNTP != nil {
|
||||
return s.TimeNTP.Servers
|
||||
}
|
||||
|
||||
if s.TimePTP != nil {
|
||||
return s.TimePTP.Devices
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
200
pkg/machinery/config/types/network/time_sync_test.go
Normal file
200
pkg/machinery/config/types/network/time_sync_test.go
Normal file
@ -0,0 +1,200 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network_test
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/siderolabs/go-pointer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/configloader"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/meta"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/network"
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
//go:embed testdata/timesyncconfig.yaml
|
||||
var expectedTimeSyncConfigDocument []byte
|
||||
|
||||
func TestTimeSyncConfigMarshalStability(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := network.NewTimeSyncConfigV1Alpha1()
|
||||
cfg.TimeEnabled = pointer.To(true)
|
||||
cfg.TimeBootTimeout = time.Minute
|
||||
cfg.TimeNTP = &network.NTPConfig{
|
||||
Servers: []string{"time.cloudflare.com"},
|
||||
}
|
||||
|
||||
marshaled, err := encoder.NewEncoder(cfg, encoder.WithComments(encoder.CommentsDisabled)).Encode()
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Log(string(marshaled))
|
||||
|
||||
assert.Equal(t, expectedTimeSyncConfigDocument, marshaled)
|
||||
}
|
||||
|
||||
func TestTimeSyncConfigUnmarshal(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
provider, err := configloader.NewFromBytes(expectedTimeSyncConfigDocument)
|
||||
require.NoError(t, err)
|
||||
|
||||
docs := provider.Documents()
|
||||
require.Len(t, docs, 1)
|
||||
|
||||
assert.Equal(t, &network.TimeSyncConfigV1Alpha1{
|
||||
Meta: meta.Meta{
|
||||
MetaAPIVersion: "v1alpha1",
|
||||
MetaKind: network.TimeSyncKind,
|
||||
},
|
||||
TimeEnabled: pointer.To(true),
|
||||
TimeBootTimeout: time.Minute,
|
||||
TimeNTP: &network.NTPConfig{
|
||||
Servers: []string{"time.cloudflare.com"},
|
||||
},
|
||||
}, docs[0])
|
||||
}
|
||||
|
||||
func TestTimeSyncValidate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
cfg func() *network.TimeSyncConfigV1Alpha1
|
||||
|
||||
expectedError string
|
||||
expectedWarnings []string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
cfg: network.NewTimeSyncConfigV1Alpha1,
|
||||
},
|
||||
{
|
||||
name: "both NTP and PTP set",
|
||||
cfg: func() *network.TimeSyncConfigV1Alpha1 {
|
||||
cfg := network.NewTimeSyncConfigV1Alpha1()
|
||||
cfg.TimeNTP = &network.NTPConfig{
|
||||
Servers: []string{"pool.ntp.org"},
|
||||
}
|
||||
cfg.TimePTP = &network.PTPConfig{
|
||||
Devices: []string{"/dev/ptp0"},
|
||||
}
|
||||
|
||||
return cfg
|
||||
},
|
||||
expectedError: "only one of ntp or ptp configuration can be specified",
|
||||
},
|
||||
{
|
||||
name: "negative boot timeout",
|
||||
cfg: func() *network.TimeSyncConfigV1Alpha1 {
|
||||
cfg := network.NewTimeSyncConfigV1Alpha1()
|
||||
cfg.TimeBootTimeout = -time.Second
|
||||
|
||||
return cfg
|
||||
},
|
||||
expectedError: "bootTimeout cannot be negative",
|
||||
},
|
||||
{
|
||||
name: "valid NTP config",
|
||||
cfg: func() *network.TimeSyncConfigV1Alpha1 {
|
||||
cfg := network.NewTimeSyncConfigV1Alpha1()
|
||||
cfg.TimeNTP = &network.NTPConfig{
|
||||
Servers: []string{"pool.ntp.org"},
|
||||
}
|
||||
cfg.TimeBootTimeout = time.Second
|
||||
|
||||
return cfg
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
warnings, err := test.cfg().Validate(validationMode{})
|
||||
|
||||
assert.Equal(t, test.expectedWarnings, warnings)
|
||||
|
||||
if test.expectedError != "" {
|
||||
assert.EqualError(t, err, test.expectedError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeSyncV1Alpha1Validate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
v1alpha1Cfg *v1alpha1.Config
|
||||
cfg func() *network.TimeSyncConfigV1Alpha1
|
||||
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
v1alpha1Cfg: &v1alpha1.Config{},
|
||||
cfg: network.NewTimeSyncConfigV1Alpha1,
|
||||
},
|
||||
{
|
||||
name: "v1alpha1 timeservers set",
|
||||
v1alpha1Cfg: &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeServers: []string{"za.pool.ntp.org"},
|
||||
},
|
||||
},
|
||||
},
|
||||
cfg: network.NewTimeSyncConfigV1Alpha1,
|
||||
|
||||
expectedError: "time servers cannot be specified in both v1alpha1 and new-style configuration",
|
||||
},
|
||||
{
|
||||
name: "v1alpha1 boot timeout set",
|
||||
v1alpha1Cfg: &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeBootTimeout: time.Second,
|
||||
},
|
||||
},
|
||||
},
|
||||
cfg: network.NewTimeSyncConfigV1Alpha1,
|
||||
|
||||
expectedError: "boot timeout cannot be specified in both v1alpha1 and new-style configuration",
|
||||
},
|
||||
{
|
||||
name: "v1alpha1 disable set",
|
||||
v1alpha1Cfg: &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeDisabled: pointer.To(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
cfg: network.NewTimeSyncConfigV1Alpha1,
|
||||
|
||||
expectedError: "time sync cannot be disabled in both v1alpha1 and new-style configuration",
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
err := test.cfg().V1Alpha1ConflictValidate(test.v1alpha1Cfg)
|
||||
if test.expectedError != "" {
|
||||
assert.EqualError(t, err, test.expectedError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -161,14 +161,6 @@ func machineEnvExamples2() Env {
|
||||
}
|
||||
}
|
||||
|
||||
func machineTimeExample() *TimeConfig {
|
||||
return &TimeConfig{
|
||||
TimeDisabled: pointer.To(false),
|
||||
TimeServers: []string{"time.cloudflare.com"},
|
||||
TimeBootTimeout: 2 * time.Minute,
|
||||
}
|
||||
}
|
||||
|
||||
func machineSysctlsExample() map[string]string {
|
||||
return map[string]string{
|
||||
"kernel.domainname": "talos.dev",
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/siderolabs/go-pointer"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config/config"
|
||||
@ -44,3 +46,47 @@ func (c *Config) AutoHostname() nethelpers.AutoHostnameKind {
|
||||
|
||||
return nethelpers.AutoHostnameKindAddr
|
||||
}
|
||||
|
||||
// Resolvers implements config.NetworkResolverConfig interface.
|
||||
func (c *Config) Resolvers() []netip.Addr {
|
||||
if c.MachineConfig == nil || c.MachineConfig.MachineNetwork == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result []netip.Addr
|
||||
|
||||
for _, r := range c.MachineConfig.MachineNetwork.NameServers {
|
||||
if addr, err := netip.ParseAddr(r); err == nil {
|
||||
result = append(result, addr)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// SearchDomains implements config.NetworkResolverConfig interface.
|
||||
func (c *Config) SearchDomains() []string {
|
||||
if c.MachineConfig == nil || c.MachineConfig.MachineNetwork == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.MachineConfig.MachineNetwork.Searches
|
||||
}
|
||||
|
||||
// DisableSearchDomain implements config.NetworkResolverConfig interface.
|
||||
func (c *Config) DisableSearchDomain() bool {
|
||||
if c.MachineConfig == nil || c.MachineConfig.MachineNetwork == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return pointer.SafeDeref(c.MachineConfig.MachineNetwork.NetworkDisableSearchDomain)
|
||||
}
|
||||
|
||||
// NetworkTimeSyncConfig implements config.NetworkTimeSyncConfig interface.
|
||||
func (c *Config) NetworkTimeSyncConfig() config.NetworkTimeSyncConfig {
|
||||
if c.MachineConfig == nil || c.MachineConfig.MachineTime == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return c.MachineConfig.MachineTime
|
||||
}
|
||||
|
||||
@ -5,7 +5,9 @@
|
||||
package v1alpha1_test
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/siderolabs/go-pointer"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@ -238,3 +240,240 @@ func TestHostnameBridging(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolverBridging(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
|
||||
cfg func(*testing.T) config.Config
|
||||
|
||||
expectedNameservers []netip.Addr
|
||||
expectedSearchDomains []string
|
||||
expectedDisableSearch bool
|
||||
}{
|
||||
{
|
||||
name: "v1alpha1 only",
|
||||
|
||||
cfg: func(*testing.T) config.Config {
|
||||
return container.NewV1Alpha1(&v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NameServers: []string{"2.2.2.2", "3.3.3.3"},
|
||||
Searches: []string{"universe.com", "galaxy.org"},
|
||||
NetworkDisableSearchDomain: pointer.To(true),
|
||||
},
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
expectedNameservers: []netip.Addr{netip.MustParseAddr("2.2.2.2"), netip.MustParseAddr("3.3.3.3")},
|
||||
expectedSearchDomains: []string{"universe.com", "galaxy.org"},
|
||||
expectedDisableSearch: true,
|
||||
},
|
||||
{
|
||||
name: "v1alpha1 empty",
|
||||
|
||||
cfg: func(*testing.T) config.Config {
|
||||
return container.NewV1Alpha1(&v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
})
|
||||
},
|
||||
|
||||
expectedNameservers: nil,
|
||||
expectedSearchDomains: nil,
|
||||
expectedDisableSearch: false,
|
||||
},
|
||||
{
|
||||
name: "new style only",
|
||||
|
||||
cfg: func(*testing.T) config.Config {
|
||||
rc := network.NewResolverConfigV1Alpha1()
|
||||
rc.ResolverNameservers = []network.NameserverConfig{
|
||||
{
|
||||
Address: network.Addr{Addr: netip.MustParseAddr("2.2.2.2")},
|
||||
},
|
||||
{
|
||||
Address: network.Addr{Addr: netip.MustParseAddr("3.3.3.3")},
|
||||
},
|
||||
}
|
||||
rc.ResolverSearchDomains = network.SearchDomainsConfig{
|
||||
SearchDomains: []string{"universe.com", "galaxy.org"},
|
||||
SearchDisableDefault: pointer.To(true),
|
||||
}
|
||||
|
||||
c, err := container.New(
|
||||
rc,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
return c
|
||||
},
|
||||
|
||||
expectedNameservers: []netip.Addr{netip.MustParseAddr("2.2.2.2"), netip.MustParseAddr("3.3.3.3")},
|
||||
expectedSearchDomains: []string{"universe.com", "galaxy.org"},
|
||||
expectedDisableSearch: true,
|
||||
},
|
||||
{
|
||||
name: "mixed",
|
||||
|
||||
cfg: func(*testing.T) config.Config {
|
||||
rc := network.NewResolverConfigV1Alpha1()
|
||||
rc.ResolverNameservers = []network.NameserverConfig{
|
||||
{
|
||||
Address: network.Addr{Addr: netip.MustParseAddr("2.2.2.2")},
|
||||
},
|
||||
{
|
||||
Address: network.Addr{Addr: netip.MustParseAddr("3.3.3.3")},
|
||||
},
|
||||
}
|
||||
|
||||
c, err := container.New(
|
||||
rc,
|
||||
&v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{},
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
return c
|
||||
},
|
||||
|
||||
expectedNameservers: []netip.Addr{netip.MustParseAddr("2.2.2.2"), netip.MustParseAddr("3.3.3.3")},
|
||||
expectedSearchDomains: nil,
|
||||
expectedDisableSearch: false,
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := test.cfg(t)
|
||||
|
||||
resolverConfig := cfg.NetworkResolverConfig()
|
||||
|
||||
require.NotNil(t, resolverConfig)
|
||||
|
||||
assert.Equal(t, test.expectedNameservers, resolverConfig.Resolvers())
|
||||
assert.Equal(t, test.expectedSearchDomains, resolverConfig.SearchDomains())
|
||||
assert.Equal(t, test.expectedDisableSearch, resolverConfig.DisableSearchDomain())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeSyncBridging(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
|
||||
cfg func(*testing.T) config.Config
|
||||
|
||||
expectedNil bool
|
||||
expectedDisabled bool
|
||||
expectedTimeservers []string
|
||||
expectedBootTimeout time.Duration
|
||||
}{
|
||||
{
|
||||
name: "v1alpha1 only",
|
||||
|
||||
cfg: func(*testing.T) config.Config {
|
||||
return container.NewV1Alpha1(&v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeDisabled: pointer.To(true),
|
||||
TimeServers: []string{"time1.example.com", "time2.example.com"},
|
||||
TimeBootTimeout: 30 * time.Second,
|
||||
},
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
expectedDisabled: true,
|
||||
expectedTimeservers: []string{"time1.example.com", "time2.example.com"},
|
||||
expectedBootTimeout: 30 * time.Second,
|
||||
},
|
||||
{
|
||||
name: "v1alpha1 empty",
|
||||
|
||||
cfg: func(*testing.T) config.Config {
|
||||
return container.NewV1Alpha1(&v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
})
|
||||
},
|
||||
|
||||
expectedNil: true,
|
||||
},
|
||||
{
|
||||
name: "new style only",
|
||||
|
||||
cfg: func(*testing.T) config.Config {
|
||||
tsc := network.NewTimeSyncConfigV1Alpha1()
|
||||
tsc.TimeBootTimeout = 10 * time.Second
|
||||
tsc.TimeNTP = &network.NTPConfig{
|
||||
Servers: []string{"time1.example.com", "time2.example.com"},
|
||||
}
|
||||
|
||||
c, err := container.New(
|
||||
tsc,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
return c
|
||||
},
|
||||
|
||||
expectedDisabled: false,
|
||||
expectedTimeservers: []string{"time1.example.com", "time2.example.com"},
|
||||
expectedBootTimeout: 10 * time.Second,
|
||||
},
|
||||
{
|
||||
name: "mixed",
|
||||
|
||||
cfg: func(*testing.T) config.Config {
|
||||
tsc := network.NewTimeSyncConfigV1Alpha1()
|
||||
tsc.TimeBootTimeout = 10 * time.Second
|
||||
tsc.TimeNTP = &network.NTPConfig{
|
||||
Servers: []string{"time1.example.com", "time2.example.com"},
|
||||
}
|
||||
|
||||
c, err := container.New(
|
||||
tsc,
|
||||
&v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{},
|
||||
},
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
return c
|
||||
},
|
||||
|
||||
expectedDisabled: false,
|
||||
expectedTimeservers: []string{"time1.example.com", "time2.example.com"},
|
||||
expectedBootTimeout: 10 * time.Second,
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := test.cfg(t)
|
||||
|
||||
timesyncConfig := cfg.NetworkTimeSyncConfig()
|
||||
|
||||
if test.expectedNil {
|
||||
require.Nil(t, timesyncConfig)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
require.NotNil(t, timesyncConfig)
|
||||
|
||||
assert.Equal(t, test.expectedTimeservers, timesyncConfig.Servers())
|
||||
assert.Equal(t, test.expectedDisabled, timesyncConfig.Disabled())
|
||||
assert.Equal(t, test.expectedBootTimeout, timesyncConfig.BootTimeout())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,15 +196,6 @@ func (m *MachineConfig) Network() config.MachineNetwork {
|
||||
return m.MachineNetwork
|
||||
}
|
||||
|
||||
// Time implements the config.Provider interface.
|
||||
func (m *MachineConfig) Time() config.Time {
|
||||
if m.MachineTime == nil {
|
||||
return &TimeConfig{}
|
||||
}
|
||||
|
||||
return m.MachineTime
|
||||
}
|
||||
|
||||
// Controlplane implements the config.Provider interface.
|
||||
func (m *MachineConfig) Controlplane() config.MachineControlPlane {
|
||||
if m.MachineControlPlane == nil {
|
||||
@ -577,11 +568,6 @@ func (r *RegistryTLSConfig) InsecureSkipVerify() bool {
|
||||
return pointer.SafeDeref(r.TLSInsecureSkipVerify)
|
||||
}
|
||||
|
||||
// DisableSearchDomain implements the config.Provider interface.
|
||||
func (n *NetworkConfig) DisableSearchDomain() bool {
|
||||
return pointer.SafeDeref(n.NetworkDisableSearchDomain)
|
||||
}
|
||||
|
||||
// Devices implements the config.Provider interface.
|
||||
func (n *NetworkConfig) Devices() []config.Device {
|
||||
return xslices.Map(n.NetworkInterfaces, func(d *Device) config.Device { return d })
|
||||
@ -604,16 +590,6 @@ func (n *NetworkConfig) getDevice(iface IfaceSelector) *Device {
|
||||
return dev
|
||||
}
|
||||
|
||||
// Resolvers implements the config.Provider interface.
|
||||
func (n *NetworkConfig) Resolvers() []string {
|
||||
return n.NameServers
|
||||
}
|
||||
|
||||
// SearchDomains implements the config.Provider interface.
|
||||
func (n *NetworkConfig) SearchDomains() []string {
|
||||
return n.Searches
|
||||
}
|
||||
|
||||
// ExtraHosts implements the config.Provider interface.
|
||||
func (n *NetworkConfig) ExtraHosts() []config.NetworkStaticHostConfig {
|
||||
return xslices.Map(n.ExtraHostEntries, func(e *ExtraHost) config.NetworkStaticHostConfig { return e })
|
||||
|
||||
@ -219,11 +219,9 @@ type MachineConfig struct {
|
||||
// ".*":
|
||||
// type: string
|
||||
MachineEnv Env `yaml:"env,omitempty"`
|
||||
// description: |
|
||||
// Used to configure the machine's time settings.
|
||||
// examples:
|
||||
// - name: Example configuration for cloudflare ntp server.
|
||||
// value: machineTimeExample()
|
||||
// docgen:nodoc
|
||||
//
|
||||
// Deprecated: Use 'TimeSyncConfig' instead.
|
||||
MachineTime *TimeConfig `yaml:"time,omitempty"`
|
||||
// description: |
|
||||
// Used to configure the machine's sysctls.
|
||||
@ -688,16 +686,13 @@ type NetworkConfig struct {
|
||||
//
|
||||
// Deprecated: use multi-doc network config.
|
||||
NetworkInterfaces NetworkDeviceList `yaml:"interfaces,omitempty"`
|
||||
// description: |
|
||||
// Used to statically set the nameservers for the machine.
|
||||
// Defaults to `1.1.1.1` and `8.8.8.8`
|
||||
// examples:
|
||||
// - value: '[]string{"8.8.8.8", "1.1.1.1"}'
|
||||
// docgen:nodoc
|
||||
//
|
||||
// Deprecated: Use `ResolverConfig` instead.
|
||||
NameServers []string `yaml:"nameservers,omitempty"`
|
||||
// description: |
|
||||
// Used to statically set arbitrary search domains.
|
||||
// examples:
|
||||
// - value: '[]string{"example.org", "example.com"}'
|
||||
// docgen:nodoc
|
||||
//
|
||||
// Deprecated: Use `ResolverConfig` instead.
|
||||
Searches []string `yaml:"searchDomains,omitempty"`
|
||||
// docgen:nodoc
|
||||
//
|
||||
@ -708,15 +703,9 @@ type NetworkConfig struct {
|
||||
// examples:
|
||||
// - value: networkKubeSpanExample()
|
||||
NetworkKubeSpan *NetworkKubeSpan `yaml:"kubespan,omitempty"`
|
||||
// description: |
|
||||
// Disable generating a default search domain in /etc/resolv.conf
|
||||
// based on the machine hostname.
|
||||
// Defaults to `false`.
|
||||
// values:
|
||||
// - true
|
||||
// - yes
|
||||
// - false
|
||||
// - no
|
||||
// docgen:nodoc
|
||||
//
|
||||
// Deprecated: Use `ResolverConfig` instead.
|
||||
NetworkDisableSearchDomain *bool `yaml:"disableSearchDomain,omitempty"`
|
||||
}
|
||||
|
||||
@ -933,6 +922,8 @@ type InstallExtensionConfig struct {
|
||||
}
|
||||
|
||||
// TimeConfig represents the options for configuring time on a machine.
|
||||
//
|
||||
//docgen:nodoc
|
||||
type TimeConfig struct {
|
||||
// description: |
|
||||
// Indicates if the time service is disabled for the machine.
|
||||
|
||||
@ -173,13 +173,7 @@ func (MachineConfig) Doc() *encoder.Doc {
|
||||
"`no_proxy`",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "time",
|
||||
Type: "TimeConfig",
|
||||
Note: "",
|
||||
Description: "Used to configure the machine's time settings.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Used to configure the machine's time settings." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{},
|
||||
{
|
||||
Name: "sysctls",
|
||||
Type: "map[string]string",
|
||||
@ -276,7 +270,6 @@ func (MachineConfig) Doc() *encoder.Doc {
|
||||
doc.Fields[12].AddExample("Environment variables definition examples.", machineEnvExamples0())
|
||||
doc.Fields[12].AddExample("", machineEnvExamples1())
|
||||
doc.Fields[12].AddExample("", machineEnvExamples2())
|
||||
doc.Fields[13].AddExample("Example configuration for cloudflare ntp server.", machineTimeExample())
|
||||
doc.Fields[14].AddExample("MachineSysctls usage example.", machineSysctlsExample())
|
||||
doc.Fields[15].AddExample("MachineSysfs usage example.", machineSysfsExample())
|
||||
doc.Fields[18].AddExample("", machineFeaturesExample())
|
||||
@ -917,20 +910,8 @@ func (NetworkConfig) Doc() *encoder.Doc {
|
||||
Fields: []encoder.Doc{
|
||||
{},
|
||||
{},
|
||||
{
|
||||
Name: "nameservers",
|
||||
Type: "[]string",
|
||||
Note: "",
|
||||
Description: "Used to statically set the nameservers for the machine.\nDefaults to `1.1.1.1` and `8.8.8.8`",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Used to statically set the nameservers for the machine." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "searchDomains",
|
||||
Type: "[]string",
|
||||
Note: "",
|
||||
Description: "Used to statically set arbitrary search domains.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Used to statically set arbitrary search domains." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{
|
||||
Name: "kubespan",
|
||||
@ -939,26 +920,12 @@ func (NetworkConfig) Doc() *encoder.Doc {
|
||||
Description: "Configures KubeSpan feature.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Configures KubeSpan feature." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "disableSearchDomain",
|
||||
Type: "bool",
|
||||
Note: "",
|
||||
Description: "Disable generating a default search domain in /etc/resolv.conf\nbased on the machine hostname.\nDefaults to `false`.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Disable generating a default search domain in /etc/resolv.conf" /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Values: []string{
|
||||
"true",
|
||||
"yes",
|
||||
"false",
|
||||
"no",
|
||||
},
|
||||
},
|
||||
{},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("Network definition example.", machineNetworkConfigExample())
|
||||
|
||||
doc.Fields[2].AddExample("", []string{"8.8.8.8", "1.1.1.1"})
|
||||
doc.Fields[3].AddExample("", []string{"example.org", "example.com"})
|
||||
doc.Fields[5].AddExample("", networkKubeSpanExample())
|
||||
|
||||
return doc
|
||||
@ -1135,47 +1102,6 @@ func (InstallDiskSelector) Doc() *encoder.Doc {
|
||||
return doc
|
||||
}
|
||||
|
||||
func (TimeConfig) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "TimeConfig",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "TimeConfig represents the options for configuring time on a machine." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
Description: "TimeConfig represents the options for configuring time on a machine.",
|
||||
AppearsIn: []encoder.Appearance{
|
||||
{
|
||||
TypeName: "MachineConfig",
|
||||
FieldName: "time",
|
||||
},
|
||||
},
|
||||
Fields: []encoder.Doc{
|
||||
{
|
||||
Name: "disabled",
|
||||
Type: "bool",
|
||||
Note: "",
|
||||
Description: "Indicates if the time service is disabled for the machine.\nDefaults to `false`.",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Indicates if the time service is disabled for the machine." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "servers",
|
||||
Type: "[]string",
|
||||
Note: "",
|
||||
Description: "description: |\n Specifies time (NTP) servers to use for setting the system time.\n Defaults to `time.cloudflare.com`.\n\n Talos can also sync to the PTP time source (e.g provided by the hypervisor),\n provide the path to the PTP device as \"/dev/ptp0\" or \"/dev/ptp_kvm\".\n",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "description: |" /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
{
|
||||
Name: "bootTimeout",
|
||||
Type: "Duration",
|
||||
Note: "",
|
||||
Description: "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \"infinity\" (waiting forever for time sync)",
|
||||
Comments: [3]string{"" /* encoder.HeadComment */, "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence." /* encoder.LineComment */, "" /* encoder.FootComment */},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
doc.AddExample("Example configuration for cloudflare ntp server.", machineTimeExample())
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
func (CoreDNS) Doc() *encoder.Doc {
|
||||
doc := &encoder.Doc{
|
||||
Type: "CoreDNS",
|
||||
@ -2652,7 +2578,6 @@ func GetFileDoc() *encoder.FileDoc {
|
||||
NetworkConfig{}.Doc(),
|
||||
InstallConfig{}.Doc(),
|
||||
InstallDiskSelector{}.Doc(),
|
||||
TimeConfig{}.Doc(),
|
||||
CoreDNS{}.Doc(),
|
||||
Endpoint{}.Doc(),
|
||||
ControlPlaneConfig{}.Doc(),
|
||||
|
||||
@ -0,0 +1,83 @@
|
||||
---
|
||||
description: ResolverConfig is a config document to configure DNS resolving.
|
||||
title: ResolverConfig
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: ResolverConfig
|
||||
# A list of nameservers (DNS servers) to use for resolving domain names.
|
||||
nameservers:
|
||||
- address: 1.1.1.1 # The IP address of the nameserver.
|
||||
- address: ff08::1 # The IP address of the nameserver.
|
||||
# Configuration for search domains (in /etc/resolv.conf).
|
||||
searchDomains:
|
||||
# A list of search domains to be used for DNS resolution.
|
||||
domains:
|
||||
- example.com
|
||||
{{< /highlight >}}
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: ResolverConfig
|
||||
# Configuration for search domains (in /etc/resolv.conf).
|
||||
searchDomains:
|
||||
disableDefault: true # Disable default search domain configuration from hostname FQDN.
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`nameservers` |<a href="#ResolverConfig.nameservers.">[]NameserverConfig</a> |A list of nameservers (DNS servers) to use for resolving domain names.<br><br>Nameservers are used to resolve domain names on the host, and they are also<br>propagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.<br><br>This overrides any nameservers obtained via DHCP or platform configuration.<br>Default configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers. | |
|
||||
|`searchDomains` |<a href="#ResolverConfig.searchDomains">SearchDomainsConfig</a> |Configuration for search domains (in /etc/resolv.conf).<br><br>The default is to derive search domains from the hostname FQDN. | |
|
||||
|
||||
|
||||
|
||||
|
||||
## nameservers[] {#ResolverConfig.nameservers.}
|
||||
|
||||
NameserverConfig represents a single nameserver configuration.
|
||||
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`address` |Addr |The IP address of the nameserver. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
address: 10.0.0.1
|
||||
{{< /highlight >}}</details> | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## searchDomains {#ResolverConfig.searchDomains}
|
||||
|
||||
SearchDomainsConfig represents search domains configuration.
|
||||
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`domains` |[]string |A list of search domains to be used for DNS resolution.<br><br>Search domains are appended to unqualified domain names during DNS resolution.<br>For example, if "example.com" is a search domain and a user tries to resolve<br>"host", the system will attempt to resolve "host.example.com".<br><br>This overrides any search domains obtained via DHCP or platform configuration.<br>The default configuration derives the search domain from the hostname FQDN. | |
|
||||
|`disableDefault` |bool |Disable default search domain configuration from hostname FQDN.<br><br>When set to true, the system will not derive search domains from the hostname FQDN.<br>This allows for a custom configuration of search domains without any defaults. | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
---
|
||||
description: TimeSyncConfig is a config document to configure time synchronization (NTP).
|
||||
title: TimeSyncConfig
|
||||
---
|
||||
|
||||
<!-- markdownlint-disable -->
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: TimeSyncConfig
|
||||
# Specifies NTP configuration to sync the time over network.
|
||||
ntp:
|
||||
# Specifies time (NTP) servers to use for setting the system time.
|
||||
servers:
|
||||
- pool.ntp.org
|
||||
{{< /highlight >}}
|
||||
|
||||
{{< highlight yaml >}}
|
||||
apiVersion: v1alpha1
|
||||
kind: TimeSyncConfig
|
||||
# Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.
|
||||
ptp:
|
||||
# description: |
|
||||
devices:
|
||||
- /dev/ptp0
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`enabled` |bool |Indicates if the time synchronization is enabled for the machine.<br>Defaults to `true`. | |
|
||||
|`bootTimeout` |Duration |Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.<br>NTP sync will be still running in the background.<br>Defaults to "infinity" (waiting forever for time sync) | |
|
||||
|`ntp` |<a href="#TimeSyncConfig.ntp">NTPConfig</a> |Specifies NTP configuration to sync the time over network.<br>Mutually exclusive with PTP configuration. | |
|
||||
|`ptp` |<a href="#TimeSyncConfig.ptp">PTPConfig</a> |Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.<br>Mutually exclusive with NTP configuration. | |
|
||||
|
||||
|
||||
|
||||
|
||||
## ntp {#TimeSyncConfig.ntp}
|
||||
|
||||
NTPConfig represents a NTP server configuration.
|
||||
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`servers` |[]string |Specifies time (NTP) servers to use for setting the system time.<br>Defaults to `time.cloudflare.com`. | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## ptp {#TimeSyncConfig.ptp}
|
||||
|
||||
PTPConfig represents a PTP (Precision Time Protocol) configuration.
|
||||
|
||||
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`devices` |[]string |description: |<br> A list of PTP devices to sync with (e.g. provided by the hypervisor).<br><br> A PTP device is typically represented as a character device file in the /dev directory,<br> such as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time<br> with an external time source that supports the Precision Time Protocol.<br> | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -144,11 +144,9 @@ pods:
|
||||
{{< /highlight >}}</details> | |
|
||||
|`network` |<a href="#Config.machine.network">NetworkConfig</a> |Provides machine specific network configuration options. <details><summary>Show example(s)</summary>Network definition example.:{{< highlight yaml >}}
|
||||
network:
|
||||
# Used to statically set the nameservers for the machine.
|
||||
nameservers:
|
||||
- 9.8.7.6
|
||||
- 8.7.6.5
|
||||
# Used to statically set arbitrary search domains.
|
||||
searchDomains:
|
||||
- example.org
|
||||
- example.com
|
||||
@ -190,14 +188,6 @@ env:
|
||||
env:
|
||||
https_proxy: http://DOMAIN\USERNAME:PASSWORD@SERVER:PORT/
|
||||
{{< /highlight >}}</details> |``GRPC_GO_LOG_VERBOSITY_LEVEL``<br />``GRPC_GO_LOG_SEVERITY_LEVEL``<br />``http_proxy``<br />``https_proxy``<br />``no_proxy``<br /> |
|
||||
|`time` |<a href="#Config.machine.time">TimeConfig</a> |Used to configure the machine's time settings. <details><summary>Show example(s)</summary>Example configuration for cloudflare ntp server.:{{< highlight yaml >}}
|
||||
time:
|
||||
disabled: false # Indicates if the time service is disabled for the machine.
|
||||
# description: |
|
||||
servers:
|
||||
- time.cloudflare.com
|
||||
bootTimeout: 2m0s # Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.
|
||||
{{< /highlight >}}</details> | |
|
||||
|`sysctls` |map[string]string |Used to configure the machine's sysctls. <details><summary>Show example(s)</summary>MachineSysctls usage example.:{{< highlight yaml >}}
|
||||
sysctls:
|
||||
kernel.domainname: talos.dev
|
||||
@ -560,11 +550,9 @@ NetworkConfig represents the machine's networking config values.
|
||||
{{< highlight yaml >}}
|
||||
machine:
|
||||
network:
|
||||
# Used to statically set the nameservers for the machine.
|
||||
nameservers:
|
||||
- 9.8.7.6
|
||||
- 8.7.6.5
|
||||
# Used to statically set arbitrary search domains.
|
||||
searchDomains:
|
||||
- example.org
|
||||
- example.com
|
||||
@ -577,21 +565,10 @@ machine:
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`nameservers` |[]string |Used to statically set the nameservers for the machine.<br>Defaults to `1.1.1.1` and `8.8.8.8` <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
nameservers:
|
||||
- 8.8.8.8
|
||||
- 1.1.1.1
|
||||
{{< /highlight >}}</details> | |
|
||||
|`searchDomains` |[]string |Used to statically set arbitrary search domains. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
searchDomains:
|
||||
- example.org
|
||||
- example.com
|
||||
{{< /highlight >}}</details> | |
|
||||
|`kubespan` |<a href="#Config.machine.network.kubespan">NetworkKubeSpan</a> |Configures KubeSpan feature. <details><summary>Show example(s)</summary>{{< highlight yaml >}}
|
||||
kubespan:
|
||||
enabled: true # Enable the KubeSpan feature.
|
||||
{{< /highlight >}}</details> | |
|
||||
|`disableSearchDomain` |bool |Disable generating a default search domain in /etc/resolv.conf<br>based on the machine hostname.<br>Defaults to `false`. |`true`<br />`yes`<br />`false`<br />`no`<br /> |
|
||||
|
||||
|
||||
|
||||
@ -771,34 +748,6 @@ machine:
|
||||
|
||||
|
||||
|
||||
### time {#Config.machine.time}
|
||||
|
||||
TimeConfig represents the options for configuring time on a machine.
|
||||
|
||||
|
||||
|
||||
{{< highlight yaml >}}
|
||||
machine:
|
||||
time:
|
||||
disabled: false # Indicates if the time service is disabled for the machine.
|
||||
# description: |
|
||||
servers:
|
||||
- time.cloudflare.com
|
||||
bootTimeout: 2m0s # Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.
|
||||
{{< /highlight >}}
|
||||
|
||||
|
||||
| Field | Type | Description | Value(s) |
|
||||
|-------|------|-------------|----------|
|
||||
|`disabled` |bool |Indicates if the time service is disabled for the machine.<br>Defaults to `false`. | |
|
||||
|`servers` |[]string |description: |<br> Specifies time (NTP) servers to use for setting the system time.<br> Defaults to `time.cloudflare.com`.<br><br> Talos can also sync to the PTP time source (e.g provided by the hypervisor),<br> provide the path to the PTP device as "/dev/ptp0" or "/dev/ptp_kvm".<br> | |
|
||||
|`bootTimeout` |Duration |Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.<br>NTP sync will be still running in the background.<br>Defaults to "infinity" (waiting forever for time sync) | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### features {#Config.machine.features}
|
||||
|
||||
FeaturesConfig describes individual Talos features that can be switched on or off.
|
||||
|
||||
@ -2249,6 +2249,101 @@
|
||||
"type": "object",
|
||||
"description": "LinkSelector selects a link to alias."
|
||||
},
|
||||
"network.NTPConfig": {
|
||||
"properties": {
|
||||
"servers": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "servers",
|
||||
"description": "Specifies time (NTP) servers to use for setting the system time.\nDefaults to time.cloudflare.com.\n",
|
||||
"markdownDescription": "Specifies time (NTP) servers to use for setting the system time.\nDefaults to `time.cloudflare.com`.",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecifies time (NTP) servers to use for setting the system time.\nDefaults to \u003ccode\u003etime.cloudflare.com\u003c/code\u003e.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "NTPConfig represents a NTP server configuration."
|
||||
},
|
||||
"network.NameserverConfig": {
|
||||
"properties": {
|
||||
"address": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-f.:]+$",
|
||||
"title": "address",
|
||||
"description": "The IP address of the nameserver.\n",
|
||||
"markdownDescription": "The IP address of the nameserver.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe IP address of the nameserver.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "NameserverConfig represents a single nameserver configuration."
|
||||
},
|
||||
"network.PTPConfig": {
|
||||
"properties": {
|
||||
"devices": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "devices",
|
||||
"description": "description: |\n A list of PTP devices to sync with (e.g. provided by the hypervisor).\n\nA PTP device is typically represented as a character device file in the /dev directory,\n\n\nsuch as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time\n with an external time source that supports the Precision Time Protocol.\n",
|
||||
"markdownDescription": "description: |\n A list of PTP devices to sync with (e.g. provided by the hypervisor).\n\n A PTP device is typically represented as a character device file in the /dev directory,\n such as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time\n with an external time source that supports the Precision Time Protocol.",
|
||||
"x-intellij-html-description": "\u003cp\u003edescription: |\n A list of PTP devices to sync with (e.g. provided by the hypervisor).\u003c/p\u003e\n\n\u003cpre\u003e\u003ccode\u003eA PTP device is typically represented as a character device file in the /dev directory,\n\u003c/code\u003e\u003c/pre\u003e\n\n\u003cp\u003esuch as /dev/ptp0 or /dev/ptp_kvm. These devices are used to synchronize the system time\n with an external time source that supports the Precision Time Protocol.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "PTPConfig represents a PTP (Precision Time Protocol) configuration."
|
||||
},
|
||||
"network.ResolverConfigV1Alpha1": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"enum": [
|
||||
"v1alpha1"
|
||||
],
|
||||
"title": "apiVersion",
|
||||
"description": "apiVersion is the API version of the resource.\n",
|
||||
"markdownDescription": "apiVersion is the API version of the resource.",
|
||||
"x-intellij-html-description": "\u003cp\u003eapiVersion is the API version of the resource.\u003c/p\u003e\n"
|
||||
},
|
||||
"kind": {
|
||||
"enum": [
|
||||
"ResolverConfig"
|
||||
],
|
||||
"title": "kind",
|
||||
"description": "kind is the kind of the resource.\n",
|
||||
"markdownDescription": "kind is the kind of the resource.",
|
||||
"x-intellij-html-description": "\u003cp\u003ekind is the kind of the resource.\u003c/p\u003e\n"
|
||||
},
|
||||
"nameservers": {
|
||||
"items": {
|
||||
"$ref": "#/$defs/network.NameserverConfig"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "nameservers",
|
||||
"description": "A list of nameservers (DNS servers) to use for resolving domain names.\n\nNameservers are used to resolve domain names on the host, and they are also\npropagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.\n\nThis overrides any nameservers obtained via DHCP or platform configuration.\nDefault configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers.\n",
|
||||
"markdownDescription": "A list of nameservers (DNS servers) to use for resolving domain names.\n\nNameservers are used to resolve domain names on the host, and they are also\npropagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.\n\nThis overrides any nameservers obtained via DHCP or platform configuration.\nDefault configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers.",
|
||||
"x-intellij-html-description": "\u003cp\u003eA list of nameservers (DNS servers) to use for resolving domain names.\u003c/p\u003e\n\n\u003cp\u003eNameservers are used to resolve domain names on the host, and they are also\npropagated to Kubernetes DNS (CoreDNS) for use by pods running on the cluster.\u003c/p\u003e\n\n\u003cp\u003eThis overrides any nameservers obtained via DHCP or platform configuration.\nDefault configuration is to use 1.1.1.1 and 8.8.8.8 as nameservers.\u003c/p\u003e\n"
|
||||
},
|
||||
"searchDomains": {
|
||||
"$ref": "#/$defs/network.SearchDomainsConfig",
|
||||
"title": "searchDomains",
|
||||
"description": "Configuration for search domains (in /etc/resolv.conf).\n\nThe default is to derive search domains from the hostname FQDN.\n",
|
||||
"markdownDescription": "Configuration for search domains (in /etc/resolv.conf).\n\nThe default is to derive search domains from the hostname FQDN.",
|
||||
"x-intellij-html-description": "\u003cp\u003eConfiguration for search domains (in /etc/resolv.conf).\u003c/p\u003e\n\n\u003cp\u003eThe default is to derive search domains from the hostname FQDN.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"apiVersion",
|
||||
"kind"
|
||||
],
|
||||
"description": "ResolverConfig is a config document to configure DNS resolving."
|
||||
},
|
||||
"network.RouteConfig": {
|
||||
"properties": {
|
||||
"destination": {
|
||||
@ -2391,6 +2486,30 @@
|
||||
"type": "object",
|
||||
"description": "RulePortSelector is a port selector for the network rule."
|
||||
},
|
||||
"network.SearchDomainsConfig": {
|
||||
"properties": {
|
||||
"domains": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "domains",
|
||||
"description": "A list of search domains to be used for DNS resolution.\n\nSearch domains are appended to unqualified domain names during DNS resolution.\nFor example, if “example.com” is a search domain and a user tries to resolve\n“host”, the system will attempt to resolve “host.example.com”.\n\nThis overrides any search domains obtained via DHCP or platform configuration.\nThe default configuration derives the search domain from the hostname FQDN.\n",
|
||||
"markdownDescription": "A list of search domains to be used for DNS resolution.\n\nSearch domains are appended to unqualified domain names during DNS resolution.\nFor example, if \"example.com\" is a search domain and a user tries to resolve\n\"host\", the system will attempt to resolve \"host.example.com\".\n\nThis overrides any search domains obtained via DHCP or platform configuration.\nThe default configuration derives the search domain from the hostname FQDN.",
|
||||
"x-intellij-html-description": "\u003cp\u003eA list of search domains to be used for DNS resolution.\u003c/p\u003e\n\n\u003cp\u003eSearch domains are appended to unqualified domain names during DNS resolution.\nFor example, if \u0026ldquo;example.com\u0026rdquo; is a search domain and a user tries to resolve\n\u0026ldquo;host\u0026rdquo;, the system will attempt to resolve \u0026ldquo;host.example.com\u0026rdquo;.\u003c/p\u003e\n\n\u003cp\u003eThis overrides any search domains obtained via DHCP or platform configuration.\nThe default configuration derives the search domain from the hostname FQDN.\u003c/p\u003e\n"
|
||||
},
|
||||
"disableDefault": {
|
||||
"type": "boolean",
|
||||
"title": "disableDefault",
|
||||
"description": "Disable default search domain configuration from hostname FQDN.\n\nWhen set to true, the system will not derive search domains from the hostname FQDN.\nThis allows for a custom configuration of search domains without any defaults.\n",
|
||||
"markdownDescription": "Disable default search domain configuration from hostname FQDN.\n\nWhen set to true, the system will not derive search domains from the hostname FQDN.\nThis allows for a custom configuration of search domains without any defaults.",
|
||||
"x-intellij-html-description": "\u003cp\u003eDisable default search domain configuration from hostname FQDN.\u003c/p\u003e\n\n\u003cp\u003eWhen set to true, the system will not derive search domains from the hostname FQDN.\nThis allows for a custom configuration of search domains without any defaults.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "SearchDomainsConfig represents search domains configuration."
|
||||
},
|
||||
"network.StaticHostConfigV1Alpha1": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
@ -2438,6 +2557,64 @@
|
||||
],
|
||||
"description": "StaticHostConfig is a config document to set /etc/hosts entries."
|
||||
},
|
||||
"network.TimeSyncConfigV1Alpha1": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
"enum": [
|
||||
"v1alpha1"
|
||||
],
|
||||
"title": "apiVersion",
|
||||
"description": "apiVersion is the API version of the resource.\n",
|
||||
"markdownDescription": "apiVersion is the API version of the resource.",
|
||||
"x-intellij-html-description": "\u003cp\u003eapiVersion is the API version of the resource.\u003c/p\u003e\n"
|
||||
},
|
||||
"kind": {
|
||||
"enum": [
|
||||
"TimeSyncConfig"
|
||||
],
|
||||
"title": "kind",
|
||||
"description": "kind is the kind of the resource.\n",
|
||||
"markdownDescription": "kind is the kind of the resource.",
|
||||
"x-intellij-html-description": "\u003cp\u003ekind is the kind of the resource.\u003c/p\u003e\n"
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"title": "enabled",
|
||||
"description": "Indicates if the time synchronization is enabled for the machine.\nDefaults to true.\n",
|
||||
"markdownDescription": "Indicates if the time synchronization is enabled for the machine.\nDefaults to `true`.",
|
||||
"x-intellij-html-description": "\u003cp\u003eIndicates if the time synchronization is enabled for the machine.\nDefaults to \u003ccode\u003etrue\u003c/code\u003e.\u003c/p\u003e\n"
|
||||
},
|
||||
"bootTimeout": {
|
||||
"type": "string",
|
||||
"pattern": "^[-+]?(((\\d+(\\.\\d*)?|\\d*(\\.\\d+)+)([nuµm]?s|m|h))|0)+$",
|
||||
"title": "bootTimeout",
|
||||
"description": "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to “infinity” (waiting forever for time sync)\n",
|
||||
"markdownDescription": "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \"infinity\" (waiting forever for time sync)",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \u0026ldquo;infinity\u0026rdquo; (waiting forever for time sync)\u003c/p\u003e\n"
|
||||
},
|
||||
"ntp": {
|
||||
"$ref": "#/$defs/network.NTPConfig",
|
||||
"title": "ntp",
|
||||
"description": "Specifies NTP configuration to sync the time over network.\nMutually exclusive with PTP configuration.\n",
|
||||
"markdownDescription": "Specifies NTP configuration to sync the time over network.\nMutually exclusive with PTP configuration.",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecifies NTP configuration to sync the time over network.\nMutually exclusive with PTP configuration.\u003c/p\u003e\n"
|
||||
},
|
||||
"ptp": {
|
||||
"$ref": "#/$defs/network.PTPConfig",
|
||||
"title": "ptp",
|
||||
"description": "Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.\nMutually exclusive with NTP configuration.\n",
|
||||
"markdownDescription": "Specific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.\nMutually exclusive with NTP configuration.",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecific PTP (Precision Time Protocol) configuration to sync the time over PTP devices.\nMutually exclusive with NTP configuration.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"required": [
|
||||
"apiVersion",
|
||||
"kind"
|
||||
],
|
||||
"description": "TimeSyncConfig is a config document to configure time synchronization (NTP)."
|
||||
},
|
||||
"network.VLANConfigV1Alpha1": {
|
||||
"properties": {
|
||||
"apiVersion": {
|
||||
@ -4412,13 +4589,6 @@
|
||||
"markdownDescription": "The `env` field allows for the addition of environment variables.\nAll environment variables are set on PID 1 in addition to every service.",
|
||||
"x-intellij-html-description": "\u003cp\u003eThe \u003ccode\u003eenv\u003c/code\u003e field allows for the addition of environment variables.\nAll environment variables are set on PID 1 in addition to every service.\u003c/p\u003e\n"
|
||||
},
|
||||
"time": {
|
||||
"$ref": "#/$defs/v1alpha1.TimeConfig",
|
||||
"title": "time",
|
||||
"description": "Used to configure the machine’s time settings.\n",
|
||||
"markdownDescription": "Used to configure the machine's time settings.",
|
||||
"x-intellij-html-description": "\u003cp\u003eUsed to configure the machine\u0026rsquo;s time settings.\u003c/p\u003e\n"
|
||||
},
|
||||
"sysctls": {
|
||||
"patternProperties": {
|
||||
".*": {
|
||||
@ -4640,39 +4810,12 @@
|
||||
},
|
||||
"v1alpha1.NetworkConfig": {
|
||||
"properties": {
|
||||
"nameservers": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "nameservers",
|
||||
"description": "Used to statically set the nameservers for the machine.\nDefaults to 1.1.1.1 and 8.8.8.8\n",
|
||||
"markdownDescription": "Used to statically set the nameservers for the machine.\nDefaults to `1.1.1.1` and `8.8.8.8`",
|
||||
"x-intellij-html-description": "\u003cp\u003eUsed to statically set the nameservers for the machine.\nDefaults to \u003ccode\u003e1.1.1.1\u003c/code\u003e and \u003ccode\u003e8.8.8.8\u003c/code\u003e\u003c/p\u003e\n"
|
||||
},
|
||||
"searchDomains": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "searchDomains",
|
||||
"description": "Used to statically set arbitrary search domains.\n",
|
||||
"markdownDescription": "Used to statically set arbitrary search domains.",
|
||||
"x-intellij-html-description": "\u003cp\u003eUsed to statically set arbitrary search domains.\u003c/p\u003e\n"
|
||||
},
|
||||
"kubespan": {
|
||||
"$ref": "#/$defs/v1alpha1.NetworkKubeSpan",
|
||||
"title": "kubespan",
|
||||
"description": "Configures KubeSpan feature.\n",
|
||||
"markdownDescription": "Configures KubeSpan feature.",
|
||||
"x-intellij-html-description": "\u003cp\u003eConfigures KubeSpan feature.\u003c/p\u003e\n"
|
||||
},
|
||||
"disableSearchDomain": {
|
||||
"type": "boolean",
|
||||
"title": "disableSearchDomain",
|
||||
"description": "Disable generating a default search domain in /etc/resolv.conf\nbased on the machine hostname.\nDefaults to false.\n",
|
||||
"markdownDescription": "Disable generating a default search domain in /etc/resolv.conf\nbased on the machine hostname.\nDefaults to `false`.",
|
||||
"x-intellij-html-description": "\u003cp\u003eDisable generating a default search domain in /etc/resolv.conf\nbased on the machine hostname.\nDefaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
@ -4886,38 +5029,6 @@
|
||||
"type": "object",
|
||||
"description": "SchedulerConfig represents the kube scheduler configuration options."
|
||||
},
|
||||
"v1alpha1.TimeConfig": {
|
||||
"properties": {
|
||||
"disabled": {
|
||||
"type": "boolean",
|
||||
"title": "disabled",
|
||||
"description": "Indicates if the time service is disabled for the machine.\nDefaults to false.\n",
|
||||
"markdownDescription": "Indicates if the time service is disabled for the machine.\nDefaults to `false`.",
|
||||
"x-intellij-html-description": "\u003cp\u003eIndicates if the time service is disabled for the machine.\nDefaults to \u003ccode\u003efalse\u003c/code\u003e.\u003c/p\u003e\n"
|
||||
},
|
||||
"servers": {
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "servers",
|
||||
"description": "description: |\n Specifies time (NTP) servers to use for setting the system time.\n Defaults to time.cloudflare.com.\n\nTalos can also sync to the PTP time source (e.g provided by the hypervisor),\n provide the path to the PTP device as “/dev/ptp0” or “/dev/ptp_kvm”.\n",
|
||||
"markdownDescription": "description: |\n Specifies time (NTP) servers to use for setting the system time.\n Defaults to `time.cloudflare.com`.\n\n Talos can also sync to the PTP time source (e.g provided by the hypervisor),\n provide the path to the PTP device as \"/dev/ptp0\" or \"/dev/ptp_kvm\".",
|
||||
"x-intellij-html-description": "\u003cp\u003edescription: |\n Specifies time (NTP) servers to use for setting the system time.\n Defaults to \u003ccode\u003etime.cloudflare.com\u003c/code\u003e.\u003c/p\u003e\n\n\u003cp\u003eTalos can also sync to the PTP time source (e.g provided by the hypervisor),\n provide the path to the PTP device as \u0026ldquo;/dev/ptp0\u0026rdquo; or \u0026ldquo;/dev/ptp_kvm\u0026rdquo;.\u003c/p\u003e\n"
|
||||
},
|
||||
"bootTimeout": {
|
||||
"type": "string",
|
||||
"pattern": "^[-+]?(((\\d+(\\.\\d*)?|\\d*(\\.\\d+)+)([nuµm]?s|m|h))|0)+$",
|
||||
"title": "bootTimeout",
|
||||
"description": "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to “infinity” (waiting forever for time sync)\n",
|
||||
"markdownDescription": "Specifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \"infinity\" (waiting forever for time sync)",
|
||||
"x-intellij-html-description": "\u003cp\u003eSpecifies the timeout when the node time is considered to be in sync unlocking the boot sequence.\nNTP sync will be still running in the background.\nDefaults to \u0026ldquo;infinity\u0026rdquo; (waiting forever for time sync)\u003c/p\u003e\n"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"type": "object",
|
||||
"description": "TimeConfig represents the options for configuring time on a machine."
|
||||
},
|
||||
"v1alpha1.UdevConfig": {
|
||||
"properties": {
|
||||
"rules": {
|
||||
@ -5037,12 +5148,18 @@
|
||||
{
|
||||
"$ref": "#/$defs/network.LinkAliasConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.ResolverConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.RuleConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.StaticHostConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.TimeSyncConfigV1Alpha1"
|
||||
},
|
||||
{
|
||||
"$ref": "#/$defs/network.VLANConfigV1Alpha1"
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user