diff --git a/Makefile b/Makefile index 0ca8944367..90cc909dfa 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ ARTIFACTS := _out TOOLS ?= ghcr.io/siderolabs/tools:v1.7.0-2-g345db93 PKGS_PREFIX ?= ghcr.io/siderolabs -PKGS ?= v1.7.0-14-g9caa8be +PKGS ?= v1.7.0-17-ga201d27 EXTRAS ?= v1.7.0-1-gbb76755 PKG_FHS ?= $(PKGS_PREFIX)/fhs:$(PKGS) diff --git a/cmd/installer/pkg/install/install.go b/cmd/installer/pkg/install/install.go index d8bffaceb6..9fa203f356 100644 --- a/cmd/installer/pkg/install/install.go +++ b/cmd/installer/pkg/install/install.go @@ -445,7 +445,7 @@ func retryBlockdeviceOpen(device string) (*blockdevice.BlockDevice, error) { switch { case os.IsNotExist(openErr): return retry.ExpectedError(openErr) - case errors.Is(openErr, syscall.ENODEV): + case errors.Is(openErr, syscall.ENODEV), errors.Is(openErr, syscall.ENXIO): return retry.ExpectedError(openErr) default: return nil diff --git a/go.mod b/go.mod index fc8f871dcc..64cbb7f3bc 100644 --- a/go.mod +++ b/go.mod @@ -49,7 +49,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 github.com/aws/aws-sdk-go-v2/service/kms v1.30.1 github.com/aws/smithy-go v1.20.2 - github.com/beevik/ntp v1.3.1 + github.com/beevik/ntp v1.4.2 github.com/benbjohnson/clock v1.3.5 // project archived on 2023-05-18 github.com/blang/semver/v4 v4.0.0 github.com/cenkalti/backoff/v4 v4.3.0 @@ -139,7 +139,7 @@ require ( github.com/siderolabs/go-procfs v0.1.2 github.com/siderolabs/go-retry v0.3.3 github.com/siderolabs/go-smbios v0.3.2 - github.com/siderolabs/go-tail v0.1.0 + github.com/siderolabs/go-tail v0.1.1 github.com/siderolabs/go-talos-support v0.1.0 github.com/siderolabs/grpc-proxy v0.4.0 github.com/siderolabs/kms-client v0.1.0 @@ -161,11 +161,11 @@ require ( go.etcd.io/etcd/etcdutl/v3 v3.5.13 go.uber.org/zap v1.27.0 go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - golang.org/x/net v0.23.0 + golang.org/x/net v0.24.0 golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.6.0 - golang.org/x/sys v0.18.0 - golang.org/x/term v0.18.0 + golang.org/x/sys v0.19.0 + golang.org/x/term v0.19.0 golang.org/x/text v0.14.0 golang.org/x/time v0.5.0 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 @@ -340,7 +340,7 @@ require ( go.opentelemetry.io/otel/trace v1.22.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.21.0 // indirect + golang.org/x/crypto v0.22.0 // indirect golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect golang.org/x/mod v0.16.0 // indirect golang.org/x/tools v0.19.0 // indirect diff --git a/go.sum b/go.sum index 1210918946..066bb0004e 100644 --- a/go.sum +++ b/go.sum @@ -119,8 +119,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= -github.com/beevik/ntp v1.3.1 h1:Y/srlT8L1yQr58kyPWFPZIxRL8ttx2SRIpVYJqZIlAM= -github.com/beevik/ntp v1.3.1/go.mod h1:fT6PylBq86Tsq23ZMEe47b7QQrZfYBFPnpzt0a9kJxw= +github.com/beevik/ntp v1.4.2 h1:cjYhZqczanf6br/ocViahE75ipj7CmKQAh7fSBaCNK4= +github.com/beevik/ntp v1.4.2/go.mod h1:zkATLTt8VUZuOfYX2KgOnir4yvtAxWbnUUA24umXFnc= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -698,8 +698,8 @@ github.com/siderolabs/go-retry v0.3.3 h1:zKV+S1vumtO72E6sYsLlmIdV/G/GcYSBLiEx/c9 github.com/siderolabs/go-retry v0.3.3/go.mod h1:Ff/VGc7v7un4uQg3DybgrmOWHEmJ8BzZds/XNn/BqMI= github.com/siderolabs/go-smbios v0.3.2 h1:/9MCz1h3HYFcNdFG9rIL9EKwtQJsHRPuGuM2ESdao3A= github.com/siderolabs/go-smbios v0.3.2/go.mod h1:AKzwL3QdFOgA81h65Hay2bs3BUnH+FBnXqNfgeChpEc= -github.com/siderolabs/go-tail v0.1.0 h1:U+ZClt7BXLGsxDNU/XQ12sz7lQElfFZBYEPdkW78Qro= -github.com/siderolabs/go-tail v0.1.0/go.mod h1:vWxumnRUS3eTZczORCJW3QMjxiTETN31vyuFdaW8rPw= +github.com/siderolabs/go-tail v0.1.1 h1:3XeJgd97OHyFAIE7nQEMcRhOfnv7DvXbu0BRKbtT6u8= +github.com/siderolabs/go-tail v0.1.1/go.mod h1:IihAL39acadXHfb5fEAOKK2DaDFIrG2+VD3b2H/ziZ0= github.com/siderolabs/go-talos-support v0.1.0 h1:ulf+RI0Wo6UGzKQJZog1uvdQE/zstogs1R46jZpAmvU= github.com/siderolabs/go-talos-support v0.1.0/go.mod h1:hiYQrdQSBH6ap7LZHyHUZLbYnL2KhC6hPrJ7utqm+P8= github.com/siderolabs/grpc-proxy v0.4.0 h1:zYrhqLYs8JlYoLHYeel7/XwXDZ4OJ5XyP9wX7JlbPew= @@ -853,8 +853,8 @@ golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -940,8 +940,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1034,8 +1034,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1045,8 +1045,8 @@ golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/hack/release.toml b/hack/release.toml index b23313c29c..25edd22084 100644 --- a/hack/release.toml +++ b/hack/release.toml @@ -6,7 +6,7 @@ github_repo = "siderolabs/talos" match_deps = "^github.com/((talos-systems|siderolabs)/[a-zA-Z0-9-]+)$" # previous release -previous = "v1.7.1" +previous = "v1.7.2" pre_release = false @@ -17,8 +17,7 @@ preface = """\ [notes.updates] title = "Component Updates" description = """\ -Kubernetes: 1.30.1 -Linux: 6.6.30 +Linux: 6.6.32 Talos is built with Go 1.22.3. """ diff --git a/internal/app/machined/pkg/controllers/network/dns_resolve_cache.go b/internal/app/machined/pkg/controllers/network/dns_resolve_cache.go index 763b4007ab..d93ccaaf48 100644 --- a/internal/app/machined/pkg/controllers/network/dns_resolve_cache.go +++ b/internal/app/machined/pkg/controllers/network/dns_resolve_cache.go @@ -37,7 +37,7 @@ type DNSResolveCacheController struct { mx sync.Mutex handler *dns.Handler nodeHandler *dns.NodeHandler - cache *dns.Cache + rootHandler dnssrv.Handler runners map[runnerConfig]pair.Pair[func(), <-chan struct{}] reconcile chan struct{} originalCtx context.Context //nolint:containedctx @@ -130,7 +130,7 @@ func (ctrl *DNSResolveCacheController) Run(ctx context.Context, r controller.Run runnerCfg := runnerConfig{net: netwk, addr: addr} if _, ok := ctrl.runners[runnerCfg]; !ok { - runner, rErr := newDNSRunner(runnerCfg, ctrl.cache, ctrl.Logger, cfg.TypedSpec().ServiceHostDNSAddress.IsValid()) + runner, rErr := newDNSRunner(runnerCfg, ctrl.rootHandler, ctrl.Logger, cfg.TypedSpec().ServiceHostDNSAddress.IsValid()) if rErr != nil { return fmt.Errorf("error creating dns runner: %w", rErr) } @@ -200,7 +200,7 @@ func (ctrl *DNSResolveCacheController) init(ctx context.Context) { ctrl.originalCtx = ctx ctrl.handler = dns.NewHandler(ctrl.Logger) ctrl.nodeHandler = dns.NewNodeHandler(ctrl.handler, &stateMapper{state: ctrl.State}, ctrl.Logger) - ctrl.cache = dns.NewCache(ctrl.nodeHandler, ctrl.Logger) + ctrl.rootHandler = dns.NewCache(ctrl.nodeHandler, ctrl.Logger) ctrl.runners = map[runnerConfig]pair.Pair[func(), <-chan struct{}]{} ctrl.reconcile = make(chan struct{}, 1) @@ -256,7 +256,7 @@ type runnerConfig struct { addr netip.AddrPort } -func newDNSRunner(cfg runnerConfig, cache *dns.Cache, logger *zap.Logger, forwardEnabled bool) (*dns.Server, error) { +func newDNSRunner(cfg runnerConfig, rootHandler dnssrv.Handler, logger *zap.Logger, forwardEnabled bool) (*dns.Server, error) { if cfg.addr.Addr().Is6() { cfg.net += "6" } @@ -279,7 +279,7 @@ func newDNSRunner(cfg runnerConfig, cache *dns.Cache, logger *zap.Logger, forwar serverOpts = dns.ServerOptions{ PacketConn: packetConn, - Handler: cache, + Handler: rootHandler, Logger: logger, } @@ -291,7 +291,7 @@ func newDNSRunner(cfg runnerConfig, cache *dns.Cache, logger *zap.Logger, forwar serverOpts = dns.ServerOptions{ Listener: listener, - Handler: cache, + Handler: rootHandler, ReadTimeout: 3 * time.Second, WriteTimeout: 5 * time.Second, IdleTimeout: func() time.Duration { return 10 * time.Second }, diff --git a/internal/app/machined/pkg/controllers/secrets/root.go b/internal/app/machined/pkg/controllers/secrets/root.go index ac7d4c5a11..230f0d332a 100644 --- a/internal/app/machined/pkg/controllers/secrets/root.go +++ b/internal/app/machined/pkg/controllers/secrets/root.go @@ -165,11 +165,11 @@ func NewRootOSController() *RootOSController { osSecrets.AcceptedCAs = append(osSecrets.AcceptedCAs, &x509.PEMEncodedCertificate{ Crt: osSecrets.IssuingCA.Crt, }) - } - if len(osSecrets.IssuingCA.Key) == 0 { - // drop incomplete issuing CA, as the machine config for workers contains just the cert - osSecrets.IssuingCA = nil + if len(osSecrets.IssuingCA.Key) == 0 { + // drop incomplete issuing CA, as the machine config for workers contains just the cert + osSecrets.IssuingCA = nil + } } osSecrets.CertSANIPs = nil diff --git a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go index cb28018ed4..dfca4b921a 100644 --- a/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go +++ b/internal/app/machined/pkg/runtime/v1alpha1/v1alpha1_sequencer_tasks.go @@ -850,7 +850,7 @@ func partitionAndFormatDisks(logger *log.Logger, r runtime.Runtime) error { for _, disk := range r.Config().Machine().Disks() { if err := func() error { - bd, err := blockdevice.Open(disk.Device(), blockdevice.WithMode(blockdevice.ReadonlyMode)) + bd, err := blockdevice.Open(disk.Device(), blockdevice.WithMode(blockdevice.ReadonlyMode), blockdevice.WithExclusiveLock(true)) if err != nil { return err } @@ -921,7 +921,7 @@ func mountDisks(logger *log.Logger, r runtime.Runtime) (err error) { mountpoints := mount.NewMountPoints() for _, disk := range r.Config().Machine().Disks() { - bd, err := blockdevice.Open(disk.Device(), blockdevice.WithMode(blockdevice.ReadonlyMode)) + bd, err := blockdevice.Open(disk.Device(), blockdevice.WithMode(blockdevice.ReadonlyMode), blockdevice.WithExclusiveLock(true)) if err != nil { return err } diff --git a/internal/integration/api/watchdog.go b/internal/integration/api/watchdog.go new file mode 100644 index 0000000000..4aa5cf5a1e --- /dev/null +++ b/internal/integration/api/watchdog.go @@ -0,0 +1,134 @@ +// 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/. + +//go:build integration_api + +package api + +import ( + "bytes" + "context" + "io" + "path/filepath" + "time" + + "github.com/cosi-project/runtime/pkg/resource" + "github.com/cosi-project/runtime/pkg/state" + + "github.com/siderolabs/talos/internal/integration/base" + "github.com/siderolabs/talos/pkg/machinery/client" + "github.com/siderolabs/talos/pkg/machinery/config/types/runtime" + runtimeres "github.com/siderolabs/talos/pkg/machinery/resources/runtime" +) + +// WatchdogSuite ... +type WatchdogSuite struct { + base.APISuite + + ctx context.Context //nolint:containedctx + ctxCancel context.CancelFunc +} + +// SuiteName ... +func (suite *WatchdogSuite) SuiteName() string { + return "api.WatchdogSuite" +} + +// SetupTest ... +func (suite *WatchdogSuite) SetupTest() { + suite.ctx, suite.ctxCancel = context.WithTimeout(context.Background(), 1*time.Minute) + + if suite.Cluster == nil || suite.Cluster.Provisioner() != "qemu" { + suite.T().Skip("skipping watchdog test since provisioner is not qemu") + } +} + +// TearDownTest ... +func (suite *WatchdogSuite) TearDownTest() { + if suite.ctxCancel != nil { + suite.ctxCancel() + } +} + +func (suite *WatchdogSuite) readWatchdogSysfs(nodeCtx context.Context, watchdog, property string) string { //nolint:unparam + r, err := suite.Client.Read(nodeCtx, filepath.Join("/sys/class/watchdog", watchdog, property)) + suite.Require().NoError(err) + + value, err := io.ReadAll(r) + suite.Require().NoError(err) + + suite.Require().NoError(r.Close()) + + return string(bytes.TrimSpace(value)) +} + +// TestWatchdogSysfs sets up the watchdog and validates its parameters from the /sys/class/watchdog. +func (suite *WatchdogSuite) TestWatchdogSysfs() { + // pick up a random node to test the watchdog on, and use it throughout the test + node := suite.RandomDiscoveredNodeInternalIP() + + suite.T().Logf("testing watchdog on node %s", node) + + // build a Talos API context which is tied to the node + nodeCtx := client.WithNode(suite.ctx, node) + + // pick a watchdog + const watchdog = "watchdog0" + + cfgDocument := runtime.NewWatchdogTimerV1Alpha1() + cfgDocument.WatchdogDevice = "/dev/" + watchdog + cfgDocument.WatchdogTimeout = 120 * time.Second + + // deactivate the watchdog + suite.RemoveMachineConfigDocuments(nodeCtx, cfgDocument.MetaKind) + + _, err := suite.Client.COSI.WatchFor(nodeCtx, runtimeres.NewWatchdogTimerStatus(runtimeres.WatchdogTimerConfigID).Metadata(), state.WithEventTypes(state.Destroyed)) + suite.Require().NoError(err) + + wdState := suite.readWatchdogSysfs(nodeCtx, watchdog, "state") + suite.Require().Equal("inactive", wdState) + + // enable watchdog with 120s timeout + suite.PatchMachineConfig(nodeCtx, cfgDocument) + + _, err = suite.Client.COSI.WatchFor(nodeCtx, runtimeres.NewWatchdogTimerStatus(runtimeres.WatchdogTimerConfigID).Metadata(), state.WithEventTypes(state.Created, state.Updated)) + suite.Require().NoError(err) + + wdState = suite.readWatchdogSysfs(nodeCtx, watchdog, "state") + suite.Require().Equal("active", wdState) + + wdTimeout := suite.readWatchdogSysfs(nodeCtx, watchdog, "timeout") + suite.Require().Equal("120", wdTimeout) + + // update watchdog timeout to 60s + cfgDocument.WatchdogTimeout = 60 * time.Second + suite.PatchMachineConfig(nodeCtx, cfgDocument) + + _, err = suite.Client.COSI.WatchFor(nodeCtx, runtimeres.NewWatchdogTimerStatus(runtimeres.WatchdogTimerConfigID).Metadata(), + state.WithEventTypes(state.Created, state.Updated), + state.WithCondition(func(r resource.Resource) (bool, error) { + return r.(*runtimeres.WatchdogTimerStatus).TypedSpec().Timeout == cfgDocument.WatchdogTimeout, nil + }), + ) + suite.Require().NoError(err) + + wdState = suite.readWatchdogSysfs(nodeCtx, watchdog, "state") + suite.Require().Equal("active", wdState) + + wdTimeout = suite.readWatchdogSysfs(nodeCtx, watchdog, "timeout") + suite.Require().Equal("60", wdTimeout) + + // deactivate the watchdog + suite.RemoveMachineConfigDocuments(nodeCtx, cfgDocument.MetaKind) + + _, err = suite.Client.COSI.WatchFor(nodeCtx, runtimeres.NewWatchdogTimerStatus(runtimeres.WatchdogTimerConfigID).Metadata(), state.WithEventTypes(state.Destroyed)) + suite.Require().NoError(err) + + wdState = suite.readWatchdogSysfs(nodeCtx, watchdog, "state") + suite.Require().Equal("inactive", wdState) +} + +func init() { + allSuites = append(allSuites, new(WatchdogSuite)) +} diff --git a/internal/integration/base/api.go b/internal/integration/base/api.go index 77721ae80b..f6cb39e0b4 100644 --- a/internal/integration/base/api.go +++ b/internal/integration/base/api.go @@ -15,15 +15,18 @@ import ( "io" "math/rand" "path/filepath" + "slices" "strings" "time" "github.com/cosi-project/runtime/pkg/safe" "github.com/cosi-project/runtime/pkg/state" + "github.com/siderolabs/gen/xslices" "github.com/siderolabs/go-retry/retry" "github.com/stretchr/testify/suite" "google.golang.org/grpc/backoff" "google.golang.org/grpc/codes" + "gopkg.in/yaml.v3" "github.com/siderolabs/talos/cmd/talosctl/pkg/talos/helpers" "github.com/siderolabs/talos/internal/app/machined/pkg/runtime" @@ -33,6 +36,9 @@ import ( "github.com/siderolabs/talos/pkg/machinery/client" clientconfig "github.com/siderolabs/talos/pkg/machinery/client/config" "github.com/siderolabs/talos/pkg/machinery/config" + configconfig "github.com/siderolabs/talos/pkg/machinery/config/config" + "github.com/siderolabs/talos/pkg/machinery/config/configpatcher" + "github.com/siderolabs/talos/pkg/machinery/config/container" "github.com/siderolabs/talos/pkg/machinery/config/machine" "github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1" "github.com/siderolabs/talos/pkg/machinery/constants" @@ -575,6 +581,59 @@ func (apiSuite *APISuite) AssertExpectedModules(ctx context.Context, node string } } +// UpdateMachineConfig fetches machine configuration, patches it and applies the changes. +func (apiSuite *APISuite) UpdateMachineConfig(nodeCtx context.Context, patch func(config.Provider) (config.Provider, error)) { + cfg, err := apiSuite.ReadConfigFromNode(nodeCtx) + apiSuite.Require().NoError(err) + + patchedCfg, err := patch(cfg) + apiSuite.Require().NoError(err) + + bytes, err := patchedCfg.Bytes() + apiSuite.Require().NoError(err) + + resp, err := apiSuite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{ + Data: bytes, + Mode: machineapi.ApplyConfigurationRequest_AUTO, + }) + apiSuite.Require().NoError(err) + + apiSuite.T().Logf("patched machine config: %s", resp.Messages[0].ModeDetails) +} + +// PatchMachineConfig patches machine configuration on the node. +func (apiSuite *APISuite) PatchMachineConfig(nodeCtx context.Context, patches ...any) { + configPatches := make([]configpatcher.Patch, 0, len(patches)) + + for _, patch := range patches { + marshaled, err := yaml.Marshal(patch) + apiSuite.Require().NoError(err) + + configPatch, err := configpatcher.LoadPatch(marshaled) + apiSuite.Require().NoError(err) + + configPatches = append(configPatches, configPatch) + } + + apiSuite.UpdateMachineConfig(nodeCtx, func(cfg config.Provider) (config.Provider, error) { + out, err := configpatcher.Apply(configpatcher.WithConfig(cfg), configPatches) + if err != nil { + return nil, err + } + + return out.Config() + }) +} + +// RemoveMachineConfigDocuments removes machine configuration documents of specified type from the node. +func (apiSuite *APISuite) RemoveMachineConfigDocuments(nodeCtx context.Context, docTypes ...string) { + apiSuite.UpdateMachineConfig(nodeCtx, func(cfg config.Provider) (config.Provider, error) { + return container.New(xslices.Filter(cfg.Documents(), func(doc configconfig.Document) bool { + return slices.Index(docTypes, doc.Kind()) == -1 + })...) + }) +} + // PatchV1Alpha1Config patches v1alpha1 config in the config provider. func (apiSuite *APISuite) PatchV1Alpha1Config(provider config.Provider, patch func(*v1alpha1.Config)) []byte { ctr, err := provider.PatchV1Alpha1(func(c *v1alpha1.Config) error { diff --git a/internal/integration/integration_test.go b/internal/integration/integration_test.go index 89c19448bb..6f48a585ca 100644 --- a/internal/integration/integration_test.go +++ b/internal/integration/integration_test.go @@ -13,6 +13,7 @@ import ( "fmt" "os" "path/filepath" + "slices" "testing" "github.com/stretchr/testify/suite" @@ -180,8 +181,5 @@ func init() { flag.StringVar(&provision_test.DefaultSettings.CustomCNIURL, "talos.provision.custom-cni-url", provision_test.DefaultSettings.CustomCNIURL, "custom CNI URL for the cluster (provision tests only)") flag.StringVar(&provision_test.DefaultSettings.CNIBundleURL, "talos.provision.cni-bundle-url", provision_test.DefaultSettings.CNIBundleURL, "URL to download CNI bundle from") - allSuites = append(allSuites, api.GetAllSuites()...) - allSuites = append(allSuites, cli.GetAllSuites()...) - allSuites = append(allSuites, k8s.GetAllSuites()...) - allSuites = append(allSuites, provision_test.GetAllSuites()...) + allSuites = slices.Concat(api.GetAllSuites(), cli.GetAllSuites(), k8s.GetAllSuites(), provision_test.GetAllSuites()) } diff --git a/internal/pkg/dns/dns.go b/internal/pkg/dns/dns.go index 3c7ec89284..b47beb025f 100644 --- a/internal/pkg/dns/dns.go +++ b/internal/pkg/dns/dns.go @@ -45,7 +45,7 @@ func NewCache(next plugin.Handler, l *zap.Logger) *Cache { // ServeDNS implements [dns.Handler]. func (c *Cache) ServeDNS(wr dns.ResponseWriter, msg *dns.Msg) { - _, err := c.cache.ServeDNS(context.Background(), wr, msg) + _, err := c.cache.ServeDNS(context.Background(), request.NewScrubWriter(msg, wr), msg) if err != nil { // we should probably call newProxy.Healthcheck() if there are too many errors c.logger.Warn("error serving dns request", zap.Error(err)) @@ -72,6 +72,8 @@ func (h *Handler) Name() string { } // ServeDNS implements plugin.Handler. +// +//nolint:gocyclo func (h *Handler) ServeDNS(ctx context.Context, wrt dns.ResponseWriter, msg *dns.Msg) (int, error) { h.mx.RLock() defer h.mx.RUnlock() @@ -102,9 +104,21 @@ func (h *Handler) ServeDNS(ctx context.Context, wrt dns.ResponseWriter, msg *dns ) for _, ups := range upstreams { - resp, err = ups.Connect(ctx, req, proxy.Options{}) - if errors.Is(err, proxy.ErrCachedClosed) { // Remote side closed conn, can only happen with TCP. - continue + opts := proxy.Options{} + + for { + resp, err = ups.Connect(ctx, req, opts) + + switch { + case errors.Is(err, proxy.ErrCachedClosed): // Remote side closed conn, can only happen with TCP. + continue + case resp != nil && resp.Truncated && !opts.ForceTCP: // Retry with TCP if truncated + opts.ForceTCP = true + + continue + } + + break } if err == nil { @@ -274,6 +288,7 @@ func NewServer(opts ServerOptions) *Server { Listener: opts.Listener, PacketConn: opts.PacketConn, Handler: opts.Handler, + UDPSize: dns.DefaultMsgSize, // 4096 since default is [dns.MinMsgSize] = 512 bytes, which is too small. ReadTimeout: opts.ReadTimeout, WriteTimeout: opts.WriteTimeout, IdleTimeout: opts.IdleTimeout, diff --git a/internal/pkg/mount/mount.go b/internal/pkg/mount/mount.go index 08c0be8946..79a83ed36f 100644 --- a/internal/pkg/mount/mount.go +++ b/internal/pkg/mount/mount.go @@ -148,7 +148,7 @@ func mountRetry(f RetryFunc, p *Point, isUnmount bool) (err error) { switch err { case unix.EBUSY: return retry.ExpectedError(err) - case unix.ENOENT, unix.ENODEV: + case unix.ENOENT, unix.ENXIO: // if udevd triggers BLKRRPART ioctl, partition device entry might disappear temporarily return retry.ExpectedError(err) case unix.EUCLEAN, unix.EIO: diff --git a/internal/pkg/mount/pseudo.go b/internal/pkg/mount/pseudo.go index 23da458b9b..d89f642b8d 100644 --- a/internal/pkg/mount/pseudo.go +++ b/internal/pkg/mount/pseudo.go @@ -32,6 +32,7 @@ func PseudoSubMountPoints() (mountpoints *Points, err error) { pseudo.Set("devpts", NewMountPoint("devpts", "/dev/pts", "devpts", unix.MS_NOSUID|unix.MS_NOEXEC, "ptmxmode=000,mode=620,gid=5")) pseudo.Set("hugetlb", NewMountPoint("hugetlbfs", "/dev/hugepages", "hugetlbfs", unix.MS_NOSUID|unix.MS_NODEV, "")) pseudo.Set("securityfs", NewMountPoint("securityfs", "/sys/kernel/security", "securityfs", unix.MS_NOSUID|unix.MS_NOEXEC|unix.MS_NODEV|unix.MS_RELATIME, "")) + pseudo.Set("tracefs", NewMountPoint("securityfs", "/sys/kernel/tracing", "tracefs", unix.MS_NOSUID|unix.MS_NOEXEC|unix.MS_NODEV, "")) if _, err := os.Stat(constants.EFIVarsMountPoint); err == nil { // mount EFI vars if they exist diff --git a/pkg/machinery/constants/constants.go b/pkg/machinery/constants/constants.go index f385bed06a..31dfed41c8 100644 --- a/pkg/machinery/constants/constants.go +++ b/pkg/machinery/constants/constants.go @@ -14,7 +14,7 @@ import ( const ( // DefaultKernelVersion is the default Linux kernel version. - DefaultKernelVersion = "6.6.30-talos" + DefaultKernelVersion = "6.6.32-talos" // KernelModulesPath is the default path to the kernel modules without the kernel version. KernelModulesPath = "/lib/modules" diff --git a/pkg/machinery/gendata/data/pkgs b/pkg/machinery/gendata/data/pkgs index 362d11fd99..3f9b7a6e24 100644 --- a/pkg/machinery/gendata/data/pkgs +++ b/pkg/machinery/gendata/data/pkgs @@ -1 +1 @@ -v1.7.0-14-g9caa8be \ No newline at end of file +v1.7.0-17-ga201d27 \ No newline at end of file diff --git a/pkg/provision/providers/vm/internal/ipxe/data/ipxe/amd64/snp.efi b/pkg/provision/providers/vm/internal/ipxe/data/ipxe/amd64/snp.efi index 9d92908655..4fd08c0864 100644 Binary files a/pkg/provision/providers/vm/internal/ipxe/data/ipxe/amd64/snp.efi and b/pkg/provision/providers/vm/internal/ipxe/data/ipxe/amd64/snp.efi differ diff --git a/pkg/provision/providers/vm/internal/ipxe/data/ipxe/arm64/snp.efi b/pkg/provision/providers/vm/internal/ipxe/data/ipxe/arm64/snp.efi index 84c991ac22..34b1765bf7 100644 Binary files a/pkg/provision/providers/vm/internal/ipxe/data/ipxe/arm64/snp.efi and b/pkg/provision/providers/vm/internal/ipxe/data/ipxe/arm64/snp.efi differ