mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-11 09:07:05 +02:00
Fixes #4407 fixes #4489 This PR started by enabling simple restart of the `kubelet` service via services API, but it turned out there's a problem: When kubelet restarts, CNI is already up, so there's an interface on the host with CNI node IP, the code which picks kubelet node IP finds it and tries to add it to the list of kubelet node IPs which completely breaks kubelet. Solution was easy: allow node IPs to be filtered out - e.g. we never want kubelet node IP to be from the pod CIDR. But this filtering feature is also useful in other cases, so I added that as well. Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
211 lines
6.0 KiB
Go
211 lines
6.0 KiB
Go
// 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_cli
|
|
// +build integration_cli
|
|
|
|
package cli
|
|
|
|
import (
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"google.golang.org/protobuf/encoding/protojson"
|
|
|
|
"github.com/talos-systems/talos/internal/integration/base"
|
|
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
|
|
clientconfig "github.com/talos-systems/talos/pkg/machinery/client/config"
|
|
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1/machine"
|
|
)
|
|
|
|
// TalosconfigSuite checks `talosctl config`.
|
|
type TalosconfigSuite struct {
|
|
base.CLISuite
|
|
}
|
|
|
|
// SuiteName implements base.NamedSuite.
|
|
func (suite *TalosconfigSuite) SuiteName() string {
|
|
return "cli.TalosconfigSuite"
|
|
}
|
|
|
|
// TestList checks `talosctl config contexts`.
|
|
func (suite *TalosconfigSuite) TestList() {
|
|
suite.RunCLI([]string{"config", "contexts"},
|
|
base.StdoutShouldMatch(regexp.MustCompile(`CURRENT`)))
|
|
}
|
|
|
|
// TestMerge checks `talosctl config merge`.
|
|
func (suite *TalosconfigSuite) TestMerge() {
|
|
tempDir := suite.T().TempDir()
|
|
|
|
suite.RunCLI([]string{"gen", "config", "-o", tempDir, "foo", "https://192.168.0.1:6443"})
|
|
|
|
talosconfigPath := filepath.Join(tempDir, "talosconfig")
|
|
|
|
suite.Assert().FileExists(talosconfigPath)
|
|
|
|
path := filepath.Join(tempDir, "merged")
|
|
|
|
suite.RunCLI([]string{"config", "merge", "--talosconfig", path, talosconfigPath},
|
|
base.StdoutEmpty())
|
|
|
|
suite.Require().FileExists(path)
|
|
|
|
c, err := clientconfig.Open(path)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().NotNil(c.Contexts["foo"])
|
|
|
|
suite.RunCLI([]string{"config", "merge", "--talosconfig", path, talosconfigPath},
|
|
base.StdoutShouldMatch(regexp.MustCompile(`renamed`)))
|
|
|
|
c, err = clientconfig.Open(path)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().NotNil(c.Contexts["foo-1"])
|
|
}
|
|
|
|
// TestNew checks `talosctl config new`.
|
|
func (suite *TalosconfigSuite) TestNew() {
|
|
stdout := suite.RunCLI([]string{"version", "--json", "--nodes", suite.RandomDiscoveredNode()})
|
|
|
|
var v machineapi.Version
|
|
err := protojson.Unmarshal([]byte(stdout), &v)
|
|
suite.Require().NoError(err)
|
|
|
|
rbacEnabled := v.Features.GetRbac()
|
|
|
|
tempDir := suite.T().TempDir()
|
|
|
|
node := suite.RandomDiscoveredNode(machine.TypeControlPlane)
|
|
|
|
readerConfig := filepath.Join(tempDir, "talosconfig")
|
|
suite.RunCLI([]string{"--nodes", node, "config", "new", "--roles", "os:reader", readerConfig},
|
|
base.StdoutEmpty())
|
|
|
|
// commands that work for both admin and reader, with and without RBAC
|
|
for _, tt := range []struct {
|
|
args []string
|
|
opts []base.RunOption
|
|
}{
|
|
{
|
|
args: []string{"ls", "/etc/hosts"},
|
|
opts: []base.RunOption{base.StdoutShouldMatch(regexp.MustCompile(`hosts`))},
|
|
},
|
|
} {
|
|
tt := tt
|
|
name := strings.Join(tt.args, "_")
|
|
suite.Run(name, func() {
|
|
suite.T().Parallel()
|
|
|
|
args := append([]string{"--nodes", node}, tt.args...)
|
|
suite.RunCLI(args, tt.opts...)
|
|
|
|
args = append([]string{"--talosconfig", readerConfig}, args...)
|
|
suite.RunCLI(args, tt.opts...)
|
|
})
|
|
}
|
|
|
|
// commands that work for admin, but not for reader (when RBAC is enabled)
|
|
for _, tt := range []struct {
|
|
args []string
|
|
adminOpts []base.RunOption
|
|
readerOpts []base.RunOption
|
|
}{
|
|
{
|
|
args: []string{"read", "/etc/hosts"},
|
|
adminOpts: []base.RunOption{base.StdoutShouldMatch(regexp.MustCompile(`localhost`))},
|
|
readerOpts: []base.RunOption{
|
|
base.StdoutEmpty(),
|
|
base.StderrShouldMatch(regexp.MustCompile(`\Qrpc error: code = PermissionDenied desc = not authorized`)),
|
|
},
|
|
},
|
|
{
|
|
args: []string{"get", "mc"},
|
|
adminOpts: []base.RunOption{base.StdoutShouldMatch(regexp.MustCompile(`MachineConfig`))},
|
|
readerOpts: []base.RunOption{
|
|
base.StdoutEmpty(),
|
|
base.StderrShouldMatch(regexp.MustCompile(`\Qrpc error: code = PermissionDenied desc = not authorized`)),
|
|
},
|
|
},
|
|
{
|
|
args: []string{"get", "osrootsecret"},
|
|
adminOpts: []base.RunOption{base.StdoutShouldMatch(regexp.MustCompile(`OSRootSecret`))},
|
|
readerOpts: []base.RunOption{
|
|
base.StdoutEmpty(),
|
|
base.StderrShouldMatch(regexp.MustCompile(`\Qrpc error: code = PermissionDenied desc = not authorized`)),
|
|
},
|
|
},
|
|
{
|
|
args: []string{"kubeconfig", "--force", tempDir},
|
|
adminOpts: []base.RunOption{base.StdoutEmpty()},
|
|
readerOpts: []base.RunOption{
|
|
base.ShouldFail(), // why this one fails, but not others?
|
|
base.StdoutEmpty(),
|
|
base.StderrShouldMatch(regexp.MustCompile(`\Qrpc error: code = PermissionDenied desc = not authorized`)),
|
|
},
|
|
},
|
|
} {
|
|
tt := tt
|
|
name := strings.Join(tt.args, "_")
|
|
suite.Run(name, func() {
|
|
suite.T().Parallel()
|
|
|
|
args := append([]string{"--nodes", node}, tt.args...)
|
|
suite.RunCLI(args, tt.adminOpts...)
|
|
|
|
args = append([]string{"--talosconfig", readerConfig}, args...)
|
|
if rbacEnabled {
|
|
suite.RunCLI(args, tt.readerOpts...)
|
|
} else {
|
|
// check that it works the same way as for admin with reader's config
|
|
suite.RunCLI(args, tt.adminOpts...)
|
|
}
|
|
})
|
|
}
|
|
|
|
// do not test destructive command with disabled RBAC
|
|
if !rbacEnabled {
|
|
return
|
|
}
|
|
|
|
// destructive commands that don't work for reader
|
|
// (and that we don't test for admin because they are destructive)
|
|
for _, tt := range []struct {
|
|
args []string
|
|
readerOpts []base.RunOption
|
|
}{
|
|
{
|
|
args: []string{"reboot"},
|
|
readerOpts: []base.RunOption{
|
|
base.ShouldFail(),
|
|
base.StdoutEmpty(),
|
|
base.StderrShouldMatch(regexp.MustCompile(`\Qrpc error: code = PermissionDenied desc = not authorized`)),
|
|
},
|
|
},
|
|
{
|
|
args: []string{"reset"},
|
|
readerOpts: []base.RunOption{
|
|
base.ShouldFail(),
|
|
base.StdoutEmpty(),
|
|
base.StderrShouldMatch(regexp.MustCompile(`\Qrpc error: code = PermissionDenied desc = not authorized`)),
|
|
},
|
|
},
|
|
} {
|
|
tt := tt
|
|
name := strings.Join(tt.args, "_")
|
|
suite.Run(name, func() {
|
|
suite.T().Parallel()
|
|
|
|
args := append([]string{"--nodes", node, "--talosconfig", readerConfig}, tt.args...)
|
|
suite.RunCLI(args, tt.readerOpts...)
|
|
})
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
allSuites = append(allSuites, new(TalosconfigSuite))
|
|
}
|