feat: update golangci-lint to 1.45.0 and gofumpt to 0.3.0
- Update golangci-lint to 1.45.0 - Update gofumpt to 0.3.0 - Fix gofumpt errors - Add goimports and format imports since gofumports is removed - Update Dockerfile - Fix .golangci.yml configuration - Fix linting errors Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
This commit is contained in:
parent
a92c614b2f
commit
e06e1473b0
@ -119,7 +119,10 @@ linters-settings:
|
||||
range-loops: true # Report preallocation suggestions on range loops, true by default
|
||||
for-loops: false # Report preallocation suggestions on for loops, false by default
|
||||
gci:
|
||||
local-prefixes: github.com/talos-systems/talos
|
||||
sections:
|
||||
- standard # Captures all standard packages if they do not match another section.
|
||||
- default # Contains all imports that could not be matched to another section type.
|
||||
- prefix(github.com/talos-systems/talos) # Groups all imports with the specified Prefix.
|
||||
cyclop:
|
||||
# the maximal code complexity to report
|
||||
max-complexity: 20
|
||||
@ -138,6 +141,7 @@ linters:
|
||||
- errorlint
|
||||
- exhaustivestruct
|
||||
- forbidigo
|
||||
- forcetypeassert
|
||||
- funlen
|
||||
- gas
|
||||
- gochecknoglobals
|
||||
@ -148,6 +152,7 @@ linters:
|
||||
- gomnd
|
||||
- ifshort
|
||||
- ireturn # we return interfaces
|
||||
- maintidx
|
||||
- nestif
|
||||
- nilnil # we return "nil, nil"
|
||||
- paralleltest
|
||||
@ -199,10 +204,10 @@ issues:
|
||||
exclude-use-default: false
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-per-linter: 0
|
||||
max-issues-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same: 0
|
||||
max-same-issues: 0
|
||||
|
||||
# Show only new issues: if there are unstaged changes or untracked files,
|
||||
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
|
||||
|
20
Dockerfile
20
Dockerfile
@ -96,9 +96,12 @@ RUN ["/toolchain/bin/ln", "-svf", "/toolchain/bin/bash", "/bin/sh"]
|
||||
RUN ["/toolchain/bin/ln", "-svf", "/toolchain/etc/ssl", "/etc/ssl"]
|
||||
ARG GOLANGCILINT_VERSION
|
||||
RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/${GOLANGCILINT_VERSION}/install.sh | bash -s -- -b /toolchain/bin ${GOLANGCILINT_VERSION}
|
||||
ARG GOIMPORTS_VERSION
|
||||
RUN go install golang.org/x/tools/cmd/goimports@${GOIMPORTS_VERSION} \
|
||||
&& mv /go/bin/goimports /toolchain/go/bin/goimports
|
||||
ARG GOFUMPT_VERSION
|
||||
RUN go install mvdan.cc/gofumpt/gofumports@${GOFUMPT_VERSION} \
|
||||
&& mv /go/bin/gofumports /toolchain/go/bin/gofumports
|
||||
RUN go install mvdan.cc/gofumpt@${GOFUMPT_VERSION} \
|
||||
&& mv /go/bin/gofumpt /toolchain/go/bin/gofumpt
|
||||
ARG STRINGER_VERSION
|
||||
RUN go install golang.org/x/tools/cmd/stringer@${STRINGER_VERSION} \
|
||||
&& mv /go/bin/stringer /toolchain/go/bin/stringer
|
||||
@ -190,18 +193,21 @@ COPY ./api/resource/secrets/secrets.proto /api/resource/secrets/secrets.proto
|
||||
RUN protoc -I/api -I/api/vendor/ --go_out=paths=source_relative:/api --go-grpc_out=paths=source_relative:/api --go-vtproto_out=paths=source_relative:/api --go-vtproto_opt=features=marshal+unmarshal+size resource/secrets/secrets.proto
|
||||
COPY ./api/inspect/inspect.proto /api/inspect/inspect.proto
|
||||
RUN protoc -I/api -I/api/vendor/ --go_out=paths=source_relative:/api --go-grpc_out=paths=source_relative:/api --go-vtproto_out=paths=source_relative:/api --go-vtproto_opt=features=marshal+unmarshal+size inspect/inspect.proto
|
||||
# Gofumports generated files to adjust import order
|
||||
RUN gofumports -w -local github.com/talos-systems/talos /api/
|
||||
# Goimports and gofumpt generated files to adjust import order
|
||||
RUN goimports -w -local github.com/talos-systems/talos /api/
|
||||
RUN gofumpt -w /api/
|
||||
|
||||
# run docgen for machinery config
|
||||
FROM build-go AS go-generate
|
||||
COPY ./pkg ./pkg
|
||||
COPY ./hack/boilerplate.txt ./hack/boilerplate.txt
|
||||
RUN --mount=type=cache,target=/.cache go generate ./pkg/...
|
||||
RUN gofumports -w -local github.com/talos-systems/talos ./pkg/
|
||||
RUN goimports -w -local github.com/talos-systems/talos ./pkg/
|
||||
RUN gofumpt -w ./pkg/
|
||||
WORKDIR /src/pkg/machinery
|
||||
RUN --mount=type=cache,target=/.cache go generate ./...
|
||||
RUN gofumports -w -local github.com/talos-systems/talos ./
|
||||
RUN goimports -w -local github.com/talos-systems/talos ./
|
||||
RUN gofumpt -w ./
|
||||
|
||||
FROM --platform=${BUILDPLATFORM} scratch AS generate
|
||||
COPY --from=proto-format-build /src/api /api/
|
||||
@ -660,8 +666,6 @@ WORKDIR /src/pkg/machinery
|
||||
RUN --mount=type=cache,target=/.cache golangci-lint run --config ../../.golangci.yml
|
||||
WORKDIR /src
|
||||
RUN --mount=type=cache,target=/.cache importvet github.com/talos-systems/talos/...
|
||||
RUN find . -name '*.pb.go' -o -name '*_string_*.go' | xargs rm
|
||||
RUN --mount=type=cache,target=/.cache FILES="$(gofumports -l -local github.com/talos-systems/talos .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumports -w -local github.com/talos-systems/talos .':\n${FILES}"; exit 1)
|
||||
|
||||
# The protolint target performs linting on protobuf files.
|
||||
|
||||
|
8
Makefile
8
Makefile
@ -16,8 +16,9 @@ TOOLS ?= ghcr.io/siderolabs/tools:v1.1.0-alpha.0-1-g99be089
|
||||
PKGS ?= v1.1.0-alpha.0-5-g58603ba
|
||||
EXTRAS ?= v1.0.0
|
||||
GO_VERSION ?= 1.17
|
||||
GOFUMPT_VERSION ?= v0.1.1
|
||||
GOLANGCILINT_VERSION ?= v1.43.0
|
||||
GOIMPORTS_VERSION ?= v0.1.10
|
||||
GOFUMPT_VERSION ?= v0.3.0
|
||||
GOLANGCILINT_VERSION ?= v1.45.0
|
||||
STRINGER_VERSION ?= v0.1.5
|
||||
ENUMER_VERSION ?= v1.1.2
|
||||
DEEPCOPY_GEN_VERSION ?= v0.21.3
|
||||
@ -85,6 +86,7 @@ COMMON_ARGS += --build-arg=TOOLS=$(TOOLS)
|
||||
COMMON_ARGS += --build-arg=PKGS=$(PKGS)
|
||||
COMMON_ARGS += --build-arg=EXTRAS=$(EXTRAS)
|
||||
COMMON_ARGS += --build-arg=GOFUMPT_VERSION=$(GOFUMPT_VERSION)
|
||||
COMMON_ARGS += --build-arg=GOIMPORTS_VERSION=$(GOIMPORTS_VERSION)
|
||||
COMMON_ARGS += --build-arg=STRINGER_VERSION=$(STRINGER_VERSION)
|
||||
COMMON_ARGS += --build-arg=ENUMER_VERSION=$(ENUMER_VERSION)
|
||||
COMMON_ARGS += --build-arg=DEEPCOPY_GEN_VERSION=$(DEEPCOPY_GEN_VERSION)
|
||||
@ -272,7 +274,7 @@ api-descriptors: ## Generates API descriptors used to detect breaking API change
|
||||
@$(MAKE) local-api-descriptors DEST=./ PLATFORM=linux/amd64
|
||||
|
||||
fmt-go: ## Formats the source code.
|
||||
@docker run --rm -it -v $(PWD):/src -w /src golang:$(GO_VERSION) bash -c "go install mvdan.cc/gofumpt/gofumports@$(GOFUMPT_VERSION) && gofumports -w -local github.com/talos-systems/talos ."
|
||||
@docker run --rm -it -v $(PWD):/src -w /src golang:$(GO_VERSION) bash -c "go install golang.org/x/tools/cmd/goimports@$(GOIMPORTS_VERSION) && goimports -w -local github.com/talos-systems/talos . && go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION) && gofumpt -w ."
|
||||
|
||||
fmt-protobuf: ## Formats protobuf files.
|
||||
@$(MAKE) local-fmt-protobuf DEST=./ PLATFORM=linux/amd64
|
||||
|
@ -123,7 +123,8 @@ func GenV1Alpha1Config(genOptions []generate.GenOption,
|
||||
kubernetesVersion string,
|
||||
configPatch []string,
|
||||
configPatchControlPlane []string,
|
||||
configPatchWorker []string) (*v1alpha1.ConfigBundle, error) {
|
||||
configPatchWorker []string,
|
||||
) (*v1alpha1.ConfigBundle, error) {
|
||||
configBundleOpts := []bundle.Option{
|
||||
bundle.WithInputOptions(
|
||||
&bundle.InputOptions{
|
||||
|
@ -22,7 +22,7 @@ type APISource struct {
|
||||
|
||||
Interval time.Duration
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
wg sync.WaitGroup
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"google.golang.org/grpc/peer"
|
||||
|
||||
"github.com/talos-systems/talos/pkg/cli"
|
||||
_ "github.com/talos-systems/talos/pkg/grpc/codec" //nolint:gci // register codec
|
||||
_ "github.com/talos-systems/talos/pkg/grpc/codec" // register codec
|
||||
"github.com/talos-systems/talos/pkg/machinery/api/common"
|
||||
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
|
||||
"github.com/talos-systems/talos/pkg/machinery/client"
|
||||
@ -44,90 +44,96 @@ const pathAutoCompleteLimit = 500
|
||||
//
|
||||
// WithClientNoNodes doesn't set any node information on request context.
|
||||
func WithClientNoNodes(action func(context.Context, *client.Client) error) error {
|
||||
return cli.WithContext(context.Background(), func(ctx context.Context) error {
|
||||
cfg, err := clientconfig.Open(Talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open config file %q: %w", Talosconfig, err)
|
||||
}
|
||||
return cli.WithContext(
|
||||
context.Background(), func(ctx context.Context) error {
|
||||
cfg, err := clientconfig.Open(Talosconfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open config file %q: %w", Talosconfig, err)
|
||||
}
|
||||
|
||||
opts := []client.OptionFunc{
|
||||
client.WithConfig(cfg),
|
||||
}
|
||||
opts := []client.OptionFunc{
|
||||
client.WithConfig(cfg),
|
||||
}
|
||||
|
||||
if Cmdcontext != "" {
|
||||
opts = append(opts, client.WithContextName(Cmdcontext))
|
||||
}
|
||||
if Cmdcontext != "" {
|
||||
opts = append(opts, client.WithContextName(Cmdcontext))
|
||||
}
|
||||
|
||||
if len(Endpoints) > 0 {
|
||||
// override endpoints from command-line flags
|
||||
opts = append(opts, client.WithEndpoints(Endpoints...))
|
||||
}
|
||||
if len(Endpoints) > 0 {
|
||||
// override endpoints from command-line flags
|
||||
opts = append(opts, client.WithEndpoints(Endpoints...))
|
||||
}
|
||||
|
||||
c, err := client.New(ctx, opts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error constructing client: %w", err)
|
||||
}
|
||||
//nolint:errcheck
|
||||
defer c.Close()
|
||||
c, err := client.New(ctx, opts...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error constructing client: %w", err)
|
||||
}
|
||||
//nolint:errcheck
|
||||
defer c.Close()
|
||||
|
||||
return action(ctx, c)
|
||||
})
|
||||
return action(ctx, c)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// WithClient builds upon WithClientNoNodes to provide set of nodes on request context based on config & flags.
|
||||
func WithClient(action func(context.Context, *client.Client) error) error {
|
||||
return WithClientNoNodes(func(ctx context.Context, c *client.Client) error {
|
||||
if len(Nodes) < 1 {
|
||||
configContext := c.GetConfigContext()
|
||||
if configContext == nil {
|
||||
return fmt.Errorf("failed to resolve config context")
|
||||
return WithClientNoNodes(
|
||||
func(ctx context.Context, c *client.Client) error {
|
||||
if len(Nodes) < 1 {
|
||||
configContext := c.GetConfigContext()
|
||||
if configContext == nil {
|
||||
return fmt.Errorf("failed to resolve config context")
|
||||
}
|
||||
|
||||
Nodes = configContext.Nodes
|
||||
}
|
||||
|
||||
Nodes = configContext.Nodes
|
||||
}
|
||||
if len(Nodes) < 1 {
|
||||
return fmt.Errorf("nodes are not set for the command: please use `--nodes` flag or configuration file to set the nodes to run the command against")
|
||||
}
|
||||
|
||||
if len(Nodes) < 1 {
|
||||
return fmt.Errorf("nodes are not set for the command: please use `--nodes` flag or configuration file to set the nodes to run the command against")
|
||||
}
|
||||
ctx = client.WithNodes(ctx, Nodes...)
|
||||
|
||||
ctx = client.WithNodes(ctx, Nodes...)
|
||||
|
||||
return action(ctx, c)
|
||||
})
|
||||
return action(ctx, c)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// WithClientMaintenance wraps common code to initialize Talos client in maintenance (insecure mode).
|
||||
func WithClientMaintenance(enforceFingerprints []string, action func(context.Context, *client.Client) error) error {
|
||||
return cli.WithContext(context.Background(), func(ctx context.Context) error {
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
if len(enforceFingerprints) > 0 {
|
||||
fingerprints := make([]x509.Fingerprint, len(enforceFingerprints))
|
||||
|
||||
for i, stringFingerprint := range enforceFingerprints {
|
||||
var err error
|
||||
|
||||
fingerprints[i], err = x509.ParseFingerprint(stringFingerprint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing certificate fingerprint %q: %v", stringFingerprint, err)
|
||||
}
|
||||
return cli.WithContext(
|
||||
context.Background(), func(ctx context.Context) error {
|
||||
tlsConfig := &tls.Config{
|
||||
InsecureSkipVerify: true,
|
||||
}
|
||||
|
||||
tlsConfig.VerifyConnection = x509.MatchSPKIFingerprints(fingerprints...)
|
||||
}
|
||||
if len(enforceFingerprints) > 0 {
|
||||
fingerprints := make([]x509.Fingerprint, len(enforceFingerprints))
|
||||
|
||||
c, err := client.New(ctx, client.WithTLSConfig(tlsConfig), client.WithEndpoints(Nodes...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i, stringFingerprint := range enforceFingerprints {
|
||||
var err error
|
||||
|
||||
//nolint:errcheck
|
||||
defer c.Close()
|
||||
fingerprints[i], err = x509.ParseFingerprint(stringFingerprint)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing certificate fingerprint %q: %v", stringFingerprint, err)
|
||||
}
|
||||
}
|
||||
|
||||
return action(ctx, c)
|
||||
})
|
||||
tlsConfig.VerifyConnection = x509.MatchSPKIFingerprints(fingerprints...)
|
||||
}
|
||||
|
||||
c, err := client.New(ctx, client.WithTLSConfig(tlsConfig), client.WithEndpoints(Nodes...))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//nolint:errcheck
|
||||
defer c.Close()
|
||||
|
||||
return action(ctx, c)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// Commands is a list of commands published by the package.
|
||||
@ -170,61 +176,66 @@ func completePathFromNode(inputPath string) []string {
|
||||
func getPathFromNode(path, filter string) map[string]struct{} {
|
||||
paths := make(map[string]struct{})
|
||||
|
||||
WithClient(func(ctx context.Context, c *client.Client) error { //nolint:errcheck
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
//nolint:errcheck
|
||||
WithClient(
|
||||
func(ctx context.Context, c *client.Client) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
stream, err := c.LS(ctx, &machineapi.ListRequest{
|
||||
Root: path,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
resp, err := stream.Recv()
|
||||
stream, err := c.LS(
|
||||
ctx, &machineapi.ListRequest{
|
||||
Root: path,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
if err == io.EOF || client.StatusCode(err) == codes.Canceled {
|
||||
return err
|
||||
}
|
||||
|
||||
for {
|
||||
resp, err := stream.Recv()
|
||||
if err != nil {
|
||||
if err == io.EOF || client.StatusCode(err) == codes.Canceled {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("error streaming results: %s", err)
|
||||
}
|
||||
|
||||
if resp.Metadata != nil && resp.Metadata.Error != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if resp.Error != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// skip reference to the same directory
|
||||
if resp.RelativeName == "." {
|
||||
continue
|
||||
}
|
||||
|
||||
// limit the results to a reasonable amount
|
||||
if len(paths) > pathAutoCompleteLimit {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("error streaming results: %s", err)
|
||||
}
|
||||
// directories have a trailing slash
|
||||
if resp.IsDir {
|
||||
fullPath := path + resp.RelativeName + "/"
|
||||
|
||||
if resp.Metadata != nil && resp.Metadata.Error != "" {
|
||||
continue
|
||||
}
|
||||
if relativeTo(fullPath, filter) {
|
||||
paths[fullPath] = struct{}{}
|
||||
}
|
||||
} else {
|
||||
fullPath := path + resp.RelativeName
|
||||
|
||||
if resp.Error != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
// skip reference to the same directory
|
||||
if resp.RelativeName == "." {
|
||||
continue
|
||||
}
|
||||
|
||||
// limit the results to a reasonable amount
|
||||
if len(paths) > pathAutoCompleteLimit {
|
||||
return nil
|
||||
}
|
||||
|
||||
// directories have a trailing slash
|
||||
if resp.IsDir {
|
||||
fullPath := path + resp.RelativeName + "/"
|
||||
|
||||
if relativeTo(fullPath, filter) {
|
||||
paths[fullPath] = struct{}{}
|
||||
}
|
||||
} else {
|
||||
fullPath := path + resp.RelativeName
|
||||
|
||||
if relativeTo(fullPath, filter) {
|
||||
paths[fullPath] = struct{}{}
|
||||
if relativeTo(fullPath, filter) {
|
||||
paths[fullPath] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
return paths
|
||||
}
|
||||
@ -232,23 +243,26 @@ func getPathFromNode(path, filter string) map[string]struct{} {
|
||||
func getServiceFromNode() []string {
|
||||
var svcIds []string
|
||||
|
||||
WithClient(func(ctx context.Context, c *client.Client) error { //nolint:errcheck
|
||||
var remotePeer peer.Peer
|
||||
//nolint:errcheck
|
||||
WithClient(
|
||||
func(ctx context.Context, c *client.Client) error {
|
||||
var remotePeer peer.Peer
|
||||
|
||||
resp, err := c.ServiceList(ctx, grpc.Peer(&remotePeer))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, msg := range resp.Messages {
|
||||
for _, s := range msg.Services {
|
||||
svc := cli.ServiceInfoWrapper{ServiceInfo: s}
|
||||
svcIds = append(svcIds, svc.Id)
|
||||
resp, err := c.ServiceList(ctx, grpc.Peer(&remotePeer))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
for _, msg := range resp.Messages {
|
||||
for _, s := range msg.Services {
|
||||
svc := cli.ServiceInfoWrapper{ServiceInfo: s}
|
||||
svcIds = append(svcIds, svc.Id)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
return svcIds
|
||||
}
|
||||
@ -256,41 +270,44 @@ func getServiceFromNode() []string {
|
||||
func getContainersFromNode(kubernetes bool) []string {
|
||||
var containerIds []string
|
||||
|
||||
WithClient(func(ctx context.Context, c *client.Client) error { //nolint:errcheck
|
||||
var (
|
||||
namespace string
|
||||
driver common.ContainerDriver
|
||||
)
|
||||
//nolint:errcheck
|
||||
WithClient(
|
||||
func(ctx context.Context, c *client.Client) error {
|
||||
var (
|
||||
namespace string
|
||||
driver common.ContainerDriver
|
||||
)
|
||||
|
||||
if kubernetes {
|
||||
namespace = criconstants.K8sContainerdNamespace
|
||||
driver = common.ContainerDriver_CRI
|
||||
} else {
|
||||
namespace = constants.SystemContainerdNamespace
|
||||
driver = common.ContainerDriver_CONTAINERD
|
||||
}
|
||||
|
||||
resp, err := c.Containers(ctx, namespace, driver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, msg := range resp.Messages {
|
||||
for _, p := range msg.Containers {
|
||||
if p.Pid == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if kubernetes && p.Id == p.PodId {
|
||||
continue
|
||||
}
|
||||
|
||||
containerIds = append(containerIds, p.Id)
|
||||
if kubernetes {
|
||||
namespace = criconstants.K8sContainerdNamespace
|
||||
driver = common.ContainerDriver_CRI
|
||||
} else {
|
||||
namespace = constants.SystemContainerdNamespace
|
||||
driver = common.ContainerDriver_CONTAINERD
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
resp, err := c.Containers(ctx, namespace, driver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, msg := range resp.Messages {
|
||||
for _, p := range msg.Containers {
|
||||
if p.Pid == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if kubernetes && p.Id == p.PodId {
|
||||
continue
|
||||
}
|
||||
|
||||
containerIds = append(containerIds, p.Id)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
return containerIds
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
"github.com/talos-systems/grpc-proxy/proxy"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/metadata"
|
||||
protobuf "google.golang.org/protobuf/proto" //nolint:depguard,gci
|
||||
protobuf "google.golang.org/protobuf/proto" //nolint:depguard
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
|
||||
@ -71,38 +71,45 @@ func (suite *APIDSuite) TestGetConnection() {
|
||||
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut1.Get("proxyfrom"))
|
||||
suite.Assert().Equal([]string{"os:admin"}, mdOut1.Get("talos-role"))
|
||||
|
||||
suite.Run("Same context", func() {
|
||||
ctx2 := ctx1
|
||||
outCtx2, conn2, err2 := suite.b.GetConnection(ctx2)
|
||||
suite.Require().NoError(err2)
|
||||
suite.Assert().Equal(conn1, conn2) // connection is cached
|
||||
suite.Assert().Equal(role.MakeSet(role.Admin), authz.GetRoles(outCtx2))
|
||||
suite.Run(
|
||||
"Same context", func() {
|
||||
ctx2 := ctx1
|
||||
outCtx2, conn2, err2 := suite.b.GetConnection(ctx2)
|
||||
suite.Require().NoError(err2)
|
||||
suite.Assert().Equal(conn1, conn2) // connection is cached
|
||||
suite.Assert().Equal(role.MakeSet(role.Admin), authz.GetRoles(outCtx2))
|
||||
|
||||
mdOut2, ok2 := metadata.FromOutgoingContext(outCtx2)
|
||||
suite.Require().True(ok2)
|
||||
suite.Assert().Equal([]string{"value1", "value2"}, mdOut2.Get("key"))
|
||||
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut2.Get("proxyfrom"))
|
||||
suite.Assert().Equal([]string{"os:admin"}, mdOut2.Get("talos-role"))
|
||||
})
|
||||
mdOut2, ok2 := metadata.FromOutgoingContext(outCtx2)
|
||||
suite.Require().True(ok2)
|
||||
suite.Assert().Equal([]string{"value1", "value2"}, mdOut2.Get("key"))
|
||||
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut2.Get("proxyfrom"))
|
||||
suite.Assert().Equal([]string{"os:admin"}, mdOut2.Get("talos-role"))
|
||||
},
|
||||
)
|
||||
|
||||
suite.Run("Other context", func() {
|
||||
md3 := metadata.New(nil)
|
||||
md3.Set(":authority", "127.0.0.2")
|
||||
md3.Set("nodes", "127.0.0.1")
|
||||
md3.Set("key", "value3", "value4")
|
||||
ctx3 := metadata.NewIncomingContext(authz.ContextWithRoles(context.Background(), role.MakeSet(role.Reader)), md3)
|
||||
suite.Run(
|
||||
"Other context", func() {
|
||||
md3 := metadata.New(nil)
|
||||
md3.Set(":authority", "127.0.0.2")
|
||||
md3.Set("nodes", "127.0.0.1")
|
||||
md3.Set("key", "value3", "value4")
|
||||
ctx3 := metadata.NewIncomingContext(
|
||||
authz.ContextWithRoles(context.Background(), role.MakeSet(role.Reader)),
|
||||
md3,
|
||||
)
|
||||
|
||||
outCtx3, conn3, err3 := suite.b.GetConnection(ctx3)
|
||||
suite.Require().NoError(err3)
|
||||
suite.Assert().Equal(conn1, conn3) // connection is cached
|
||||
suite.Assert().Equal(role.MakeSet(role.Reader), authz.GetRoles(outCtx3))
|
||||
outCtx3, conn3, err3 := suite.b.GetConnection(ctx3)
|
||||
suite.Require().NoError(err3)
|
||||
suite.Assert().Equal(conn1, conn3) // connection is cached
|
||||
suite.Assert().Equal(role.MakeSet(role.Reader), authz.GetRoles(outCtx3))
|
||||
|
||||
mdOut3, ok3 := metadata.FromOutgoingContext(outCtx3)
|
||||
suite.Require().True(ok3)
|
||||
suite.Assert().Equal([]string{"value3", "value4"}, mdOut3.Get("key"))
|
||||
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut3.Get("proxyfrom"))
|
||||
suite.Assert().Equal([]string{"os:reader"}, mdOut3.Get("talos-role"))
|
||||
})
|
||||
mdOut3, ok3 := metadata.FromOutgoingContext(outCtx3)
|
||||
suite.Require().True(ok3)
|
||||
suite.Assert().Equal([]string{"value3", "value4"}, mdOut3.Get("key"))
|
||||
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut3.Get("proxyfrom"))
|
||||
suite.Assert().Equal([]string{"os:reader"}, mdOut3.Get("talos-role"))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *APIDSuite) TestAppendInfoUnary() {
|
||||
@ -221,30 +228,37 @@ func TestAPIIdiosyncrasies(t *testing.T) {
|
||||
for j := 0; j < methods.Len(); j++ {
|
||||
method := methods.Get(j)
|
||||
|
||||
t.Run(string(method.FullName()), func(t *testing.T) {
|
||||
response := method.Output()
|
||||
responseFields := response.Fields()
|
||||
t.Run(
|
||||
string(method.FullName()), func(t *testing.T) {
|
||||
response := method.Output()
|
||||
responseFields := response.Fields()
|
||||
|
||||
if method.IsStreamingServer() {
|
||||
metadata := responseFields.Get(0)
|
||||
assert.Equal(t, "metadata", metadata.TextName())
|
||||
assert.Equal(t, 1, int(metadata.Number()))
|
||||
} else {
|
||||
require.Equal(t, 1, responseFields.Len(), "unary responses should have exactly one field")
|
||||
if method.IsStreamingServer() {
|
||||
metadata := responseFields.Get(0)
|
||||
assert.Equal(t, "metadata", metadata.TextName())
|
||||
assert.Equal(t, 1, int(metadata.Number()))
|
||||
} else {
|
||||
require.Equal(t, 1, responseFields.Len(), "unary responses should have exactly one field")
|
||||
|
||||
messages := responseFields.Get(0)
|
||||
assert.Equal(t, "messages", messages.TextName())
|
||||
assert.Equal(t, 1, int(messages.Number()))
|
||||
messages := responseFields.Get(0)
|
||||
assert.Equal(t, "messages", messages.TextName())
|
||||
assert.Equal(t, 1, int(messages.Number()))
|
||||
|
||||
reply := messages.Message()
|
||||
replyFields := reply.Fields()
|
||||
require.GreaterOrEqual(t, replyFields.Len(), 1, "unary replies should have at least one field")
|
||||
reply := messages.Message()
|
||||
replyFields := reply.Fields()
|
||||
require.GreaterOrEqual(
|
||||
t,
|
||||
replyFields.Len(),
|
||||
1,
|
||||
"unary replies should have at least one field",
|
||||
)
|
||||
|
||||
metadata := replyFields.Get(0)
|
||||
assert.Equal(t, "metadata", metadata.TextName())
|
||||
assert.Equal(t, 1, int(metadata.Number()))
|
||||
}
|
||||
})
|
||||
metadata := replyFields.Get(0)
|
||||
assert.Equal(t, "metadata", metadata.TextName())
|
||||
assert.Equal(t, 1, int(metadata.Number()))
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -294,8 +308,10 @@ func getOptions(t *testing.T, descriptor protoreflect.Descriptor) (deprecated bo
|
||||
func testDeprecated(t *testing.T, descriptor protoreflect.Descriptor, currentVersion *config.VersionContract) {
|
||||
deprecated, version := getOptions(t, descriptor)
|
||||
|
||||
assert.Equal(t, deprecated, version != "",
|
||||
"%s: `deprecated` and `remove_deprecated_XXX_in` options should be used together", descriptor.FullName())
|
||||
assert.Equal(
|
||||
t, deprecated, version != "",
|
||||
"%s: `deprecated` and `remove_deprecated_XXX_in` options should be used together", descriptor.FullName(),
|
||||
)
|
||||
|
||||
if !deprecated || version == "" {
|
||||
return
|
||||
|
@ -47,7 +47,6 @@ func (s *InspectServer) ControllerRuntimeDependencies(ctx context.Context, in *e
|
||||
}
|
||||
|
||||
edges = append(edges, &inspectapi.ControllerDependencyEdge{
|
||||
|
||||
ControllerName: graph.Edges[i].ControllerName,
|
||||
|
||||
EdgeType: edgeType,
|
||||
|
@ -263,25 +263,32 @@ func run() error {
|
||||
}
|
||||
|
||||
// Watch and handle runtime events.
|
||||
_ = c.Runtime().Events().Watch(func(events <-chan runtime.EventInfo) { //nolint:errcheck
|
||||
for {
|
||||
for event := range events {
|
||||
switch msg := event.Payload.(type) {
|
||||
case *machine.SequenceEvent:
|
||||
if msg.Error != nil {
|
||||
if msg.Error.GetCode() == common.Code_LOCKED {
|
||||
// ignore sequence lock errors, they're not fatal
|
||||
continue
|
||||
}
|
||||
//nolint:errcheck
|
||||
_ = c.Runtime().Events().Watch(
|
||||
func(events <-chan runtime.EventInfo) {
|
||||
for {
|
||||
for event := range events {
|
||||
switch msg := event.Payload.(type) {
|
||||
case *machine.SequenceEvent:
|
||||
if msg.Error != nil {
|
||||
if msg.Error.GetCode() == common.Code_LOCKED {
|
||||
// ignore sequence lock errors, they're not fatal
|
||||
continue
|
||||
}
|
||||
|
||||
errCh <- fmt.Errorf("fatal sequencer error in %q sequence: %v", msg.GetSequence(), msg.GetError().String())
|
||||
errCh <- fmt.Errorf(
|
||||
"fatal sequencer error in %q sequence: %v",
|
||||
msg.GetSequence(),
|
||||
msg.GetError().String(),
|
||||
)
|
||||
}
|
||||
case *machine.RestartEvent:
|
||||
errCh <- runtime.RebootError{Cmd: int(msg.Cmd)}
|
||||
}
|
||||
case *machine.RestartEvent:
|
||||
errCh <- runtime.RebootError{Cmd: int(msg.Cmd)}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
return <-errCh
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ type ClusterSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -96,10 +96,14 @@ func (suite *ClusterSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ type K8sAddressFilterSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
//nolint:containedctx
|
||||
ctx context.Context
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
@ -67,7 +68,10 @@ func (suite *K8sAddressFilterSuite) startRuntime() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *K8sAddressFilterSuite) assertResource(md resource.Metadata, check func(res resource.Resource) error) func() error {
|
||||
func (suite *K8sAddressFilterSuite) assertResource(
|
||||
md resource.Metadata,
|
||||
check func(res resource.Resource) error,
|
||||
) func() error {
|
||||
return func() error {
|
||||
r, err := suite.state.Get(suite.ctx, md)
|
||||
if err != nil {
|
||||
@ -86,56 +90,78 @@ func (suite *K8sAddressFilterSuite) TestReconcile() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
ServiceSubnet: []string{
|
||||
"10.200.0.0/22",
|
||||
"fd40:10:200::/112",
|
||||
},
|
||||
PodSubnet: []string{
|
||||
"10.32.0.0/12",
|
||||
"fd00:10:32::/102",
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
ServiceSubnet: []string{
|
||||
"10.200.0.0/22",
|
||||
"fd40:10:200::/112",
|
||||
},
|
||||
PodSubnet: []string{
|
||||
"10.32.0.0/12",
|
||||
"fd00:10:32::/102",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(network.NamespaceName, network.NodeAddressFilterType, k8s.NodeAddressFilterOnlyK8s, resource.VersionUndefined),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.NodeAddressFilter).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.NodeAddressFilterType,
|
||||
k8s.NodeAddressFilterOnlyK8s,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.NodeAddressFilter).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("[10.32.0.0/12 fd00:10:32::/102 10.200.0.0/22 fd40:10:200::/112]", fmt.Sprintf("%s", spec.IncludeSubnets))
|
||||
suite.Assert().Empty(spec.ExcludeSubnets)
|
||||
suite.Assert().Equal(
|
||||
"[10.32.0.0/12 fd00:10:32::/102 10.200.0.0/22 fd40:10:200::/112]",
|
||||
fmt.Sprintf("%s", spec.IncludeSubnets),
|
||||
)
|
||||
suite.Assert().Empty(spec.ExcludeSubnets)
|
||||
|
||||
return nil
|
||||
},
|
||||
return nil
|
||||
},
|
||||
),
|
||||
),
|
||||
))
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(network.NamespaceName, network.NodeAddressFilterType, k8s.NodeAddressFilterNoK8s, resource.VersionUndefined),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.NodeAddressFilter).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.NodeAddressFilterType,
|
||||
k8s.NodeAddressFilterNoK8s,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.NodeAddressFilter).TypedSpec()
|
||||
|
||||
suite.Assert().Empty(spec.IncludeSubnets)
|
||||
suite.Assert().Equal("[10.32.0.0/12 fd00:10:32::/102 10.200.0.0/22 fd40:10:200::/112]", fmt.Sprintf("%s", spec.ExcludeSubnets))
|
||||
suite.Assert().Empty(spec.IncludeSubnets)
|
||||
suite.Assert().Equal(
|
||||
"[10.32.0.0/12 fd00:10:32::/102 10.200.0.0/22 fd40:10:200::/112]",
|
||||
fmt.Sprintf("%s", spec.ExcludeSubnets),
|
||||
)
|
||||
|
||||
return nil
|
||||
},
|
||||
return nil
|
||||
},
|
||||
),
|
||||
),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *K8sAddressFilterSuite) TearDownTest() {
|
||||
|
@ -40,7 +40,7 @@ type K8sControlPlaneSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -70,7 +70,10 @@ func (suite *K8sControlPlaneSuite) startRuntime() {
|
||||
}
|
||||
|
||||
func (suite *K8sControlPlaneSuite) assertK8sControlPlanes(manifests []string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(config.NamespaceName, config.K8sControlPlaneType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(config.NamespaceName, config.K8sControlPlaneType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -97,20 +100,22 @@ func (suite *K8sControlPlaneSuite) setupMachine(cfg *config.MachineConfig) confi
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, machineType))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertK8sControlPlanes(
|
||||
[]string{
|
||||
config.K8sAdmissionControlID,
|
||||
config.K8sExtraManifestsID,
|
||||
config.K8sControlPlaneAPIServerID,
|
||||
config.K8sControlPlaneControllerManagerID,
|
||||
config.K8sControlPlaneSchedulerID,
|
||||
config.K8sManifestsID,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertK8sControlPlanes(
|
||||
[]string{
|
||||
config.K8sAdmissionControlID,
|
||||
config.K8sExtraManifestsID,
|
||||
config.K8sControlPlaneAPIServerID,
|
||||
config.K8sControlPlaneControllerManagerID,
|
||||
config.K8sControlPlaneSchedulerID,
|
||||
config.K8sManifestsID,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
r, err := suite.state.Get(suite.ctx, config.NewK8sControlPlaneAPIServer().Metadata())
|
||||
suite.Require().NoError(err)
|
||||
@ -125,17 +130,19 @@ func (suite *K8sControlPlaneSuite) TestReconcileDefaults() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
apiServerCfg := suite.setupMachine(cfg)
|
||||
suite.Assert().Empty(apiServerCfg.CloudProvider)
|
||||
@ -149,86 +156,96 @@ func (suite *K8sControlPlaneSuite) TestReconcileExtraVolumes() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
APIServerConfig: &v1alpha1.APIServerConfig{
|
||||
ExtraVolumesConfig: []v1alpha1.VolumeMountConfig{
|
||||
{
|
||||
VolumeHostPath: "/var/lib",
|
||||
VolumeMountPath: "/var/foo/",
|
||||
APIServerConfig: &v1alpha1.APIServerConfig{
|
||||
ExtraVolumesConfig: []v1alpha1.VolumeMountConfig{
|
||||
{
|
||||
VolumeHostPath: "/var/lib",
|
||||
VolumeMountPath: "/var/foo/",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
apiServerCfg := suite.setupMachine(cfg)
|
||||
suite.Assert().Equal([]config.K8sExtraVolume{
|
||||
{
|
||||
Name: "var-foo",
|
||||
HostPath: "/var/lib",
|
||||
MountPath: "/var/foo/",
|
||||
ReadOnly: false,
|
||||
},
|
||||
}, apiServerCfg.ExtraVolumes)
|
||||
suite.Assert().Equal(
|
||||
[]config.K8sExtraVolume{
|
||||
{
|
||||
Name: "var-foo",
|
||||
HostPath: "/var/lib",
|
||||
MountPath: "/var/foo/",
|
||||
ReadOnly: false,
|
||||
},
|
||||
}, apiServerCfg.ExtraVolumes,
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *K8sControlPlaneSuite) TestReconcileEnvironment() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
APIServerConfig: &v1alpha1.APIServerConfig{
|
||||
EnvConfig: v1alpha1.Env{
|
||||
"HTTP_PROXY": "foo",
|
||||
APIServerConfig: &v1alpha1.APIServerConfig{
|
||||
EnvConfig: v1alpha1.Env{
|
||||
"HTTP_PROXY": "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
apiServerCfg := suite.setupMachine(cfg)
|
||||
suite.Assert().Equal(map[string]string{
|
||||
"HTTP_PROXY": "foo",
|
||||
}, apiServerCfg.EnvironmentVariables)
|
||||
suite.Assert().Equal(
|
||||
map[string]string{
|
||||
"HTTP_PROXY": "foo",
|
||||
}, apiServerCfg.EnvironmentVariables,
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *K8sControlPlaneSuite) TestReconcileExternalCloudProvider() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
ExternalCloudProviderConfig: &v1alpha1.ExternalCloudProviderConfig{
|
||||
ExternalEnabled: true,
|
||||
ExternalManifests: []string{
|
||||
"https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml",
|
||||
"https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.yaml",
|
||||
ExternalCloudProviderConfig: &v1alpha1.ExternalCloudProviderConfig{
|
||||
ExternalEnabled: true,
|
||||
ExternalManifests: []string{
|
||||
"https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml",
|
||||
"https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.yaml",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
apiServerCfg := suite.setupMachine(cfg)
|
||||
suite.Assert().Equal("external", apiServerCfg.CloudProvider)
|
||||
@ -240,63 +257,71 @@ func (suite *K8sControlPlaneSuite) TestReconcileExternalCloudProvider() {
|
||||
r, err = suite.state.Get(suite.ctx, config.NewK8sExtraManifests().Metadata())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().Equal(config.K8sExtraManifestsSpec{
|
||||
ExtraManifests: []config.ExtraManifest{
|
||||
{
|
||||
Name: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml",
|
||||
URL: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml",
|
||||
Priority: "30",
|
||||
suite.Assert().Equal(
|
||||
config.K8sExtraManifestsSpec{
|
||||
ExtraManifests: []config.ExtraManifest{
|
||||
{
|
||||
Name: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml",
|
||||
URL: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml",
|
||||
Priority: "30",
|
||||
},
|
||||
{
|
||||
Name: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.yaml",
|
||||
URL: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.yaml",
|
||||
Priority: "30",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.yaml",
|
||||
URL: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.yaml",
|
||||
Priority: "30",
|
||||
},
|
||||
},
|
||||
}, r.(*config.K8sControlPlane).ExtraManifests())
|
||||
}, r.(*config.K8sControlPlane).ExtraManifests(),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *K8sControlPlaneSuite) TestReconcileInlineManifests() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterInlineManifests: v1alpha1.ClusterInlineManifests{
|
||||
{
|
||||
InlineManifestName: "namespace-ci",
|
||||
InlineManifestContents: strings.TrimSpace(`
|
||||
ClusterInlineManifests: v1alpha1.ClusterInlineManifests{
|
||||
{
|
||||
InlineManifestName: "namespace-ci",
|
||||
InlineManifestContents: strings.TrimSpace(
|
||||
`
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: ci
|
||||
`),
|
||||
`,
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.setupMachine(cfg)
|
||||
|
||||
r, err := suite.state.Get(suite.ctx, config.NewK8sExtraManifests().Metadata())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().Equal(config.K8sExtraManifestsSpec{
|
||||
ExtraManifests: []config.ExtraManifest{
|
||||
{
|
||||
Name: "namespace-ci",
|
||||
Priority: "99",
|
||||
InlineManifest: "apiVersion: v1\nkind: Namespace\nmetadata:\n\tname: ci",
|
||||
suite.Assert().Equal(
|
||||
config.K8sExtraManifestsSpec{
|
||||
ExtraManifests: []config.ExtraManifest{
|
||||
{
|
||||
Name: "namespace-ci",
|
||||
Priority: "99",
|
||||
InlineManifest: "apiVersion: v1\nkind: Namespace\nmetadata:\n\tname: ci",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, r.(*config.K8sControlPlane).ExtraManifests())
|
||||
}, r.(*config.K8sControlPlane).ExtraManifests(),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *K8sControlPlaneSuite) TearDownTest() {
|
||||
@ -307,8 +332,19 @@ func (suite *K8sControlPlaneSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, "-")))
|
||||
suite.Assert().NoError(suite.state.Destroy(context.Background(), config.NewK8sControlPlaneAPIServer().Metadata(), state.WithDestroyOwner("config.K8sControlPlaneController")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, "-"),
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
suite.state.Destroy(
|
||||
context.Background(),
|
||||
config.NewK8sControlPlaneAPIServer().Metadata(),
|
||||
state.WithDestroyOwner("config.K8sControlPlaneController"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestK8sControlPlaneSuite(t *testing.T) {
|
||||
|
@ -35,7 +35,7 @@ type EtcFileSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
etcPath string
|
||||
@ -57,10 +57,14 @@ func (suite *EtcFileSuite) SetupTest() {
|
||||
suite.etcPath = suite.T().TempDir()
|
||||
suite.shadowPath = suite.T().TempDir()
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&filesctrl.EtcFileController{
|
||||
EtcPath: suite.etcPath,
|
||||
ShadowPath: suite.shadowPath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&filesctrl.EtcFileController{
|
||||
EtcPath: suite.etcPath,
|
||||
ShadowPath: suite.shadowPath,
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *EtcFileSuite) startRuntime() {
|
||||
@ -83,7 +87,10 @@ func (suite *EtcFileSuite) assertEtcFile(filename, contents string, expectedVers
|
||||
return retry.ExpectedErrorf("contents don't match %q != %q", string(b), contents)
|
||||
}
|
||||
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(files.NamespaceName, files.EtcFileStatusType, filename, resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(files.NamespaceName, files.EtcFileStatusType, filename, resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
@ -118,10 +125,13 @@ func (suite *EtcFileSuite) TestFiles() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, etcFileSpec))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertEtcFile("test1", "foo", etcFileSpec.Metadata().Version())
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertEtcFile("test1", "foo", etcFileSpec.Metadata().Version())
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
for _, r := range []resource.Resource{etcFileSpec} {
|
||||
for {
|
||||
|
@ -276,7 +276,8 @@ func envVars(environment map[string]string) []v1.EnvVar {
|
||||
}
|
||||
|
||||
func (ctrl *ControlPlaneStaticPodController) manageAPIServer(ctx context.Context, r controller.Runtime, logger *zap.Logger,
|
||||
configResource *config.K8sControlPlane, secretsVersion, configVersion string) (string, error) {
|
||||
configResource *config.K8sControlPlane, secretsVersion, configVersion string,
|
||||
) (string, error) {
|
||||
cfg := configResource.APIServer()
|
||||
|
||||
enabledAdmissionPlugins := []string{"NodeRestriction"}
|
||||
@ -465,7 +466,8 @@ func (ctrl *ControlPlaneStaticPodController) manageAPIServer(ctx context.Context
|
||||
}
|
||||
|
||||
func (ctrl *ControlPlaneStaticPodController) manageControllerManager(ctx context.Context, r controller.Runtime,
|
||||
logger *zap.Logger, configResource *config.K8sControlPlane, secretsVersion, configVersion string) (string, error) {
|
||||
logger *zap.Logger, configResource *config.K8sControlPlane, secretsVersion, configVersion string,
|
||||
) (string, error) {
|
||||
cfg := configResource.ControllerManager()
|
||||
|
||||
if !cfg.Enabled {
|
||||
@ -594,7 +596,8 @@ func (ctrl *ControlPlaneStaticPodController) manageControllerManager(ctx context
|
||||
}
|
||||
|
||||
func (ctrl *ControlPlaneStaticPodController) manageScheduler(ctx context.Context, r controller.Runtime,
|
||||
logger *zap.Logger, configResource *config.K8sControlPlane, secretsVersion, configVersion string) (string, error) {
|
||||
logger *zap.Logger, configResource *config.K8sControlPlane, secretsVersion, configVersion string,
|
||||
) (string, error) {
|
||||
cfg := configResource.Scheduler()
|
||||
|
||||
if !cfg.Enabled {
|
||||
|
@ -41,7 +41,7 @@ type ControlPlaneStaticPodSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -78,7 +78,10 @@ func (suite *ControlPlaneStaticPodSuite) startRuntime() {
|
||||
|
||||
//nolint:dupl
|
||||
func (suite *ControlPlaneStaticPodSuite) assertControlPlaneStaticPods(manifests []string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -109,51 +112,60 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileDefaults() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configControllerManager))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
"kube-controller-manager",
|
||||
"kube-scheduler",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
"kube-controller-manager",
|
||||
"kube-scheduler",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// tear down etcd service
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, v1alpha1.NewService("etcd").Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
list, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
list, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(list.Items) > 0 {
|
||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
||||
}
|
||||
if len(list.Items) > 0 {
|
||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraMounts() {
|
||||
secretStatus := k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, k8s.StaticPodSecretsStaticPodID)
|
||||
configStatus := k8s.NewConfigStatus(k8s.ControlPlaneNamespaceName, k8s.ConfigStatusStaticPodID)
|
||||
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
||||
configAPIServer.SetAPIServer(config.K8sControlPlaneAPIServerSpec{
|
||||
ExtraVolumes: []config.K8sExtraVolume{
|
||||
{
|
||||
Name: "foo",
|
||||
HostPath: "/var/lib",
|
||||
MountPath: "/var/foo",
|
||||
ReadOnly: true,
|
||||
configAPIServer.SetAPIServer(
|
||||
config.K8sControlPlaneAPIServerSpec{
|
||||
ExtraVolumes: []config.K8sExtraVolume{
|
||||
{
|
||||
Name: "foo",
|
||||
HostPath: "/var/lib",
|
||||
MountPath: "/var/foo",
|
||||
ReadOnly: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
configControllerManager := config.NewK8sControlPlaneControllerManager()
|
||||
configScheduler := config.NewK8sControlPlaneScheduler()
|
||||
@ -164,19 +176,24 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraMounts() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configControllerManager))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
"kube-controller-manager",
|
||||
"kube-scheduler",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
"kube-controller-manager",
|
||||
"kube-scheduler",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "kube-apiserver", resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "kube-apiserver", resource.VersionUndefined),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
apiServerPod, err := k8sadapter.StaticPod(r.(*k8s.StaticPod)).Pod()
|
||||
@ -185,65 +202,81 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraMounts() {
|
||||
suite.Assert().Len(apiServerPod.Spec.Volumes, 4)
|
||||
suite.Assert().Len(apiServerPod.Spec.Containers[0].VolumeMounts, 4)
|
||||
|
||||
suite.Assert().Equal(v1.Volume{
|
||||
Name: "secrets",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: constants.KubernetesAPIServerSecretsDir,
|
||||
suite.Assert().Equal(
|
||||
v1.Volume{
|
||||
Name: "secrets",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: constants.KubernetesAPIServerSecretsDir,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, apiServerPod.Spec.Volumes[0])
|
||||
}, apiServerPod.Spec.Volumes[0],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(v1.Volume{
|
||||
Name: "config",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: constants.KubernetesAPIServerConfigDir,
|
||||
suite.Assert().Equal(
|
||||
v1.Volume{
|
||||
Name: "config",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: constants.KubernetesAPIServerConfigDir,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, apiServerPod.Spec.Volumes[1])
|
||||
}, apiServerPod.Spec.Volumes[1],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(v1.Volume{
|
||||
Name: "audit",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: constants.KubernetesAuditLogDir,
|
||||
suite.Assert().Equal(
|
||||
v1.Volume{
|
||||
Name: "audit",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: constants.KubernetesAuditLogDir,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, apiServerPod.Spec.Volumes[2])
|
||||
}, apiServerPod.Spec.Volumes[2],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(v1.Volume{
|
||||
Name: "foo",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/var/lib",
|
||||
suite.Assert().Equal(
|
||||
v1.Volume{
|
||||
Name: "foo",
|
||||
VolumeSource: v1.VolumeSource{
|
||||
HostPath: &v1.HostPathVolumeSource{
|
||||
Path: "/var/lib",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, apiServerPod.Spec.Volumes[3])
|
||||
}, apiServerPod.Spec.Volumes[3],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(v1.VolumeMount{
|
||||
Name: "secrets",
|
||||
MountPath: constants.KubernetesAPIServerSecretsDir,
|
||||
ReadOnly: true,
|
||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[0])
|
||||
suite.Assert().Equal(
|
||||
v1.VolumeMount{
|
||||
Name: "secrets",
|
||||
MountPath: constants.KubernetesAPIServerSecretsDir,
|
||||
ReadOnly: true,
|
||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[0],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(v1.VolumeMount{
|
||||
Name: "config",
|
||||
MountPath: constants.KubernetesAPIServerConfigDir,
|
||||
ReadOnly: true,
|
||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[1])
|
||||
suite.Assert().Equal(
|
||||
v1.VolumeMount{
|
||||
Name: "config",
|
||||
MountPath: constants.KubernetesAPIServerConfigDir,
|
||||
ReadOnly: true,
|
||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[1],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(v1.VolumeMount{
|
||||
Name: "audit",
|
||||
MountPath: constants.KubernetesAuditLogDir,
|
||||
ReadOnly: false,
|
||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[2])
|
||||
suite.Assert().Equal(
|
||||
v1.VolumeMount{
|
||||
Name: "audit",
|
||||
MountPath: constants.KubernetesAuditLogDir,
|
||||
ReadOnly: false,
|
||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[2],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(v1.VolumeMount{
|
||||
Name: "foo",
|
||||
MountPath: "/var/foo",
|
||||
ReadOnly: true,
|
||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[3])
|
||||
suite.Assert().Equal(
|
||||
v1.VolumeMount{
|
||||
Name: "foo",
|
||||
MountPath: "/var/foo",
|
||||
ReadOnly: true,
|
||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[3],
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraArgs() {
|
||||
@ -278,9 +311,11 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraArgs() {
|
||||
secretStatus := k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, k8s.StaticPodSecretsStaticPodID)
|
||||
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
||||
|
||||
configAPIServer.SetAPIServer(config.K8sControlPlaneAPIServerSpec{
|
||||
ExtraArgs: test.args,
|
||||
})
|
||||
configAPIServer.SetAPIServer(
|
||||
config.K8sControlPlaneAPIServerSpec{
|
||||
ExtraArgs: test.args,
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configStatus))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, secretStatus))
|
||||
@ -290,23 +325,31 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraArgs() {
|
||||
// wait for some time to ensure that controller has picked the input
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
_, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "kube-apiserver", resource.VersionUndefined))
|
||||
_, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "kube-apiserver", resource.VersionUndefined),
|
||||
)
|
||||
suite.Require().Error(err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "kube-apiserver", resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "kube-apiserver", resource.VersionUndefined),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
apiServerPod, err := k8sadapter.StaticPod(r.(*k8s.StaticPod)).Pod()
|
||||
@ -332,20 +375,25 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraArgs() {
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, secretStatus.Metadata()))
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, configAPIServer.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
list, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
list, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(list.Items) > 0 {
|
||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
||||
}
|
||||
if len(list.Items) > 0 {
|
||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,23 +449,30 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileEnvironmentVariables() {
|
||||
for _, test := range tests {
|
||||
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
||||
|
||||
configAPIServer.SetAPIServer(config.K8sControlPlaneAPIServerSpec{
|
||||
EnvironmentVariables: test.env,
|
||||
})
|
||||
configAPIServer.SetAPIServer(
|
||||
config.K8sControlPlaneAPIServerSpec{
|
||||
EnvironmentVariables: test.env,
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configAPIServer))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "kube-apiserver", resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "kube-apiserver", resource.VersionUndefined),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
apiServerPod, err := k8sadapter.StaticPod(r.(*k8s.StaticPod)).Pod()
|
||||
@ -429,20 +484,25 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileEnvironmentVariables() {
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, configAPIServer.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
list, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
list, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(list.Items) > 0 {
|
||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
||||
}
|
||||
if len(list.Items) > 0 {
|
||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,40 +519,46 @@ func (suite *ControlPlaneStaticPodSuite) TestControlPlaneStaticPodsExceptSchedul
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configControllerManager))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
"kube-controller-manager",
|
||||
"kube-scheduler",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
"kube-controller-manager",
|
||||
"kube-scheduler",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// flip enabled to disable scheduler
|
||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, configScheduler.Metadata(), func(r resource.Resource) error {
|
||||
spec := r.(*config.K8sControlPlane).Scheduler()
|
||||
spec.Enabled = false
|
||||
r.(*config.K8sControlPlane).SetScheduler(spec)
|
||||
_, err := suite.state.UpdateWithConflicts(
|
||||
suite.ctx, configScheduler.Metadata(), func(r resource.Resource) error {
|
||||
spec := r.(*config.K8sControlPlane).Scheduler()
|
||||
spec.Enabled = false
|
||||
r.(*config.K8sControlPlane).SetScheduler(spec)
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
configScheduler.SetScheduler(config.K8sControlPlaneSchedulerSpec{Enabled: false})
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
"kube-controller-manager",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertControlPlaneStaticPods(
|
||||
[]string{
|
||||
"kube-apiserver",
|
||||
"kube-controller-manager",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ControlPlaneStaticPodSuite) TearDownTest() {
|
||||
@ -503,7 +569,12 @@ func (suite *ControlPlaneStaticPodSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, "-")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, "-"),
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), config.NewK8sManifests()))
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@ type ExtraManifestSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -71,7 +71,10 @@ func (suite *ExtraManifestSuite) startRuntime() {
|
||||
|
||||
//nolint:dupl
|
||||
func (suite *ExtraManifestSuite) assertExtraManifests(manifests []string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -91,12 +94,14 @@ func (suite *ExtraManifestSuite) assertExtraManifests(manifests []string) error
|
||||
|
||||
func (suite *ExtraManifestSuite) TestReconcileInlineManifests() {
|
||||
configExtraManifests := config.NewK8sExtraManifests()
|
||||
configExtraManifests.SetExtraManifests(config.K8sExtraManifestsSpec{
|
||||
ExtraManifests: []config.ExtraManifest{
|
||||
{
|
||||
Name: "namespaces",
|
||||
Priority: "99",
|
||||
InlineManifest: strings.TrimSpace(`
|
||||
configExtraManifests.SetExtraManifests(
|
||||
config.K8sExtraManifestsSpec{
|
||||
ExtraManifests: []config.ExtraManifest{
|
||||
{
|
||||
Name: "namespaces",
|
||||
Priority: "99",
|
||||
InlineManifest: strings.TrimSpace(
|
||||
`
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
@ -106,10 +111,12 @@ apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: build
|
||||
`),
|
||||
`,
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
statusNetwork := network.NewStatus(network.NamespaceName, network.StatusID)
|
||||
statusNetwork.TypedSpec().AddressReady = true
|
||||
@ -118,17 +125,27 @@ metadata:
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, configExtraManifests))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, statusNetwork))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertExtraManifests(
|
||||
[]string{
|
||||
"99-namespaces",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertExtraManifests(
|
||||
[]string{
|
||||
"99-namespaces",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "99-namespaces", resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.ControlPlaneNamespaceName,
|
||||
k8s.ManifestType,
|
||||
"99-namespaces",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
manifest := r.(*k8s.Manifest) //nolint:errcheck,forcetypeassert
|
||||
|
@ -38,7 +38,7 @@ type KubeletConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -71,139 +71,165 @@ func (suite *KubeletConfigSuite) TestReconcile() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||
KubeletImage: "kubelet",
|
||||
KubeletClusterDNS: []string{"10.0.0.1"},
|
||||
KubeletExtraArgs: map[string]string{
|
||||
"enable-feature": "foo",
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||
KubeletImage: "kubelet",
|
||||
KubeletClusterDNS: []string{"10.0.0.1"},
|
||||
KubeletExtraArgs: map[string]string{
|
||||
"enable-feature": "foo",
|
||||
},
|
||||
KubeletExtraMounts: []v1alpha1.ExtraMount{
|
||||
{
|
||||
Mount: specs.Mount{
|
||||
Destination: "/tmp",
|
||||
Source: "/var",
|
||||
Type: "tmpfs",
|
||||
},
|
||||
},
|
||||
},
|
||||
KubeletExtraConfig: v1alpha1.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"serverTLSBootstrap": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
KubeletExtraMounts: []v1alpha1.ExtraMount{
|
||||
{
|
||||
Mount: specs.Mount{
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
ExternalCloudProviderConfig: &v1alpha1.ExternalCloudProviderConfig{
|
||||
ExternalEnabled: true,
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
DNSDomain: "service.svc",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletConfig, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.NamespaceName,
|
||||
k8s.KubeletConfigType,
|
||||
k8s.KubeletID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
spec := kubeletConfig.(*k8s.KubeletConfig).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("kubelet", spec.Image)
|
||||
suite.Assert().Equal([]string{"10.0.0.1"}, spec.ClusterDNS)
|
||||
suite.Assert().Equal("service.svc", spec.ClusterDomain)
|
||||
suite.Assert().Equal(
|
||||
map[string]string{
|
||||
"enable-feature": "foo",
|
||||
},
|
||||
spec.ExtraArgs,
|
||||
)
|
||||
suite.Assert().Equal(
|
||||
[]specs.Mount{
|
||||
{
|
||||
Destination: "/tmp",
|
||||
Source: "/var",
|
||||
Type: "tmpfs",
|
||||
},
|
||||
},
|
||||
},
|
||||
KubeletExtraConfig: v1alpha1.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
spec.ExtraMounts,
|
||||
)
|
||||
suite.Assert().Equal(
|
||||
map[string]interface{}{
|
||||
"serverTLSBootstrap": true,
|
||||
},
|
||||
},
|
||||
spec.ExtraConfig,
|
||||
)
|
||||
suite.Assert().True(spec.CloudProviderExternal)
|
||||
|
||||
return nil
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
ExternalCloudProviderConfig: &v1alpha1.ExternalCloudProviderConfig{
|
||||
ExternalEnabled: true,
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
DNSDomain: "service.svc",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletConfig, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletConfigType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
spec := kubeletConfig.(*k8s.KubeletConfig).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("kubelet", spec.Image)
|
||||
suite.Assert().Equal([]string{"10.0.0.1"}, spec.ClusterDNS)
|
||||
suite.Assert().Equal("service.svc", spec.ClusterDomain)
|
||||
suite.Assert().Equal(
|
||||
map[string]string{
|
||||
"enable-feature": "foo",
|
||||
},
|
||||
spec.ExtraArgs)
|
||||
suite.Assert().Equal(
|
||||
[]specs.Mount{
|
||||
{
|
||||
Destination: "/tmp",
|
||||
Source: "/var",
|
||||
Type: "tmpfs",
|
||||
},
|
||||
},
|
||||
spec.ExtraMounts)
|
||||
suite.Assert().Equal(
|
||||
map[string]interface{}{
|
||||
"serverTLSBootstrap": true,
|
||||
},
|
||||
spec.ExtraConfig,
|
||||
)
|
||||
suite.Assert().True(spec.CloudProviderExternal)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *KubeletConfigSuite) TestReconcileDefaults() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||
KubeletImage: "kubelet",
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||
KubeletImage: "kubelet",
|
||||
},
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
ServiceSubnet: []string{constants.DefaultIPv4ServiceNet},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
ServiceSubnet: []string{constants.DefaultIPv4ServiceNet},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletConfig, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletConfigType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletConfig, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.NamespaceName,
|
||||
k8s.KubeletConfigType,
|
||||
k8s.KubeletID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := kubeletConfig.(*k8s.KubeletConfig).TypedSpec()
|
||||
|
||||
spec := kubeletConfig.(*k8s.KubeletConfig).TypedSpec()
|
||||
suite.Assert().Equal("kubelet", spec.Image)
|
||||
suite.Assert().Equal([]string{"10.96.0.10"}, spec.ClusterDNS)
|
||||
suite.Assert().Equal("", spec.ClusterDomain)
|
||||
suite.Assert().Empty(spec.ExtraArgs)
|
||||
suite.Assert().Empty(spec.ExtraMounts)
|
||||
suite.Assert().False(spec.CloudProviderExternal)
|
||||
|
||||
suite.Assert().Equal("kubelet", spec.Image)
|
||||
suite.Assert().Equal([]string{"10.96.0.10"}, spec.ClusterDNS)
|
||||
suite.Assert().Equal("", spec.ClusterDomain)
|
||||
suite.Assert().Empty(spec.ExtraArgs)
|
||||
suite.Assert().Empty(spec.ExtraMounts)
|
||||
suite.Assert().False(spec.CloudProviderExternal)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *KubeletConfigSuite) TearDownTest() {
|
||||
|
@ -43,7 +43,7 @@ type KubeletSpecSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -99,41 +99,52 @@ func (suite *KubeletSpecSuite) TestReconcileDefault() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodename))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletSpec, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletSpecType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletSpec, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.NamespaceName,
|
||||
k8s.KubeletSpecType,
|
||||
k8s.KubeletID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := kubeletSpec.(*k8s.KubeletSpec).TypedSpec()
|
||||
|
||||
spec := kubeletSpec.(*k8s.KubeletSpec).TypedSpec()
|
||||
suite.Assert().Equal(cfg.TypedSpec().Image, spec.Image)
|
||||
suite.Assert().Equal(
|
||||
[]string{
|
||||
"--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig",
|
||||
"--cert-dir=/var/lib/kubelet/pki",
|
||||
"--cloud-provider=external",
|
||||
"--config=/etc/kubernetes/kubelet.yaml",
|
||||
"--container-runtime=remote",
|
||||
"--container-runtime-endpoint=unix:///run/containerd/containerd.sock",
|
||||
"--foo=bar",
|
||||
"--hostname-override=example.com",
|
||||
"--kubeconfig=/etc/kubernetes/kubeconfig-kubelet",
|
||||
"--node-ip=172.20.0.2",
|
||||
}, spec.Args,
|
||||
)
|
||||
suite.Assert().Equal(cfg.TypedSpec().ExtraMounts, spec.ExtraMounts)
|
||||
|
||||
suite.Assert().Equal(cfg.TypedSpec().Image, spec.Image)
|
||||
suite.Assert().Equal(
|
||||
[]string{
|
||||
"--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig",
|
||||
"--cert-dir=/var/lib/kubelet/pki",
|
||||
"--cloud-provider=external",
|
||||
"--config=/etc/kubernetes/kubelet.yaml",
|
||||
"--container-runtime=remote",
|
||||
"--container-runtime-endpoint=unix:///run/containerd/containerd.sock",
|
||||
"--foo=bar",
|
||||
"--hostname-override=example.com",
|
||||
"--kubeconfig=/etc/kubernetes/kubeconfig-kubelet",
|
||||
"--node-ip=172.20.0.2",
|
||||
}, spec.Args)
|
||||
suite.Assert().Equal(cfg.TypedSpec().ExtraMounts, spec.ExtraMounts)
|
||||
suite.Assert().Equal([]interface{}{"10.96.0.10"}, spec.Config["clusterDNS"])
|
||||
suite.Assert().Equal("cluster.local", spec.Config["clusterDomain"])
|
||||
|
||||
suite.Assert().Equal([]interface{}{"10.96.0.10"}, spec.Config["clusterDNS"])
|
||||
suite.Assert().Equal("cluster.local", spec.Config["clusterDomain"])
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *KubeletSpecSuite) TestReconcileWithExplicitNodeIP() {
|
||||
@ -150,35 +161,46 @@ func (suite *KubeletSpecSuite) TestReconcileWithExplicitNodeIP() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodename))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletSpec, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletSpecType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletSpec, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.NamespaceName,
|
||||
k8s.KubeletSpecType,
|
||||
k8s.KubeletID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := kubeletSpec.(*k8s.KubeletSpec).TypedSpec()
|
||||
|
||||
spec := kubeletSpec.(*k8s.KubeletSpec).TypedSpec()
|
||||
suite.Assert().Equal(cfg.TypedSpec().Image, spec.Image)
|
||||
suite.Assert().Equal(
|
||||
[]string{
|
||||
"--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig",
|
||||
"--cert-dir=/var/lib/kubelet/pki",
|
||||
"--config=/etc/kubernetes/kubelet.yaml",
|
||||
"--container-runtime=remote",
|
||||
"--container-runtime-endpoint=unix:///run/containerd/containerd.sock",
|
||||
"--hostname-override=example.com",
|
||||
"--kubeconfig=/etc/kubernetes/kubeconfig-kubelet",
|
||||
"--node-ip=10.0.0.1",
|
||||
}, spec.Args,
|
||||
)
|
||||
|
||||
suite.Assert().Equal(cfg.TypedSpec().Image, spec.Image)
|
||||
suite.Assert().Equal(
|
||||
[]string{
|
||||
"--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubeconfig",
|
||||
"--cert-dir=/var/lib/kubelet/pki",
|
||||
"--config=/etc/kubernetes/kubelet.yaml",
|
||||
"--container-runtime=remote",
|
||||
"--container-runtime-endpoint=unix:///run/containerd/containerd.sock",
|
||||
"--hostname-override=example.com",
|
||||
"--kubeconfig=/etc/kubernetes/kubeconfig-kubelet",
|
||||
"--node-ip=10.0.0.1",
|
||||
}, spec.Args)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *KubeletSpecSuite) TestReconcileWithExtraConfig() {
|
||||
@ -202,32 +224,45 @@ func (suite *KubeletSpecSuite) TestReconcileWithExtraConfig() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodeIP))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletSpec, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletSpecType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletSpec, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.NamespaceName,
|
||||
k8s.KubeletSpecType,
|
||||
k8s.KubeletID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := kubeletSpec.(*k8s.KubeletSpec).TypedSpec()
|
||||
|
||||
spec := kubeletSpec.(*k8s.KubeletSpec).TypedSpec()
|
||||
var kubeletConfiguration kubeletconfig.KubeletConfiguration
|
||||
|
||||
var kubeletConfiguration kubeletconfig.KubeletConfiguration
|
||||
if err := k8sruntime.DefaultUnstructuredConverter.FromUnstructured(
|
||||
spec.Config,
|
||||
&kubeletConfiguration,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := k8sruntime.DefaultUnstructuredConverter.FromUnstructured(spec.Config, &kubeletConfiguration); err != nil {
|
||||
return err
|
||||
}
|
||||
suite.Assert().Equal("/", kubeletConfiguration.CgroupRoot)
|
||||
suite.Assert().Equal(cfg.TypedSpec().ClusterDomain, kubeletConfiguration.ClusterDomain)
|
||||
suite.Assert().True(kubeletConfiguration.ServerTLSBootstrap)
|
||||
|
||||
suite.Assert().Equal("/", kubeletConfiguration.CgroupRoot)
|
||||
suite.Assert().Equal(cfg.TypedSpec().ClusterDomain, kubeletConfiguration.ClusterDomain)
|
||||
suite.Assert().True(kubeletConfiguration.ServerTLSBootstrap)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *KubeletSpecSuite) TearDownTest() {
|
||||
@ -276,68 +311,74 @@ func TestNewKubeletConfigurationFail(t *testing.T) {
|
||||
} {
|
||||
tt := tt
|
||||
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := k8sctrl.NewKubeletConfiguration([]string{"10.96.0.10"}, "cluster.svc", tt.extraConfig)
|
||||
require.Error(t, err)
|
||||
t.Run(
|
||||
tt.name, func(t *testing.T) {
|
||||
_, err := k8sctrl.NewKubeletConfiguration([]string{"10.96.0.10"}, "cluster.svc", tt.extraConfig)
|
||||
require.Error(t, err)
|
||||
|
||||
assert.EqualError(t, err, tt.expectedErr)
|
||||
})
|
||||
assert.EqualError(t, err, tt.expectedErr)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewKubeletConfigurationSuccess(t *testing.T) {
|
||||
config, err := k8sctrl.NewKubeletConfiguration([]string{"10.0.0.5"}, "cluster.local", map[string]interface{}{
|
||||
"oomScoreAdj": -300,
|
||||
"enableDebuggingHandlers": true,
|
||||
})
|
||||
config, err := k8sctrl.NewKubeletConfiguration(
|
||||
[]string{"10.0.0.5"}, "cluster.local", map[string]interface{}{
|
||||
"oomScoreAdj": -300,
|
||||
"enableDebuggingHandlers": true,
|
||||
},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, &kubeletconfig.KubeletConfiguration{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: kubeletconfig.SchemeGroupVersion.String(),
|
||||
Kind: "KubeletConfiguration",
|
||||
},
|
||||
StaticPodPath: constants.ManifestsDirectory,
|
||||
Port: constants.KubeletPort,
|
||||
Authentication: kubeletconfig.KubeletAuthentication{
|
||||
X509: kubeletconfig.KubeletX509Authentication{
|
||||
ClientCAFile: constants.KubernetesCACert,
|
||||
assert.Equal(
|
||||
t, &kubeletconfig.KubeletConfiguration{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: kubeletconfig.SchemeGroupVersion.String(),
|
||||
Kind: "KubeletConfiguration",
|
||||
},
|
||||
Webhook: kubeletconfig.KubeletWebhookAuthentication{
|
||||
Enabled: pointer.ToBool(true),
|
||||
StaticPodPath: constants.ManifestsDirectory,
|
||||
Port: constants.KubeletPort,
|
||||
Authentication: kubeletconfig.KubeletAuthentication{
|
||||
X509: kubeletconfig.KubeletX509Authentication{
|
||||
ClientCAFile: constants.KubernetesCACert,
|
||||
},
|
||||
Webhook: kubeletconfig.KubeletWebhookAuthentication{
|
||||
Enabled: pointer.ToBool(true),
|
||||
},
|
||||
Anonymous: kubeletconfig.KubeletAnonymousAuthentication{
|
||||
Enabled: pointer.ToBool(false),
|
||||
},
|
||||
},
|
||||
Anonymous: kubeletconfig.KubeletAnonymousAuthentication{
|
||||
Enabled: pointer.ToBool(false),
|
||||
Authorization: kubeletconfig.KubeletAuthorization{
|
||||
Mode: kubeletconfig.KubeletAuthorizationModeWebhook,
|
||||
},
|
||||
CgroupRoot: "/",
|
||||
SystemCgroups: constants.CgroupSystem,
|
||||
KubeletCgroups: constants.CgroupKubelet,
|
||||
RotateCertificates: true,
|
||||
ProtectKernelDefaults: true,
|
||||
Address: "0.0.0.0",
|
||||
OOMScoreAdj: pointer.ToInt32(-300),
|
||||
ClusterDomain: "cluster.local",
|
||||
ClusterDNS: []string{"10.0.0.5"},
|
||||
SerializeImagePulls: pointer.ToBool(false),
|
||||
FailSwapOn: pointer.ToBool(false),
|
||||
SystemReserved: map[string]string{
|
||||
"cpu": constants.KubeletSystemReservedCPU,
|
||||
"memory": constants.KubeletSystemReservedMemory,
|
||||
"pid": constants.KubeletSystemReservedPid,
|
||||
"ephemeral-storage": constants.KubeletSystemReservedEphemeralStorage,
|
||||
},
|
||||
Logging: v1alpha1.LoggingConfiguration{
|
||||
Format: "json",
|
||||
},
|
||||
ShutdownGracePeriod: metav1.Duration{Duration: constants.KubeletShutdownGracePeriod},
|
||||
ShutdownGracePeriodCriticalPods: metav1.Duration{Duration: constants.KubeletShutdownGracePeriodCriticalPods},
|
||||
StreamingConnectionIdleTimeout: metav1.Duration{Duration: 5 * time.Minute},
|
||||
TLSMinVersion: "VersionTLS13",
|
||||
EnableDebuggingHandlers: pointer.ToBool(true),
|
||||
},
|
||||
Authorization: kubeletconfig.KubeletAuthorization{
|
||||
Mode: kubeletconfig.KubeletAuthorizationModeWebhook,
|
||||
},
|
||||
CgroupRoot: "/",
|
||||
SystemCgroups: constants.CgroupSystem,
|
||||
KubeletCgroups: constants.CgroupKubelet,
|
||||
RotateCertificates: true,
|
||||
ProtectKernelDefaults: true,
|
||||
Address: "0.0.0.0",
|
||||
OOMScoreAdj: pointer.ToInt32(-300),
|
||||
ClusterDomain: "cluster.local",
|
||||
ClusterDNS: []string{"10.0.0.5"},
|
||||
SerializeImagePulls: pointer.ToBool(false),
|
||||
FailSwapOn: pointer.ToBool(false),
|
||||
SystemReserved: map[string]string{
|
||||
"cpu": constants.KubeletSystemReservedCPU,
|
||||
"memory": constants.KubeletSystemReservedMemory,
|
||||
"pid": constants.KubeletSystemReservedPid,
|
||||
"ephemeral-storage": constants.KubeletSystemReservedEphemeralStorage,
|
||||
},
|
||||
Logging: v1alpha1.LoggingConfiguration{
|
||||
Format: "json",
|
||||
},
|
||||
ShutdownGracePeriod: metav1.Duration{Duration: constants.KubeletShutdownGracePeriod},
|
||||
ShutdownGracePeriodCriticalPods: metav1.Duration{Duration: constants.KubeletShutdownGracePeriodCriticalPods},
|
||||
StreamingConnectionIdleTimeout: metav1.Duration{Duration: 5 * time.Minute},
|
||||
TLSMinVersion: "VersionTLS13",
|
||||
EnableDebuggingHandlers: pointer.ToBool(true),
|
||||
},
|
||||
config)
|
||||
config,
|
||||
)
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ type ManifestSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -70,7 +70,10 @@ func (suite *ManifestSuite) startRuntime() {
|
||||
|
||||
//nolint:dupl
|
||||
func (suite *ManifestSuite) assertManifests(manifests []string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -124,25 +127,27 @@ func (suite *ManifestSuite) TestReconcileDefaults() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, rootSecrets))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertManifests(
|
||||
[]string{
|
||||
"00-kubelet-bootstrapping-token",
|
||||
"01-csr-approver-role-binding",
|
||||
"01-csr-node-bootstrap",
|
||||
"01-csr-renewal-role-binding",
|
||||
"02-kube-system-sa-role-binding",
|
||||
"03-default-pod-security-policy",
|
||||
"05-flannel",
|
||||
"10-kube-proxy",
|
||||
"11-core-dns",
|
||||
"11-core-dns-svc",
|
||||
"11-kube-config-in-cluster",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertManifests(
|
||||
[]string{
|
||||
"00-kubelet-bootstrapping-token",
|
||||
"01-csr-approver-role-binding",
|
||||
"01-csr-node-bootstrap",
|
||||
"01-csr-renewal-role-binding",
|
||||
"02-kube-system-sa-role-binding",
|
||||
"03-default-pod-security-policy",
|
||||
"05-flannel",
|
||||
"10-kube-proxy",
|
||||
"11-core-dns",
|
||||
"11-core-dns-svc",
|
||||
"11-kube-config-in-cluster",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ManifestSuite) TestReconcileDisableKubeProxy() {
|
||||
@ -155,24 +160,26 @@ func (suite *ManifestSuite) TestReconcileDisableKubeProxy() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, rootSecrets))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertManifests(
|
||||
[]string{
|
||||
"00-kubelet-bootstrapping-token",
|
||||
"01-csr-approver-role-binding",
|
||||
"01-csr-node-bootstrap",
|
||||
"01-csr-renewal-role-binding",
|
||||
"02-kube-system-sa-role-binding",
|
||||
"03-default-pod-security-policy",
|
||||
"05-flannel",
|
||||
"11-core-dns",
|
||||
"11-core-dns-svc",
|
||||
"11-kube-config-in-cluster",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertManifests(
|
||||
[]string{
|
||||
"00-kubelet-bootstrapping-token",
|
||||
"01-csr-approver-role-binding",
|
||||
"01-csr-node-bootstrap",
|
||||
"01-csr-renewal-role-binding",
|
||||
"02-kube-system-sa-role-binding",
|
||||
"03-default-pod-security-policy",
|
||||
"05-flannel",
|
||||
"11-core-dns",
|
||||
"11-core-dns-svc",
|
||||
"11-kube-config-in-cluster",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ManifestSuite) TestReconcileKubeProxyExtraArgs() {
|
||||
@ -185,27 +192,37 @@ func (suite *ManifestSuite) TestReconcileKubeProxyExtraArgs() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, rootSecrets))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertManifests(
|
||||
[]string{
|
||||
"00-kubelet-bootstrapping-token",
|
||||
"01-csr-approver-role-binding",
|
||||
"01-csr-node-bootstrap",
|
||||
"01-csr-renewal-role-binding",
|
||||
"02-kube-system-sa-role-binding",
|
||||
"03-default-pod-security-policy",
|
||||
"05-flannel",
|
||||
"10-kube-proxy",
|
||||
"11-core-dns",
|
||||
"11-core-dns-svc",
|
||||
"11-kube-config-in-cluster",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertManifests(
|
||||
[]string{
|
||||
"00-kubelet-bootstrapping-token",
|
||||
"01-csr-approver-role-binding",
|
||||
"01-csr-node-bootstrap",
|
||||
"01-csr-renewal-role-binding",
|
||||
"02-kube-system-sa-role-binding",
|
||||
"03-default-pod-security-policy",
|
||||
"05-flannel",
|
||||
"10-kube-proxy",
|
||||
"11-core-dns",
|
||||
"11-core-dns-svc",
|
||||
"11-kube-config-in-cluster",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.ControlPlaneNamespaceName, k8s.ManifestType, "10-kube-proxy", resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.ControlPlaneNamespaceName,
|
||||
k8s.ManifestType,
|
||||
"10-kube-proxy",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
manifest := r.(*k8s.Manifest) //nolint:errcheck,forcetypeassert
|
||||
@ -230,24 +247,26 @@ func (suite *ManifestSuite) TestReconcileDisablePSP() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, rootSecrets))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertManifests(
|
||||
[]string{
|
||||
"00-kubelet-bootstrapping-token",
|
||||
"01-csr-approver-role-binding",
|
||||
"01-csr-node-bootstrap",
|
||||
"01-csr-renewal-role-binding",
|
||||
"02-kube-system-sa-role-binding",
|
||||
"05-flannel",
|
||||
"10-kube-proxy",
|
||||
"11-core-dns",
|
||||
"11-core-dns-svc",
|
||||
"11-kube-config-in-cluster",
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertManifests(
|
||||
[]string{
|
||||
"00-kubelet-bootstrapping-token",
|
||||
"01-csr-approver-role-binding",
|
||||
"01-csr-node-bootstrap",
|
||||
"01-csr-renewal-role-binding",
|
||||
"02-kube-system-sa-role-binding",
|
||||
"05-flannel",
|
||||
"10-kube-proxy",
|
||||
"11-core-dns",
|
||||
"11-core-dns-svc",
|
||||
"11-kube-config-in-cluster",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ManifestSuite) TearDownTest() {
|
||||
|
@ -37,7 +37,7 @@ type NodeIPConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -70,109 +70,139 @@ func (suite *NodeIPConfigSuite) TestReconcileWithSubnets() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||
KubeletNodeIP: v1alpha1.KubeletNodeIPConfig{
|
||||
KubeletNodeIPValidSubnets: []string{"10.0.0.0/24"},
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||
KubeletNodeIP: v1alpha1.KubeletNodeIPConfig{
|
||||
KubeletNodeIPValidSubnets: []string{"10.0.0.0/24"},
|
||||
},
|
||||
},
|
||||
},
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "1.2.3.4",
|
||||
},
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 100,
|
||||
VlanVIP: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "5.6.7.8",
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "1.2.3.4",
|
||||
},
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 100,
|
||||
VlanVIP: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "5.6.7.8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
ServiceSubnet: []string{constants.DefaultIPv4ServiceNet},
|
||||
PodSubnet: []string{constants.DefaultIPv4PodNet},
|
||||
},
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
ServiceSubnet: []string{constants.DefaultIPv4ServiceNet},
|
||||
PodSubnet: []string{constants.DefaultIPv4PodNet},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
NodeIPConfig, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPConfigType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
NodeIPConfig, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.NamespaceName,
|
||||
k8s.NodeIPConfigType,
|
||||
k8s.KubeletID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := NodeIPConfig.(*k8s.NodeIPConfig).TypedSpec()
|
||||
|
||||
spec := NodeIPConfig.(*k8s.NodeIPConfig).TypedSpec()
|
||||
suite.Assert().Equal([]string{"10.0.0.0/24"}, spec.ValidSubnets)
|
||||
suite.Assert().Equal(
|
||||
[]string{"10.244.0.0/16", "10.96.0.0/12", "1.2.3.4", "5.6.7.8"},
|
||||
spec.ExcludeSubnets,
|
||||
)
|
||||
|
||||
suite.Assert().Equal([]string{"10.0.0.0/24"}, spec.ValidSubnets)
|
||||
suite.Assert().Equal([]string{"10.244.0.0/16", "10.96.0.0/12", "1.2.3.4", "5.6.7.8"}, spec.ExcludeSubnets)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *NodeIPConfigSuite) TestReconcileDefaults() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
ServiceSubnet: []string{constants.DefaultIPv4ServiceNet, constants.DefaultIPv6ServiceNet},
|
||||
PodSubnet: []string{constants.DefaultIPv4PodNet, constants.DefaultIPv6PodNet},
|
||||
},
|
||||
},
|
||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||
ServiceSubnet: []string{constants.DefaultIPv4ServiceNet, constants.DefaultIPv6ServiceNet},
|
||||
PodSubnet: []string{constants.DefaultIPv4PodNet, constants.DefaultIPv6PodNet},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
NodeIPConfig, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPConfigType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
NodeIPConfig, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
k8s.NamespaceName,
|
||||
k8s.NodeIPConfigType,
|
||||
k8s.KubeletID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := NodeIPConfig.(*k8s.NodeIPConfig).TypedSpec()
|
||||
|
||||
spec := NodeIPConfig.(*k8s.NodeIPConfig).TypedSpec()
|
||||
suite.Assert().Equal([]string{"0.0.0.0/0", "::/0"}, spec.ValidSubnets)
|
||||
suite.Assert().Equal(
|
||||
[]string{"10.244.0.0/16", "fc00:db8:10::/56", "10.96.0.0/12", "fc00:db8:20::/112"},
|
||||
spec.ExcludeSubnets,
|
||||
)
|
||||
|
||||
suite.Assert().Equal([]string{"0.0.0.0/0", "::/0"}, spec.ValidSubnets)
|
||||
suite.Assert().Equal([]string{"10.244.0.0/16", "fc00:db8:10::/56", "10.96.0.0/12", "fc00:db8:20::/112"}, spec.ExcludeSubnets)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *NodeIPConfigSuite) TearDownTest() {
|
||||
|
@ -36,7 +36,7 @@ type NodeIPSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -75,7 +75,10 @@ func (suite *NodeIPSuite) TestReconcileIPv4() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
addresses := network.NewNodeAddress(network.NamespaceName, network.FilteredNodeAddressID(network.NodeAddressCurrentID, k8s.NodeAddressFilterNoK8s))
|
||||
addresses := network.NewNodeAddress(
|
||||
network.NamespaceName,
|
||||
network.FilteredNodeAddressID(network.NodeAddressCurrentID, k8s.NodeAddressFilterNoK8s),
|
||||
)
|
||||
|
||||
addresses.TypedSpec().Addresses = []netaddr.IPPrefix{
|
||||
netaddr.MustParseIPPrefix("10.0.0.2/32"), // excluded explicitly
|
||||
@ -85,24 +88,29 @@ func (suite *NodeIPSuite) TestReconcileIPv4() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, addresses))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
NodeIP, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
NodeIP, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPType, k8s.KubeletID, resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := NodeIP.(*k8s.NodeIP).TypedSpec()
|
||||
|
||||
spec := NodeIP.(*k8s.NodeIP).TypedSpec()
|
||||
suite.Assert().Equal("[10.0.0.5]", fmt.Sprintf("%s", spec.Addresses))
|
||||
|
||||
suite.Assert().Equal("[10.0.0.5]", fmt.Sprintf("%s", spec.Addresses))
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *NodeIPSuite) TestReconcileDefaultSubnets() {
|
||||
@ -114,7 +122,10 @@ func (suite *NodeIPSuite) TestReconcileDefaultSubnets() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
addresses := network.NewNodeAddress(network.NamespaceName, network.FilteredNodeAddressID(network.NodeAddressCurrentID, k8s.NodeAddressFilterNoK8s))
|
||||
addresses := network.NewNodeAddress(
|
||||
network.NamespaceName,
|
||||
network.FilteredNodeAddressID(network.NodeAddressCurrentID, k8s.NodeAddressFilterNoK8s),
|
||||
)
|
||||
|
||||
addresses.TypedSpec().Addresses = []netaddr.IPPrefix{
|
||||
netaddr.MustParseIPPrefix("10.0.0.5/24"),
|
||||
@ -125,24 +136,29 @@ func (suite *NodeIPSuite) TestReconcileDefaultSubnets() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, addresses))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
NodeIP, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPType, k8s.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
NodeIP, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPType, k8s.KubeletID, resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := NodeIP.(*k8s.NodeIP).TypedSpec()
|
||||
|
||||
spec := NodeIP.(*k8s.NodeIP).TypedSpec()
|
||||
suite.Assert().Equal("[10.0.0.5 2001:db8:85a3::8a2e:370:7334]", fmt.Sprintf("%s", spec.Addresses))
|
||||
|
||||
suite.Assert().Equal("[10.0.0.5 2001:db8:85a3::8a2e:370:7334]", fmt.Sprintf("%s", spec.Addresses))
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *NodeIPSuite) TearDownTest() {
|
||||
|
@ -38,7 +38,7 @@ type NodenameSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -69,7 +69,10 @@ func (suite *NodenameSuite) startRuntime() {
|
||||
|
||||
//nolint:dupl
|
||||
func (suite *NodenameSuite) assertNodename(expected string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodenameType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(k8s.NamespaceName, k8s.NodenameType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -83,7 +86,11 @@ func (suite *NodenameSuite) assertNodename(expected string) error {
|
||||
}
|
||||
|
||||
if resources.Items[0].(*k8s.Nodename).TypedSpec().Nodename != expected {
|
||||
return retry.ExpectedErrorf("expected %q, got %q", expected, resources.Items[0].(*k8s.Nodename).TypedSpec().Nodename)
|
||||
return retry.ExpectedErrorf(
|
||||
"expected %q, got %q",
|
||||
expected,
|
||||
resources.Items[0].(*k8s.Nodename).TypedSpec().Nodename,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -93,17 +100,19 @@ func (suite *NodenameSuite) TestDefault() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
@ -113,32 +122,36 @@ func (suite *NodenameSuite) TestDefault() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNodename("foo")
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNodename("foo")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *NodenameSuite) TestFQDN() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||
KubeletRegisterWithFQDN: true,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||
KubeletRegisterWithFQDN: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
@ -148,11 +161,13 @@ func (suite *NodenameSuite) TestFQDN() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNodename("foo.bar.ltd")
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNodename("foo.bar.ltd")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *NodenameSuite) TearDownTest() {
|
||||
@ -163,17 +178,26 @@ func (suite *NodenameSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewHostnameStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewHostnameStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestNodenameSuite(t *testing.T) {
|
||||
|
@ -36,7 +36,7 @@ type StaticPodConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -65,7 +65,10 @@ func (suite *StaticPodConfigSuite) startRuntime() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *StaticPodConfigSuite) assertResource(md resource.Metadata, check func(res resource.Resource) error) func() error {
|
||||
func (suite *StaticPodConfigSuite) assertResource(
|
||||
md resource.Metadata,
|
||||
check func(res resource.Resource) error,
|
||||
) func() error {
|
||||
return func() error {
|
||||
r, err := suite.state.Get(suite.ctx, md)
|
||||
if err != nil {
|
||||
@ -96,47 +99,51 @@ func (suite *StaticPodConfigSuite) assertNoResource(md resource.Metadata) func()
|
||||
}
|
||||
|
||||
func (suite *StaticPodConfigSuite) TestReconcile() {
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachinePods: []v1alpha1.Unstructured{
|
||||
{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "pod",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "nginx",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"containers": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "nginx",
|
||||
"image": "nginx",
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachinePods: []v1alpha1.Unstructured{
|
||||
{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "v1",
|
||||
"kind": "pod",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "nginx",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"containers": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "nginx",
|
||||
"image": "nginx",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
*k8s.NewStaticPod(k8s.NamespaceName, "default-nginx").Metadata(),
|
||||
func(res resource.Resource) error {
|
||||
v, ok, err := unstructured.NestedString(res.(*k8s.StaticPod).TypedSpec().Pod, "kind")
|
||||
suite.Require().NoError(err)
|
||||
suite.Assert().True(ok)
|
||||
suite.Assert().Equal("pod", v)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
*k8s.NewStaticPod(k8s.NamespaceName, "default-nginx").Metadata(),
|
||||
func(res resource.Resource) error {
|
||||
v, ok, err := unstructured.NestedString(res.(*k8s.StaticPod).TypedSpec().Pod, "kind")
|
||||
suite.Require().NoError(err)
|
||||
suite.Assert().True(ok)
|
||||
suite.Assert().Equal("pod", v)
|
||||
|
||||
return nil
|
||||
},
|
||||
return nil
|
||||
},
|
||||
),
|
||||
),
|
||||
))
|
||||
)
|
||||
|
||||
// update the pod changing the namespace
|
||||
cfg.Config().Raw().(*v1alpha1.Config).MachineConfig.MachinePods[0].Object["metadata"].(map[string]interface{})["namespace"] = "custom"
|
||||
@ -144,24 +151,32 @@ func (suite *StaticPodConfigSuite) TestReconcile() {
|
||||
cfg.Metadata().BumpVersion()
|
||||
suite.Require().NoError(suite.state.Update(suite.ctx, oldVersion, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResource(
|
||||
*k8s.NewStaticPod(k8s.NamespaceName, "default-nginx").Metadata(),
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResource(
|
||||
*k8s.NewStaticPod(k8s.NamespaceName, "default-nginx").Metadata(),
|
||||
),
|
||||
),
|
||||
))
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
*k8s.NewStaticPod(k8s.NamespaceName, "custom-nginx").Metadata(),
|
||||
func(res resource.Resource) error {
|
||||
v, ok, err := unstructured.NestedString(res.(*k8s.StaticPod).TypedSpec().Pod, "metadata", "namespace")
|
||||
suite.Require().NoError(err)
|
||||
suite.Assert().True(ok)
|
||||
suite.Assert().Equal("custom", v)
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
*k8s.NewStaticPod(k8s.NamespaceName, "custom-nginx").Metadata(),
|
||||
func(res resource.Resource) error {
|
||||
v, ok, err := unstructured.NestedString(
|
||||
res.(*k8s.StaticPod).TypedSpec().Pod,
|
||||
"metadata",
|
||||
"namespace",
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
suite.Assert().True(ok)
|
||||
suite.Assert().Equal("custom", v)
|
||||
|
||||
return nil
|
||||
},
|
||||
return nil
|
||||
},
|
||||
),
|
||||
),
|
||||
))
|
||||
)
|
||||
|
||||
// remove all pods
|
||||
cfg.Config().Raw().(*v1alpha1.Config).MachineConfig.MachinePods = nil
|
||||
@ -169,11 +184,13 @@ func (suite *StaticPodConfigSuite) TestReconcile() {
|
||||
cfg.Metadata().BumpVersion()
|
||||
suite.Require().NoError(suite.state.Update(suite.ctx, oldVersion, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResource(
|
||||
*k8s.NewStaticPod(k8s.NamespaceName, "custom-nginx").Metadata(),
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResource(
|
||||
*k8s.NewStaticPod(k8s.NamespaceName, "custom-nginx").Metadata(),
|
||||
),
|
||||
),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *StaticPodConfigSuite) TearDownTest() {
|
||||
|
@ -33,7 +33,7 @@ type KubeSpanSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -136,10 +136,14 @@ func (suite *KubeSpanSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
@ -40,10 +40,12 @@ func (suite *ManagerSuite) TestDisabled() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResourceType(
|
||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, "", resource.VersionUndefined),
|
||||
)),
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResourceType(
|
||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, "", resource.VersionUndefined),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -114,18 +116,22 @@ func (suite *ManagerSuite) TestReconcile() {
|
||||
mockWireguard := &mockWireguardClient{}
|
||||
mockNfTables := &mockNftablesManager{}
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&kubespanctrl.ManagerController{
|
||||
WireguardClientFactory: func() (kubespanctrl.WireguardClient, error) {
|
||||
return mockWireguard, nil
|
||||
},
|
||||
RulesManagerFactory: func(_, _ int) kubespanctrl.RulesManager {
|
||||
return mockRulesManager{}
|
||||
},
|
||||
NfTablesManagerFactory: func(_, _ uint32) kubespanctrl.NfTablesManager {
|
||||
return mockNfTables
|
||||
},
|
||||
PeerReconcileInterval: time.Second,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&kubespanctrl.ManagerController{
|
||||
WireguardClientFactory: func() (kubespanctrl.WireguardClient, error) {
|
||||
return mockWireguard, nil
|
||||
},
|
||||
RulesManagerFactory: func(_, _ int) kubespanctrl.RulesManager {
|
||||
return mockRulesManager{}
|
||||
},
|
||||
NfTablesManagerFactory: func(_, _ uint32) kubespanctrl.NfTablesManager {
|
||||
return mockNfTables
|
||||
},
|
||||
PeerReconcileInterval: time.Second,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -140,82 +146,116 @@ func (suite *ManagerSuite) TestReconcile() {
|
||||
|
||||
localIdentity := kubespan.NewIdentity(kubespan.NamespaceName, kubespan.LocalIdentity)
|
||||
suite.Require().NoError(kubespanadapter.IdentitySpec(localIdentity.TypedSpec()).GenerateKey())
|
||||
suite.Require().NoError(kubespanadapter.IdentitySpec(localIdentity.TypedSpec()).UpdateAddress("v16UCWpO2iOm82n6F8dGCJ41ZXXBvDrjRDs2su7C_zs=", mac))
|
||||
suite.Require().NoError(
|
||||
kubespanadapter.IdentitySpec(localIdentity.TypedSpec()).UpdateAddress(
|
||||
"v16UCWpO2iOm82n6F8dGCJ41ZXXBvDrjRDs2su7C_zs=",
|
||||
mac,
|
||||
),
|
||||
)
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, localIdentity))
|
||||
|
||||
// initial setup: link should be created without any peers
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.LinkSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
||||
resource.VersionUndefined,
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.LinkSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.LinkSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal(network.ConfigOperator, spec.ConfigLayer)
|
||||
suite.Assert().Equal(constants.KubeSpanLinkName, spec.Name)
|
||||
suite.Assert().Equal(nethelpers.LinkNone, spec.Type)
|
||||
suite.Assert().Equal("wireguard", spec.Kind)
|
||||
suite.Assert().True(spec.Up)
|
||||
suite.Assert().True(spec.Logical)
|
||||
|
||||
suite.Assert().Equal(localIdentity.TypedSpec().PrivateKey, spec.Wireguard.PrivateKey)
|
||||
suite.Assert().Equal(constants.KubeSpanDefaultPort, spec.Wireguard.ListenPort)
|
||||
suite.Assert().Equal(constants.KubeSpanDefaultFirewallMark, spec.Wireguard.FirewallMark)
|
||||
suite.Assert().Len(spec.Wireguard.Peers, 0)
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.LinkSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal(network.ConfigOperator, spec.ConfigLayer)
|
||||
suite.Assert().Equal(constants.KubeSpanLinkName, spec.Name)
|
||||
suite.Assert().Equal(nethelpers.LinkNone, spec.Type)
|
||||
suite.Assert().Equal("wireguard", spec.Kind)
|
||||
suite.Assert().True(spec.Up)
|
||||
suite.Assert().True(spec.Logical)
|
||||
|
||||
suite.Assert().Equal(localIdentity.TypedSpec().PrivateKey, spec.Wireguard.PrivateKey)
|
||||
suite.Assert().Equal(constants.KubeSpanDefaultPort, spec.Wireguard.ListenPort)
|
||||
suite.Assert().Equal(constants.KubeSpanDefaultFirewallMark, spec.Wireguard.FirewallMark)
|
||||
suite.Assert().Len(spec.Wireguard.Peers, 0)
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
))
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.AddressSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.AddressID(constants.KubeSpanLinkName, localIdentity.TypedSpec().Address)),
|
||||
resource.VersionUndefined,
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.AddressSpecType,
|
||||
network.LayeredID(
|
||||
network.ConfigOperator,
|
||||
network.AddressID(constants.KubeSpanLinkName, localIdentity.TypedSpec().Address),
|
||||
),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.AddressSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal(localIdentity.TypedSpec().Address.IP(), spec.Address.IP())
|
||||
suite.Assert().Equal(localIdentity.TypedSpec().Subnet.Bits(), spec.Address.Bits())
|
||||
suite.Assert().Equal(network.ConfigOperator, spec.ConfigLayer)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||
suite.Assert().Equal(nethelpers.AddressFlags(nethelpers.AddressPermanent), spec.Flags)
|
||||
suite.Assert().Equal(constants.KubeSpanLinkName, spec.LinkName)
|
||||
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.AddressSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal(localIdentity.TypedSpec().Address.IP(), spec.Address.IP())
|
||||
suite.Assert().Equal(localIdentity.TypedSpec().Subnet.Bits(), spec.Address.Bits())
|
||||
suite.Assert().Equal(network.ConfigOperator, spec.ConfigLayer)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||
suite.Assert().Equal(nethelpers.AddressFlags(nethelpers.AddressPermanent), spec.Flags)
|
||||
suite.Assert().Equal(constants.KubeSpanLinkName, spec.LinkName)
|
||||
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
))
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResourceIDs(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.RouteSpecType,
|
||||
"",
|
||||
resource.VersionUndefined,
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResourceIDs(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.RouteSpecType,
|
||||
"",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
[]resource.ID{
|
||||
network.LayeredID(
|
||||
network.ConfigOperator,
|
||||
network.RouteID(
|
||||
constants.KubeSpanDefaultRoutingTable,
|
||||
nethelpers.FamilyInet4,
|
||||
netaddr.IPPrefix{},
|
||||
netaddr.IP{},
|
||||
1,
|
||||
),
|
||||
),
|
||||
network.LayeredID(
|
||||
network.ConfigOperator,
|
||||
network.RouteID(
|
||||
constants.KubeSpanDefaultRoutingTable,
|
||||
nethelpers.FamilyInet6,
|
||||
netaddr.IPPrefix{},
|
||||
netaddr.IP{},
|
||||
1,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
[]resource.ID{
|
||||
network.LayeredID(network.ConfigOperator, network.RouteID(constants.KubeSpanDefaultRoutingTable, nethelpers.FamilyInet4, netaddr.IPPrefix{}, netaddr.IP{}, 1)),
|
||||
network.LayeredID(network.ConfigOperator, network.RouteID(constants.KubeSpanDefaultRoutingTable, nethelpers.FamilyInet6, netaddr.IPPrefix{}, netaddr.IP{}, 1)),
|
||||
},
|
||||
),
|
||||
))
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResourceType(
|
||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, "", resource.VersionUndefined),
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResourceType(
|
||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, "", resource.VersionUndefined),
|
||||
),
|
||||
),
|
||||
))
|
||||
)
|
||||
|
||||
// add two peers, they should be added to the wireguard link spec and should be tracked in peer statuses
|
||||
peer1 := kubespan.NewPeerSpec(kubespan.NamespaceName, "3FxU7UuwektMjbyuJBs7i1hDj2rQA6tHnbNB6WrQxww=")
|
||||
@ -246,72 +286,83 @@ func (suite *ManagerSuite) TestReconcile() {
|
||||
key2, err := wgtypes.ParseKey(peer2.Metadata().ID())
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.LinkSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.LinkSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.LinkSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*network.LinkSpec).TypedSpec()
|
||||
|
||||
if len(spec.Wireguard.Peers) != 2 {
|
||||
return retry.ExpectedErrorf("peers not set up yet")
|
||||
if len(spec.Wireguard.Peers) != 2 {
|
||||
return retry.ExpectedErrorf("peers not set up yet")
|
||||
}
|
||||
|
||||
for i, peer := range []*kubespan.PeerSpec{peer1, peer2} {
|
||||
suite.Assert().Equal(peer.Metadata().ID(), spec.Wireguard.Peers[i].PublicKey)
|
||||
suite.Assert().Equal(cfg.TypedSpec().SharedSecret, spec.Wireguard.Peers[i].PresharedKey)
|
||||
suite.Assert().Equal(peer.TypedSpec().AllowedIPs, spec.Wireguard.Peers[i].AllowedIPs)
|
||||
suite.Assert().Equal(peer.TypedSpec().Endpoints[0].String(), spec.Wireguard.Peers[i].Endpoint)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
for _, peer := range []*kubespan.PeerSpec{peer1, peer2} {
|
||||
peer := peer
|
||||
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
kubespan.NamespaceName,
|
||||
kubespan.PeerStatusType,
|
||||
peer.Metadata().ID(),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*kubespan.PeerStatus).TypedSpec()
|
||||
|
||||
suite.Assert().Equal(peer.TypedSpec().Label, spec.Label)
|
||||
suite.Assert().Equal(kubespan.PeerStateUnknown, spec.State)
|
||||
suite.Assert().Equal(peer.TypedSpec().Endpoints[0], spec.Endpoint)
|
||||
suite.Assert().Equal(peer.TypedSpec().Endpoints[0], spec.LastUsedEndpoint)
|
||||
suite.Assert().WithinDuration(time.Now(), spec.LastEndpointChange, 3*time.Second)
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
ipSet := mockNfTables.IPSet()
|
||||
|
||||
if ipSet == nil {
|
||||
return retry.ExpectedErrorf("ipset is nil")
|
||||
}
|
||||
|
||||
for i, peer := range []*kubespan.PeerSpec{peer1, peer2} {
|
||||
suite.Assert().Equal(peer.Metadata().ID(), spec.Wireguard.Peers[i].PublicKey)
|
||||
suite.Assert().Equal(cfg.TypedSpec().SharedSecret, spec.Wireguard.Peers[i].PresharedKey)
|
||||
suite.Assert().Equal(peer.TypedSpec().AllowedIPs, spec.Wireguard.Peers[i].AllowedIPs)
|
||||
suite.Assert().Equal(peer.TypedSpec().Endpoints[0].String(), spec.Wireguard.Peers[i].Endpoint)
|
||||
ranges := fmt.Sprintf("%v", ipSet.Ranges())
|
||||
expected := "[10.244.1.0-10.244.2.255]"
|
||||
|
||||
if ranges != expected {
|
||||
return retry.ExpectedErrorf("ranges %s != expected %s", ranges, expected)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
))
|
||||
|
||||
for _, peer := range []*kubespan.PeerSpec{peer1, peer2} {
|
||||
peer := peer
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, peer.Metadata().ID(), resource.VersionUndefined),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*kubespan.PeerStatus).TypedSpec()
|
||||
|
||||
suite.Assert().Equal(peer.TypedSpec().Label, spec.Label)
|
||||
suite.Assert().Equal(kubespan.PeerStateUnknown, spec.State)
|
||||
suite.Assert().Equal(peer.TypedSpec().Endpoints[0], spec.Endpoint)
|
||||
suite.Assert().Equal(peer.TypedSpec().Endpoints[0], spec.LastUsedEndpoint)
|
||||
suite.Assert().WithinDuration(time.Now(), spec.LastEndpointChange, 3*time.Second)
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
ipSet := mockNfTables.IPSet()
|
||||
|
||||
if ipSet == nil {
|
||||
return retry.ExpectedErrorf("ipset is nil")
|
||||
}
|
||||
|
||||
ranges := fmt.Sprintf("%v", ipSet.Ranges())
|
||||
expected := "[10.244.1.0-10.244.2.255]"
|
||||
|
||||
if ranges != expected {
|
||||
return retry.ExpectedErrorf("ranges %s != expected %s", ranges, expected)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
)
|
||||
|
||||
// update config and disable force routing, nothing should be routed
|
||||
oldVersion := cfg.Metadata().Version()
|
||||
@ -319,76 +370,89 @@ func (suite *ManagerSuite) TestReconcile() {
|
||||
cfg.Metadata().BumpVersion()
|
||||
suite.Require().NoError(suite.state.Update(suite.ctx, oldVersion, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
ipSet := mockNfTables.IPSet()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
ipSet := mockNfTables.IPSet()
|
||||
|
||||
if ipSet == nil {
|
||||
return retry.ExpectedErrorf("ipset is nil")
|
||||
}
|
||||
if ipSet == nil {
|
||||
return retry.ExpectedErrorf("ipset is nil")
|
||||
}
|
||||
|
||||
if len(ipSet.Prefixes()) != 0 {
|
||||
return retry.ExpectedErrorf("expected empty ipset: %v", ipSet.Ranges())
|
||||
}
|
||||
if len(ipSet.Prefixes()) != 0 {
|
||||
return retry.ExpectedErrorf("expected empty ipset: %v", ipSet.Ranges())
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// report up status via wireguard mock
|
||||
mockWireguard.update(&wgtypes.Device{
|
||||
Peers: []wgtypes.Peer{
|
||||
{
|
||||
PublicKey: key1,
|
||||
Endpoint: peer1.TypedSpec().Endpoints[0].UDPAddr(),
|
||||
LastHandshakeTime: time.Now(),
|
||||
},
|
||||
{
|
||||
PublicKey: key2,
|
||||
Endpoint: peer2.TypedSpec().Endpoints[0].UDPAddr(),
|
||||
LastHandshakeTime: time.Now(),
|
||||
mockWireguard.update(
|
||||
&wgtypes.Device{
|
||||
Peers: []wgtypes.Peer{
|
||||
{
|
||||
PublicKey: key1,
|
||||
Endpoint: peer1.TypedSpec().Endpoints[0].UDPAddr(),
|
||||
LastHandshakeTime: time.Now(),
|
||||
},
|
||||
{
|
||||
PublicKey: key2,
|
||||
Endpoint: peer2.TypedSpec().Endpoints[0].UDPAddr(),
|
||||
LastHandshakeTime: time.Now(),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
for _, peer := range []*kubespan.PeerSpec{peer1, peer2} {
|
||||
peer := peer
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, peer.Metadata().ID(), resource.VersionUndefined),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*kubespan.PeerStatus).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertResource(
|
||||
resource.NewMetadata(
|
||||
kubespan.NamespaceName,
|
||||
kubespan.PeerStatusType,
|
||||
peer.Metadata().ID(),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
func(res resource.Resource) error {
|
||||
spec := res.(*kubespan.PeerStatus).TypedSpec()
|
||||
|
||||
if spec.State != kubespan.PeerStateUp {
|
||||
return retry.ExpectedErrorf("peer state is not up yet: %s", spec.State)
|
||||
}
|
||||
if spec.State != kubespan.PeerStateUp {
|
||||
return retry.ExpectedErrorf("peer state is not up yet: %s", spec.State)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
return nil
|
||||
},
|
||||
),
|
||||
),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
// as the peers are now up, all traffic should be routed via KubeSpan
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
ipSet := mockNfTables.IPSet()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
ipSet := mockNfTables.IPSet()
|
||||
|
||||
if ipSet == nil {
|
||||
return retry.ExpectedErrorf("ipset is nil")
|
||||
}
|
||||
if ipSet == nil {
|
||||
return retry.ExpectedErrorf("ipset is nil")
|
||||
}
|
||||
|
||||
ranges := fmt.Sprintf("%v", ipSet.Ranges())
|
||||
expected := "[10.244.1.0-10.244.2.255]"
|
||||
ranges := fmt.Sprintf("%v", ipSet.Ranges())
|
||||
expected := "[10.244.1.0-10.244.2.255]"
|
||||
|
||||
if ranges != expected {
|
||||
return retry.ExpectedErrorf("ranges %s != expected %s", ranges, expected)
|
||||
}
|
||||
if ranges != expected {
|
||||
return retry.ExpectedErrorf("ranges %s != expected %s", ranges, expected)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// update config and disable wireguard, everything should be cleaned up
|
||||
oldVersion = cfg.Metadata().Version()
|
||||
@ -396,11 +460,18 @@ func (suite *ManagerSuite) TestReconcile() {
|
||||
cfg.Metadata().BumpVersion()
|
||||
suite.Require().NoError(suite.state.Update(suite.ctx, oldVersion, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResource(
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)), resource.VersionUndefined),
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
suite.assertNoResource(
|
||||
resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.LinkSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
),
|
||||
),
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
func TestManagerSuite(t *testing.T) {
|
||||
|
@ -41,7 +41,7 @@ type AddressConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -73,7 +73,10 @@ func (suite *AddressConfigSuite) assertAddresses(requiredIDs []string, check fun
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.AddressSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.AddressSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -103,42 +106,60 @@ func (suite *AddressConfigSuite) TestLoopback() {
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
"default/lo/127.0.0.1/8",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
suite.Assert().Equal("lo", r.TypedSpec().LinkName)
|
||||
suite.Assert().Equal(nethelpers.ScopeHost, r.TypedSpec().Scope)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
"default/lo/127.0.0.1/8",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
suite.Assert().Equal("lo", r.TypedSpec().LinkName)
|
||||
suite.Assert().Equal(nethelpers.ScopeHost, r.TypedSpec().Scope)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *AddressConfigSuite) TestCmdline() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.AddressConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.AddressConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
"cmdline/eth1/172.20.0.2/24",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
"cmdline/eth1/172.20.0.2/24",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *AddressConfigSuite) TestCmdlineNoNetmask() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.AddressConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.AddressConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -160,17 +181,22 @@ func (suite *AddressConfigSuite) TestCmdlineNoNetmask() {
|
||||
|
||||
suite.Assert().NotEmpty(ifaceName)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
fmt.Sprintf("cmdline/%s/172.20.0.2/32", ifaceName),
|
||||
}, func(r *network.AddressSpec) error {
|
||||
suite.Assert().Equal(ifaceName, r.TypedSpec().LinkName)
|
||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
fmt.Sprintf("cmdline/%s/172.20.0.2/32", ifaceName),
|
||||
}, func(r *network.AddressSpec) error {
|
||||
suite.Assert().Equal(ifaceName, r.TypedSpec().LinkName)
|
||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *AddressConfigSuite) TestMachineConfiguration() {
|
||||
@ -181,78 +207,85 @@ func (suite *AddressConfigSuite) TestMachineConfiguration() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceCIDR: "192.168.0.24/28",
|
||||
},
|
||||
{
|
||||
DeviceIgnore: true,
|
||||
DeviceInterface: "eth4",
|
||||
DeviceCIDR: "192.168.0.24/28",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
DeviceCIDR: "2001:470:6d:30e:8ed2:b60c:9d2f:803a/64",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth5",
|
||||
DeviceCIDR: "10.5.0.7",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth6",
|
||||
DeviceAddresses: []string{
|
||||
"10.5.0.8",
|
||||
"2001:470:6d:30e:8ed2:b60c:9d2f:803b/64",
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceCIDR: "192.168.0.24/28",
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 24,
|
||||
VlanCIDR: "10.0.0.1/8",
|
||||
{
|
||||
DeviceIgnore: true,
|
||||
DeviceInterface: "eth4",
|
||||
DeviceCIDR: "192.168.0.24/28",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
DeviceCIDR: "2001:470:6d:30e:8ed2:b60c:9d2f:803a/64",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth5",
|
||||
DeviceCIDR: "10.5.0.7",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth6",
|
||||
DeviceAddresses: []string{
|
||||
"10.5.0.8",
|
||||
"2001:470:6d:30e:8ed2:b60c:9d2f:803b/64",
|
||||
},
|
||||
{
|
||||
VlanID: 25,
|
||||
VlanAddresses: []string{
|
||||
"11.0.0.1/8",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 24,
|
||||
VlanCIDR: "10.0.0.1/8",
|
||||
},
|
||||
{
|
||||
VlanID: 25,
|
||||
VlanAddresses: []string{
|
||||
"11.0.0.1/8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
"configuration/eth2/2001:470:6d:30e:8ed2:b60c:9d2f:803a/64",
|
||||
"configuration/eth3/192.168.0.24/28",
|
||||
"configuration/eth5/10.5.0.7/32",
|
||||
"configuration/eth6/10.5.0.8/32",
|
||||
"configuration/eth6/2001:470:6d:30e:8ed2:b60c:9d2f:803b/64",
|
||||
"configuration/eth0.24/10.0.0.1/8",
|
||||
"configuration/eth0.25/11.0.0.1/8",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
"configuration/eth2/2001:470:6d:30e:8ed2:b60c:9d2f:803a/64",
|
||||
"configuration/eth3/192.168.0.24/28",
|
||||
"configuration/eth5/10.5.0.7/32",
|
||||
"configuration/eth6/10.5.0.8/32",
|
||||
"configuration/eth6/2001:470:6d:30e:8ed2:b60c:9d2f:803b/64",
|
||||
"configuration/eth0.24/10.0.0.1/8",
|
||||
"configuration/eth0.25/11.0.0.1/8",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *AddressConfigSuite) TearDownTest() {
|
||||
@ -263,10 +296,14 @@ func (suite *AddressConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ type AddressEventsSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -67,9 +67,13 @@ func (suite *AddressEventsSuite) SetupTest() {
|
||||
suite.runtime, err = runtime.NewRuntime(suite.state, logging.Wrap(log.Writer()))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&network.AddressEventController{
|
||||
V1Alpha1Events: suite.events,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&network.AddressEventController{
|
||||
V1Alpha1Events: suite.events,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
}
|
||||
@ -92,38 +96,42 @@ func (suite *AddressEventsSuite) TestReconcile() {
|
||||
|
||||
var event *machine.AddressEvent
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
suite.events.messagesMu.Lock()
|
||||
defer suite.events.messagesMu.Unlock()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
suite.events.messagesMu.Lock()
|
||||
defer suite.events.messagesMu.Unlock()
|
||||
|
||||
if len(suite.events.messages) == 0 {
|
||||
return retry.ExpectedError(fmt.Errorf("no events created"))
|
||||
}
|
||||
if len(suite.events.messages) == 0 {
|
||||
return retry.ExpectedError(fmt.Errorf("no events created"))
|
||||
}
|
||||
|
||||
m := suite.events.messages[len(suite.events.messages)-1]
|
||||
m := suite.events.messages[len(suite.events.messages)-1]
|
||||
|
||||
var ok bool
|
||||
var ok bool
|
||||
|
||||
event, ok = m.(*machine.AddressEvent)
|
||||
if !ok {
|
||||
return fmt.Errorf("not an endpoint event")
|
||||
}
|
||||
event, ok = m.(*machine.AddressEvent)
|
||||
if !ok {
|
||||
return fmt.Errorf("not an endpoint event")
|
||||
}
|
||||
|
||||
if event.Hostname == "" {
|
||||
return retry.ExpectedError(fmt.Errorf("expected hostname to be set"))
|
||||
}
|
||||
if event.Hostname == "" {
|
||||
return retry.ExpectedError(fmt.Errorf("expected hostname to be set"))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().Equal(hostname.TypedSpec().Hostname, event.Hostname)
|
||||
suite.Require().Empty(event.Addresses)
|
||||
|
||||
nodeAddress := networkresource.NewNodeAddress(networkresource.NamespaceName, networkresource.FilteredNodeAddressID(
|
||||
networkresource.NodeAddressCurrentID,
|
||||
k8s.NodeAddressFilterNoK8s),
|
||||
nodeAddress := networkresource.NewNodeAddress(
|
||||
networkresource.NamespaceName, networkresource.FilteredNodeAddressID(
|
||||
networkresource.NodeAddressCurrentID,
|
||||
k8s.NodeAddressFilterNoK8s,
|
||||
),
|
||||
)
|
||||
|
||||
addrs := []string{
|
||||
@ -139,31 +147,33 @@ func (suite *AddressEventsSuite) TestReconcile() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodeAddress))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
suite.events.messagesMu.Lock()
|
||||
defer suite.events.messagesMu.Unlock()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
suite.events.messagesMu.Lock()
|
||||
defer suite.events.messagesMu.Unlock()
|
||||
|
||||
if len(suite.events.messages) == 0 {
|
||||
return retry.ExpectedError(fmt.Errorf("no events created"))
|
||||
}
|
||||
if len(suite.events.messages) == 0 {
|
||||
return retry.ExpectedError(fmt.Errorf("no events created"))
|
||||
}
|
||||
|
||||
m := suite.events.messages[len(suite.events.messages)-1]
|
||||
m := suite.events.messages[len(suite.events.messages)-1]
|
||||
|
||||
var ok bool
|
||||
var ok bool
|
||||
|
||||
event, ok = m.(*machine.AddressEvent)
|
||||
if !ok {
|
||||
return fmt.Errorf("not an address event")
|
||||
}
|
||||
event, ok = m.(*machine.AddressEvent)
|
||||
if !ok {
|
||||
return fmt.Errorf("not an address event")
|
||||
}
|
||||
|
||||
if len(event.Addresses) == 0 {
|
||||
return retry.ExpectedError(fmt.Errorf("expected addresses to be set"))
|
||||
}
|
||||
if len(event.Addresses) == 0 {
|
||||
return retry.ExpectedError(fmt.Errorf("expected addresses to be set"))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().Equal(addrs, event.Addresses)
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ type AddressMergeSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -73,7 +73,10 @@ func (suite *AddressMergeSuite) assertAddresses(requiredIDs []string, check func
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.AddressSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.AddressSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -99,7 +102,10 @@ func (suite *AddressMergeSuite) assertAddresses(requiredIDs []string, check func
|
||||
}
|
||||
|
||||
func (suite *AddressMergeSuite) assertNoAddress(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.AddressSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.AddressSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -154,41 +160,54 @@ func (suite *AddressMergeSuite) TestMerge() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
"lo/127.0.0.1/8",
|
||||
"eth0/10.0.0.1/8",
|
||||
"eth0/10.0.0.35/32",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "lo/127.0.0.1/8":
|
||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
||||
case "eth0/10.0.0.1/8":
|
||||
suite.Assert().Equal(*override.TypedSpec(), *r.TypedSpec())
|
||||
case "eth0/10.0.0.35/32":
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
"lo/127.0.0.1/8",
|
||||
"eth0/10.0.0.1/8",
|
||||
"eth0/10.0.0.35/32",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "lo/127.0.0.1/8":
|
||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
||||
case "eth0/10.0.0.1/8":
|
||||
suite.Assert().Equal(*override.TypedSpec(), *r.TypedSpec())
|
||||
case "eth0/10.0.0.35/32":
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
"lo/127.0.0.1/8",
|
||||
"eth0/10.0.0.35/32",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoAddress("eth0/10.0.0.35/32")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
"lo/127.0.0.1/8",
|
||||
"eth0/10.0.0.35/32",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoAddress("eth0/10.0.0.35/32")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
@ -236,50 +255,75 @@ func (suite *AddressMergeSuite) TestMergeFlapping() {
|
||||
|
||||
eg.Go(flipflop(0))
|
||||
eg.Go(flipflop(1))
|
||||
eg.Go(func() error {
|
||||
// add/remove finalizer to the merged resource
|
||||
for i := 0; i < 1000; i++ {
|
||||
if err := suite.state.AddFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.AddressSpecType, "eth0/10.0.0.1/8", resource.VersionUndefined), "foo"); err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
return err
|
||||
eg.Go(
|
||||
func() error {
|
||||
// add/remove finalizer to the merged resource
|
||||
for i := 0; i < 1000; i++ {
|
||||
if err := suite.state.AddFinalizer(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.AddressSpecType,
|
||||
"eth0/10.0.0.1/8",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
"foo",
|
||||
); err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
suite.T().Log("finalizer added")
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
suite.T().Log("finalizer added")
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
if err := suite.state.RemoveFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.AddressSpecType, "eth0/10.0.0.1/8", resource.VersionUndefined), "foo"); err != nil {
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return err
|
||||
if err := suite.state.RemoveFinalizer(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.AddressSpecType,
|
||||
"eth0/10.0.0.1/8",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
"foo",
|
||||
); err != nil {
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(eg.Wait())
|
||||
|
||||
suite.Assert().NoError(retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
"eth0/10.0.0.1/8",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
"eth0/10.0.0.1/8",
|
||||
}, func(r *network.AddressSpec) error {
|
||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
||||
}
|
||||
|
||||
if *override.TypedSpec() != *r.TypedSpec() {
|
||||
// using retry here, as it might not be reconciled immediately
|
||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||
}
|
||||
if *override.TypedSpec() != *r.TypedSpec() {
|
||||
// using retry here, as it might not be reconciled immediately
|
||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *AddressMergeSuite) TearDownTest() {
|
||||
@ -290,7 +334,12 @@ func (suite *AddressMergeSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewAddressSpec(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewAddressSpec(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestAddressMergeSuite(t *testing.T) {
|
||||
|
@ -146,7 +146,8 @@ func findAddress(addrs []rtnetlink.AddressMessage, linkIndex uint32, ipPrefix ne
|
||||
|
||||
//nolint:gocyclo
|
||||
func (ctrl *AddressSpecController) syncAddress(ctx context.Context, r controller.Runtime, logger *zap.Logger, conn *rtnetlink.Conn,
|
||||
links []rtnetlink.LinkMessage, addrs []rtnetlink.AddressMessage, address *network.AddressSpec) error {
|
||||
links []rtnetlink.LinkMessage, addrs []rtnetlink.AddressMessage, address *network.AddressSpec,
|
||||
) error {
|
||||
linkIndex := resolveLinkName(links, address.TypedSpec().LinkName)
|
||||
|
||||
switch address.Metadata().Phase() {
|
||||
|
@ -40,7 +40,7 @@ type AddressSpecSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -144,10 +144,13 @@ func (suite *AddressSpecSuite) TestLoopback() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinkAddress("lo", "127.11.0.1/32")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinkAddress("lo", "127.11.0.1/32")
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the address
|
||||
for {
|
||||
@ -191,26 +194,33 @@ func (suite *AddressSpecSuite) TestDummy() {
|
||||
}
|
||||
|
||||
// create dummy interface
|
||||
suite.Require().NoError(conn.Link.New(&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Attributes: &rtnetlink.LinkAttributes{
|
||||
Name: dummyInterface,
|
||||
MTU: 1400,
|
||||
Info: &rtnetlink.LinkInfo{
|
||||
Kind: "dummy",
|
||||
suite.Require().NoError(
|
||||
conn.Link.New(
|
||||
&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Attributes: &rtnetlink.LinkAttributes{
|
||||
Name: dummyInterface,
|
||||
MTU: 1400,
|
||||
Info: &rtnetlink.LinkInfo{
|
||||
Kind: "dummy",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
),
|
||||
)
|
||||
|
||||
iface, err := net.InterfaceByName(dummyInterface)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
defer conn.Link.Delete(uint32(iface.Index)) //nolint:errcheck
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinkAddress(dummyInterface, "10.0.0.1/8")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinkAddress(dummyInterface, "10.0.0.1/8")
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// delete dummy interface, address should be unassigned automatically
|
||||
suite.Require().NoError(conn.Link.Delete(uint32(iface.Index)))
|
||||
@ -236,7 +246,12 @@ func (suite *AddressSpecSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewAddressSpec(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewAddressSpec(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestAddressSpecSuite(t *testing.T) {
|
||||
|
@ -34,7 +34,7 @@ type AddressStatusSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -70,7 +70,10 @@ func (suite *AddressStatusSuite) assertAddresses(requiredIDs []string, check fun
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.AddressStatusType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.AddressStatusType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -96,12 +99,17 @@ func (suite *AddressStatusSuite) assertAddresses(requiredIDs []string, check fun
|
||||
}
|
||||
|
||||
func (suite *AddressStatusSuite) TestLoopback() {
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{"lo/127.0.0.1/8"}, func(r *network.AddressStatus) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{"lo/127.0.0.1/8"}, func(r *network.AddressStatus) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *AddressStatusSuite) TearDownTest() {
|
||||
|
@ -39,7 +39,7 @@ type EtcFileConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
cfg *config.MachineConfig
|
||||
@ -65,30 +65,32 @@ func (suite *EtcFileConfigSuite) SetupTest() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.cfg = config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
ExtraHostEntries: []*v1alpha1.ExtraHost{
|
||||
{
|
||||
HostIP: "10.0.0.1",
|
||||
HostAliases: []string{"a", "b"},
|
||||
suite.cfg = config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
ExtraHostEntries: []*v1alpha1.ExtraHost{
|
||||
{
|
||||
HostIP: "10.0.0.1",
|
||||
HostAliases: []string{"a", "b"},
|
||||
},
|
||||
{
|
||||
HostIP: "10.0.0.2",
|
||||
HostAliases: []string{"c", "d"},
|
||||
},
|
||||
},
|
||||
{
|
||||
HostIP: "10.0.0.2",
|
||||
HostAliases: []string{"c", "d"},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.defaultAddress = network.NewNodeAddress(network.NamespaceName, network.NodeAddressDefaultID)
|
||||
suite.defaultAddress.TypedSpec().Addresses = []netaddr.IPPrefix{netaddr.MustParseIPPrefix("33.11.22.44/32")}
|
||||
@ -98,7 +100,12 @@ func (suite *EtcFileConfigSuite) SetupTest() {
|
||||
suite.hostnameStatus.TypedSpec().Domainname = "example.com"
|
||||
|
||||
suite.resolverStatus = network.NewResolverStatus(network.NamespaceName, network.ResolverID)
|
||||
suite.resolverStatus.TypedSpec().DNSServers = []netaddr.IP{netaddr.MustParseIP("1.1.1.1"), netaddr.MustParseIP("2.2.2.2"), netaddr.MustParseIP("3.3.3.3"), netaddr.MustParseIP("4.4.4.4")}
|
||||
suite.resolverStatus.TypedSpec().DNSServers = []netaddr.IP{
|
||||
netaddr.MustParseIP("1.1.1.1"),
|
||||
netaddr.MustParseIP("2.2.2.2"),
|
||||
netaddr.MustParseIP("3.3.3.3"),
|
||||
netaddr.MustParseIP("4.4.4.4"),
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *EtcFileConfigSuite) startRuntime() {
|
||||
@ -118,7 +125,10 @@ func (suite *EtcFileConfigSuite) assertEtcFiles(requiredIDs []string, check func
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(files.NamespaceName, files.EtcFileSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(files.NamespaceName, files.EtcFileSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -144,7 +154,10 @@ func (suite *EtcFileConfigSuite) assertEtcFiles(requiredIDs []string, check func
|
||||
}
|
||||
|
||||
func (suite *EtcFileConfigSuite) assertNoEtcFile(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(files.NamespaceName, files.EtcFileSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(files.NamespaceName, files.EtcFileSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -177,41 +190,50 @@ func (suite *EtcFileConfigSuite) testFiles(resources []resource.Resource, resolv
|
||||
unexpectedIds = append(unexpectedIds, "hosts")
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertEtcFiles(
|
||||
expectedIds,
|
||||
func(r *files.EtcFileSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "hosts":
|
||||
suite.Assert().Equal(hosts, string(r.TypedSpec().Contents))
|
||||
case "resolv.conf":
|
||||
suite.Assert().Equal(resolvConf, string(r.TypedSpec().Contents))
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertEtcFiles(
|
||||
expectedIds,
|
||||
func(r *files.EtcFileSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "hosts":
|
||||
suite.Assert().Equal(hosts, string(r.TypedSpec().Contents))
|
||||
case "resolv.conf":
|
||||
suite.Assert().Equal(resolvConf, string(r.TypedSpec().Contents))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
for _, id := range unexpectedIds {
|
||||
id := id
|
||||
|
||||
suite.Assert().NoError(retry.Constant(1*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoEtcFile(id)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(1*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoEtcFile(id)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *EtcFileConfigSuite) TestComplete() {
|
||||
suite.testFiles([]resource.Resource{suite.cfg, suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus},
|
||||
suite.testFiles(
|
||||
[]resource.Resource{suite.cfg, suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus},
|
||||
"nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n\nsearch example.com\n",
|
||||
"127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n\n10.0.0.1 a b \n10.0.0.2 c d ", //nolint:lll
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *EtcFileConfigSuite) TestNoExtraHosts() {
|
||||
suite.testFiles([]resource.Resource{suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus},
|
||||
suite.testFiles(
|
||||
[]resource.Resource{suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus},
|
||||
"nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n\nsearch example.com\n",
|
||||
"127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters",
|
||||
)
|
||||
@ -220,21 +242,24 @@ func (suite *EtcFileConfigSuite) TestNoExtraHosts() {
|
||||
func (suite *EtcFileConfigSuite) TestNoDomainname() {
|
||||
suite.hostnameStatus.TypedSpec().Domainname = ""
|
||||
|
||||
suite.testFiles([]resource.Resource{suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus},
|
||||
suite.testFiles(
|
||||
[]resource.Resource{suite.defaultAddress, suite.hostnameStatus, suite.resolverStatus},
|
||||
"nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n",
|
||||
"127.0.0.1 localhost\n33.11.22.44 foo \n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters",
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *EtcFileConfigSuite) TestOnlyResolvers() {
|
||||
suite.testFiles([]resource.Resource{suite.resolverStatus},
|
||||
suite.testFiles(
|
||||
[]resource.Resource{suite.resolverStatus},
|
||||
"nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n",
|
||||
"",
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *EtcFileConfigSuite) TestOnlyHostname() {
|
||||
suite.testFiles([]resource.Resource{suite.defaultAddress, suite.hostnameStatus},
|
||||
suite.testFiles(
|
||||
[]resource.Resource{suite.defaultAddress, suite.hostnameStatus},
|
||||
"",
|
||||
"127.0.0.1 localhost\n33.11.22.44 foo.example.com foo\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters",
|
||||
)
|
||||
@ -248,19 +273,38 @@ func (suite *EtcFileConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewHostnameStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewResolverStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewNodeAddress(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewHostnameStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewResolverStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewNodeAddress(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestEtcFileConfigSuite(t *testing.T) {
|
||||
|
@ -36,7 +36,7 @@ type HardwareAddrSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ func (suite *HardwareAddrSuite) assertHWAddr(requiredIDs []string, check func(*n
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.HardwareAddrType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.HardwareAddrType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -98,7 +101,10 @@ func (suite *HardwareAddrSuite) assertHWAddr(requiredIDs []string, check func(*n
|
||||
}
|
||||
|
||||
func (suite *HardwareAddrSuite) assertNoHWAddr(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.HardwareAddrType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.HardwareAddrType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -136,37 +142,50 @@ func (suite *HardwareAddrSuite) TestFirst() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, bond0))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, eth1))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHWAddr([]string{network.FirstHardwareAddr}, func(r *network.HardwareAddr) error {
|
||||
if r.TypedSpec().Name != eth1.Metadata().ID() && net.HardwareAddr(r.TypedSpec().HardwareAddr).String() != "6a:2b:bd:b2:fc:e0" {
|
||||
return retry.ExpectedErrorf("should be eth1")
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHWAddr(
|
||||
[]string{network.FirstHardwareAddr}, func(r *network.HardwareAddr) error {
|
||||
if r.TypedSpec().Name != eth1.Metadata().ID() && net.HardwareAddr(r.TypedSpec().HardwareAddr).String() != "6a:2b:bd:b2:fc:e0" {
|
||||
return retry.ExpectedErrorf("should be eth1")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, eth0))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHWAddr([]string{network.FirstHardwareAddr}, func(r *network.HardwareAddr) error {
|
||||
if r.TypedSpec().Name != eth0.Metadata().ID() && net.HardwareAddr(r.TypedSpec().HardwareAddr).String() != "56:a0:a0:87:1c:fa" {
|
||||
return retry.ExpectedErrorf("should be eth0")
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHWAddr(
|
||||
[]string{network.FirstHardwareAddr}, func(r *network.HardwareAddr) error {
|
||||
if r.TypedSpec().Name != eth0.Metadata().ID() && net.HardwareAddr(r.TypedSpec().HardwareAddr).String() != "56:a0:a0:87:1c:fa" {
|
||||
return retry.ExpectedErrorf("should be eth0")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, eth0.Metadata()))
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, eth1.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoHWAddr(network.FirstHardwareAddr)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoHWAddr(network.FirstHardwareAddr)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *HardwareAddrSuite) TearDownTest() {
|
||||
@ -177,7 +196,12 @@ func (suite *HardwareAddrSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewLinkStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewLinkStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHardwareAddrSuite(t *testing.T) {
|
||||
|
@ -40,7 +40,7 @@ type HostnameConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ func (suite *HostnameConfigSuite) assertHostnames(requiredIDs []string, check fu
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.HostnameSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.HostnameSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -98,7 +101,10 @@ func (suite *HostnameConfigSuite) assertHostnames(requiredIDs []string, check fu
|
||||
}
|
||||
|
||||
func (suite *HostnameConfigSuite) assertNoHostname(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.HostnameSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.HostnameSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -122,39 +128,53 @@ func (suite *HostnameConfigSuite) TestDefaults() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, defaultAddress))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames([]string{
|
||||
"default/hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
suite.Assert().Equal("talos-33-11-22-44", r.TypedSpec().Hostname)
|
||||
suite.Assert().Equal("", r.TypedSpec().Domainname)
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames(
|
||||
[]string{
|
||||
"default/hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
suite.Assert().Equal("talos-33-11-22-44", r.TypedSpec().Hostname)
|
||||
suite.Assert().Equal("", r.TypedSpec().Domainname)
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *HostnameConfigSuite) TestCmdline() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.HostnameConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2:172.21.0.1:172.20.0.1:255.255.255.0:master1.domain.tld:eth1::10.0.0.1:10.0.0.2:10.0.0.1"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.HostnameConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2:172.21.0.1:172.20.0.1:255.255.255.0:master1.domain.tld:eth1::10.0.0.1:10.0.0.2:10.0.0.1"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames([]string{
|
||||
"cmdline/hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
suite.Assert().Equal("master1", r.TypedSpec().Hostname)
|
||||
suite.Assert().Equal("domain.tld", r.TypedSpec().Domainname)
|
||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames(
|
||||
[]string{
|
||||
"cmdline/hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
suite.Assert().Equal("master1", r.TypedSpec().Hostname)
|
||||
suite.Assert().Equal("domain.tld", r.TypedSpec().Domainname)
|
||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *HostnameConfigSuite) TestMachineConfiguration() {
|
||||
@ -165,48 +185,63 @@ func (suite *HostnameConfigSuite) TestMachineConfiguration() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkHostname: "foo",
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkHostname: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames([]string{
|
||||
"configuration/hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
suite.Assert().Equal("foo", r.TypedSpec().Hostname)
|
||||
suite.Assert().Equal("", r.TypedSpec().Domainname)
|
||||
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames(
|
||||
[]string{
|
||||
"configuration/hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
suite.Assert().Equal("foo", r.TypedSpec().Hostname)
|
||||
suite.Assert().Equal("", r.TypedSpec().Domainname)
|
||||
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, cfg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineNetwork.NetworkHostname = strings.Repeat("a", 128)
|
||||
_, err = suite.state.UpdateWithConflicts(
|
||||
suite.ctx, cfg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineNetwork.NetworkHostname = strings.Repeat(
|
||||
"a",
|
||||
128,
|
||||
)
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoHostname("configuration/hostname")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoHostname("configuration/hostname")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *HostnameConfigSuite) TearDownTest() {
|
||||
@ -217,17 +252,26 @@ func (suite *HostnameConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewNodeAddress(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewNodeAddress(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHostnameConfigSuite(t *testing.T) {
|
||||
|
@ -34,7 +34,7 @@ type HostnameMergeSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -70,7 +70,10 @@ func (suite *HostnameMergeSuite) assertHostnames(requiredIDs []string, check fun
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.HostnameSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.HostnameSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -126,33 +129,43 @@ func (suite *HostnameMergeSuite) TestMerge() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames([]string{
|
||||
"hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
suite.Assert().Equal("bar.com", r.TypedSpec().FQDN())
|
||||
suite.Assert().Equal("bar", r.TypedSpec().Hostname)
|
||||
suite.Assert().Equal("com", r.TypedSpec().Domainname)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames(
|
||||
[]string{
|
||||
"hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
suite.Assert().Equal("bar.com", r.TypedSpec().FQDN())
|
||||
suite.Assert().Equal("bar", r.TypedSpec().Hostname)
|
||||
suite.Assert().Equal("com", r.TypedSpec().Domainname)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames([]string{
|
||||
"hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
if r.TypedSpec().FQDN() != "eth-0" {
|
||||
return retry.ExpectedErrorf("unexpected hostname %q", r.TypedSpec().FQDN())
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertHostnames(
|
||||
[]string{
|
||||
"hostname",
|
||||
}, func(r *network.HostnameSpec) error {
|
||||
if r.TypedSpec().FQDN() != "eth-0" {
|
||||
return retry.ExpectedErrorf("unexpected hostname %q", r.TypedSpec().FQDN())
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *HostnameMergeSuite) TearDownTest() {
|
||||
@ -163,7 +176,12 @@ func (suite *HostnameMergeSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewHostnameSpec(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewHostnameSpec(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHostnameMergeSuite(t *testing.T) {
|
||||
|
@ -33,7 +33,7 @@ type HostnameSpecSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -47,9 +47,13 @@ func (suite *HostnameSpecSuite) SetupTest() {
|
||||
suite.runtime, err = runtime.NewRuntime(suite.state, logging.Wrap(log.Writer()))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.HostnameSpecController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeContainer, // run in container mode to skip _actually_ setting hostname
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.HostnameSpecController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeContainer, // run in container mode to skip _actually_ setting hostname
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
}
|
||||
@ -65,7 +69,10 @@ func (suite *HostnameSpecSuite) startRuntime() {
|
||||
}
|
||||
|
||||
func (suite *HostnameSpecSuite) assertStatus(id string, fqdn string) error {
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(network.NamespaceName, network.HostnameStatusType, id, resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.HostnameStatusType, id, resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
@ -95,10 +102,13 @@ func (suite *HostnameSpecSuite) TestSpec() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus("hostname", "foo.bar")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus("hostname", "foo.bar")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *HostnameSpecSuite) TearDownTest() {
|
||||
@ -109,7 +119,12 @@ func (suite *HostnameSpecSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewHostnameSpec(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewHostnameSpec(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHostnameSpecSuite(t *testing.T) {
|
||||
|
@ -40,7 +40,7 @@ type LinkConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ func (suite *LinkConfigSuite) assertLinks(requiredIDs []string, check func(*netw
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -104,7 +107,10 @@ func (suite *LinkConfigSuite) assertNoLinks(unexpectedIDs []string) error {
|
||||
unexpIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -124,41 +130,55 @@ func (suite *LinkConfigSuite) TestLoopback() {
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"default/lo",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal("lo", r.TypedSpec().Name)
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().False(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"default/lo",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal("lo", r.TypedSpec().Name)
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().False(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkConfigSuite) TestCmdline() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.LinkConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"cmdline/eth1",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().Name)
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().False(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"cmdline/eth1",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().Name)
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().False(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkConfigSuite) TestMachineConfiguration() {
|
||||
@ -169,67 +189,69 @@ func (suite *LinkConfigSuite) TestMachineConfiguration() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 24,
|
||||
VlanMTU: 1000,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.1/8",
|
||||
},
|
||||
},
|
||||
{
|
||||
VlanID: 48,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.2/8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceMTU: 9001,
|
||||
},
|
||||
{
|
||||
DeviceIgnore: true,
|
||||
DeviceInterface: "eth2",
|
||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "bond0",
|
||||
DeviceBond: &v1alpha1.Bond{
|
||||
BondInterfaces: []string{"eth2", "eth3"},
|
||||
BondMode: "balance-xor",
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "dummy0",
|
||||
DeviceDummy: true,
|
||||
},
|
||||
{
|
||||
DeviceInterface: "wireguard0",
|
||||
DeviceWireguardConfig: &v1alpha1.DeviceWireguardConfig{
|
||||
WireguardPrivateKey: "ABC",
|
||||
WireguardPeers: []*v1alpha1.DeviceWireguardPeer{
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
WireguardPublicKey: "DEF",
|
||||
WireguardEndpoint: "10.0.0.1:3000",
|
||||
WireguardAllowedIPs: []string{
|
||||
"10.2.3.0/24",
|
||||
"10.2.4.0/24",
|
||||
VlanID: 24,
|
||||
VlanMTU: 1000,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.1/8",
|
||||
},
|
||||
},
|
||||
{
|
||||
VlanID: 48,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.2/8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceMTU: 9001,
|
||||
},
|
||||
{
|
||||
DeviceIgnore: true,
|
||||
DeviceInterface: "eth2",
|
||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "bond0",
|
||||
DeviceBond: &v1alpha1.Bond{
|
||||
BondInterfaces: []string{"eth2", "eth3"},
|
||||
BondMode: "balance-xor",
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "dummy0",
|
||||
DeviceDummy: true,
|
||||
},
|
||||
{
|
||||
DeviceInterface: "wireguard0",
|
||||
DeviceWireguardConfig: &v1alpha1.DeviceWireguardConfig{
|
||||
WireguardPrivateKey: "ABC",
|
||||
WireguardPeers: []*v1alpha1.DeviceWireguardPeer{
|
||||
{
|
||||
WireguardPublicKey: "DEF",
|
||||
WireguardEndpoint: "10.0.0.1:3000",
|
||||
WireguardAllowedIPs: []string{
|
||||
"10.2.3.0/24",
|
||||
"10.2.4.0/24",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -237,98 +259,109 @@ func (suite *LinkConfigSuite) TestMachineConfiguration() {
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"configuration/eth0",
|
||||
"configuration/eth0.24",
|
||||
"configuration/eth0.48",
|
||||
"configuration/eth1",
|
||||
"configuration/eth2",
|
||||
"configuration/eth3",
|
||||
"configuration/bond0",
|
||||
"configuration/dummy0",
|
||||
"configuration/wireguard0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"configuration/eth0",
|
||||
"configuration/eth0.24",
|
||||
"configuration/eth0.48",
|
||||
"configuration/eth1",
|
||||
"configuration/eth2",
|
||||
"configuration/eth3",
|
||||
"configuration/bond0",
|
||||
"configuration/dummy0",
|
||||
"configuration/wireguard0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
||||
|
||||
switch r.TypedSpec().Name {
|
||||
case "eth0", "eth1":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().False(r.TypedSpec().Logical)
|
||||
switch r.TypedSpec().Name {
|
||||
case "eth0", "eth1":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().False(r.TypedSpec().Logical)
|
||||
|
||||
if r.TypedSpec().Name == "eth0" {
|
||||
suite.Assert().EqualValues(0, r.TypedSpec().MTU)
|
||||
} else {
|
||||
suite.Assert().EqualValues(9001, r.TypedSpec().MTU)
|
||||
}
|
||||
case "eth0.24", "eth0.48":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().True(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(nethelpers.LinkEther, r.TypedSpec().Type)
|
||||
suite.Assert().Equal(network.LinkKindVLAN, r.TypedSpec().Kind)
|
||||
suite.Assert().Equal("eth0", r.TypedSpec().ParentName)
|
||||
suite.Assert().Equal(nethelpers.VLANProtocol8021Q, r.TypedSpec().VLAN.Protocol)
|
||||
if r.TypedSpec().Name == "eth0" {
|
||||
suite.Assert().EqualValues(0, r.TypedSpec().MTU)
|
||||
} else {
|
||||
suite.Assert().EqualValues(9001, r.TypedSpec().MTU)
|
||||
}
|
||||
case "eth0.24", "eth0.48":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().True(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(nethelpers.LinkEther, r.TypedSpec().Type)
|
||||
suite.Assert().Equal(network.LinkKindVLAN, r.TypedSpec().Kind)
|
||||
suite.Assert().Equal("eth0", r.TypedSpec().ParentName)
|
||||
suite.Assert().Equal(nethelpers.VLANProtocol8021Q, r.TypedSpec().VLAN.Protocol)
|
||||
|
||||
if r.TypedSpec().Name == "eth0.24" {
|
||||
suite.Assert().EqualValues(24, r.TypedSpec().VLAN.VID)
|
||||
suite.Assert().EqualValues(1000, r.TypedSpec().MTU)
|
||||
} else {
|
||||
suite.Assert().EqualValues(48, r.TypedSpec().VLAN.VID)
|
||||
suite.Assert().EqualValues(0, r.TypedSpec().MTU)
|
||||
}
|
||||
case "eth2", "eth3":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().False(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal("bond0", r.TypedSpec().MasterName)
|
||||
case "bond0":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().True(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(nethelpers.LinkEther, r.TypedSpec().Type)
|
||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
||||
suite.Assert().Equal(nethelpers.BondModeXOR, r.TypedSpec().BondMaster.Mode)
|
||||
suite.Assert().True(r.TypedSpec().BondMaster.UseCarrier)
|
||||
case "wireguard0":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().True(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(nethelpers.LinkNone, r.TypedSpec().Type)
|
||||
suite.Assert().Equal(network.LinkKindWireguard, r.TypedSpec().Kind)
|
||||
suite.Assert().Equal(network.WireguardSpec{
|
||||
PrivateKey: "ABC",
|
||||
Peers: []network.WireguardPeer{
|
||||
{
|
||||
PublicKey: "DEF",
|
||||
Endpoint: "10.0.0.1:3000",
|
||||
AllowedIPs: []netaddr.IPPrefix{
|
||||
netaddr.MustParseIPPrefix("10.2.3.0/24"),
|
||||
netaddr.MustParseIPPrefix("10.2.4.0/24"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, r.TypedSpec().Wireguard)
|
||||
}
|
||||
if r.TypedSpec().Name == "eth0.24" {
|
||||
suite.Assert().EqualValues(24, r.TypedSpec().VLAN.VID)
|
||||
suite.Assert().EqualValues(1000, r.TypedSpec().MTU)
|
||||
} else {
|
||||
suite.Assert().EqualValues(48, r.TypedSpec().VLAN.VID)
|
||||
suite.Assert().EqualValues(0, r.TypedSpec().MTU)
|
||||
}
|
||||
case "eth2", "eth3":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().False(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal("bond0", r.TypedSpec().MasterName)
|
||||
case "bond0":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().True(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(nethelpers.LinkEther, r.TypedSpec().Type)
|
||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
||||
suite.Assert().Equal(nethelpers.BondModeXOR, r.TypedSpec().BondMaster.Mode)
|
||||
suite.Assert().True(r.TypedSpec().BondMaster.UseCarrier)
|
||||
case "wireguard0":
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().True(r.TypedSpec().Logical)
|
||||
suite.Assert().Equal(nethelpers.LinkNone, r.TypedSpec().Type)
|
||||
suite.Assert().Equal(network.LinkKindWireguard, r.TypedSpec().Kind)
|
||||
suite.Assert().Equal(
|
||||
network.WireguardSpec{
|
||||
PrivateKey: "ABC",
|
||||
Peers: []network.WireguardPeer{
|
||||
{
|
||||
PublicKey: "DEF",
|
||||
Endpoint: "10.0.0.1:3000",
|
||||
AllowedIPs: []netaddr.IPPrefix{
|
||||
netaddr.MustParseIPPrefix("10.2.3.0/24"),
|
||||
netaddr.MustParseIPPrefix("10.2.4.0/24"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, r.TypedSpec().Wireguard,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkConfigSuite) TestDefaultUp() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.LinkConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
for _, link := range []string{"eth0", "eth1", "eth2", "eth3", "eth4"} {
|
||||
linkStatus := network.NewLinkStatus(network.NamespaceName, link)
|
||||
@ -341,74 +374,86 @@ func (suite *LinkConfigSuite) TestDefaultUp() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 24,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.1/8",
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 24,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.1/8",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VlanID: 48,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.2/8",
|
||||
{
|
||||
VlanID: 48,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.2/8",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "bond0",
|
||||
DeviceBond: &v1alpha1.Bond{
|
||||
BondInterfaces: []string{
|
||||
"eth3",
|
||||
"eth4",
|
||||
{
|
||||
DeviceInterface: "bond0",
|
||||
DeviceBond: &v1alpha1.Bond{
|
||||
BondInterfaces: []string{
|
||||
"eth3",
|
||||
"eth4",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"default/eth1",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"default/eth1",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().True(r.TypedSpec().Up)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoLinks([]string{
|
||||
"default/eth0",
|
||||
"default/eth2",
|
||||
"default/eth3",
|
||||
"default/eth4",
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoLinks(
|
||||
[]string{
|
||||
"default/eth0",
|
||||
"default/eth2",
|
||||
"default/eth3",
|
||||
"default/eth4",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkConfigSuite) TearDownTest() {
|
||||
@ -419,17 +464,26 @@ func (suite *LinkConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewLinkStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewLinkStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestLinkConfigSuite(t *testing.T) {
|
||||
|
@ -36,7 +36,7 @@ type LinkMergeSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ func (suite *LinkMergeSuite) assertLinks(requiredIDs []string, check func(*netwo
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.LinkSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -98,7 +101,10 @@ func (suite *LinkMergeSuite) assertLinks(requiredIDs []string, check func(*netwo
|
||||
}
|
||||
|
||||
func (suite *LinkMergeSuite) assertNoLinks(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.AddressStatusType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.AddressStatusType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -140,51 +146,64 @@ func (suite *LinkMergeSuite) TestMerge() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"lo",
|
||||
"eth0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "lo":
|
||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
||||
case "eth0":
|
||||
suite.Assert().EqualValues(1500, r.TypedSpec().MTU) // static should override dhcp
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"lo",
|
||||
"eth0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "lo":
|
||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
||||
case "eth0":
|
||||
suite.Assert().EqualValues(1500, r.TypedSpec().MTU) // static should override dhcp
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"lo",
|
||||
"eth0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "lo":
|
||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
||||
case "eth0":
|
||||
// reconcile happens eventually, so give it some time
|
||||
if r.TypedSpec().MTU != 1450 {
|
||||
return retry.ExpectedErrorf("MTU %d != 1450", r.TypedSpec().MTU)
|
||||
}
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"lo",
|
||||
"eth0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "lo":
|
||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
||||
case "eth0":
|
||||
// reconcile happens eventually, so give it some time
|
||||
if r.TypedSpec().MTU != 1450 {
|
||||
return retry.ExpectedErrorf("MTU %d != 1450", r.TypedSpec().MTU)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, loopback.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoLinks("lo")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoLinks("lo")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkMergeSuite) TestMergeLogicalLink() {
|
||||
@ -211,21 +230,26 @@ func (suite *LinkMergeSuite) TestMergeLogicalLink() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"bond0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
if r.TypedSpec().MTU != 1450 {
|
||||
return retry.ExpectedErrorf("not merged yet")
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"bond0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
if r.TypedSpec().MTU != 1450 {
|
||||
return retry.ExpectedErrorf("not merged yet")
|
||||
}
|
||||
|
||||
suite.Assert().True(r.TypedSpec().Logical)
|
||||
suite.Assert().EqualValues(1450, r.TypedSpec().MTU)
|
||||
suite.Assert().True(r.TypedSpec().Logical)
|
||||
suite.Assert().EqualValues(1450, r.TypedSpec().MTU)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
@ -271,49 +295,74 @@ func (suite *LinkMergeSuite) TestMergeFlapping() {
|
||||
|
||||
eg.Go(flipflop(0))
|
||||
eg.Go(flipflop(1))
|
||||
eg.Go(func() error {
|
||||
// add/remove finalizer to the merged resource
|
||||
for i := 0; i < 1000; i++ {
|
||||
if err := suite.state.AddFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkSpecType, "eth0", resource.VersionUndefined), "foo"); err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
return err
|
||||
eg.Go(
|
||||
func() error {
|
||||
// add/remove finalizer to the merged resource
|
||||
for i := 0; i < 1000; i++ {
|
||||
if err := suite.state.AddFinalizer(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.LinkSpecType,
|
||||
"eth0",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
"foo",
|
||||
); err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
suite.T().Log("finalizer added")
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
suite.T().Log("finalizer added")
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
if err := suite.state.RemoveFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkSpecType, "eth0", resource.VersionUndefined), "foo"); err != nil {
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return err
|
||||
if err := suite.state.RemoveFinalizer(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.LinkSpecType,
|
||||
"eth0",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
"foo",
|
||||
); err != nil {
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(eg.Wait())
|
||||
|
||||
suite.Assert().NoError(retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"eth0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"eth0",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
||||
}
|
||||
|
||||
if r.TypedSpec().MTU != 1500 {
|
||||
return retry.ExpectedErrorf("MTU %d != 1500", r.TypedSpec().MTU)
|
||||
}
|
||||
if r.TypedSpec().MTU != 1500 {
|
||||
return retry.ExpectedErrorf("MTU %d != 1500", r.TypedSpec().MTU)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkMergeSuite) TestMergeWireguard() {
|
||||
@ -352,41 +401,52 @@ func (suite *LinkMergeSuite) TestMergeWireguard() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks([]string{
|
||||
"kubespan",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal("IG9MqCII7z54Ysof1fQ9a7WcMNG+qNJRMyRCQz3JTUY=", r.TypedSpec().Wireguard.PrivateKey)
|
||||
suite.Assert().Equal(1234, r.TypedSpec().Wireguard.ListenPort)
|
||||
suite.Assert().Len(r.TypedSpec().Wireguard.Peers, 2)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertLinks(
|
||||
[]string{
|
||||
"kubespan",
|
||||
}, func(r *network.LinkSpec) error {
|
||||
suite.Assert().Equal(
|
||||
"IG9MqCII7z54Ysof1fQ9a7WcMNG+qNJRMyRCQz3JTUY=",
|
||||
r.TypedSpec().Wireguard.PrivateKey,
|
||||
)
|
||||
suite.Assert().Equal(1234, r.TypedSpec().Wireguard.ListenPort)
|
||||
suite.Assert().Len(r.TypedSpec().Wireguard.Peers, 2)
|
||||
|
||||
suite.Assert().Equal(
|
||||
network.WireguardPeer{
|
||||
PublicKey: "RXdQkMTD1Jcxd/Wizr9k8syw8ANs57l5jTormDVHAVs=",
|
||||
Endpoint: "127.0.0.1:1234",
|
||||
suite.Assert().Equal(
|
||||
network.WireguardPeer{
|
||||
PublicKey: "RXdQkMTD1Jcxd/Wizr9k8syw8ANs57l5jTormDVHAVs=",
|
||||
Endpoint: "127.0.0.1:1234",
|
||||
},
|
||||
r.TypedSpec().Wireguard.Peers[0],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(
|
||||
network.WireguardPeer{
|
||||
PublicKey: "bGsc2rOpl6JHd/Pm4fYrIkEABL0ZxW7IlaSyh77IMhw=",
|
||||
Endpoint: "127.0.0.1:9999",
|
||||
},
|
||||
r.TypedSpec().Wireguard.Peers[1],
|
||||
)
|
||||
|
||||
return nil
|
||||
},
|
||||
r.TypedSpec().Wireguard.Peers[0],
|
||||
)
|
||||
|
||||
suite.Assert().Equal(
|
||||
network.WireguardPeer{
|
||||
PublicKey: "bGsc2rOpl6JHd/Pm4fYrIkEABL0ZxW7IlaSyh77IMhw=",
|
||||
Endpoint: "127.0.0.1:9999",
|
||||
},
|
||||
r.TypedSpec().Wireguard.Peers[1],
|
||||
)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, kubespanOperator.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoLinks("kubespan")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoLinks("kubespan")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkMergeSuite) TearDownTest() {
|
||||
@ -397,7 +457,12 @@ func (suite *LinkMergeSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewLinkSpec(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewLinkSpec(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestLinkMergeSuite(t *testing.T) {
|
||||
|
@ -160,7 +160,8 @@ func findLink(links []rtnetlink.LinkMessage, name string) *rtnetlink.LinkMessage
|
||||
//
|
||||
//nolint:gocyclo,cyclop
|
||||
func (ctrl *LinkSpecController) syncLink(ctx context.Context, r controller.Runtime, logger *zap.Logger, conn *rtnetlink.Conn, wgClient *wgctrl.Client,
|
||||
links *[]rtnetlink.LinkMessage, link *network.LinkSpec) error {
|
||||
links *[]rtnetlink.LinkMessage, link *network.LinkSpec,
|
||||
) error {
|
||||
logger = logger.With(zap.String("link", link.TypedSpec().Name))
|
||||
|
||||
switch link.Metadata().Phase() {
|
||||
|
@ -39,7 +39,7 @@ type LinkSpecSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -78,7 +78,10 @@ func (suite *LinkSpecSuite) assertInterfaces(requiredIDs []string, check func(*n
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -104,7 +107,10 @@ func (suite *LinkSpecSuite) assertInterfaces(requiredIDs []string, check func(*n
|
||||
}
|
||||
|
||||
func (suite *LinkSpecSuite) assertNoInterface(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -134,12 +140,17 @@ func (suite *LinkSpecSuite) TestLoopback() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{"lo"}, func(r *network.LinkStatus) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{"lo"}, func(r *network.LinkStatus) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkSpecSuite) TestDummy() {
|
||||
@ -160,22 +171,27 @@ func (suite *LinkSpecSuite) TestDummy() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{dummyInterface}, func(r *network.LinkStatus) error {
|
||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{dummyInterface}, func(r *network.LinkStatus) error {
|
||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up")
|
||||
}
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up")
|
||||
}
|
||||
|
||||
if r.TypedSpec().MTU != 1400 {
|
||||
return retry.ExpectedErrorf("unexpected MTU %d", r.TypedSpec().MTU)
|
||||
}
|
||||
if r.TypedSpec().MTU != 1400 {
|
||||
return retry.ExpectedErrorf("unexpected MTU %d", r.TypedSpec().MTU)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the link
|
||||
for {
|
||||
@ -189,10 +205,13 @@ func (suite *LinkSpecSuite) TestDummy() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(dummyInterface)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(dummyInterface)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
@ -245,49 +264,61 @@ func (suite *LinkSpecSuite) TestVLAN() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{dummyInterface, vlanName1, vlanName2}, func(r *network.LinkStatus) error {
|
||||
switch r.Metadata().ID() {
|
||||
case dummyInterface:
|
||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||
case vlanName1, vlanName2:
|
||||
suite.Assert().Equal(network.LinkKindVLAN, r.TypedSpec().Kind)
|
||||
suite.Assert().Equal(nethelpers.VLANProtocol8021Q, r.TypedSpec().VLAN.Protocol)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{dummyInterface, vlanName1, vlanName2}, func(r *network.LinkStatus) error {
|
||||
switch r.Metadata().ID() {
|
||||
case dummyInterface:
|
||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||
case vlanName1, vlanName2:
|
||||
suite.Assert().Equal(network.LinkKindVLAN, r.TypedSpec().Kind)
|
||||
suite.Assert().Equal(nethelpers.VLANProtocol8021Q, r.TypedSpec().VLAN.Protocol)
|
||||
|
||||
if r.Metadata().ID() == vlanName1 {
|
||||
suite.Assert().EqualValues(2, r.TypedSpec().VLAN.VID)
|
||||
} else {
|
||||
suite.Assert().EqualValues(4, r.TypedSpec().VLAN.VID)
|
||||
}
|
||||
}
|
||||
if r.Metadata().ID() == vlanName1 {
|
||||
suite.Assert().EqualValues(2, r.TypedSpec().VLAN.VID)
|
||||
} else {
|
||||
suite.Assert().EqualValues(4, r.TypedSpec().VLAN.VID)
|
||||
}
|
||||
}
|
||||
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up")
|
||||
}
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// attempt to change VLAN ID
|
||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, vlan1.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkSpec).TypedSpec().VLAN.VID = 42
|
||||
_, err := suite.state.UpdateWithConflicts(
|
||||
suite.ctx, vlan1.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkSpec).TypedSpec().VLAN.VID = 42
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{vlanName1}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().VLAN.VID != 42 {
|
||||
return retry.ExpectedErrorf("vlan ID is not 42: %d", r.TypedSpec().VLAN.VID)
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{vlanName1}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().VLAN.VID != 42 {
|
||||
return retry.ExpectedErrorf("vlan ID is not 42: %d", r.TypedSpec().VLAN.VID)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the links
|
||||
for _, r := range []resource.Resource{vlan1, vlan2, dummy} {
|
||||
@ -303,10 +334,13 @@ func (suite *LinkSpecSuite) TestVLAN() {
|
||||
}
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(dummyInterface)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(dummyInterface)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
@ -362,69 +396,92 @@ func (suite *LinkSpecSuite) TestBond() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{dummy0Name, dummy1Name, bondName}, func(r *network.LinkStatus) error {
|
||||
switch r.Metadata().ID() {
|
||||
case bondName:
|
||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{dummy0Name, dummy1Name, bondName}, func(r *network.LinkStatus) error {
|
||||
switch r.Metadata().ID() {
|
||||
case bondName:
|
||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
||||
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||
}
|
||||
case dummy0Name, dummy1Name:
|
||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||
}
|
||||
case dummy0Name, dummy1Name:
|
||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||
}
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||
}
|
||||
|
||||
if r.TypedSpec().MasterIndex == 0 {
|
||||
return retry.ExpectedErrorf("masterIndex should be non-zero")
|
||||
}
|
||||
}
|
||||
if r.TypedSpec().MasterIndex == 0 {
|
||||
return retry.ExpectedErrorf("masterIndex should be non-zero")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// attempt to change bond type
|
||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, bond.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkSpec).TypedSpec().BondMaster.Mode = nethelpers.BondModeRoundrobin
|
||||
_, err := suite.state.UpdateWithConflicts(
|
||||
suite.ctx, bond.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkSpec).TypedSpec().BondMaster.Mode = nethelpers.BondModeRoundrobin
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{bondName}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().BondMaster.Mode != nethelpers.BondModeRoundrobin {
|
||||
return retry.ExpectedErrorf("bond mode is not %s: %s", nethelpers.BondModeRoundrobin, r.TypedSpec().BondMaster.Mode)
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{bondName}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().BondMaster.Mode != nethelpers.BondModeRoundrobin {
|
||||
return retry.ExpectedErrorf(
|
||||
"bond mode is not %s: %s",
|
||||
nethelpers.BondModeRoundrobin,
|
||||
r.TypedSpec().BondMaster.Mode,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// unslave one of the interfaces
|
||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, dummy0.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkSpec).TypedSpec().MasterName = ""
|
||||
_, err = suite.state.UpdateWithConflicts(
|
||||
suite.ctx, dummy0.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkSpec).TypedSpec().MasterName = ""
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{dummy0Name}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().MasterIndex != 0 {
|
||||
return retry.ExpectedErrorf("iface not unslaved yet")
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{dummy0Name}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().MasterIndex != 0 {
|
||||
return retry.ExpectedErrorf("iface not unslaved yet")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the links
|
||||
for _, r := range []resource.Resource{dummy0, dummy1, bond} {
|
||||
@ -440,10 +497,13 @@ func (suite *LinkSpecSuite) TestBond() {
|
||||
}
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(bondName)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(bondName)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
@ -490,32 +550,37 @@ func (suite *LinkSpecSuite) TestBond8023ad() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(append(dummyNames, bondName), func(r *network.LinkStatus) error {
|
||||
if r.Metadata().ID() == bondName {
|
||||
// master
|
||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
append(dummyNames, bondName), func(r *network.LinkStatus) error {
|
||||
if r.Metadata().ID() == bondName {
|
||||
// master
|
||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
||||
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||
}
|
||||
} else {
|
||||
// slaves
|
||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||
}
|
||||
} else {
|
||||
// slaves
|
||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||
}
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||
}
|
||||
|
||||
if r.TypedSpec().MasterIndex == 0 {
|
||||
return retry.ExpectedErrorf("masterIndex should be non-zero")
|
||||
}
|
||||
}
|
||||
if r.TypedSpec().MasterIndex == 0 {
|
||||
return retry.ExpectedErrorf("masterIndex should be non-zero")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the links
|
||||
for _, r := range append(dummies, bond) {
|
||||
@ -531,10 +596,13 @@ func (suite *LinkSpecSuite) TestBond8023ad() {
|
||||
}
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(bondName)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(bondName)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkSpecSuite) TestWireguard() {
|
||||
@ -583,48 +651,60 @@ func (suite *LinkSpecSuite) TestWireguard() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{wgInterface}, func(r *network.LinkStatus) error {
|
||||
suite.Assert().Equal("wireguard", r.TypedSpec().Kind)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{wgInterface}, func(r *network.LinkStatus) error {
|
||||
suite.Assert().Equal("wireguard", r.TypedSpec().Kind)
|
||||
|
||||
if r.TypedSpec().Wireguard.PublicKey != priv.PublicKey().String() {
|
||||
return retry.ExpectedErrorf("private key not set")
|
||||
}
|
||||
if r.TypedSpec().Wireguard.PublicKey != priv.PublicKey().String() {
|
||||
return retry.ExpectedErrorf("private key not set")
|
||||
}
|
||||
|
||||
if len(r.TypedSpec().Wireguard.Peers) != 2 {
|
||||
return retry.ExpectedErrorf("peers are not set up")
|
||||
}
|
||||
if len(r.TypedSpec().Wireguard.Peers) != 2 {
|
||||
return retry.ExpectedErrorf("peers are not set up")
|
||||
}
|
||||
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up")
|
||||
}
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||
return retry.ExpectedErrorf("link is not up")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// attempt to change wireguard private key
|
||||
priv2, err := wgtypes.GeneratePrivateKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, wg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkSpec).TypedSpec().Wireguard.PrivateKey = priv2.String()
|
||||
_, err = suite.state.UpdateWithConflicts(
|
||||
suite.ctx, wg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkSpec).TypedSpec().Wireguard.PrivateKey = priv2.String()
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{wgInterface}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().Wireguard.PublicKey != priv2.PublicKey().String() {
|
||||
return retry.ExpectedErrorf("private key was not updated")
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{wgInterface}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().Wireguard.PublicKey != priv2.PublicKey().String() {
|
||||
return retry.ExpectedErrorf("private key was not updated")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the links
|
||||
for _, r := range []resource.Resource{wg} {
|
||||
@ -640,10 +720,13 @@ func (suite *LinkSpecSuite) TestWireguard() {
|
||||
}
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(wgInterface)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(wgInterface)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkSpecSuite) TearDownTest() {
|
||||
|
@ -39,7 +39,7 @@ type LinkStatusSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -79,7 +79,10 @@ func (suite *LinkStatusSuite) assertInterfaces(requiredIDs []string, check func(
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -105,7 +108,10 @@ func (suite *LinkStatusSuite) assertInterfaces(requiredIDs []string, check func(
|
||||
}
|
||||
|
||||
func (suite *LinkStatusSuite) assertNoInterface(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -120,15 +126,20 @@ func (suite *LinkStatusSuite) assertNoInterface(id string) error {
|
||||
}
|
||||
|
||||
func (suite *LinkStatusSuite) TestLoopbackInterface() {
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{"lo"}, func(r *network.LinkStatus) error {
|
||||
suite.Assert().Equal("loopback", r.TypedSpec().Type.String())
|
||||
suite.Assert().EqualValues(65536, r.TypedSpec().MTU)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{"lo"}, func(r *network.LinkStatus) error {
|
||||
suite.Assert().Equal("loopback", r.TypedSpec().Type.String())
|
||||
suite.Assert().EqualValues(65536, r.TypedSpec().MTU)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkStatusSuite) TestDummyInterface() {
|
||||
@ -139,57 +150,83 @@ func (suite *LinkStatusSuite) TestDummyInterface() {
|
||||
|
||||
defer conn.Close() //nolint:errcheck
|
||||
|
||||
suite.Require().NoError(conn.Link.New(&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Attributes: &rtnetlink.LinkAttributes{
|
||||
Name: dummyInterface,
|
||||
MTU: 1400,
|
||||
Info: &rtnetlink.LinkInfo{
|
||||
Kind: "dummy",
|
||||
suite.Require().NoError(
|
||||
conn.Link.New(
|
||||
&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Attributes: &rtnetlink.LinkAttributes{
|
||||
Name: dummyInterface,
|
||||
MTU: 1400,
|
||||
Info: &rtnetlink.LinkInfo{
|
||||
Kind: "dummy",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
),
|
||||
)
|
||||
|
||||
iface, err := net.InterfaceByName(dummyInterface)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
defer conn.Link.Delete(uint32(iface.Index)) //nolint:errcheck
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{dummyInterface}, func(r *network.LinkStatus) error {
|
||||
suite.Assert().Equal("ether", r.TypedSpec().Type.String())
|
||||
suite.Assert().EqualValues(1400, r.TypedSpec().MTU)
|
||||
suite.Assert().Equal(nethelpers.OperStateDown, r.TypedSpec().OperationalState)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{dummyInterface}, func(r *network.LinkStatus) error {
|
||||
suite.Assert().Equal("ether", r.TypedSpec().Type.String())
|
||||
suite.Assert().EqualValues(1400, r.TypedSpec().MTU)
|
||||
suite.Assert().Equal(nethelpers.OperStateDown, r.TypedSpec().OperationalState)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(conn.Link.Set(&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Index: uint32(iface.Index),
|
||||
Flags: unix.IFF_UP,
|
||||
Change: unix.IFF_UP,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
conn.Link.Set(
|
||||
&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Index: uint32(iface.Index),
|
||||
Flags: unix.IFF_UP,
|
||||
Change: unix.IFF_UP,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces([]string{dummyInterface}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUp && r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
||||
return retry.ExpectedError(fmt.Errorf("operational state is not up: %s", r.TypedSpec().OperationalState))
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertInterfaces(
|
||||
[]string{dummyInterface}, func(r *network.LinkStatus) error {
|
||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUp && r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
||||
return retry.ExpectedError(
|
||||
fmt.Errorf(
|
||||
"operational state is not up: %s",
|
||||
r.TypedSpec().OperationalState,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(conn.Link.Delete(uint32(iface.Index)))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(dummyInterface)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoInterface(dummyInterface)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *LinkStatusSuite) TearDownTest() {
|
||||
@ -200,7 +237,12 @@ func (suite *LinkStatusSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewLinkRefresh(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewLinkRefresh(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestLinkStatusSuite(t *testing.T) {
|
||||
|
@ -39,7 +39,7 @@ type NodeAddressSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -75,7 +75,10 @@ func (suite *NodeAddressSuite) assertAddresses(requiredIDs []string, check func(
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.NodeAddressType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.NodeAddressType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -104,34 +107,43 @@ func (suite *NodeAddressSuite) TestDefaults() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.AddressStatusController{}))
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkStatusController{}))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
network.NodeAddressDefaultID,
|
||||
network.NodeAddressCurrentID,
|
||||
network.NodeAddressAccumulativeID,
|
||||
}, func(r *network.NodeAddress) error {
|
||||
addrs := r.TypedSpec().Addresses
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
network.NodeAddressDefaultID,
|
||||
network.NodeAddressCurrentID,
|
||||
network.NodeAddressAccumulativeID,
|
||||
}, func(r *network.NodeAddress) error {
|
||||
addrs := r.TypedSpec().Addresses
|
||||
|
||||
suite.T().Logf("id %q val %s", r.Metadata().ID(), addrs)
|
||||
suite.T().Logf("id %q val %s", r.Metadata().ID(), addrs)
|
||||
|
||||
suite.Assert().True(sort.SliceIsSorted(addrs, func(i, j int) bool {
|
||||
return addrs[i].IP().Compare(addrs[j].IP()) < 0
|
||||
}), "addresses %s", addrs)
|
||||
suite.Assert().True(
|
||||
sort.SliceIsSorted(
|
||||
addrs, func(i, j int) bool {
|
||||
return addrs[i].IP().Compare(addrs[j].IP()) < 0
|
||||
},
|
||||
), "addresses %s", addrs,
|
||||
)
|
||||
|
||||
if r.Metadata().ID() == network.NodeAddressDefaultID {
|
||||
if len(addrs) != 1 {
|
||||
return fmt.Errorf("there should be only one default address")
|
||||
}
|
||||
} else {
|
||||
if len(addrs) == 0 {
|
||||
return fmt.Errorf("there should be some addresses")
|
||||
}
|
||||
}
|
||||
if r.Metadata().ID() == network.NodeAddressDefaultID {
|
||||
if len(addrs) != 1 {
|
||||
return fmt.Errorf("there should be only one default address")
|
||||
}
|
||||
} else {
|
||||
if len(addrs) == 0 {
|
||||
return fmt.Errorf("there should be some addresses")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
@ -158,17 +170,34 @@ func (suite *NodeAddressSuite) TestFilters() {
|
||||
addressStatus.TypedSpec().Address = addr
|
||||
addressStatus.TypedSpec().LinkName = link.Metadata().ID()
|
||||
addressStatus.TypedSpec().LinkIndex = link.TypedSpec().Index
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, addressStatus, state.WithCreateOwner(addressStatusController.Name())))
|
||||
suite.Require().NoError(
|
||||
suite.state.Create(
|
||||
suite.ctx,
|
||||
addressStatus,
|
||||
state.WithCreateOwner(addressStatusController.Name()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
newExternalAddress := func(addr netaddr.IPPrefix) {
|
||||
addressStatus := network.NewAddressStatus(network.NamespaceName, network.AddressID("external", addr))
|
||||
addressStatus.TypedSpec().Address = addr
|
||||
addressStatus.TypedSpec().LinkName = "external"
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, addressStatus, state.WithCreateOwner(platformConfigController.Name())))
|
||||
suite.Require().NoError(
|
||||
suite.state.Create(
|
||||
suite.ctx,
|
||||
addressStatus,
|
||||
state.WithCreateOwner(platformConfigController.Name()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
for _, addr := range []string{"10.0.0.1/8", "25.3.7.9/32", "2001:470:6d:30e:4a62:b3ba:180b:b5b8/64", "127.0.0.1/8"} {
|
||||
for _, addr := range []string{
|
||||
"10.0.0.1/8",
|
||||
"25.3.7.9/32",
|
||||
"2001:470:6d:30e:4a62:b3ba:180b:b5b8/64",
|
||||
"127.0.0.1/8",
|
||||
} {
|
||||
newAddress(netaddr.MustParseIPPrefix(addr), linkUp)
|
||||
}
|
||||
|
||||
@ -185,56 +214,76 @@ func (suite *NodeAddressSuite) TestFilters() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, filter1))
|
||||
|
||||
filter2 := network.NewNodeAddressFilter(network.NamespaceName, "only-k8s")
|
||||
filter2.TypedSpec().IncludeSubnets = []netaddr.IPPrefix{netaddr.MustParseIPPrefix("10.0.0.0/8"), netaddr.MustParseIPPrefix("192.168.0.0/16")}
|
||||
filter2.TypedSpec().IncludeSubnets = []netaddr.IPPrefix{
|
||||
netaddr.MustParseIPPrefix("10.0.0.0/8"),
|
||||
netaddr.MustParseIPPrefix("192.168.0.0/16"),
|
||||
}
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, filter2))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses([]string{
|
||||
network.NodeAddressDefaultID,
|
||||
network.NodeAddressCurrentID,
|
||||
network.NodeAddressAccumulativeID,
|
||||
network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter1.Metadata().ID()),
|
||||
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter1.Metadata().ID()),
|
||||
network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter2.Metadata().ID()),
|
||||
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter2.Metadata().ID()),
|
||||
}, func(r *network.NodeAddress) error {
|
||||
addrs := r.TypedSpec().Addresses
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertAddresses(
|
||||
[]string{
|
||||
network.NodeAddressDefaultID,
|
||||
network.NodeAddressCurrentID,
|
||||
network.NodeAddressAccumulativeID,
|
||||
network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter1.Metadata().ID()),
|
||||
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter1.Metadata().ID()),
|
||||
network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter2.Metadata().ID()),
|
||||
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter2.Metadata().ID()),
|
||||
}, func(r *network.NodeAddress) error {
|
||||
addrs := r.TypedSpec().Addresses
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case network.NodeAddressDefaultID:
|
||||
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.NodeAddressCurrentID:
|
||||
if !reflect.DeepEqual(addrs, ipList("1.2.3.4/32 10.0.0.1/8 25.3.7.9/32 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.NodeAddressAccumulativeID:
|
||||
if !reflect.DeepEqual(addrs, ipList("1.2.3.4/32 10.0.0.1/8 10.0.0.2/8 25.3.7.9/32 192.168.3.7/24 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter1.Metadata().ID()):
|
||||
if !reflect.DeepEqual(addrs, ipList("1.2.3.4/32 25.3.7.9/32 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter1.Metadata().ID()):
|
||||
if !reflect.DeepEqual(addrs, ipList("1.2.3.4/32 25.3.7.9/32 192.168.3.7/24 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter2.Metadata().ID()):
|
||||
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter2.Metadata().ID()):
|
||||
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8 10.0.0.2/8 192.168.3.7/24")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case network.NodeAddressDefaultID:
|
||||
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.NodeAddressCurrentID:
|
||||
if !reflect.DeepEqual(
|
||||
addrs,
|
||||
ipList("1.2.3.4/32 10.0.0.1/8 25.3.7.9/32 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64"),
|
||||
) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.NodeAddressAccumulativeID:
|
||||
if !reflect.DeepEqual(
|
||||
addrs,
|
||||
ipList("1.2.3.4/32 10.0.0.1/8 10.0.0.2/8 25.3.7.9/32 192.168.3.7/24 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64"),
|
||||
) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter1.Metadata().ID()):
|
||||
if !reflect.DeepEqual(
|
||||
addrs,
|
||||
ipList("1.2.3.4/32 25.3.7.9/32 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64"),
|
||||
) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter1.Metadata().ID()):
|
||||
if !reflect.DeepEqual(
|
||||
addrs,
|
||||
ipList("1.2.3.4/32 25.3.7.9/32 192.168.3.7/24 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64"),
|
||||
) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter2.Metadata().ID()):
|
||||
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
case network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter2.Metadata().ID()):
|
||||
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8 10.0.0.2/8 192.168.3.7/24")) {
|
||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *NodeAddressSuite) TearDownTest() {
|
||||
@ -245,8 +294,18 @@ func (suite *NodeAddressSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewAddressStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewLinkStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewAddressStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewLinkStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestNodeAddressSuite(t *testing.T) {
|
||||
|
@ -40,7 +40,7 @@ type OperatorConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ func (suite *OperatorConfigSuite) assertOperators(requiredIDs []string, check fu
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.OperatorSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.OperatorSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -104,7 +107,10 @@ func (suite *OperatorConfigSuite) assertNoOperators(unexpectedIDs []string) erro
|
||||
unexpIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.OperatorSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.OperatorSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -120,9 +126,13 @@ func (suite *OperatorConfigSuite) assertNoOperators(unexpectedIDs []string) erro
|
||||
}
|
||||
|
||||
func (suite *OperatorConfigSuite) TestDefaultDHCP() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.OperatorConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.OperatorConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -134,32 +144,41 @@ func (suite *OperatorConfigSuite) TestDefaultDHCP() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkStatus))
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators([]string{
|
||||
"default/dhcp4/eth0",
|
||||
"default/dhcp4/eth1",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators(
|
||||
[]string{
|
||||
"default/dhcp4/eth0",
|
||||
"default/dhcp4/eth1",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case "default/dhcp4/eth0":
|
||||
suite.Assert().Equal("eth0", r.TypedSpec().LinkName)
|
||||
case "default/dhcp4/eth1":
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case "default/dhcp4/eth0":
|
||||
suite.Assert().Equal("eth0", r.TypedSpec().LinkName)
|
||||
case "default/dhcp4/eth1":
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorConfigSuite) TestDefaultDHCPCmdline() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.OperatorConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.OperatorConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -171,46 +190,69 @@ func (suite *OperatorConfigSuite) TestDefaultDHCPCmdline() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkStatus))
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators([]string{
|
||||
"default/dhcp4/eth0",
|
||||
"default/dhcp4/eth2",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators(
|
||||
[]string{
|
||||
"default/dhcp4/eth0",
|
||||
"default/dhcp4/eth2",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case "default/dhcp4/eth0":
|
||||
suite.Assert().Equal("eth0", r.TypedSpec().LinkName)
|
||||
case "default/dhcp4/eth2":
|
||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case "default/dhcp4/eth0":
|
||||
suite.Assert().Equal("eth0", r.TypedSpec().LinkName)
|
||||
case "default/dhcp4/eth2":
|
||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// remove link
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "eth2", resource.VersionUndefined)))
|
||||
suite.Require().NoError(
|
||||
suite.state.Destroy(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.LinkStatusType, "eth2", resource.VersionUndefined),
|
||||
),
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoOperators([]string{
|
||||
"default/dhcp4/eth2",
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoOperators(
|
||||
[]string{
|
||||
"default/dhcp4/eth2",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP4() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.OperatorConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth5"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.OperatorConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth5"),
|
||||
},
|
||||
),
|
||||
)
|
||||
// add LinkConfig controller to produce link specs based on machine configuration
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth5"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.LinkConfigController{
|
||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth5"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -225,97 +267,109 @@ func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP4() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceDHCP: true,
|
||||
},
|
||||
{
|
||||
DeviceIgnore: true,
|
||||
DeviceInterface: "eth2",
|
||||
DeviceDHCP: true,
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||
DHCPIPv4: pointer.ToBool(true),
|
||||
DHCPRouteMetric: 256,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth4",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 25,
|
||||
VlanDHCP: true,
|
||||
},
|
||||
{
|
||||
VlanID: 26,
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceDHCP: true,
|
||||
},
|
||||
{
|
||||
DeviceIgnore: true,
|
||||
DeviceInterface: "eth2",
|
||||
DeviceDHCP: true,
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||
DHCPIPv4: pointer.ToBool(true),
|
||||
DHCPRouteMetric: 256,
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth4",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 25,
|
||||
VlanDHCP: true,
|
||||
},
|
||||
{
|
||||
VlanID: 26,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth5",
|
||||
DeviceDHCP: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth5",
|
||||
DeviceDHCP: true,
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators([]string{
|
||||
"configuration/dhcp4/eth1",
|
||||
"configuration/dhcp4/eth3",
|
||||
"configuration/dhcp4/eth4.25",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators(
|
||||
[]string{
|
||||
"configuration/dhcp4/eth1",
|
||||
"configuration/dhcp4/eth3",
|
||||
"configuration/dhcp4/eth4.25",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case "configuration/dhcp4/eth1":
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||
case "configuration/dhcp4/eth3":
|
||||
suite.Assert().Equal("eth3", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(256, r.TypedSpec().DHCP4.RouteMetric)
|
||||
case "configuration/dhcp4/eth4.25":
|
||||
suite.Assert().Equal("eth4.25", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case "configuration/dhcp4/eth1":
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||
case "configuration/dhcp4/eth3":
|
||||
suite.Assert().Equal("eth3", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(256, r.TypedSpec().DHCP4.RouteMetric)
|
||||
case "configuration/dhcp4/eth4.25":
|
||||
suite.Assert().Equal("eth4.25", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoOperators([]string{
|
||||
"configuration/dhcp4/eth0",
|
||||
"default/dhcp4/eth0",
|
||||
"configuration/dhcp4/eth2",
|
||||
"default/dhcp4/eth2",
|
||||
"configuration/dhcp4/eth4.26",
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoOperators(
|
||||
[]string{
|
||||
"configuration/dhcp4/eth0",
|
||||
"default/dhcp4/eth0",
|
||||
"configuration/dhcp4/eth2",
|
||||
"default/dhcp4/eth2",
|
||||
"configuration/dhcp4/eth4.26",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP6() {
|
||||
@ -326,75 +380,87 @@ func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP6() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||
DHCPIPv4: pointer.ToBool(true),
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||
DHCPIPv4: pointer.ToBool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||
DHCPIPv6: pointer.ToBool(true),
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||
DHCPIPv6: pointer.ToBool(true),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||
DHCPIPv6: pointer.ToBool(true),
|
||||
DHCPRouteMetric: 512,
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||
DHCPIPv6: pointer.ToBool(true),
|
||||
DHCPRouteMetric: 512,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators([]string{
|
||||
"configuration/dhcp6/eth2",
|
||||
"configuration/dhcp6/eth3",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorDHCP6, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators(
|
||||
[]string{
|
||||
"configuration/dhcp6/eth2",
|
||||
"configuration/dhcp6/eth3",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorDHCP6, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case "configuration/dhcp6/eth2":
|
||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP6.RouteMetric)
|
||||
case "configuration/dhcp6/eth3":
|
||||
suite.Assert().Equal("eth3", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(512, r.TypedSpec().DHCP6.RouteMetric)
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case "configuration/dhcp6/eth2":
|
||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP6.RouteMetric)
|
||||
case "configuration/dhcp6/eth3":
|
||||
suite.Assert().Equal("eth3", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(512, r.TypedSpec().DHCP6.RouteMetric)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoOperators([]string{
|
||||
"configuration/dhcp6/eth1",
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoOperators(
|
||||
[]string{
|
||||
"configuration/dhcp6/eth1",
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorConfigSuite) TearDownTest() {
|
||||
@ -405,17 +471,26 @@ func (suite *OperatorConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewLinkStatus(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewLinkStatus(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestOperatorConfigSuite(t *testing.T) {
|
||||
|
@ -35,7 +35,7 @@ type OperatorMergeSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -71,7 +71,10 @@ func (suite *OperatorMergeSuite) assertOperators(requiredIDs []string, check fun
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.OperatorSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.OperatorSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -97,7 +100,10 @@ func (suite *OperatorMergeSuite) assertOperators(requiredIDs []string, check fun
|
||||
}
|
||||
|
||||
func (suite *OperatorMergeSuite) assertNoOperator(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.OperatorSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.OperatorSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -139,37 +145,50 @@ func (suite *OperatorMergeSuite) TestMerge() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators([]string{
|
||||
"dhcp4/eth0",
|
||||
"dhcp6/eth0",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "dhcp4/eth0":
|
||||
suite.Assert().Equal(*dhcp2.TypedSpec(), *r.TypedSpec())
|
||||
case "dhcp6/eth0":
|
||||
suite.Assert().Equal(*dhcp6.TypedSpec(), *r.TypedSpec())
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators(
|
||||
[]string{
|
||||
"dhcp4/eth0",
|
||||
"dhcp6/eth0",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "dhcp4/eth0":
|
||||
suite.Assert().Equal(*dhcp2.TypedSpec(), *r.TypedSpec())
|
||||
case "dhcp6/eth0":
|
||||
suite.Assert().Equal(*dhcp6.TypedSpec(), *r.TypedSpec())
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, dhcp6.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators([]string{
|
||||
"dhcp4/eth0",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoOperator("dhcp6/eth0")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators(
|
||||
[]string{
|
||||
"dhcp4/eth0",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoOperator("dhcp6/eth0")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
@ -214,50 +233,75 @@ func (suite *OperatorMergeSuite) TestMergeFlapping() {
|
||||
|
||||
eg.Go(flipflop(0))
|
||||
eg.Go(flipflop(1))
|
||||
eg.Go(func() error {
|
||||
// add/remove finalizer to the merged resource
|
||||
for i := 0; i < 1000; i++ {
|
||||
if err := suite.state.AddFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.OperatorSpecType, "dhcp4/eth0", resource.VersionUndefined), "foo"); err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
return err
|
||||
eg.Go(
|
||||
func() error {
|
||||
// add/remove finalizer to the merged resource
|
||||
for i := 0; i < 1000; i++ {
|
||||
if err := suite.state.AddFinalizer(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.OperatorSpecType,
|
||||
"dhcp4/eth0",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
"foo",
|
||||
); err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
suite.T().Log("finalizer added")
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
suite.T().Log("finalizer added")
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
if err := suite.state.RemoveFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.OperatorSpecType, "dhcp4/eth0", resource.VersionUndefined), "foo"); err != nil {
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return err
|
||||
if err := suite.state.RemoveFinalizer(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.OperatorSpecType,
|
||||
"dhcp4/eth0",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
"foo",
|
||||
); err != nil {
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(eg.Wait())
|
||||
|
||||
suite.Assert().NoError(retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators([]string{
|
||||
"dhcp4/eth0",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators(
|
||||
[]string{
|
||||
"dhcp4/eth0",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
||||
}
|
||||
|
||||
if *override.TypedSpec() != *r.TypedSpec() {
|
||||
// using retry here, as it might not be reconciled immediately
|
||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||
}
|
||||
if *override.TypedSpec() != *r.TypedSpec() {
|
||||
// using retry here, as it might not be reconciled immediately
|
||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorMergeSuite) TearDownTest() {
|
||||
@ -268,7 +312,12 @@ func (suite *OperatorMergeSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewOperatorSpec(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewOperatorSpec(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestOperatorMergeSuite(t *testing.T) {
|
||||
|
@ -37,7 +37,7 @@ type OperatorSpecSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -155,9 +155,13 @@ func (suite *OperatorSpecSuite) SetupTest() {
|
||||
|
||||
runningOperators = map[string]*mockOperator{}
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.OperatorSpecController{
|
||||
Factory: suite.newOperator,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.OperatorSpecController{
|
||||
Factory: suite.newOperator,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
}
|
||||
@ -214,7 +218,10 @@ func (suite *OperatorSpecSuite) assertResources(resourceType resource.Type, requ
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, resourceType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, resourceType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -255,12 +262,17 @@ func (suite *OperatorSpecSuite) TestScheduling() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, specVIP))
|
||||
|
||||
// operators shouldn't be running yet, as link state is not known yet
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(nil, func(op *mockOperator) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(
|
||||
nil, func(op *mockOperator) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
linkState := network.NewLinkStatus(network.NamespaceName, "eth0")
|
||||
*linkState.TypedSpec() = network.LinkStatusSpec{
|
||||
@ -270,79 +282,105 @@ func (suite *OperatorSpecSuite) TestScheduling() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkState))
|
||||
|
||||
// vip operator should be scheduled now, as VIP operator doesn't require link to be up
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning([]string{"vip/eth0"}, func(op *mockOperator) error {
|
||||
suite.Assert().Equal(netaddr.MustParseIP("1.2.3.4"), op.spec.VIP.IP)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(
|
||||
[]string{"vip/eth0"}, func(op *mockOperator) error {
|
||||
suite.Assert().Equal(netaddr.MustParseIP("1.2.3.4"), op.spec.VIP.IP)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateUp
|
||||
_, err := suite.state.UpdateWithConflicts(
|
||||
suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateUp
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// now all operators should be scheduled
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning([]string{"dhcp4/eth0", "vip/eth0"}, func(op *mockOperator) error {
|
||||
switch op.spec.Operator { //nolint:exhaustive
|
||||
case network.OperatorDHCP4:
|
||||
suite.Assert().EqualValues(1024, op.spec.DHCP4.RouteMetric)
|
||||
case network.OperatorVIP:
|
||||
suite.Assert().Equal(netaddr.MustParseIP("1.2.3.4"), op.spec.VIP.IP)
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(
|
||||
[]string{"dhcp4/eth0", "vip/eth0"}, func(op *mockOperator) error {
|
||||
switch op.spec.Operator { //nolint:exhaustive
|
||||
case network.OperatorDHCP4:
|
||||
suite.Assert().EqualValues(1024, op.spec.DHCP4.RouteMetric)
|
||||
case network.OperatorVIP:
|
||||
suite.Assert().Equal(netaddr.MustParseIP("1.2.3.4"), op.spec.VIP.IP)
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// change the spec, operator should be rescheduled
|
||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, specVIP.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.OperatorSpec).TypedSpec().VIP.IP = netaddr.MustParseIP("3.4.5.6")
|
||||
_, err = suite.state.UpdateWithConflicts(
|
||||
suite.ctx, specVIP.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.OperatorSpec).TypedSpec().VIP.IP = netaddr.MustParseIP("3.4.5.6")
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning([]string{"dhcp4/eth0", "vip/eth0"}, func(op *mockOperator) error {
|
||||
switch op.spec.Operator { //nolint:exhaustive
|
||||
case network.OperatorDHCP4:
|
||||
suite.Assert().EqualValues(1024, op.spec.DHCP4.RouteMetric)
|
||||
case network.OperatorVIP:
|
||||
if op.spec.VIP.IP.Compare(netaddr.MustParseIP("3.4.5.6")) != 0 {
|
||||
return retry.ExpectedErrorf("unexpected vip: %s", op.spec.VIP.IP)
|
||||
}
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(
|
||||
[]string{"dhcp4/eth0", "vip/eth0"}, func(op *mockOperator) error {
|
||||
switch op.spec.Operator { //nolint:exhaustive
|
||||
case network.OperatorDHCP4:
|
||||
suite.Assert().EqualValues(1024, op.spec.DHCP4.RouteMetric)
|
||||
case network.OperatorVIP:
|
||||
if op.spec.VIP.IP.Compare(netaddr.MustParseIP("3.4.5.6")) != 0 {
|
||||
return retry.ExpectedErrorf("unexpected vip: %s", op.spec.VIP.IP)
|
||||
}
|
||||
default:
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// bring down the interface, operator should be stopped
|
||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateDown
|
||||
_, err = suite.state.UpdateWithConflicts(
|
||||
suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateDown
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning([]string{"vip/eth0"}, func(op *mockOperator) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(
|
||||
[]string{"vip/eth0"}, func(op *mockOperator) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorSpecSuite) TestPanic() {
|
||||
@ -366,25 +404,35 @@ func (suite *OperatorSpecSuite) TestPanic() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkState))
|
||||
|
||||
// DHCP6 operator should panic and then restart
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning([]string{"dhcp6/eth0"}, func(op *mockOperator) error { return nil })
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning([]string{"dhcp6/eth0"}, func(op *mockOperator) error { return nil })
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// bring down the interface, operator should be stopped
|
||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateDown
|
||||
_, err := suite.state.UpdateWithConflicts(
|
||||
suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateDown
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(nil, func(op *mockOperator) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(
|
||||
nil, func(op *mockOperator) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
||||
@ -407,12 +455,17 @@ func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkState))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning([]string{"dhcp4/eth0"}, func(op *mockOperator) error {
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRunning(
|
||||
[]string{"dhcp4/eth0"}, func(op *mockOperator) error {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// pretend dhcp has some specs ready
|
||||
runningOperatorsMu.Lock()
|
||||
@ -447,18 +500,27 @@ func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
||||
|
||||
dhcpMock.notify()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.AddressSpecType, []string{"dhcp4/eth0/eth0/10.5.0.2/24"})
|
||||
}))
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.LinkSpecType, []string{"dhcp4/eth0/eth0"})
|
||||
}))
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.HostnameSpecType, []string{"dhcp4/eth0/hostname"})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.AddressSpecType, []string{"dhcp4/eth0/eth0/10.5.0.2/24"})
|
||||
},
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.LinkSpecType, []string{"dhcp4/eth0/eth0"})
|
||||
},
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.HostnameSpecType, []string{"dhcp4/eth0/hostname"})
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// update specs
|
||||
dhcpMock.mu.Lock()
|
||||
@ -476,10 +538,13 @@ func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
||||
|
||||
dhcpMock.notify()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.AddressSpecType, []string{"dhcp4/eth0/eth0/10.5.0.3/24"})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.AddressSpecType, []string{"dhcp4/eth0/eth0/10.5.0.3/24"})
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorSpecSuite) TearDownTest() {
|
||||
@ -490,7 +555,12 @@ func (suite *OperatorSpecSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewOperatorSpec(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewOperatorSpec(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestOperatorSpecSuite(t *testing.T) {
|
||||
|
@ -38,7 +38,7 @@ type OperatorVIPConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -63,14 +63,20 @@ func (suite *OperatorVIPConfigSuite) startRuntime() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *OperatorVIPConfigSuite) assertOperators(requiredIDs []string, check func(*network.OperatorSpec) error) error {
|
||||
func (suite *OperatorVIPConfigSuite) assertOperators(
|
||||
requiredIDs []string,
|
||||
check func(*network.OperatorSpec) error,
|
||||
) error {
|
||||
missingIDs := make(map[string]struct{}, len(requiredIDs))
|
||||
|
||||
for _, id := range requiredIDs {
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.OperatorSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.OperatorSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -103,76 +109,86 @@ func (suite *OperatorVIPConfigSuite) TestMachineConfigurationVIP() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceDHCP: true,
|
||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "2.3.4.5",
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceDHCP: true,
|
||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "2.3.4.5",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
DeviceDHCP: true,
|
||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "fd7a:115c:a1e0:ab12:4843:cd96:6277:2302",
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
DeviceDHCP: true,
|
||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "fd7a:115c:a1e0:ab12:4843:cd96:6277:2302",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceDHCP: true,
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 26,
|
||||
VlanVIP: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "5.5.4.4",
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceDHCP: true,
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 26,
|
||||
VlanVIP: &v1alpha1.DeviceVIPConfig{
|
||||
SharedIP: "5.5.4.4",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators([]string{
|
||||
"configuration/vip/eth1",
|
||||
"configuration/vip/eth2",
|
||||
"configuration/vip/eth3.26",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorVIP, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertOperators(
|
||||
[]string{
|
||||
"configuration/vip/eth1",
|
||||
"configuration/vip/eth2",
|
||||
"configuration/vip/eth3.26",
|
||||
}, func(r *network.OperatorSpec) error {
|
||||
suite.Assert().Equal(network.OperatorVIP, r.TypedSpec().Operator)
|
||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case "configuration/vip/eth1":
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netaddr.MustParseIP("2.3.4.5"), r.TypedSpec().VIP.IP)
|
||||
case "configuration/vip/eth2":
|
||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netaddr.MustParseIP("fd7a:115c:a1e0:ab12:4843:cd96:6277:2302"), r.TypedSpec().VIP.IP)
|
||||
case "configuration/vip/eth3.26":
|
||||
suite.Assert().Equal("eth3.26", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netaddr.MustParseIP("5.5.4.4"), r.TypedSpec().VIP.IP)
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case "configuration/vip/eth1":
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netaddr.MustParseIP("2.3.4.5"), r.TypedSpec().VIP.IP)
|
||||
case "configuration/vip/eth2":
|
||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(
|
||||
netaddr.MustParseIP("fd7a:115c:a1e0:ab12:4843:cd96:6277:2302"),
|
||||
r.TypedSpec().VIP.IP,
|
||||
)
|
||||
case "configuration/vip/eth3.26":
|
||||
suite.Assert().Equal("eth3.26", r.TypedSpec().LinkName)
|
||||
suite.Assert().EqualValues(netaddr.MustParseIP("5.5.4.4"), r.TypedSpec().VIP.IP)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *OperatorVIPConfigSuite) TearDownTest() {
|
||||
@ -183,17 +199,26 @@ func (suite *OperatorVIPConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewLinkStatus(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewLinkStatus(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestOperatorVIPConfigSuite(t *testing.T) {
|
||||
|
@ -45,7 +45,7 @@ type PlatformConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -72,14 +72,22 @@ func (suite *PlatformConfigSuite) startRuntime() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) assertResources(resourceNamespace resource.Namespace, resourceType resource.Type, requiredIDs []string, check func(resource.Resource) error) error {
|
||||
func (suite *PlatformConfigSuite) assertResources(
|
||||
resourceNamespace resource.Namespace,
|
||||
resourceType resource.Type,
|
||||
requiredIDs []string,
|
||||
check func(resource.Resource) error,
|
||||
) error {
|
||||
missingIDs := make(map[string]struct{}, len(requiredIDs))
|
||||
|
||||
for _, id := range requiredIDs {
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(resourceNamespace, resourceType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(resourceNamespace, resourceType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -102,7 +110,10 @@ func (suite *PlatformConfigSuite) assertResources(resourceNamespace resource.Nam
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) assertNoResource(resourceType resource.Type, id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, resourceType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, resourceType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -121,261 +132,360 @@ func (suite *PlatformConfigSuite) TestNoPlatform() {
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoResource(network.HostnameSpecType, "platform/hostname")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoResource(network.HostnameSpecType, "platform/hostname")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockHostname() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl.c.talos-testbed.internal")},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl.c.talos-testbed.internal")},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||
"platform/hostname",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||
"platform/hostname",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||
suite.Assert().Equal("c.talos-testbed.internal", spec.Domainname)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().Equal("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||
suite.Assert().Equal("c.talos-testbed.internal", spec.Domainname)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockHostnameNoDomain() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl")},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl")},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||
"platform/hostname",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||
"platform/hostname",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||
suite.Assert().Equal("", spec.Domainname)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().Equal("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||
suite.Assert().Equal("", spec.Domainname)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockAddresses() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
addresses: []netaddr.IPPrefix{netaddr.MustParseIPPrefix("192.168.1.24/24"), netaddr.MustParseIPPrefix("2001:fd::3/64")},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
addresses: []netaddr.IPPrefix{
|
||||
netaddr.MustParseIPPrefix("192.168.1.24/24"),
|
||||
netaddr.MustParseIPPrefix("2001:fd::3/64"),
|
||||
},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.AddressSpecType, []string{
|
||||
"platform/eth0/192.168.1.24/24",
|
||||
"platform/eth0/2001:fd::3/64",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.AddressSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.AddressSpecType, []string{
|
||||
"platform/eth0/192.168.1.24/24",
|
||||
"platform/eth0/2001:fd::3/64",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.AddressSpec).TypedSpec()
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case "platform/eth0/192.168.1.24/24":
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||
suite.Assert().Equal("192.168.1.24/24", spec.Address.String())
|
||||
case "platform/eth0/2001:fd::3/64":
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||
suite.Assert().Equal("2001:fd::3/64", spec.Address.String())
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case "platform/eth0/192.168.1.24/24":
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||
suite.Assert().Equal("192.168.1.24/24", spec.Address.String())
|
||||
case "platform/eth0/2001:fd::3/64":
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||
suite.Assert().Equal("2001:fd::3/64", spec.Address.String())
|
||||
}
|
||||
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockLinks() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
linksUp: []string{"eth0", "eth1"},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
linksUp: []string{"eth0", "eth1"},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.LinkSpecType, []string{
|
||||
"platform/eth0",
|
||||
"platform/eth1",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.LinkSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.LinkSpecType, []string{
|
||||
"platform/eth0",
|
||||
"platform/eth1",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.LinkSpec).TypedSpec()
|
||||
|
||||
suite.Assert().True(spec.Up)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().True(spec.Up)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockRoutes() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
defaultRoutes: []netaddr.IP{netaddr.MustParseIP("10.0.0.1")},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
defaultRoutes: []netaddr.IP{netaddr.MustParseIP("10.0.0.1")},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.RouteSpecType, []string{
|
||||
"platform/inet4/10.0.0.1//1024",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.RouteSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.RouteSpecType, []string{
|
||||
"platform/inet4/10.0.0.1//1024",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.RouteSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("10.0.0.1", spec.Gateway.String())
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().Equal("10.0.0.1", spec.Gateway.String())
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockOperators() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
dhcp4Links: []string{"eth1", "eth2"},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
dhcp4Links: []string{"eth1", "eth2"},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.OperatorSpecType, []string{
|
||||
"platform/dhcp4/eth1",
|
||||
"platform/dhcp4/eth2",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.OperatorSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.OperatorSpecType, []string{
|
||||
"platform/dhcp4/eth1",
|
||||
"platform/dhcp4/eth2",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.OperatorSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal(network.OperatorDHCP4, spec.Operator)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().Equal(network.OperatorDHCP4, spec.Operator)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockResolvers() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
resolvers: []netaddr.IP{netaddr.MustParseIP("1.1.1.1")},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
resolvers: []netaddr.IP{netaddr.MustParseIP("1.1.1.1")},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.ResolverSpecType, []string{
|
||||
"platform/resolvers",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.ResolverSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.ResolverSpecType, []string{
|
||||
"platform/resolvers",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.ResolverSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("[1.1.1.1]", fmt.Sprintf("%s", spec.DNSServers))
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().Equal("[1.1.1.1]", fmt.Sprintf("%s", spec.DNSServers))
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockTimeServers() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
timeServers: []string{"pool.ntp.org"},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
timeServers: []string{"pool.ntp.org"},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.TimeServerSpecType, []string{
|
||||
"platform/timeservers",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.TimeServerSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.TimeServerSpecType, []string{
|
||||
"platform/timeservers",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.TimeServerSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("[pool.ntp.org]", fmt.Sprintf("%s", spec.NTPServers))
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().Equal("[pool.ntp.org]", fmt.Sprintf("%s", spec.NTPServers))
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestPlatformMockExternalIPs() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{externalIPs: []netaddr.IP{netaddr.MustParseIP("10.3.4.5"), netaddr.MustParseIP("2001:470:6d:30e:96f4:4219:5733:b860")}},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
externalIPs: []netaddr.IP{
|
||||
netaddr.MustParseIP("10.3.4.5"),
|
||||
netaddr.MustParseIP("2001:470:6d:30e:96f4:4219:5733:b860"),
|
||||
},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.NamespaceName, network.AddressStatusType, []string{
|
||||
"external/10.3.4.5/32",
|
||||
"external/2001:470:6d:30e:96f4:4219:5733:b860/128",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.AddressStatus).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.NamespaceName, network.AddressStatusType, []string{
|
||||
"external/10.3.4.5/32",
|
||||
"external/2001:470:6d:30e:96f4:4219:5733:b860/128",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.AddressStatus).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("external", spec.LinkName)
|
||||
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
||||
suite.Assert().Equal("external", spec.LinkName)
|
||||
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
||||
|
||||
if r.Metadata().ID() == "external/10.3.4.5/32" {
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||
} else {
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||
}
|
||||
if r.Metadata().ID() == "external/10.3.4.5/32" {
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||
} else {
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
const sampleStoredConfig = "addresses: []\nlinks: []\nroutes: []\nhostnames:\n - hostname: talos-e2e-897b4e49-gcp-controlplane-jvcnl\n domainname: \"\"\n layer: default\nresolvers: []\ntimeServers: []\noperators: []\nexternalIPs:\n - 10.3.4.5\n - 2001:470:6d:30e:96f4:4219:5733:b860\n" //nolint:lll
|
||||
|
||||
func (suite *PlatformConfigSuite) TestStoreConfig() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl"),
|
||||
externalIPs: []netaddr.IP{netaddr.MustParseIP("10.3.4.5"), netaddr.MustParseIP("2001:470:6d:30e:96f4:4219:5733:b860")},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl"),
|
||||
externalIPs: []netaddr.IP{
|
||||
netaddr.MustParseIP("10.3.4.5"),
|
||||
netaddr.MustParseIP("2001:470:6d:30e:96f4:4219:5733:b860"),
|
||||
},
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -383,75 +493,98 @@ func (suite *PlatformConfigSuite) TestStoreConfig() {
|
||||
|
||||
suite.Assert().NoError(suite.state.Create(suite.ctx, stateMount))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
contents, err := os.ReadFile(filepath.Join(suite.statePath, constants.PlatformNetworkConfigFilename))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
contents, err := os.ReadFile(filepath.Join(suite.statePath, constants.PlatformNetworkConfigFilename))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
suite.Assert().Equal(sampleStoredConfig, string(contents))
|
||||
|
||||
suite.Assert().Equal(sampleStoredConfig, string(contents))
|
||||
|
||||
return nil
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TestLoadConfig() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
noData: true,
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.PlatformConfigController{
|
||||
V1alpha1Platform: &platformMock{
|
||||
noData: true,
|
||||
},
|
||||
StatePath: suite.statePath,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Require().NoError(os.WriteFile(filepath.Join(suite.statePath, constants.PlatformNetworkConfigFilename), []byte(sampleStoredConfig), 0o400))
|
||||
suite.Require().NoError(
|
||||
os.WriteFile(
|
||||
filepath.Join(suite.statePath, constants.PlatformNetworkConfigFilename),
|
||||
[]byte(sampleStoredConfig),
|
||||
0o400,
|
||||
),
|
||||
)
|
||||
|
||||
stateMount := runtimeres.NewMountStatus(v1alpha1.NamespaceName, constants.StatePartitionLabel)
|
||||
|
||||
suite.Assert().NoError(suite.state.Create(suite.ctx, stateMount))
|
||||
|
||||
// controller should pick up cached network configuration
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.NamespaceName, network.AddressStatusType, []string{
|
||||
"external/10.3.4.5/32",
|
||||
"external/2001:470:6d:30e:96f4:4219:5733:b860/128",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.AddressStatus).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.NamespaceName, network.AddressStatusType, []string{
|
||||
"external/10.3.4.5/32",
|
||||
"external/2001:470:6d:30e:96f4:4219:5733:b860/128",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.AddressStatus).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("external", spec.LinkName)
|
||||
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
||||
suite.Assert().Equal("external", spec.LinkName)
|
||||
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
||||
|
||||
if r.Metadata().ID() == "external/10.3.4.5/32" {
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||
} else {
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||
}
|
||||
if r.Metadata().ID() == "external/10.3.4.5/32" {
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||
} else {
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||
"platform/hostname",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResources(
|
||||
network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||
"platform/hostname",
|
||||
}, func(r resource.Resource) error {
|
||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
||||
|
||||
suite.Assert().Equal("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||
suite.Assert().Equal("", spec.Domainname)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
suite.Assert().Equal("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||
suite.Assert().Equal("", spec.Domainname)
|
||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PlatformConfigSuite) TearDownTest() {
|
||||
@ -496,7 +629,10 @@ func (mock *platformMock) KernelArgs() procfs.Parameters {
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
func (mock *platformMock) NetworkConfiguration(ctx context.Context, ch chan<- *v1alpha1runtime.PlatformNetworkConfig) error {
|
||||
func (mock *platformMock) NetworkConfiguration(
|
||||
ctx context.Context,
|
||||
ch chan<- *v1alpha1runtime.PlatformNetworkConfig,
|
||||
) error {
|
||||
if mock.noData {
|
||||
return nil
|
||||
}
|
||||
@ -520,7 +656,8 @@ func (mock *platformMock) NetworkConfiguration(ctx context.Context, ch chan<- *v
|
||||
family = nethelpers.FamilyInet6
|
||||
}
|
||||
|
||||
networkConfig.Addresses = append(networkConfig.Addresses,
|
||||
networkConfig.Addresses = append(
|
||||
networkConfig.Addresses,
|
||||
network.AddressSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
LinkName: "eth0",
|
||||
@ -528,7 +665,8 @@ func (mock *platformMock) NetworkConfiguration(ctx context.Context, ch chan<- *v
|
||||
Scope: nethelpers.ScopeGlobal,
|
||||
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
|
||||
Family: family,
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
for _, gw := range mock.defaultRoutes {
|
||||
@ -554,34 +692,42 @@ func (mock *platformMock) NetworkConfiguration(ctx context.Context, ch chan<- *v
|
||||
}
|
||||
|
||||
for _, link := range mock.linksUp {
|
||||
networkConfig.Links = append(networkConfig.Links, network.LinkSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
Name: link,
|
||||
Up: true,
|
||||
})
|
||||
networkConfig.Links = append(
|
||||
networkConfig.Links, network.LinkSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
Name: link,
|
||||
Up: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if len(mock.resolvers) > 0 {
|
||||
networkConfig.Resolvers = append(networkConfig.Resolvers, network.ResolverSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
DNSServers: mock.resolvers,
|
||||
})
|
||||
networkConfig.Resolvers = append(
|
||||
networkConfig.Resolvers, network.ResolverSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
DNSServers: mock.resolvers,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if len(mock.timeServers) > 0 {
|
||||
networkConfig.TimeServers = append(networkConfig.TimeServers, network.TimeServerSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
NTPServers: mock.timeServers,
|
||||
})
|
||||
networkConfig.TimeServers = append(
|
||||
networkConfig.TimeServers, network.TimeServerSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
NTPServers: mock.timeServers,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
for _, link := range mock.dhcp4Links {
|
||||
networkConfig.Operators = append(networkConfig.Operators, network.OperatorSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
LinkName: link,
|
||||
Operator: network.OperatorDHCP4,
|
||||
DHCP4: network.DHCP4OperatorSpec{},
|
||||
})
|
||||
networkConfig.Operators = append(
|
||||
networkConfig.Operators, network.OperatorSpecSpec{
|
||||
ConfigLayer: network.ConfigPlatform,
|
||||
LinkName: link,
|
||||
Operator: network.OperatorDHCP4,
|
||||
DHCP4: network.DHCP4OperatorSpec{},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
select {
|
||||
|
@ -40,7 +40,7 @@ type ResolverConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ func (suite *ResolverConfigSuite) assertResolvers(requiredIDs []string, check fu
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.ResolverSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.ResolverSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -98,7 +101,10 @@ func (suite *ResolverConfigSuite) assertResolvers(requiredIDs []string, check fu
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) assertNoResolver(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.ResolverSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.ResolverSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -117,36 +123,60 @@ func (suite *ResolverConfigSuite) TestDefaults() {
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers([]string{
|
||||
"default/resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
suite.Assert().Equal([]netaddr.IP{netaddr.MustParseIP(constants.DefaultPrimaryResolver), netaddr.MustParseIP(constants.DefaultSecondaryResolver)}, r.TypedSpec().DNSServers)
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers(
|
||||
[]string{
|
||||
"default/resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
suite.Assert().Equal(
|
||||
[]netaddr.IP{
|
||||
netaddr.MustParseIP(constants.DefaultPrimaryResolver),
|
||||
netaddr.MustParseIP(constants.DefaultSecondaryResolver),
|
||||
}, r.TypedSpec().DNSServers,
|
||||
)
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) TestCmdline() {
|
||||
suite.Require().NoError(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.Require().NoError(
|
||||
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.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers([]string{
|
||||
"cmdline/resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
suite.Assert().Equal([]netaddr.IP{netaddr.MustParseIP("10.0.0.1"), netaddr.MustParseIP("10.0.0.2")}, r.TypedSpec().DNSServers)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers(
|
||||
[]string{
|
||||
"cmdline/resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
suite.Assert().Equal(
|
||||
[]netaddr.IP{
|
||||
netaddr.MustParseIP("10.0.0.1"),
|
||||
netaddr.MustParseIP("10.0.0.2"),
|
||||
}, r.TypedSpec().DNSServers,
|
||||
)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) TestMachineConfiguration() {
|
||||
@ -157,46 +187,63 @@ func (suite *ResolverConfigSuite) TestMachineConfiguration() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NameServers: []string{"2.2.2.2", "3.3.3.3"},
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NameServers: []string{"2.2.2.2", "3.3.3.3"},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers([]string{
|
||||
"configuration/resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
suite.Assert().Equal([]netaddr.IP{netaddr.MustParseIP("2.2.2.2"), netaddr.MustParseIP("3.3.3.3")}, r.TypedSpec().DNSServers)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers(
|
||||
[]string{
|
||||
"configuration/resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
suite.Assert().Equal(
|
||||
[]netaddr.IP{
|
||||
netaddr.MustParseIP("2.2.2.2"),
|
||||
netaddr.MustParseIP("3.3.3.3"),
|
||||
}, r.TypedSpec().DNSServers,
|
||||
)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, cfg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineNetwork.NameServers = nil
|
||||
_, err = suite.state.UpdateWithConflicts(
|
||||
suite.ctx, cfg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineNetwork.NameServers = nil
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoResolver("configuration/resolvers")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoResolver("configuration/resolvers")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ResolverConfigSuite) TearDownTest() {
|
||||
@ -207,10 +254,14 @@ func (suite *ResolverConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ type ResolverMergeSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -73,7 +73,10 @@ func (suite *ResolverMergeSuite) assertResolvers(requiredIDs []string, check fun
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.ResolverSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.ResolverSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -101,7 +104,10 @@ func (suite *ResolverMergeSuite) assertResolvers(requiredIDs []string, check fun
|
||||
func (suite *ResolverMergeSuite) TestMerge() {
|
||||
def := network.NewResolverSpec(network.ConfigNamespaceName, "default/resolvers")
|
||||
*def.TypedSpec() = network.ResolverSpecSpec{
|
||||
DNSServers: []netaddr.IP{netaddr.MustParseIP(constants.DefaultPrimaryResolver), netaddr.MustParseIP(constants.DefaultSecondaryResolver)},
|
||||
DNSServers: []netaddr.IP{
|
||||
netaddr.MustParseIP(constants.DefaultPrimaryResolver),
|
||||
netaddr.MustParseIP(constants.DefaultSecondaryResolver),
|
||||
},
|
||||
ConfigLayer: network.ConfigDefault,
|
||||
}
|
||||
|
||||
@ -127,31 +133,44 @@ func (suite *ResolverMergeSuite) TestMerge() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers([]string{
|
||||
"resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers(
|
||||
[]string{
|
||||
"resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers([]string{
|
||||
"resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
if !reflect.DeepEqual(r.TypedSpec().DNSServers, []netaddr.IP{netaddr.MustParseIP("1.1.2.0"), netaddr.MustParseIP("1.1.2.1")}) {
|
||||
return retry.ExpectedErrorf("unexpected servers %q", r.TypedSpec().DNSServers)
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertResolvers(
|
||||
[]string{
|
||||
"resolvers",
|
||||
}, func(r *network.ResolverSpec) error {
|
||||
if !reflect.DeepEqual(
|
||||
r.TypedSpec().DNSServers,
|
||||
[]netaddr.IP{netaddr.MustParseIP("1.1.2.0"), netaddr.MustParseIP("1.1.2.1")},
|
||||
) {
|
||||
return retry.ExpectedErrorf("unexpected servers %q", r.TypedSpec().DNSServers)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ResolverMergeSuite) TearDownTest() {
|
||||
@ -162,7 +181,12 @@ func (suite *ResolverMergeSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewResolverSpec(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewResolverSpec(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestResolverMergeSuite(t *testing.T) {
|
||||
|
@ -36,7 +36,7 @@ type ResolverSpecSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -66,7 +66,10 @@ func (suite *ResolverSpecSuite) startRuntime() {
|
||||
}
|
||||
|
||||
func (suite *ResolverSpecSuite) assertStatus(id string, servers ...netaddr.IP) error {
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(network.NamespaceName, network.ResolverStatusType, id, resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.ResolverStatusType, id, resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
@ -95,10 +98,13 @@ func (suite *ResolverSpecSuite) TestSpec() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus("resolvers", netaddr.MustParseIP(constants.DefaultPrimaryResolver))
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus("resolvers", netaddr.MustParseIP(constants.DefaultPrimaryResolver))
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ResolverSpecSuite) TearDownTest() {
|
||||
@ -109,7 +115,12 @@ func (suite *ResolverSpecSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewResolverSpec(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewResolverSpec(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestResolverSpecSuite(t *testing.T) {
|
||||
|
@ -40,7 +40,7 @@ type RouteConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -72,7 +72,10 @@ func (suite *RouteConfigSuite) assertRoutes(requiredIDs []string, check func(*ne
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.RouteSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.RouteSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -98,25 +101,34 @@ func (suite *RouteConfigSuite) assertRoutes(requiredIDs []string, check func(*ne
|
||||
}
|
||||
|
||||
func (suite *RouteConfigSuite) TestCmdline() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.RouteConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&netctrl.RouteConfigController{
|
||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes([]string{
|
||||
"cmdline/inet4/172.20.0.1//1024",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes(
|
||||
[]string{
|
||||
"cmdline/inet4/172.20.0.1//1024",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *RouteConfigSuite) TestMachineConfiguration() {
|
||||
@ -127,127 +139,134 @@ func (suite *RouteConfigSuite) TestMachineConfiguration() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "192.168.0.0/18",
|
||||
RouteGateway: "192.168.0.25",
|
||||
RouteMetric: 25,
|
||||
},
|
||||
{
|
||||
RouteNetwork: "169.254.254.254/32",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceIgnore: true,
|
||||
DeviceInterface: "eth4",
|
||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "192.168.0.0/18",
|
||||
RouteGateway: "192.168.0.26",
|
||||
RouteMetric: 25,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
DeviceAddresses: []string{"2001:470:6d:30e:8ed2:b60c:9d2f:803a/64"},
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteGateway: "2001:470:6d:30e:8ed2:b60c:9d2f:803b",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 24,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.1/8",
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth3",
|
||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "192.168.0.0/18",
|
||||
RouteGateway: "192.168.0.25",
|
||||
RouteMetric: 25,
|
||||
},
|
||||
VlanRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "10.0.3.0/24",
|
||||
RouteGateway: "10.0.3.1",
|
||||
{
|
||||
RouteNetwork: "169.254.254.254/32",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceIgnore: true,
|
||||
DeviceInterface: "eth4",
|
||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "192.168.0.0/18",
|
||||
RouteGateway: "192.168.0.26",
|
||||
RouteMetric: 25,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth2",
|
||||
DeviceAddresses: []string{"2001:470:6d:30e:8ed2:b60c:9d2f:803a/64"},
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteGateway: "2001:470:6d:30e:8ed2:b60c:9d2f:803b",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceVlans: []*v1alpha1.Vlan{
|
||||
{
|
||||
VlanID: 24,
|
||||
VlanAddresses: []string{
|
||||
"10.0.0.1/8",
|
||||
},
|
||||
VlanRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "10.0.3.0/24",
|
||||
RouteGateway: "10.0.3.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "192.244.0.0/24",
|
||||
RouteGateway: "192.244.0.1",
|
||||
RouteSource: "192.244.0.10",
|
||||
{
|
||||
DeviceInterface: "eth1",
|
||||
DeviceRoutes: []*v1alpha1.Route{
|
||||
{
|
||||
RouteNetwork: "192.244.0.0/24",
|
||||
RouteGateway: "192.244.0.1",
|
||||
RouteSource: "192.244.0.10",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes([]string{
|
||||
"configuration/inet6/2001:470:6d:30e:8ed2:b60c:9d2f:803b//1024",
|
||||
"configuration/inet4/10.0.3.1/10.0.3.0/24/1024",
|
||||
"configuration/inet4/192.168.0.25/192.168.0.0/18/25",
|
||||
"configuration/inet4/192.244.0.1/192.244.0.0/24/1024",
|
||||
"configuration/inet4//169.254.254.254/32/1024",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "configuration/inet6/2001:470:6d:30e:8ed2:b60c:9d2f:803b//1024":
|
||||
suite.Assert().Equal("eth2", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
case "configuration/inet4/10.0.3.1/10.0.3.0/24/1024":
|
||||
suite.Assert().Equal("eth0.24", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
case "configuration/inet4/192.168.0.25/192.168.0.0/18/25":
|
||||
suite.Assert().Equal("eth3", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(25, r.TypedSpec().Priority)
|
||||
case "configuration/inet4/192.244.0.1/192.244.0.0/24/1024":
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
suite.Assert().EqualValues(netaddr.MustParseIP("192.244.0.10"), r.TypedSpec().Source)
|
||||
case "configuration/inet4//169.254.254.254/32/1024":
|
||||
suite.Assert().Equal("eth3", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
suite.Assert().Equal(nethelpers.ScopeLink, r.TypedSpec().Scope)
|
||||
suite.Assert().Equal("169.254.254.254/32", r.TypedSpec().Destination.String())
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes(
|
||||
[]string{
|
||||
"configuration/inet6/2001:470:6d:30e:8ed2:b60c:9d2f:803b//1024",
|
||||
"configuration/inet4/10.0.3.1/10.0.3.0/24/1024",
|
||||
"configuration/inet4/192.168.0.25/192.168.0.0/18/25",
|
||||
"configuration/inet4/192.244.0.1/192.244.0.0/24/1024",
|
||||
"configuration/inet4//169.254.254.254/32/1024",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
switch r.Metadata().ID() {
|
||||
case "configuration/inet6/2001:470:6d:30e:8ed2:b60c:9d2f:803b//1024":
|
||||
suite.Assert().Equal("eth2", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
case "configuration/inet4/10.0.3.1/10.0.3.0/24/1024":
|
||||
suite.Assert().Equal("eth0.24", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
case "configuration/inet4/192.168.0.25/192.168.0.0/18/25":
|
||||
suite.Assert().Equal("eth3", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(25, r.TypedSpec().Priority)
|
||||
case "configuration/inet4/192.244.0.1/192.244.0.0/24/1024":
|
||||
suite.Assert().Equal("eth1", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
suite.Assert().EqualValues(netaddr.MustParseIP("192.244.0.10"), r.TypedSpec().Source)
|
||||
case "configuration/inet4//169.254.254.254/32/1024":
|
||||
suite.Assert().Equal("eth3", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||
suite.Assert().Equal(nethelpers.ScopeLink, r.TypedSpec().Scope)
|
||||
suite.Assert().Equal("169.254.254.254/32", r.TypedSpec().Destination.String())
|
||||
}
|
||||
|
||||
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *RouteConfigSuite) TearDownTest() {
|
||||
@ -258,10 +277,14 @@ func (suite *RouteConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ type RouteMergeSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -73,7 +73,10 @@ func (suite *RouteMergeSuite) assertRoutes(requiredIDs []string, check func(*net
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.RouteSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.RouteSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -99,7 +102,10 @@ func (suite *RouteMergeSuite) assertRoutes(requiredIDs []string, check func(*net
|
||||
}
|
||||
|
||||
func (suite *RouteMergeSuite) assertNoRoute(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.RouteSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.RouteSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -155,55 +161,68 @@ func (suite *RouteMergeSuite) TestMerge() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes([]string{
|
||||
"inet4/10.5.0.3//50",
|
||||
"inet4/10.0.0.34/10.0.0.35/32/1024",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
suite.Assert().Equal(resource.PhaseRunning, r.Metadata().Phase())
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes(
|
||||
[]string{
|
||||
"inet4/10.5.0.3//50",
|
||||
"inet4/10.0.0.34/10.0.0.35/32/1024",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
suite.Assert().Equal(resource.PhaseRunning, r.Metadata().Phase())
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case "inet4/10.5.0.3//50":
|
||||
suite.Assert().Equal(*dhcp.TypedSpec(), *r.TypedSpec())
|
||||
case "inet4/10.0.0.34/10.0.0.35/32/1024":
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case "inet4/10.5.0.3//50":
|
||||
suite.Assert().Equal(*dhcp.TypedSpec(), *r.TypedSpec())
|
||||
case "inet4/10.0.0.34/10.0.0.35/32/1024":
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, dhcp.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes([]string{
|
||||
"inet4/10.5.0.3//50",
|
||||
"inet4/10.0.0.34/10.0.0.35/32/1024",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
suite.Assert().Equal(resource.PhaseRunning, r.Metadata().Phase())
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes(
|
||||
[]string{
|
||||
"inet4/10.5.0.3//50",
|
||||
"inet4/10.0.0.34/10.0.0.35/32/1024",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
suite.Assert().Equal(resource.PhaseRunning, r.Metadata().Phase())
|
||||
|
||||
switch r.Metadata().ID() {
|
||||
case "inet4/10.5.0.3//50":
|
||||
if *cmdline.TypedSpec() != *r.TypedSpec() {
|
||||
// using retry here, as it might not be reconciled immediately
|
||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||
}
|
||||
case "inet4/10.0.0.34/10.0.0.35/32/1024":
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
}
|
||||
switch r.Metadata().ID() {
|
||||
case "inet4/10.5.0.3//50":
|
||||
if *cmdline.TypedSpec() != *r.TypedSpec() {
|
||||
// using retry here, as it might not be reconciled immediately
|
||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||
}
|
||||
case "inet4/10.0.0.34/10.0.0.35/32/1024":
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoRoute("inet4/10.0.0.34/10.0.0.35/32/1024")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoRoute("inet4/10.0.0.34/10.0.0.35/32/1024")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
//nolint:gocyclo
|
||||
@ -257,50 +276,75 @@ func (suite *RouteMergeSuite) TestMergeFlapping() {
|
||||
|
||||
eg.Go(flipflop(0))
|
||||
eg.Go(flipflop(1))
|
||||
eg.Go(func() error {
|
||||
// add/remove finalizer to the merged resource
|
||||
for i := 0; i < 1000; i++ {
|
||||
if err := suite.state.AddFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.RouteSpecType, "inet4/10.5.0.3//50", resource.VersionUndefined), "foo"); err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
return err
|
||||
eg.Go(
|
||||
func() error {
|
||||
// add/remove finalizer to the merged resource
|
||||
for i := 0; i < 1000; i++ {
|
||||
if err := suite.state.AddFinalizer(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.RouteSpecType,
|
||||
"inet4/10.5.0.3//50",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
"foo",
|
||||
); err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
suite.T().Log("finalizer added")
|
||||
}
|
||||
|
||||
continue
|
||||
} else {
|
||||
suite.T().Log("finalizer added")
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
if err := suite.state.RemoveFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.RouteSpecType, "inet4/10.5.0.3//50", resource.VersionUndefined), "foo"); err != nil {
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return err
|
||||
if err := suite.state.RemoveFinalizer(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
network.NamespaceName,
|
||||
network.RouteSpecType,
|
||||
"inet4/10.5.0.3//50",
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
"foo",
|
||||
); err != nil {
|
||||
if err != nil && !state.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(eg.Wait())
|
||||
|
||||
suite.Assert().NoError(retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes([]string{
|
||||
"inet4/10.5.0.3//50",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes(
|
||||
[]string{
|
||||
"inet4/10.5.0.3//50",
|
||||
}, func(r *network.RouteSpec) error {
|
||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
||||
}
|
||||
|
||||
if *dhcp.TypedSpec() != *r.TypedSpec() {
|
||||
// using retry here, as it might not be reconciled immediately
|
||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||
}
|
||||
if *dhcp.TypedSpec() != *r.TypedSpec() {
|
||||
// using retry here, as it might not be reconciled immediately
|
||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *RouteMergeSuite) TearDownTest() {
|
||||
@ -311,7 +355,12 @@ func (suite *RouteMergeSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewRouteSpec(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewRouteSpec(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestRouteMergeSuite(t *testing.T) {
|
||||
|
@ -149,7 +149,8 @@ func findRoutes(routes []rtnetlink.RouteMessage, family nethelpers.Family, desti
|
||||
|
||||
//nolint:gocyclo,cyclop
|
||||
func (ctrl *RouteSpecController) syncRoute(ctx context.Context, r controller.Runtime, logger *zap.Logger, conn *rtnetlink.Conn,
|
||||
links []rtnetlink.LinkMessage, routes []rtnetlink.RouteMessage, route *network.RouteSpec) error {
|
||||
links []rtnetlink.LinkMessage, routes []rtnetlink.RouteMessage, route *network.RouteSpec,
|
||||
) error {
|
||||
linkIndex := resolveLinkName(links, route.TypedSpec().OutLinkName)
|
||||
|
||||
destinationStr := route.TypedSpec().Destination.String()
|
||||
|
@ -40,7 +40,7 @@ type RouteSpecSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -73,7 +73,11 @@ func (suite *RouteSpecSuite) startRuntime() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *RouteSpecSuite) assertRoute(destination netaddr.IPPrefix, gateway netaddr.IP, check func(rtnetlink.RouteMessage) error) error {
|
||||
func (suite *RouteSpecSuite) assertRoute(
|
||||
destination netaddr.IPPrefix,
|
||||
gateway netaddr.IP,
|
||||
check func(rtnetlink.RouteMessage) error,
|
||||
) error {
|
||||
conn, err := rtnetlink.Dial(nil)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
@ -150,14 +154,21 @@ func (suite *RouteSpecSuite) TestLoopback() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoute(netaddr.MustParseIPPrefix("127.0.11.0/24"), netaddr.MustParseIP("127.0.11.1"), func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().EqualValues(0, route.Attributes.Priority)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoute(
|
||||
netaddr.MustParseIPPrefix("127.0.11.0/24"),
|
||||
netaddr.MustParseIP("127.0.11.1"),
|
||||
func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().EqualValues(0, route.Attributes.Priority)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the route
|
||||
for {
|
||||
@ -172,7 +183,12 @@ func (suite *RouteSpecSuite) TestLoopback() {
|
||||
}
|
||||
|
||||
// torn down address should be removed immediately
|
||||
suite.Assert().NoError(suite.assertNoRoute(netaddr.MustParseIPPrefix("127.0.11.0/24"), netaddr.MustParseIP("127.0.11.1")))
|
||||
suite.Assert().NoError(
|
||||
suite.assertNoRoute(
|
||||
netaddr.MustParseIPPrefix("127.0.11.0/24"),
|
||||
netaddr.MustParseIP("127.0.11.1"),
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, loopback.Metadata()))
|
||||
}
|
||||
@ -197,38 +213,50 @@ func (suite *RouteSpecSuite) TestDefaultRoute() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoute(netaddr.IPPrefix{}, netaddr.MustParseIP("127.0.11.2"), func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().Nil(route.Attributes.Dst)
|
||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoute(
|
||||
netaddr.IPPrefix{}, netaddr.MustParseIP("127.0.11.2"), func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().Nil(route.Attributes.Dst)
|
||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// update the route metric
|
||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, def.Metadata(), func(r resource.Resource) error {
|
||||
defR := r.(*network.RouteSpec) //nolint:forcetypeassert,errcheck
|
||||
_, err := suite.state.UpdateWithConflicts(
|
||||
suite.ctx, def.Metadata(), func(r resource.Resource) error {
|
||||
defR := r.(*network.RouteSpec) //nolint:forcetypeassert,errcheck
|
||||
|
||||
defR.TypedSpec().Priority = 1048577
|
||||
defR.TypedSpec().Priority = 1048577
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Assert().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoute(netaddr.IPPrefix{}, netaddr.MustParseIP("127.0.11.2"), func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().Nil(route.Attributes.Dst)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoute(
|
||||
netaddr.IPPrefix{}, netaddr.MustParseIP("127.0.11.2"), func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().Nil(route.Attributes.Dst)
|
||||
|
||||
if route.Attributes.Priority != 1048577 {
|
||||
return fmt.Errorf("route metric wasn't updated: %d", route.Attributes.Priority)
|
||||
}
|
||||
if route.Attributes.Priority != 1048577 {
|
||||
return fmt.Errorf("route metric wasn't updated: %d", route.Attributes.Priority)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the route
|
||||
for {
|
||||
@ -256,18 +284,22 @@ func (suite *RouteSpecSuite) TestDefaultAndInterfaceRoutes() {
|
||||
|
||||
defer conn.Close() //nolint:errcheck
|
||||
|
||||
suite.Require().NoError(conn.Link.New(&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Flags: unix.IFF_UP,
|
||||
Change: unix.IFF_UP,
|
||||
Attributes: &rtnetlink.LinkAttributes{
|
||||
Name: dummyInterface,
|
||||
MTU: 1400,
|
||||
Info: &rtnetlink.LinkInfo{
|
||||
Kind: "dummy",
|
||||
suite.Require().NoError(
|
||||
conn.Link.New(
|
||||
&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Flags: unix.IFF_UP,
|
||||
Change: unix.IFF_UP,
|
||||
Attributes: &rtnetlink.LinkAttributes{
|
||||
Name: dummyInterface,
|
||||
MTU: 1400,
|
||||
Info: &rtnetlink.LinkInfo{
|
||||
Kind: "dummy",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
),
|
||||
)
|
||||
|
||||
iface, err := net.InterfaceByName(dummyInterface)
|
||||
suite.Require().NoError(err)
|
||||
@ -276,16 +308,20 @@ func (suite *RouteSpecSuite) TestDefaultAndInterfaceRoutes() {
|
||||
|
||||
localIP := net.ParseIP("10.28.0.27").To4()
|
||||
|
||||
suite.Require().NoError(conn.Address.New(&rtnetlink.AddressMessage{
|
||||
Family: unix.AF_INET,
|
||||
PrefixLength: 32,
|
||||
Scope: unix.RT_SCOPE_UNIVERSE,
|
||||
Index: uint32(iface.Index),
|
||||
Attributes: &rtnetlink.AddressAttributes{
|
||||
Address: localIP,
|
||||
Local: localIP,
|
||||
},
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
conn.Address.New(
|
||||
&rtnetlink.AddressMessage{
|
||||
Family: unix.AF_INET,
|
||||
PrefixLength: 32,
|
||||
Scope: unix.RT_SCOPE_UNIVERSE,
|
||||
Index: uint32(iface.Index),
|
||||
Attributes: &rtnetlink.AddressAttributes{
|
||||
Address: localIP,
|
||||
Local: localIP,
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
def := network.NewRouteSpec(network.NamespaceName, "default")
|
||||
*def.TypedSpec() = network.RouteSpecSpec{
|
||||
@ -321,24 +357,31 @@ func (suite *RouteSpecSuite) TestDefaultAndInterfaceRoutes() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
if err := suite.assertRoute(netaddr.IPPrefix{}, netaddr.MustParseIP("10.28.0.1"), func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().Nil(route.Attributes.Dst)
|
||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
if err := suite.assertRoute(
|
||||
netaddr.IPPrefix{}, netaddr.MustParseIP("10.28.0.1"), func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().Nil(route.Attributes.Dst)
|
||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return suite.assertRoute(netaddr.MustParseIPPrefix("10.28.0.1/32"), netaddr.IP{}, func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().Nil(route.Attributes.Gateway)
|
||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||
return suite.assertRoute(
|
||||
netaddr.MustParseIPPrefix("10.28.0.1/32"), netaddr.IP{}, func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().Nil(route.Attributes.Gateway)
|
||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the routes
|
||||
for {
|
||||
@ -378,18 +421,22 @@ func (suite *RouteSpecSuite) TestLinkLocalRoute() {
|
||||
|
||||
defer conn.Close() //nolint:errcheck
|
||||
|
||||
suite.Require().NoError(conn.Link.New(&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Flags: unix.IFF_UP,
|
||||
Change: unix.IFF_UP,
|
||||
Attributes: &rtnetlink.LinkAttributes{
|
||||
Name: dummyInterface,
|
||||
MTU: 1500,
|
||||
Info: &rtnetlink.LinkInfo{
|
||||
Kind: "dummy",
|
||||
suite.Require().NoError(
|
||||
conn.Link.New(
|
||||
&rtnetlink.LinkMessage{
|
||||
Type: unix.ARPHRD_ETHER,
|
||||
Flags: unix.IFF_UP,
|
||||
Change: unix.IFF_UP,
|
||||
Attributes: &rtnetlink.LinkAttributes{
|
||||
Name: dummyInterface,
|
||||
MTU: 1500,
|
||||
Info: &rtnetlink.LinkInfo{
|
||||
Kind: "dummy",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
),
|
||||
)
|
||||
|
||||
iface, err := net.InterfaceByName(dummyInterface)
|
||||
suite.Require().NoError(err)
|
||||
@ -398,16 +445,20 @@ func (suite *RouteSpecSuite) TestLinkLocalRoute() {
|
||||
|
||||
localIP := net.ParseIP("10.28.0.27").To4()
|
||||
|
||||
suite.Require().NoError(conn.Address.New(&rtnetlink.AddressMessage{
|
||||
Family: unix.AF_INET,
|
||||
PrefixLength: 24,
|
||||
Scope: unix.RT_SCOPE_UNIVERSE,
|
||||
Index: uint32(iface.Index),
|
||||
Attributes: &rtnetlink.AddressAttributes{
|
||||
Address: localIP,
|
||||
Local: localIP,
|
||||
},
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
conn.Address.New(
|
||||
&rtnetlink.AddressMessage{
|
||||
Family: unix.AF_INET,
|
||||
PrefixLength: 24,
|
||||
Scope: unix.RT_SCOPE_UNIVERSE,
|
||||
Index: uint32(iface.Index),
|
||||
Attributes: &rtnetlink.AddressAttributes{
|
||||
Address: localIP,
|
||||
Local: localIP,
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
ll := network.NewRouteSpec(network.NamespaceName, "ll")
|
||||
*ll.TypedSpec() = network.RouteSpecSpec{
|
||||
@ -428,14 +479,21 @@ func (suite *RouteSpecSuite) TestLinkLocalRoute() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoute(netaddr.MustParseIPPrefix("169.254.169.254/32"), netaddr.MustParseIP("10.28.0.1"), func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoute(
|
||||
netaddr.MustParseIPPrefix("169.254.169.254/32"),
|
||||
netaddr.MustParseIP("10.28.0.1"),
|
||||
func(route rtnetlink.RouteMessage) error {
|
||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
// teardown the routes
|
||||
for {
|
||||
@ -450,7 +508,12 @@ func (suite *RouteSpecSuite) TestLinkLocalRoute() {
|
||||
}
|
||||
|
||||
// torn down route should be removed immediately
|
||||
suite.Assert().NoError(suite.assertNoRoute(netaddr.MustParseIPPrefix("169.254.169.254/32"), netaddr.MustParseIP("10.28.0.1")))
|
||||
suite.Assert().NoError(
|
||||
suite.assertNoRoute(
|
||||
netaddr.MustParseIPPrefix("169.254.169.254/32"),
|
||||
netaddr.MustParseIP("10.28.0.1"),
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, ll.Metadata()))
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ type RouteStatusSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -71,7 +71,10 @@ func (suite *RouteStatusSuite) assertRoutes(requiredIDs []string, check func(*ne
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.RouteStatusType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.RouteStatusType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -97,19 +100,24 @@ func (suite *RouteStatusSuite) assertRoutes(requiredIDs []string, check func(*ne
|
||||
}
|
||||
|
||||
func (suite *RouteStatusSuite) TestRoutes() {
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes([]string{"local/inet4//127.0.0.0/8/0"}, func(r *network.RouteStatus) error {
|
||||
suite.Assert().True(r.TypedSpec().Source.IsLoopback())
|
||||
suite.Assert().Equal("lo", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.TableLocal, r.TypedSpec().Table)
|
||||
suite.Assert().Equal(nethelpers.ScopeHost, r.TypedSpec().Scope)
|
||||
suite.Assert().Equal(nethelpers.TypeLocal, r.TypedSpec().Type)
|
||||
suite.Assert().Equal(nethelpers.ProtocolKernel, r.TypedSpec().Protocol)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertRoutes(
|
||||
[]string{"local/inet4//127.0.0.0/8/0"}, func(r *network.RouteStatus) error {
|
||||
suite.Assert().True(r.TypedSpec().Source.IsLoopback())
|
||||
suite.Assert().Equal("lo", r.TypedSpec().OutLinkName)
|
||||
suite.Assert().Equal(nethelpers.TableLocal, r.TypedSpec().Table)
|
||||
suite.Assert().Equal(nethelpers.ScopeHost, r.TypedSpec().Scope)
|
||||
suite.Assert().Equal(nethelpers.TypeLocal, r.TypedSpec().Type)
|
||||
suite.Assert().Equal(nethelpers.ProtocolKernel, r.TypedSpec().Protocol)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *RouteStatusSuite) TearDownTest() {
|
||||
|
@ -35,7 +35,7 @@ type StatusSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -65,7 +65,10 @@ func (suite *StatusSuite) startRuntime() {
|
||||
}
|
||||
|
||||
func (suite *StatusSuite) assertStatus(expected network.StatusSpec) error {
|
||||
status, err := suite.state.Get(suite.ctx, resource.NewMetadata(network.NamespaceName, network.StatusType, network.StatusID, resource.VersionUndefined))
|
||||
status, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.StatusType, network.StatusID, resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
if !state.IsNotFoundError(err) {
|
||||
suite.Require().NoError(err)
|
||||
@ -82,10 +85,13 @@ func (suite *StatusSuite) assertStatus(expected network.StatusSpec) error {
|
||||
}
|
||||
|
||||
func (suite *StatusSuite) TestNone() {
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{})
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *StatusSuite) TestAddresses() {
|
||||
@ -94,10 +100,13 @@ func (suite *StatusSuite) TestAddresses() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodeAddress))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{AddressReady: true})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{AddressReady: true})
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *StatusSuite) TestRoutes() {
|
||||
@ -106,10 +115,13 @@ func (suite *StatusSuite) TestRoutes() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, route))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{ConnectivityReady: true})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{ConnectivityReady: true})
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *StatusSuite) TestHostname() {
|
||||
@ -118,10 +130,13 @@ func (suite *StatusSuite) TestHostname() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostname))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{HostnameReady: true})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{HostnameReady: true})
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *StatusSuite) TestEtcFiles() {
|
||||
@ -131,10 +146,13 @@ func (suite *StatusSuite) TestEtcFiles() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, hosts))
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, resolv))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{EtcFilesReady: true})
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus(network.StatusSpec{EtcFilesReady: true})
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *StatusSuite) TearDownTest() {
|
||||
@ -145,9 +163,24 @@ func (suite *StatusSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewNodeAddress(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewResolverStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewHostnameStatus(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewNodeAddress(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewResolverStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewHostnameStatus(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), files.NewEtcFileStatus(files.NamespaceName, "bar")))
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ type TimeServerConfigSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -64,14 +64,20 @@ func (suite *TimeServerConfigSuite) startRuntime() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) assertTimeServers(requiredIDs []string, check func(*network.TimeServerSpec) error) error {
|
||||
func (suite *TimeServerConfigSuite) assertTimeServers(
|
||||
requiredIDs []string,
|
||||
check func(*network.TimeServerSpec) error,
|
||||
) error {
|
||||
missingIDs := make(map[string]struct{}, len(requiredIDs))
|
||||
|
||||
for _, id := range requiredIDs {
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.TimeServerSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.TimeServerSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -97,7 +103,10 @@ func (suite *TimeServerConfigSuite) assertTimeServers(requiredIDs []string, chec
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) assertNoTimeServer(id string) error {
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.ConfigNamespaceName, network.TimeServerSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.ConfigNamespaceName, network.TimeServerSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -116,36 +125,50 @@ func (suite *TimeServerConfigSuite) TestDefaults() {
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers([]string{
|
||||
"default/timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
suite.Assert().Equal([]string{constants.DefaultNTPServer}, r.TypedSpec().NTPServers)
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers(
|
||||
[]string{
|
||||
"default/timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
suite.Assert().Equal([]string{constants.DefaultNTPServer}, r.TypedSpec().NTPServers)
|
||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) TestCmdline() {
|
||||
suite.Require().NoError(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.Require().NoError(
|
||||
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.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers([]string{
|
||||
"cmdline/timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
suite.Assert().Equal([]string{"10.0.0.1"}, r.TypedSpec().NTPServers)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers(
|
||||
[]string{
|
||||
"cmdline/timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
suite.Assert().Equal([]string{"10.0.0.1"}, r.TypedSpec().NTPServers)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) TestMachineConfiguration() {
|
||||
@ -156,46 +179,58 @@ func (suite *TimeServerConfigSuite) TestMachineConfiguration() {
|
||||
u, err := url.Parse("https://foo:6443")
|
||||
suite.Require().NoError(err)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeServers: []string{"za.pool.ntp.org", "pool.ntp.org"},
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeServers: []string{"za.pool.ntp.org", "pool.ntp.org"},
|
||||
},
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers([]string{
|
||||
"configuration/timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
suite.Assert().Equal([]string{"za.pool.ntp.org", "pool.ntp.org"}, r.TypedSpec().NTPServers)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers(
|
||||
[]string{
|
||||
"configuration/timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
suite.Assert().Equal([]string{"za.pool.ntp.org", "pool.ntp.org"}, r.TypedSpec().NTPServers)
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, cfg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineTime = nil
|
||||
_, err = suite.state.UpdateWithConflicts(
|
||||
suite.ctx, cfg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineTime = nil
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoTimeServer("configuration/timeservers")
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertNoTimeServer("configuration/timeservers")
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *TimeServerConfigSuite) TearDownTest() {
|
||||
@ -206,10 +241,14 @@ func (suite *TimeServerConfigSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ type TimeServerMergeSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -65,14 +65,20 @@ func (suite *TimeServerMergeSuite) startRuntime() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (suite *TimeServerMergeSuite) assertTimeServers(requiredIDs []string, check func(*network.TimeServerSpec) error) error {
|
||||
func (suite *TimeServerMergeSuite) assertTimeServers(
|
||||
requiredIDs []string,
|
||||
check func(*network.TimeServerSpec) error,
|
||||
) error {
|
||||
missingIDs := make(map[string]struct{}, len(requiredIDs))
|
||||
|
||||
for _, id := range requiredIDs {
|
||||
missingIDs[id] = struct{}{}
|
||||
}
|
||||
|
||||
resources, err := suite.state.List(suite.ctx, resource.NewMetadata(network.NamespaceName, network.TimeServerSpecType, "", resource.VersionUndefined))
|
||||
resources, err := suite.state.List(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(network.NamespaceName, network.TimeServerSpecType, "", resource.VersionUndefined),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -126,31 +132,41 @@ func (suite *TimeServerMergeSuite) TestMerge() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers([]string{
|
||||
"timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers(
|
||||
[]string{
|
||||
"timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers([]string{
|
||||
"timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
if !reflect.DeepEqual(r.TypedSpec().NTPServers, []string{"ntp.eth0", "ntp.eth1"}) {
|
||||
return retry.ExpectedErrorf("unexpected servers %q", r.TypedSpec().NTPServers)
|
||||
}
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeServers(
|
||||
[]string{
|
||||
"timeservers",
|
||||
}, func(r *network.TimeServerSpec) error {
|
||||
if !reflect.DeepEqual(r.TypedSpec().NTPServers, []string{"ntp.eth0", "ntp.eth1"}) {
|
||||
return retry.ExpectedErrorf("unexpected servers %q", r.TypedSpec().NTPServers)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *TimeServerMergeSuite) TearDownTest() {
|
||||
@ -161,7 +177,12 @@ func (suite *TimeServerMergeSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewTimeServerSpec(network.ConfigNamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewTimeServerSpec(network.ConfigNamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestTimeServerMergeSuite(t *testing.T) {
|
||||
|
@ -35,7 +35,7 @@ type TimeServerSpecSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -65,7 +65,10 @@ func (suite *TimeServerSpecSuite) startRuntime() {
|
||||
}
|
||||
|
||||
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))
|
||||
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)
|
||||
@ -94,10 +97,13 @@ func (suite *TimeServerSpecSuite) TestSpec() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
||||
}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus("timeservers", constants.DefaultNTPServer)
|
||||
}))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertStatus("timeservers", constants.DefaultNTPServer)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *TimeServerSpecSuite) TearDownTest() {
|
||||
@ -108,7 +114,12 @@ func (suite *TimeServerSpecSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewTimeServerSpec(network.NamespaceName, "bar")))
|
||||
suite.Assert().NoError(
|
||||
suite.state.Create(
|
||||
context.Background(),
|
||||
network.NewTimeServerSpec(network.NamespaceName, "bar"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func TestTimeServerSpecSuite(t *testing.T) {
|
||||
|
@ -33,6 +33,7 @@ type PerfSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
//nolint:containedctx
|
||||
ctx context.Context
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
@ -65,36 +66,54 @@ func (suite *PerfSuite) TestReconcile() {
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
cpu, err := suite.state.Get(suite.ctx, resource.NewMetadata(perfresource.NamespaceName, perfresource.CPUType, perfresource.CPUID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
cpu, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
perfresource.NamespaceName,
|
||||
perfresource.CPUType,
|
||||
perfresource.CPUID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
mem, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
perfresource.NamespaceName,
|
||||
perfresource.MemoryType,
|
||||
perfresource.MemoryID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
mem, err := suite.state.Get(suite.ctx, resource.NewMetadata(perfresource.NamespaceName, perfresource.MemoryType, perfresource.MemoryID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
cpuSpec := cpu.Spec().(*perfresource.CPUSpec) //nolint:errcheck,forcetypeassert
|
||||
memSpec := mem.Spec().(*perfresource.MemorySpec) //nolint:errcheck,forcetypeassert
|
||||
|
||||
cpuSpec := cpu.Spec().(*perfresource.CPUSpec) //nolint:errcheck,forcetypeassert
|
||||
memSpec := mem.Spec().(*perfresource.MemorySpec) //nolint:errcheck,forcetypeassert
|
||||
if len(cpuSpec.CPU) == 0 || memSpec.MemTotal == 0 {
|
||||
return retry.ExpectedError(fmt.Errorf("cpu spec does not contain any CPU or Total memory is zero"))
|
||||
}
|
||||
|
||||
if len(cpuSpec.CPU) == 0 || memSpec.MemTotal == 0 {
|
||||
return retry.ExpectedError(fmt.Errorf("cpu spec does not contain any CPU or Total memory is zero"))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *PerfSuite) TearDownTest() {
|
||||
|
@ -38,7 +38,7 @@ type RuntimeSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -92,10 +92,14 @@ func (suite *RuntimeSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ type EventsSinkSuite struct {
|
||||
wg sync.WaitGroup
|
||||
eg errgroup.Group
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -84,11 +84,15 @@ func (suite *EventsSinkSuite) SetupTest() {
|
||||
suite.cmdline = procfs.NewCmdline(fmt.Sprintf("%s=%s", constants.KernelParamEventsSink, "localhost"))
|
||||
suite.drainer = talosruntime.NewDrainer()
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&controllerruntime.EventsSinkController{
|
||||
V1Alpha1Events: suite.events,
|
||||
Cmdline: suite.cmdline,
|
||||
Drainer: suite.drainer,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&controllerruntime.EventsSinkController{
|
||||
V1Alpha1Events: suite.events,
|
||||
Cmdline: suite.cmdline,
|
||||
Drainer: suite.drainer,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
}
|
||||
@ -121,46 +125,56 @@ func (suite *EventsSinkSuite) startServer(ctx context.Context) {
|
||||
suite.server = grpc.NewServer()
|
||||
eventsapi.RegisterEventSinkServiceServer(suite.server, suite.sink)
|
||||
|
||||
suite.eg.Go(func() error {
|
||||
<-ctx.Done()
|
||||
suite.eg.Go(
|
||||
func() error {
|
||||
<-ctx.Done()
|
||||
|
||||
suite.server.Stop()
|
||||
suite.server.Stop()
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
suite.eg.Go(func() error {
|
||||
return suite.server.Serve(lis)
|
||||
})
|
||||
suite.eg.Go(
|
||||
func() error {
|
||||
return suite.server.Serve(lis)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *EventsSinkSuite) TestPublish() {
|
||||
ctx, cancel := context.WithCancel(suite.ctx)
|
||||
defer cancel()
|
||||
|
||||
suite.events.Publish(&machine.AddressEvent{
|
||||
Hostname: "localhost",
|
||||
})
|
||||
suite.events.Publish(
|
||||
&machine.AddressEvent{
|
||||
Hostname: "localhost",
|
||||
},
|
||||
)
|
||||
|
||||
suite.events.Publish(&machine.PhaseEvent{
|
||||
Phase: "test",
|
||||
Action: machine.PhaseEvent_START,
|
||||
})
|
||||
suite.events.Publish(
|
||||
&machine.PhaseEvent{
|
||||
Phase: "test",
|
||||
Action: machine.PhaseEvent_START,
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().Equal(0, len(suite.handler.events))
|
||||
|
||||
suite.startServer(ctx)
|
||||
|
||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(func() error {
|
||||
suite.handler.eventsMu.Lock()
|
||||
defer suite.handler.eventsMu.Unlock()
|
||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(
|
||||
func() error {
|
||||
suite.handler.eventsMu.Lock()
|
||||
defer suite.handler.eventsMu.Unlock()
|
||||
|
||||
if len(suite.handler.events) != 2 {
|
||||
return retry.ExpectedErrorf("expected 2 events")
|
||||
}
|
||||
if len(suite.handler.events) != 2 {
|
||||
return retry.ExpectedErrorf("expected 2 events")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
@ -169,14 +183,18 @@ func (suite *EventsSinkSuite) TestDrain() {
|
||||
defer cancel()
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
suite.events.Publish(&machine.PhaseEvent{
|
||||
Phase: "test",
|
||||
Action: machine.PhaseEvent_START,
|
||||
})
|
||||
suite.events.Publish(&machine.PhaseEvent{
|
||||
Phase: "test",
|
||||
Action: machine.PhaseEvent_STOP,
|
||||
})
|
||||
suite.events.Publish(
|
||||
&machine.PhaseEvent{
|
||||
Phase: "test",
|
||||
Action: machine.PhaseEvent_START,
|
||||
},
|
||||
)
|
||||
suite.events.Publish(
|
||||
&machine.PhaseEvent{
|
||||
Phase: "test",
|
||||
Action: machine.PhaseEvent_STOP,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
suite.Require().Equal(0, len(suite.handler.events))
|
||||
@ -188,28 +206,34 @@ func (suite *EventsSinkSuite) TestDrain() {
|
||||
|
||||
var eg errgroup.Group
|
||||
|
||||
eg.Go(func() error {
|
||||
return suite.drainer.Drain(c)
|
||||
})
|
||||
eg.Go(
|
||||
func() error {
|
||||
return suite.drainer.Drain(c)
|
||||
},
|
||||
)
|
||||
|
||||
eg.Go(func() error {
|
||||
time.Sleep(time.Millisecond * 300)
|
||||
eg.Go(
|
||||
func() error {
|
||||
time.Sleep(time.Millisecond * 300)
|
||||
|
||||
suite.startServer(ctx)
|
||||
suite.startServer(ctx)
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(func() error {
|
||||
suite.handler.eventsMu.Lock()
|
||||
defer suite.handler.eventsMu.Unlock()
|
||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(
|
||||
func() error {
|
||||
suite.handler.eventsMu.Lock()
|
||||
defer suite.handler.eventsMu.Unlock()
|
||||
|
||||
if len(suite.handler.events) != 20 {
|
||||
return retry.ExpectedErrorf("expected 20 events, got %d", len(suite.handler.events))
|
||||
}
|
||||
if len(suite.handler.events) != 20 {
|
||||
return retry.ExpectedErrorf("expected 20 events, got %d", len(suite.handler.events))
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Require().NoError(eg.Wait())
|
||||
|
@ -60,7 +60,7 @@ type KmsgLogDeliverySuite struct {
|
||||
drainer *talosruntime.Drainer
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
handler *logHandler
|
||||
@ -92,13 +92,23 @@ func (suite *KmsgLogDeliverySuite) SetupTest() {
|
||||
suite.srv.Serve() //nolint:errcheck
|
||||
}()
|
||||
|
||||
suite.cmdline = procfs.NewCmdline(fmt.Sprintf("%s=%s", constants.KernelParamLoggingKernel, fmt.Sprintf("tcp://%s", listener.Addr())))
|
||||
suite.cmdline = procfs.NewCmdline(
|
||||
fmt.Sprintf(
|
||||
"%s=%s",
|
||||
constants.KernelParamLoggingKernel,
|
||||
fmt.Sprintf("tcp://%s", listener.Addr()),
|
||||
),
|
||||
)
|
||||
suite.drainer = talosruntime.NewDrainer()
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&controllerruntime.KmsgLogDeliveryController{
|
||||
Cmdline: suite.cmdline,
|
||||
Drainer: suite.drainer,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&controllerruntime.KmsgLogDeliveryController{
|
||||
Cmdline: suite.cmdline,
|
||||
Drainer: suite.drainer,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
status := network.NewStatus(network.NamespaceName, network.StatusID)
|
||||
status.TypedSpec().AddressReady = true
|
||||
@ -120,13 +130,15 @@ func (suite *KmsgLogDeliverySuite) TestDelivery() {
|
||||
suite.startRuntime()
|
||||
|
||||
// controller should deliver some kernel logs from host's kmsg buffer
|
||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(func() error {
|
||||
if suite.handler.getCount() == 0 {
|
||||
return retry.ExpectedErrorf("no logs received")
|
||||
}
|
||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(
|
||||
func() error {
|
||||
if suite.handler.getCount() == 0 {
|
||||
return retry.ExpectedErrorf("no logs received")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
@ -134,13 +146,15 @@ func (suite *KmsgLogDeliverySuite) TestDrain() {
|
||||
suite.startRuntime()
|
||||
|
||||
// wait for controller to start delivering some logs
|
||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(func() error {
|
||||
if suite.handler.getCount() == 0 {
|
||||
return retry.ExpectedErrorf("no logs received")
|
||||
}
|
||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(
|
||||
func() error {
|
||||
if suite.handler.getCount() == 0 {
|
||||
return retry.ExpectedErrorf("no logs received")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
// drain should be successful, i.e. controller should stop on its own before context is canceled
|
||||
|
@ -332,7 +332,8 @@ func (ctrl *APIController) generateControlPlane(ctx context.Context, r controlle
|
||||
}
|
||||
|
||||
func (ctrl *APIController) generateJoin(ctx context.Context, r controller.Runtime, logger *zap.Logger,
|
||||
rootSpec *secrets.OSRootSpec, endpointsStr []string, certSANs *secrets.CertSANSpec) error {
|
||||
rootSpec *secrets.OSRootSpec, endpointsStr []string, certSANs *secrets.CertSANSpec,
|
||||
) error {
|
||||
remoteGen, err := gen.NewRemoteGenerator(rootSpec.Token, endpointsStr, rootSpec.CA)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed creating trustd client: %w", err)
|
||||
|
@ -37,7 +37,7 @@ type APICertSANsSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -78,30 +78,46 @@ func (suite *APICertSANsSuite) TestReconcileControlPlane() {
|
||||
hostnameStatus.TypedSpec().Domainname = "some.org"
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||
|
||||
nodeAddresses := network.NewNodeAddress(network.NamespaceName, network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, k8s.NodeAddressFilterNoK8s))
|
||||
nodeAddresses.TypedSpec().Addresses = []netaddr.IPPrefix{netaddr.MustParseIPPrefix("10.2.1.3/24"), netaddr.MustParseIPPrefix("172.16.0.1/32")}
|
||||
nodeAddresses := network.NewNodeAddress(
|
||||
network.NamespaceName,
|
||||
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, k8s.NodeAddressFilterNoK8s),
|
||||
)
|
||||
nodeAddresses.TypedSpec().Addresses = []netaddr.IPPrefix{
|
||||
netaddr.MustParseIPPrefix("10.2.1.3/24"),
|
||||
netaddr.MustParseIPPrefix("172.16.0.1/32"),
|
||||
}
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodeAddresses))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
certSANs, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.CertSANType, secrets.CertSANAPIID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
certSANs, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
secrets.NamespaceName,
|
||||
secrets.CertSANType,
|
||||
secrets.CertSANAPIID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := certSANs.(*secrets.CertSAN).TypedSpec()
|
||||
|
||||
spec := certSANs.(*secrets.CertSAN).TypedSpec()
|
||||
suite.Assert().Equal([]string{"bar", "bar.some.org", "some.org"}, spec.DNSNames)
|
||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", spec.IPs))
|
||||
suite.Assert().Equal("bar.some.org", spec.FQDN)
|
||||
|
||||
suite.Assert().Equal([]string{"bar", "bar.some.org", "some.org"}, spec.DNSNames)
|
||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", spec.IPs))
|
||||
suite.Assert().Equal("bar.some.org", spec.FQDN)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *APICertSANsSuite) TearDownTest() {
|
||||
|
@ -41,7 +41,7 @@ type APISuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -110,49 +110,65 @@ func (suite *APISuite) TestReconcileControlPlane() {
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, certSANs))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
certs, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.APIType, secrets.APIID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
certs, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
secrets.NamespaceName,
|
||||
secrets.APIType,
|
||||
secrets.APIID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
apiCerts := certs.(*secrets.API).TypedSpec()
|
||||
|
||||
apiCerts := certs.(*secrets.API).TypedSpec()
|
||||
suite.Assert().Equal(talosCA.CrtPEM, apiCerts.CA.Crt)
|
||||
suite.Assert().Nil(apiCerts.CA.Key)
|
||||
|
||||
suite.Assert().Equal(talosCA.CrtPEM, apiCerts.CA.Crt)
|
||||
suite.Assert().Nil(apiCerts.CA.Key)
|
||||
serverCert, err := apiCerts.Server.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
serverCert, err := apiCerts.Server.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
suite.Assert().Equal([]string{"example.com", "foo", "foo.example.com"}, serverCert.DNSNames)
|
||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", serverCert.IPAddresses))
|
||||
|
||||
suite.Assert().Equal([]string{"example.com", "foo", "foo.example.com"}, serverCert.DNSNames)
|
||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", serverCert.IPAddresses))
|
||||
suite.Assert().Equal("foo.example.com", serverCert.Subject.CommonName)
|
||||
suite.Assert().Empty(serverCert.Subject.Organization)
|
||||
|
||||
suite.Assert().Equal("foo.example.com", serverCert.Subject.CommonName)
|
||||
suite.Assert().Empty(serverCert.Subject.Organization)
|
||||
suite.Assert().Equal(
|
||||
stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment,
|
||||
serverCert.KeyUsage,
|
||||
)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageServerAuth}, serverCert.ExtKeyUsage)
|
||||
|
||||
suite.Assert().Equal(stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment, serverCert.KeyUsage)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageServerAuth}, serverCert.ExtKeyUsage)
|
||||
clientCert, err := apiCerts.Client.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
clientCert, err := apiCerts.Client.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
suite.Assert().Empty(clientCert.DNSNames)
|
||||
suite.Assert().Empty(clientCert.IPAddresses)
|
||||
|
||||
suite.Assert().Empty(clientCert.DNSNames)
|
||||
suite.Assert().Empty(clientCert.IPAddresses)
|
||||
suite.Assert().Equal("foo.example.com", clientCert.Subject.CommonName)
|
||||
suite.Assert().Equal([]string{string(role.Impersonator)}, clientCert.Subject.Organization)
|
||||
|
||||
suite.Assert().Equal("foo.example.com", clientCert.Subject.CommonName)
|
||||
suite.Assert().Equal([]string{string(role.Impersonator)}, clientCert.Subject.Organization)
|
||||
suite.Assert().Equal(
|
||||
stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment,
|
||||
clientCert.KeyUsage,
|
||||
)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageClientAuth}, clientCert.ExtKeyUsage)
|
||||
|
||||
suite.Assert().Equal(stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment, clientCert.KeyUsage)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageClientAuth}, clientCert.ExtKeyUsage)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *APISuite) TearDownTest() {
|
||||
|
@ -37,7 +37,7 @@ type KubeletSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -75,43 +75,55 @@ func (suite *KubeletSuite) TestReconcile() {
|
||||
|
||||
k8sCA := x509.NewCertificateAndKeyFromCertificateAuthority(ca)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||
Endpoint: &v1alpha1.Endpoint{
|
||||
URL: u,
|
||||
},
|
||||
},
|
||||
ClusterCA: k8sCA,
|
||||
BootstrapToken: "abc.def",
|
||||
},
|
||||
ClusterCA: k8sCA,
|
||||
BootstrapToken: "abc.def",
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletSecrets, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubeletType, secrets.KubeletID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
kubeletSecrets, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
secrets.NamespaceName,
|
||||
secrets.KubeletType,
|
||||
secrets.KubeletID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := kubeletSecrets.(*secrets.Kubelet).TypedSpec()
|
||||
|
||||
spec := kubeletSecrets.(*secrets.Kubelet).TypedSpec()
|
||||
suite.Assert().Equal("https://foo:6443", spec.Endpoint.String())
|
||||
suite.Assert().Equal(k8sCA, spec.CA)
|
||||
suite.Assert().Equal("abc", spec.BootstrapTokenID)
|
||||
suite.Assert().Equal("def", spec.BootstrapTokenSecret)
|
||||
|
||||
suite.Assert().Equal("https://foo:6443", spec.Endpoint.String())
|
||||
suite.Assert().Equal(k8sCA, spec.CA)
|
||||
suite.Assert().Equal("abc", spec.BootstrapTokenID)
|
||||
suite.Assert().Equal("def", spec.BootstrapTokenSecret)
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *KubeletSuite) TearDownTest() {
|
||||
|
@ -177,7 +177,8 @@ func (ctrl *KubernetesController) Run(ctx context.Context, r controller.Runtime,
|
||||
}
|
||||
|
||||
func (ctrl *KubernetesController) updateSecrets(k8sRoot *secrets.KubernetesRootSpec, k8sSecrets *secrets.KubernetesCertsSpec,
|
||||
certSANs *secrets.CertSANSpec) error {
|
||||
certSANs *secrets.CertSANSpec,
|
||||
) error {
|
||||
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(k8sRoot.CA)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse CA certificate: %w", err)
|
||||
|
@ -39,7 +39,7 @@ type KubernetesCertSANsSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -86,40 +86,57 @@ func (suite *KubernetesCertSANsSuite) TestReconcile() {
|
||||
hostnameStatus.TypedSpec().Domainname = "example.com"
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||
|
||||
nodeAddresses := network.NewNodeAddress(network.NamespaceName, network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, k8s.NodeAddressFilterNoK8s))
|
||||
nodeAddresses.TypedSpec().Addresses = []netaddr.IPPrefix{netaddr.MustParseIPPrefix("10.2.1.3/24"), netaddr.MustParseIPPrefix("172.16.0.1/32")}
|
||||
nodeAddresses := network.NewNodeAddress(
|
||||
network.NamespaceName,
|
||||
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, k8s.NodeAddressFilterNoK8s),
|
||||
)
|
||||
nodeAddresses.TypedSpec().Addresses = []netaddr.IPPrefix{
|
||||
netaddr.MustParseIPPrefix("10.2.1.3/24"),
|
||||
netaddr.MustParseIPPrefix("172.16.0.1/32"),
|
||||
}
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodeAddresses))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
certSANs, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.CertSANType, secrets.CertSANKubernetesID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
certSANs, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
secrets.NamespaceName,
|
||||
secrets.CertSANType,
|
||||
secrets.CertSANKubernetesID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
spec := certSANs.(*secrets.CertSAN).TypedSpec()
|
||||
|
||||
spec := certSANs.(*secrets.CertSAN).TypedSpec()
|
||||
suite.Assert().Equal(
|
||||
[]string{
|
||||
"example.com",
|
||||
"foo",
|
||||
"foo.example.com",
|
||||
"kubernetes",
|
||||
"kubernetes.default",
|
||||
"kubernetes.default.svc",
|
||||
"kubernetes.default.svc.cluster.remote",
|
||||
"localhost",
|
||||
"some.url",
|
||||
}, spec.DNSNames,
|
||||
)
|
||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", spec.IPs))
|
||||
|
||||
suite.Assert().Equal(
|
||||
[]string{
|
||||
"example.com",
|
||||
"foo",
|
||||
"foo.example.com",
|
||||
"kubernetes",
|
||||
"kubernetes.default",
|
||||
"kubernetes.default.svc",
|
||||
"kubernetes.default.svc.cluster.remote",
|
||||
"localhost",
|
||||
"some.url",
|
||||
}, spec.DNSNames)
|
||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", spec.IPs))
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *KubernetesCertSANsSuite) TearDownTest() {
|
||||
|
@ -44,7 +44,7 @@ type KubernetesSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -138,81 +138,116 @@ func (suite *KubernetesSuite) TestReconcile() {
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, certSANs))
|
||||
|
||||
timeSync := timeresource.NewStatus()
|
||||
timeSync.SetStatus(timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
})
|
||||
timeSync.SetStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeSync))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
certs, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubernetesType, secrets.KubernetesID, resource.VersionUndefined))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
certs, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
secrets.NamespaceName,
|
||||
secrets.KubernetesType,
|
||||
secrets.KubernetesID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
kubernetesCerts := certs.(*secrets.Kubernetes).Certs()
|
||||
|
||||
kubernetesCerts := certs.(*secrets.Kubernetes).Certs()
|
||||
|
||||
apiCert, err := kubernetesCerts.APIServer.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().Equal(
|
||||
[]string{
|
||||
"example.com",
|
||||
"foo",
|
||||
"foo.example.com",
|
||||
"kubernetes",
|
||||
"kubernetes.default",
|
||||
"kubernetes.default.svc",
|
||||
"kubernetes.default.svc.cluster.remote",
|
||||
"localhost",
|
||||
"some.url",
|
||||
}, apiCert.DNSNames)
|
||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", apiCert.IPAddresses))
|
||||
|
||||
suite.Assert().Equal("kube-apiserver", apiCert.Subject.CommonName)
|
||||
suite.Assert().Equal([]string{"kube-master"}, apiCert.Subject.Organization)
|
||||
|
||||
suite.Assert().Equal(stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment, apiCert.KeyUsage)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageServerAuth}, apiCert.ExtKeyUsage)
|
||||
|
||||
clientCert, err := kubernetesCerts.APIServerKubeletClient.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().Empty(clientCert.DNSNames)
|
||||
suite.Assert().Empty(clientCert.IPAddresses)
|
||||
|
||||
suite.Assert().Equal(constants.KubernetesAPIServerKubeletClientCommonName, clientCert.Subject.CommonName)
|
||||
suite.Assert().Equal([]string{constants.KubernetesAdminCertOrganization}, clientCert.Subject.Organization)
|
||||
|
||||
suite.Assert().Equal(stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment, clientCert.KeyUsage)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageClientAuth}, clientCert.ExtKeyUsage)
|
||||
|
||||
frontProxyCert, err := kubernetesCerts.FrontProxy.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().Empty(frontProxyCert.DNSNames)
|
||||
suite.Assert().Empty(frontProxyCert.IPAddresses)
|
||||
|
||||
suite.Assert().Equal("front-proxy-client", frontProxyCert.Subject.CommonName)
|
||||
suite.Assert().Empty(frontProxyCert.Subject.Organization)
|
||||
|
||||
suite.Assert().Equal(stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment, frontProxyCert.KeyUsage)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageClientAuth}, frontProxyCert.ExtKeyUsage)
|
||||
|
||||
for _, kubeconfig := range []string{kubernetesCerts.ControllerManagerKubeconfig, kubernetesCerts.SchedulerKubeconfig, kubernetesCerts.AdminKubeconfig} {
|
||||
config, err := clientcmd.Load([]byte(kubeconfig))
|
||||
apiCert, err := kubernetesCerts.APIServer.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(clientcmd.ConfirmUsable(*config, config.CurrentContext))
|
||||
}
|
||||
suite.Assert().Equal(
|
||||
[]string{
|
||||
"example.com",
|
||||
"foo",
|
||||
"foo.example.com",
|
||||
"kubernetes",
|
||||
"kubernetes.default",
|
||||
"kubernetes.default.svc",
|
||||
"kubernetes.default.svc.cluster.remote",
|
||||
"localhost",
|
||||
"some.url",
|
||||
}, apiCert.DNSNames,
|
||||
)
|
||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", apiCert.IPAddresses))
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
suite.Assert().Equal("kube-apiserver", apiCert.Subject.CommonName)
|
||||
suite.Assert().Equal([]string{"kube-master"}, apiCert.Subject.Organization)
|
||||
|
||||
suite.Assert().Equal(
|
||||
stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment,
|
||||
apiCert.KeyUsage,
|
||||
)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageServerAuth}, apiCert.ExtKeyUsage)
|
||||
|
||||
clientCert, err := kubernetesCerts.APIServerKubeletClient.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().Empty(clientCert.DNSNames)
|
||||
suite.Assert().Empty(clientCert.IPAddresses)
|
||||
|
||||
suite.Assert().Equal(
|
||||
constants.KubernetesAPIServerKubeletClientCommonName,
|
||||
clientCert.Subject.CommonName,
|
||||
)
|
||||
suite.Assert().Equal(
|
||||
[]string{constants.KubernetesAdminCertOrganization},
|
||||
clientCert.Subject.Organization,
|
||||
)
|
||||
|
||||
suite.Assert().Equal(
|
||||
stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment,
|
||||
clientCert.KeyUsage,
|
||||
)
|
||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageClientAuth}, clientCert.ExtKeyUsage)
|
||||
|
||||
frontProxyCert, err := kubernetesCerts.FrontProxy.GetCert()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().Empty(frontProxyCert.DNSNames)
|
||||
suite.Assert().Empty(frontProxyCert.IPAddresses)
|
||||
|
||||
suite.Assert().Equal("front-proxy-client", frontProxyCert.Subject.CommonName)
|
||||
suite.Assert().Empty(frontProxyCert.Subject.Organization)
|
||||
|
||||
suite.Assert().Equal(
|
||||
stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment,
|
||||
frontProxyCert.KeyUsage,
|
||||
)
|
||||
suite.Assert().Equal(
|
||||
[]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageClientAuth},
|
||||
frontProxyCert.ExtKeyUsage,
|
||||
)
|
||||
|
||||
for _, kubeconfig := range []string{
|
||||
kubernetesCerts.ControllerManagerKubeconfig,
|
||||
kubernetesCerts.SchedulerKubeconfig,
|
||||
kubernetesCerts.AdminKubeconfig,
|
||||
} {
|
||||
config, err := clientcmd.Load([]byte(kubeconfig))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(clientcmd.ConfirmUsable(*config, config.CurrentContext))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *KubernetesSuite) TearDownTest() {
|
||||
|
@ -40,7 +40,7 @@ type ManagerSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
s *grpc.Server
|
||||
@ -90,9 +90,13 @@ func (suite *ManagerSuite) SetupTest() {
|
||||
|
||||
cmdline := procfs.NewCmdline(fmt.Sprintf("%s=%s", constants.KernelParamSideroLink, lis.Addr().String()))
|
||||
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&siderolinkctrl.ManagerController{
|
||||
Cmdline: cmdline,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&siderolinkctrl.ManagerController{
|
||||
Cmdline: cmdline,
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ManagerSuite) startRuntime() {
|
||||
@ -113,56 +117,76 @@ func (suite *ManagerSuite) TestReconcile() {
|
||||
|
||||
nodeAddress := netaddr.MustParseIPPrefix(mockNodeAddressPrefix)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
addressResource, err := suite.state.Get(suite.ctx, resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.AddressSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.AddressID(constants.SideroLinkName, nodeAddress)),
|
||||
resource.VersionUndefined,
|
||||
))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
addressResource, err := suite.state.Get(
|
||||
suite.ctx, resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.AddressSpecType,
|
||||
network.LayeredID(
|
||||
network.ConfigOperator,
|
||||
network.AddressID(constants.SideroLinkName, nodeAddress),
|
||||
),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
address := addressResource.(*network.AddressSpec).TypedSpec()
|
||||
|
||||
address := addressResource.(*network.AddressSpec).TypedSpec()
|
||||
suite.Assert().Equal(nodeAddress, address.Address)
|
||||
suite.Assert().Equal(network.ConfigOperator, address.ConfigLayer)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, address.Family)
|
||||
suite.Assert().Equal(constants.SideroLinkName, address.LinkName)
|
||||
|
||||
suite.Assert().Equal(nodeAddress, address.Address)
|
||||
suite.Assert().Equal(network.ConfigOperator, address.ConfigLayer)
|
||||
suite.Assert().Equal(nethelpers.FamilyInet6, address.Family)
|
||||
suite.Assert().Equal(constants.SideroLinkName, address.LinkName)
|
||||
linkResource, err := suite.state.Get(
|
||||
suite.ctx, resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.LinkSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.SideroLinkName)),
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
linkResource, err := suite.state.Get(suite.ctx, resource.NewMetadata(
|
||||
network.ConfigNamespaceName,
|
||||
network.LinkSpecType,
|
||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.SideroLinkName)),
|
||||
resource.VersionUndefined,
|
||||
))
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
link := linkResource.(*network.LinkSpec).TypedSpec()
|
||||
|
||||
link := linkResource.(*network.LinkSpec).TypedSpec()
|
||||
suite.Assert().Equal("wireguard", link.Kind)
|
||||
suite.Assert().Equal(network.ConfigOperator, link.ConfigLayer)
|
||||
suite.Assert().NotEmpty(link.Wireguard.PrivateKey)
|
||||
suite.Assert().Len(link.Wireguard.Peers, 1)
|
||||
suite.Assert().Equal(mockServerEndpoint, link.Wireguard.Peers[0].Endpoint)
|
||||
suite.Assert().Equal(mockServerPublicKey, link.Wireguard.Peers[0].PublicKey)
|
||||
suite.Assert().Equal(
|
||||
[]netaddr.IPPrefix{
|
||||
netaddr.IPPrefixFrom(
|
||||
netaddr.MustParseIP(mockServerAddress),
|
||||
128,
|
||||
),
|
||||
}, link.Wireguard.Peers[0].AllowedIPs,
|
||||
)
|
||||
suite.Assert().Equal(
|
||||
constants.SideroLinkDefaultPeerKeepalive,
|
||||
link.Wireguard.Peers[0].PersistentKeepaliveInterval,
|
||||
)
|
||||
|
||||
suite.Assert().Equal("wireguard", link.Kind)
|
||||
suite.Assert().Equal(network.ConfigOperator, link.ConfigLayer)
|
||||
suite.Assert().NotEmpty(link.Wireguard.PrivateKey)
|
||||
suite.Assert().Len(link.Wireguard.Peers, 1)
|
||||
suite.Assert().Equal(mockServerEndpoint, link.Wireguard.Peers[0].Endpoint)
|
||||
suite.Assert().Equal(mockServerPublicKey, link.Wireguard.Peers[0].PublicKey)
|
||||
suite.Assert().Equal([]netaddr.IPPrefix{netaddr.IPPrefixFrom(netaddr.MustParseIP(mockServerAddress), 128)}, link.Wireguard.Peers[0].AllowedIPs)
|
||||
suite.Assert().Equal(constants.SideroLinkDefaultPeerKeepalive, link.Wireguard.Peers[0].PersistentKeepaliveInterval)
|
||||
|
||||
return nil
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *ManagerSuite) TearDownTest() {
|
||||
|
@ -41,7 +41,7 @@ type SyncSuite struct {
|
||||
runtime *runtime.Runtime
|
||||
wg sync.WaitGroup
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
syncerMu sync.Mutex
|
||||
@ -72,7 +72,15 @@ func (suite *SyncSuite) startRuntime() {
|
||||
}
|
||||
|
||||
func (suite *SyncSuite) assertTimeStatus(spec timeresource.StatusSpec) error {
|
||||
r, err := suite.state.Get(suite.ctx, resource.NewMetadata(v1alpha1resource.NamespaceName, timeresource.StatusType, timeresource.StatusID, resource.VersionUndefined))
|
||||
r, err := suite.state.Get(
|
||||
suite.ctx,
|
||||
resource.NewMetadata(
|
||||
v1alpha1resource.NamespaceName,
|
||||
timeresource.StatusType,
|
||||
timeresource.StatusID,
|
||||
resource.VersionUndefined,
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return retry.ExpectedError(err)
|
||||
@ -91,10 +99,14 @@ func (suite *SyncSuite) assertTimeStatus(spec timeresource.StatusSpec) error {
|
||||
}
|
||||
|
||||
func (suite *SyncSuite) TestReconcileContainerMode() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeContainer,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeContainer,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
timeServers := network.NewTimeServerStatus(network.NamespaceName, network.TimeServerID)
|
||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||
@ -102,24 +114,30 @@ func (suite *SyncSuite) TestReconcileContainerMode() {
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 0,
|
||||
SyncDisabled: true,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 0,
|
||||
SyncDisabled: true,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *SyncSuite) TestReconcileSyncDisabled() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -127,48 +145,58 @@ func (suite *SyncSuite) TestReconcileSyncDisabled() {
|
||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeDisabled: true,
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeDisabled: true,
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 0,
|
||||
SyncDisabled: true,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 0,
|
||||
SyncDisabled: true,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *SyncSuite) TestReconcileSyncDefaultConfig() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -176,32 +204,40 @@ func (suite *SyncSuite) TestReconcileSyncDefaultConfig() {
|
||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
})
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *SyncSuite) TestReconcileSyncChangeConfig() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -209,126 +245,150 @@ func (suite *SyncSuite) TestReconcileSyncChangeConfig() {
|
||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
})
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
var mockSyncer *mockSyncer
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
mockSyncer = suite.getMockSyncer()
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
mockSyncer = suite.getMockSyncer()
|
||||
|
||||
if mockSyncer == nil {
|
||||
return retry.ExpectedError(fmt.Errorf("syncer not created yet"))
|
||||
}
|
||||
if mockSyncer == nil {
|
||||
return retry.ExpectedError(fmt.Errorf("syncer not created yet"))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.Assert().Equal([]string{constants.DefaultNTPServer}, mockSyncer.getTimeServers())
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
close(mockSyncer.syncedCh)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
_, err := suite.state.UpdateWithConflicts(
|
||||
suite.ctx, timeServers.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.TimeServerStatus).TypedSpec().NTPServers = []string{"127.0.0.1"}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
|
||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, timeServers.Metadata(), func(r resource.Resource) error {
|
||||
r.(*network.TimeServerStatus).TypedSpec().NTPServers = []string{"127.0.0.1"}
|
||||
|
||||
return nil
|
||||
})
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
if !reflect.DeepEqual(mockSyncer.getTimeServers(), []string{"127.0.0.1"}) {
|
||||
return retry.ExpectedError(fmt.Errorf("time servers not updated yet"))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
if !reflect.DeepEqual(mockSyncer.getTimeServers(), []string{"127.0.0.1"}) {
|
||||
return retry.ExpectedError(fmt.Errorf("time servers not updated yet"))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
mockSyncer.epochCh <- struct{}{}
|
||||
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 1,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
_, err = suite.state.UpdateWithConflicts(
|
||||
suite.ctx, cfg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineTime = &v1alpha1.TimeConfig{
|
||||
TimeDisabled: true,
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
))
|
||||
|
||||
mockSyncer.epochCh <- struct{}{}
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 1,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
|
||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, cfg.Metadata(), func(r resource.Resource) error {
|
||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineTime = &v1alpha1.TimeConfig{
|
||||
TimeDisabled: true,
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 1,
|
||||
SyncDisabled: true,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 1,
|
||||
SyncDisabled: true,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *SyncSuite) TestReconcileSyncBootTimeout() {
|
||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
}))
|
||||
suite.Require().NoError(
|
||||
suite.runtime.RegisterController(
|
||||
&timectrl.SyncController{
|
||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||
NewNTPSyncer: suite.newMockSyncer,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.startRuntime()
|
||||
|
||||
@ -336,41 +396,47 @@ func (suite *SyncSuite) TestReconcileSyncBootTimeout() {
|
||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
|
||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeBootTimeout: 5 * time.Second,
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: false,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
cfg := config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineTime: &v1alpha1.TimeConfig{
|
||||
TimeBootTimeout: 5 * time.Second,
|
||||
},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||
})
|
||||
)
|
||||
|
||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||
|
||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
suite.Assert().NoError(
|
||||
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||
func() error {
|
||||
return suite.assertTimeStatus(
|
||||
timeresource.StatusSpec{
|
||||
Synced: true,
|
||||
Epoch: 0,
|
||||
SyncDisabled: false,
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (suite *SyncSuite) TearDownTest() {
|
||||
@ -381,10 +447,14 @@ func (suite *SyncSuite) TearDownTest() {
|
||||
suite.wg.Wait()
|
||||
|
||||
// trigger updates in resources to stop watch loops
|
||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
}))
|
||||
err := suite.state.Create(
|
||||
context.Background(), config.NewMachineConfig(
|
||||
&v1alpha1.Config{
|
||||
ConfigVersion: "v1alpha1",
|
||||
MachineConfig: &v1alpha1.MachineConfig{},
|
||||
},
|
||||
),
|
||||
)
|
||||
if state.IsConflictError(err) {
|
||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
package rpi4
|
||||
|
||||
import (
|
||||
_ "embed" //nolint:gci
|
||||
_ "embed"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
|
@ -1845,7 +1845,8 @@ func StopDBus(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc
|
||||
}
|
||||
|
||||
func pauseOnFailure(callback func(runtime.Sequence, interface{}) (runtime.TaskExecutionFunc, string),
|
||||
timeout time.Duration) func(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||
timeout time.Duration,
|
||||
) func(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||
return func(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||
f, name := callback(seq, data)
|
||||
|
||||
|
@ -34,7 +34,7 @@ type containerdRunner struct {
|
||||
stopped chan struct{}
|
||||
|
||||
client *containerd.Client
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
container containerd.Container
|
||||
stdinCloser *StdinCloser
|
||||
}
|
||||
@ -196,7 +196,13 @@ func (c *containerdRunner) Run(eventSink events.Recorder) error {
|
||||
return nil
|
||||
case <-c.stop:
|
||||
// graceful stop the task
|
||||
eventSink(events.StateStopping, "Sending SIGTERM to task %s (PID %d, container %s)", task.ID(), task.Pid(), c.container.ID())
|
||||
eventSink(
|
||||
events.StateStopping,
|
||||
"Sending SIGTERM to task %s (PID %d, container %s)",
|
||||
task.ID(),
|
||||
task.Pid(),
|
||||
c.container.ID(),
|
||||
)
|
||||
|
||||
if err = task.Kill(c.ctx, syscall.SIGTERM, containerd.WithKillAll); err != nil {
|
||||
return fmt.Errorf("error sending SIGTERM: %w", err)
|
||||
@ -209,7 +215,13 @@ func (c *containerdRunner) Run(eventSink events.Recorder) error {
|
||||
return nil
|
||||
case <-time.After(c.opts.GracefulShutdownTimeout):
|
||||
// kill the process
|
||||
eventSink(events.StateStopping, "Sending SIGKILL to task %s (PID %d, container %s)", task.ID(), task.Pid(), c.container.ID())
|
||||
eventSink(
|
||||
events.StateStopping,
|
||||
"Sending SIGKILL to task %s (PID %d, container %s)",
|
||||
task.ID(),
|
||||
task.Pid(),
|
||||
c.container.ID(),
|
||||
)
|
||||
|
||||
if err = task.Kill(c.ctx, syscall.SIGKILL, containerd.WithKillAll); err != nil {
|
||||
return fmt.Errorf("error sending SIGKILL: %w", err)
|
||||
@ -233,21 +245,27 @@ func (c *containerdRunner) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *containerdRunner) newContainerOpts(image containerd.Image, specOpts []oci.SpecOpts) []containerd.NewContainerOpts {
|
||||
func (c *containerdRunner) newContainerOpts(
|
||||
image containerd.Image,
|
||||
specOpts []oci.SpecOpts,
|
||||
) []containerd.NewContainerOpts {
|
||||
containerOpts := []containerd.NewContainerOpts{}
|
||||
|
||||
if image != nil {
|
||||
containerOpts = append(containerOpts,
|
||||
containerOpts = append(
|
||||
containerOpts,
|
||||
containerd.WithImage(image),
|
||||
containerd.WithNewSnapshot(c.args.ID, image),
|
||||
)
|
||||
}
|
||||
|
||||
containerOpts = append(containerOpts,
|
||||
containerOpts = append(
|
||||
containerOpts,
|
||||
containerd.WithNewSpec(specOpts...),
|
||||
)
|
||||
|
||||
containerOpts = append(containerOpts,
|
||||
containerOpts = append(
|
||||
containerOpts,
|
||||
c.opts.ContainerOpts...,
|
||||
)
|
||||
|
||||
@ -258,12 +276,14 @@ func (c *containerdRunner) newOCISpecOpts(image oci.Image) []oci.SpecOpts {
|
||||
specOpts := []oci.SpecOpts{}
|
||||
|
||||
if image != nil {
|
||||
specOpts = append(specOpts,
|
||||
specOpts = append(
|
||||
specOpts,
|
||||
oci.WithImageConfig(image),
|
||||
)
|
||||
}
|
||||
|
||||
specOpts = append(specOpts,
|
||||
specOpts = append(
|
||||
specOpts,
|
||||
oci.WithProcessArgs(c.args.ProcessArgs...),
|
||||
oci.WithEnv(c.opts.Env),
|
||||
oci.WithHostHostsFile,
|
||||
@ -272,27 +292,32 @@ func (c *containerdRunner) newOCISpecOpts(image oci.Image) []oci.SpecOpts {
|
||||
)
|
||||
|
||||
if c.opts.OOMScoreAdj != 0 {
|
||||
specOpts = append(specOpts,
|
||||
specOpts = append(
|
||||
specOpts,
|
||||
WithOOMScoreAdj(c.opts.OOMScoreAdj),
|
||||
)
|
||||
}
|
||||
|
||||
if c.opts.CgroupPath != "" {
|
||||
specOpts = append(specOpts,
|
||||
specOpts = append(
|
||||
specOpts,
|
||||
oci.WithCgroup(c.opts.CgroupPath),
|
||||
)
|
||||
}
|
||||
|
||||
specOpts = append(specOpts,
|
||||
specOpts = append(
|
||||
specOpts,
|
||||
c.opts.OCISpecOpts...,
|
||||
)
|
||||
|
||||
if c.opts.OverrideSeccompProfile != nil {
|
||||
specOpts = append(specOpts,
|
||||
specOpts = append(
|
||||
specOpts,
|
||||
WithCustomSeccompProfile(c.opts.OverrideSeccompProfile),
|
||||
)
|
||||
} else {
|
||||
specOpts = append(specOpts,
|
||||
specOpts = append(
|
||||
specOpts,
|
||||
seccomp.WithDefaultProfile(), // add seccomp profile last, as it depends on process capabilities
|
||||
)
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ type goroutineRunner struct {
|
||||
|
||||
opts *runner.Options
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
wg sync.WaitGroup
|
||||
|
@ -41,7 +41,7 @@ type ServiceRunner struct {
|
||||
stateSubscribers map[StateEvent][]chan<- struct{}
|
||||
|
||||
ctxMu sync.Mutex
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -291,7 +291,12 @@ func (svcrunner *ServiceRunner) run(ctx context.Context, runnr runner.Runner) er
|
||||
defer healthWg.Done()
|
||||
|
||||
//nolint:errcheck
|
||||
health.Run(ctx, healthSvc.HealthSettings(svcrunner.runtime), &svcrunner.healthState, healthSvc.HealthFunc(svcrunner.runtime))
|
||||
health.Run(
|
||||
ctx,
|
||||
healthSvc.HealthSettings(svcrunner.runtime),
|
||||
&svcrunner.healthState,
|
||||
healthSvc.HealthFunc(svcrunner.runtime),
|
||||
)
|
||||
}()
|
||||
|
||||
notifyCh := make(chan health.StateChange, 2)
|
||||
|
@ -51,7 +51,7 @@ const assertRebootedRebootTimeout = 10 * time.Minute
|
||||
type ApplyConfigSuite struct {
|
||||
base.K8sSuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -109,30 +109,38 @@ func (suite *ApplyConfigSuite) TestApply() {
|
||||
cfgDataOut, err := cfg.Bytes()
|
||||
suite.Assert().Nilf(err, "failed to marshal updated machine config data (node %q): %w", node, err)
|
||||
|
||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: cfgDataOut,
|
||||
Mode: machineapi.ApplyConfigurationRequest_REBOOT,
|
||||
})
|
||||
if err != nil {
|
||||
// It is expected that the connection will EOF here, so just log the error
|
||||
suite.Assert().Nilf("failed to apply configuration (node %q): %w", node, err)
|
||||
}
|
||||
suite.AssertRebooted(
|
||||
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
_, err = suite.Client.ApplyConfiguration(
|
||||
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: cfgDataOut,
|
||||
Mode: machineapi.ApplyConfigurationRequest_REBOOT,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
// It is expected that the connection will EOF here, so just log the error
|
||||
suite.Assert().Nilf("failed to apply configuration (node %q): %w", node, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, assertRebootedRebootTimeout)
|
||||
return nil
|
||||
}, assertRebootedRebootTimeout,
|
||||
)
|
||||
|
||||
// Verify configuration change
|
||||
var newProvider config.Provider
|
||||
|
||||
suite.Require().Nilf(retry.Constant(time.Minute, retry.WithUnits(time.Second)).Retry(func() error {
|
||||
newProvider, err = suite.ReadConfigFromNode(nodeCtx)
|
||||
if err != nil {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
suite.Require().Nilf(
|
||||
retry.Constant(time.Minute, retry.WithUnits(time.Second)).Retry(
|
||||
func() error {
|
||||
newProvider, err = suite.ReadConfigFromNode(nodeCtx)
|
||||
if err != nil {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}), "failed to read updated configuration from node %q: %w", node, err)
|
||||
return nil
|
||||
},
|
||||
), "failed to read updated configuration from node %q: %w", node, err,
|
||||
)
|
||||
|
||||
suite.Assert().Equal(
|
||||
newProvider.Machine().Sysctls()[applyConfigTestSysctl],
|
||||
@ -168,10 +176,12 @@ func (suite *ApplyConfigSuite) TestApplyWithoutReboot() {
|
||||
cfgDataOut, err := cfg.Bytes()
|
||||
suite.Require().NoError(err, "failed to marshal updated machine config data (node %q)", node)
|
||||
|
||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: cfgDataOut,
|
||||
Mode: mode,
|
||||
})
|
||||
_, err = suite.Client.ApplyConfiguration(
|
||||
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: cfgDataOut,
|
||||
Mode: mode,
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err, "failed to apply deferred configuration (node %q): %w", node)
|
||||
|
||||
// Verify configuration change
|
||||
@ -195,10 +205,12 @@ func (suite *ApplyConfigSuite) TestApplyWithoutReboot() {
|
||||
cfgDataOut, err = cfg.Bytes()
|
||||
suite.Require().NoError(err, "failed to marshal updated machine config data (node %q)", node)
|
||||
|
||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: cfgDataOut,
|
||||
Mode: mode,
|
||||
})
|
||||
_, err = suite.Client.ApplyConfiguration(
|
||||
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: cfgDataOut,
|
||||
Mode: mode,
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err, "failed to apply deferred configuration (node %q): %w", node)
|
||||
}
|
||||
}
|
||||
@ -295,32 +307,40 @@ func (suite *ApplyConfigSuite) TestApplyConfigRotateEncryptionSecrets() {
|
||||
data, err := machineConfig.Bytes()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: data,
|
||||
Mode: machineapi.ApplyConfigurationRequest_REBOOT,
|
||||
})
|
||||
if err != nil {
|
||||
// It is expected that the connection will EOF here, so just log the error
|
||||
suite.Assert().Nilf("failed to apply configuration (node %q): %w", node, err)
|
||||
}
|
||||
suite.AssertRebooted(
|
||||
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
_, err = suite.Client.ApplyConfiguration(
|
||||
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: data,
|
||||
Mode: machineapi.ApplyConfigurationRequest_REBOOT,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
// It is expected that the connection will EOF here, so just log the error
|
||||
suite.Assert().Nilf("failed to apply configuration (node %q): %w", node, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, assertRebootedRebootTimeout)
|
||||
return nil
|
||||
}, assertRebootedRebootTimeout,
|
||||
)
|
||||
|
||||
suite.ClearConnectionRefused(suite.ctx, node)
|
||||
|
||||
// Verify configuration change
|
||||
var newProvider config.Provider
|
||||
|
||||
suite.Require().Nilf(retry.Constant(time.Minute, retry.WithUnits(time.Second)).Retry(func() error {
|
||||
newProvider, err = suite.ReadConfigFromNode(nodeCtx)
|
||||
if err != nil {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
suite.Require().Nilf(
|
||||
retry.Constant(time.Minute, retry.WithUnits(time.Second)).Retry(
|
||||
func() error {
|
||||
newProvider, err = suite.ReadConfigFromNode(nodeCtx)
|
||||
if err != nil {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}), "failed to read updated configuration from node %q: %w", node, err)
|
||||
return nil
|
||||
},
|
||||
), "failed to read updated configuration from node %q: %w", node, err,
|
||||
)
|
||||
|
||||
e := newProvider.Machine().SystemDiskEncryption().Get(constants.EphemeralPartitionLabel)
|
||||
|
||||
@ -370,10 +390,12 @@ func (suite *ApplyConfigSuite) TestApplyNoReboot() {
|
||||
cfgDataOut, err := cfg.Bytes()
|
||||
suite.Assert().Nilf(err, "failed to marshal updated machine config data (node %q): %w", node, err)
|
||||
|
||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: cfgDataOut,
|
||||
Mode: machineapi.ApplyConfigurationRequest_NO_REBOOT,
|
||||
})
|
||||
_, err = suite.Client.ApplyConfiguration(
|
||||
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||
Data: cfgDataOut,
|
||||
Mode: machineapi.ApplyConfigurationRequest_NO_REBOOT,
|
||||
},
|
||||
)
|
||||
suite.Require().Error(err)
|
||||
|
||||
var (
|
||||
|
@ -28,7 +28,7 @@ import (
|
||||
type DiscoverySuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,10 @@ import (
|
||||
type DiskUsageSuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
nodeCtx context.Context
|
||||
nodeCtx context.Context //nolint:containedctx
|
||||
}
|
||||
|
||||
// SuiteName ...
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
type DmesgSuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ import (
|
||||
type EtcdRecoverSuite struct {
|
||||
base.K8sSuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -112,39 +112,52 @@ func (suite *EtcdRecoverSuite) TestSnapshotRecover() {
|
||||
return fmt.Errorf("error reading pre-reset boot ID: %w", err)
|
||||
}
|
||||
|
||||
if err = base.IgnoreGRPCUnavailable(suite.Client.ResetGeneric(nodeCtx, &machineapi.ResetRequest{
|
||||
Reboot: true,
|
||||
Graceful: false,
|
||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||
{
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
Wipe: true,
|
||||
if err = base.IgnoreGRPCUnavailable(
|
||||
suite.Client.ResetGeneric(
|
||||
nodeCtx, &machineapi.ResetRequest{
|
||||
Reboot: true,
|
||||
Graceful: false,
|
||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||
{
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
Wipe: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})); err != nil {
|
||||
),
|
||||
); err != nil {
|
||||
return fmt.Errorf("error resetting the node %q: %w", node, err)
|
||||
}
|
||||
|
||||
var bootIDAfter string
|
||||
|
||||
return retry.Constant(5 * time.Minute).Retry(func() error {
|
||||
requestCtx, requestCtxCancel := context.WithTimeout(nodeCtx, 5*time.Second)
|
||||
defer requestCtxCancel()
|
||||
return retry.Constant(5 * time.Minute).Retry(
|
||||
func() error {
|
||||
requestCtx, requestCtxCancel := context.WithTimeout(nodeCtx, 5*time.Second)
|
||||
defer requestCtxCancel()
|
||||
|
||||
bootIDAfter, err = suite.ReadBootID(requestCtx)
|
||||
bootIDAfter, err = suite.ReadBootID(requestCtx)
|
||||
|
||||
if err != nil {
|
||||
// API might be unresponsive during reboot
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
if err != nil {
|
||||
// API might be unresponsive during reboot
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
if bootIDAfter == bootIDBefore {
|
||||
// bootID should be different after reboot
|
||||
return retry.ExpectedError(fmt.Errorf("bootID didn't change for node %q: before %s, after %s", node, bootIDBefore, bootIDAfter))
|
||||
}
|
||||
if bootIDAfter == bootIDBefore {
|
||||
// bootID should be different after reboot
|
||||
return retry.ExpectedError(
|
||||
fmt.Errorf(
|
||||
"bootID didn't change for node %q: before %s, after %s",
|
||||
node,
|
||||
bootIDBefore,
|
||||
bootIDAfter,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}()
|
||||
}()
|
||||
}
|
||||
@ -203,36 +216,42 @@ func (suite *EtcdRecoverSuite) recoverEtcd(recoverNode string, src io.ReadSeeker
|
||||
|
||||
suite.T().Log("uploading the snapshot")
|
||||
|
||||
if err := retry.Constant(time.Minute, retry.WithUnits(time.Millisecond*200)).RetryWithContext(ctx, func(ctx context.Context) error {
|
||||
_, err := src.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
if err := retry.Constant(time.Minute, retry.WithUnits(time.Millisecond*200)).RetryWithContext(
|
||||
ctx, func(ctx context.Context) error {
|
||||
_, err := src.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = suite.Client.EtcdRecover(ctx, src)
|
||||
|
||||
if client.StatusCode(err) == codes.FailedPrecondition {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = suite.Client.EtcdRecover(ctx, src)
|
||||
|
||||
if client.StatusCode(err) == codes.FailedPrecondition {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}); err != nil {
|
||||
},
|
||||
); err != nil {
|
||||
return fmt.Errorf("error uploading snapshot: %w", err)
|
||||
}
|
||||
|
||||
suite.T().Log("bootstrapping from the snapshot")
|
||||
|
||||
return retry.Constant(time.Minute, retry.WithUnits(time.Millisecond*200)).RetryWithContext(ctx, func(ctx context.Context) error {
|
||||
err := suite.Client.Bootstrap(ctx, &machineapi.BootstrapRequest{
|
||||
RecoverEtcd: true,
|
||||
})
|
||||
return retry.Constant(time.Minute, retry.WithUnits(time.Millisecond*200)).RetryWithContext(
|
||||
ctx, func(ctx context.Context) error {
|
||||
err := suite.Client.Bootstrap(
|
||||
ctx, &machineapi.BootstrapRequest{
|
||||
RecoverEtcd: true,
|
||||
},
|
||||
)
|
||||
|
||||
if client.StatusCode(err) == codes.FailedPrecondition || client.StatusCode(err) == codes.DeadlineExceeded {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
if client.StatusCode(err) == codes.FailedPrecondition || client.StatusCode(err) == codes.DeadlineExceeded {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
})
|
||||
return err
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
type EtcdSuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -67,7 +67,10 @@ func (suite *EtcdSuite) TestEtcdForfeitLeadership() {
|
||||
var leader string
|
||||
|
||||
for _, node := range nodes {
|
||||
resp, err := suite.Client.EtcdForfeitLeadership(client.WithNodes(suite.ctx, node), &machineapi.EtcdForfeitLeadershipRequest{})
|
||||
resp, err := suite.Client.EtcdForfeitLeadership(
|
||||
client.WithNodes(suite.ctx, node),
|
||||
&machineapi.EtcdForfeitLeadershipRequest{},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
if resp.Messages[0].GetMember() != "" {
|
||||
@ -130,16 +133,21 @@ func (suite *EtcdSuite) TestEtcdLeaveCluster() {
|
||||
}
|
||||
}
|
||||
|
||||
suite.Assert().Equal("rpc error: code = Unknown desc = lstat /var/lib/etcd: no such file or directory", info.Metadata.Error)
|
||||
suite.Assert().Equal(
|
||||
"rpc error: code = Unknown desc = lstat /var/lib/etcd: no such file or directory",
|
||||
info.Metadata.Error,
|
||||
)
|
||||
}
|
||||
|
||||
// NB: Reboot the node so that it can rejoin the etcd cluster. This allows us
|
||||
// to check the cluster health and catch any issues in rejoining.
|
||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
_, err = suite.Client.MachineClient.Reboot(nodeCtx, &machineapi.RebootRequest{})
|
||||
suite.AssertRebooted(
|
||||
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
_, err = suite.Client.MachineClient.Reboot(nodeCtx, &machineapi.RebootRequest{})
|
||||
|
||||
return err
|
||||
}, 10*time.Minute)
|
||||
return err
|
||||
}, 10*time.Minute,
|
||||
)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -20,10 +20,10 @@ import (
|
||||
type EventsSuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
nodeCtx context.Context
|
||||
nodeCtx context.Context //nolint:containedctx
|
||||
}
|
||||
|
||||
// SuiteName ...
|
||||
@ -54,25 +54,29 @@ func (suite *EventsSuite) TestEventsWatch() {
|
||||
watchCtx, watchCtxCancel := context.WithCancel(suite.nodeCtx)
|
||||
defer watchCtxCancel()
|
||||
|
||||
suite.Assert().NoError(suite.Client.EventsWatch(watchCtx, func(ch <-chan client.Event) {
|
||||
defer watchCtxCancel()
|
||||
suite.Assert().NoError(
|
||||
suite.Client.EventsWatch(
|
||||
watchCtx, func(ch <-chan client.Event) {
|
||||
defer watchCtxCancel()
|
||||
|
||||
timer := time.NewTimer(500 * time.Millisecond)
|
||||
defer timer.Stop()
|
||||
timer := time.NewTimer(500 * time.Millisecond)
|
||||
defer timer.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-ch:
|
||||
if !ok {
|
||||
return
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-ch:
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
result = append(result, event)
|
||||
case <-timer.C:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, event)
|
||||
case <-timer.C:
|
||||
return
|
||||
}
|
||||
}
|
||||
}, opts...))
|
||||
}, opts...,
|
||||
),
|
||||
)
|
||||
|
||||
return result
|
||||
}
|
||||
@ -88,7 +92,10 @@ func (suite *EventsSuite) TestEventsWatch() {
|
||||
// (as check excludes that event with picked ID)
|
||||
id := allEvents[len(allEvents)-15].ID
|
||||
eventsSinceID := receiveEvents(client.WithTailID(id))
|
||||
suite.Require().GreaterOrEqual(len(eventsSinceID), 14) // there might some new events since allEvents, but at least 15 should be received
|
||||
suite.Require().GreaterOrEqual(
|
||||
len(eventsSinceID),
|
||||
14,
|
||||
) // there might some new events since allEvents, but at least 15 should be received
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -26,7 +26,7 @@ import (
|
||||
type GenerateConfigSuite struct {
|
||||
base.K8sSuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -104,9 +104,18 @@ func (suite *GenerateConfigSuite) TestGenerate() {
|
||||
suite.Require().EqualValues(request.ClusterConfig.Name, config.Cluster().Name())
|
||||
suite.Require().EqualValues(request.ClusterConfig.ControlPlane.Endpoint, config.Cluster().Endpoint().String())
|
||||
suite.Require().EqualValues(request.ClusterConfig.ClusterNetwork.DnsDomain, config.Cluster().Network().DNSDomain())
|
||||
suite.Require().EqualValues(request.ClusterConfig.ClusterNetwork.CniConfig.Name, config.Cluster().Network().CNI().Name())
|
||||
suite.Require().EqualValues(request.ClusterConfig.ClusterNetwork.CniConfig.Urls, config.Cluster().Network().CNI().URLs())
|
||||
suite.Require().EqualValues(fmt.Sprintf("%s:v%s", constants.KubeletImage, request.MachineConfig.KubernetesVersion), config.Machine().Kubelet().Image())
|
||||
suite.Require().EqualValues(
|
||||
request.ClusterConfig.ClusterNetwork.CniConfig.Name,
|
||||
config.Cluster().Network().CNI().Name(),
|
||||
)
|
||||
suite.Require().EqualValues(
|
||||
request.ClusterConfig.ClusterNetwork.CniConfig.Urls,
|
||||
config.Cluster().Network().CNI().URLs(),
|
||||
)
|
||||
suite.Require().EqualValues(
|
||||
fmt.Sprintf("%s:v%s", constants.KubeletImage, request.MachineConfig.KubernetesVersion),
|
||||
config.Machine().Kubelet().Image(),
|
||||
)
|
||||
suite.Require().EqualValues(request.MachineConfig.InstallConfig.InstallDisk, disk)
|
||||
suite.Require().EqualValues(request.MachineConfig.InstallConfig.InstallImage, config.Machine().Install().Image())
|
||||
suite.Require().EqualValues(request.MachineConfig.NetworkConfig.Hostname, config.Machine().Network().Hostname())
|
||||
@ -149,15 +158,30 @@ func (suite *GenerateConfigSuite) TestGenerate() {
|
||||
suite.Require().EqualValues(request.ConfigVersion, joinedConfig.Version())
|
||||
suite.Require().EqualValues(request.ClusterConfig.Name, joinedConfig.Cluster().Name())
|
||||
suite.Require().EqualValues(request.ClusterConfig.ControlPlane.Endpoint, joinedConfig.Cluster().Endpoint().String())
|
||||
suite.Require().EqualValues(request.ClusterConfig.ClusterNetwork.DnsDomain, joinedConfig.Cluster().Network().DNSDomain())
|
||||
suite.Require().EqualValues(fmt.Sprintf("%s:v%s", constants.KubeletImage, request.MachineConfig.KubernetesVersion), joinedConfig.Machine().Kubelet().Image())
|
||||
suite.Require().EqualValues(
|
||||
request.ClusterConfig.ClusterNetwork.DnsDomain,
|
||||
joinedConfig.Cluster().Network().DNSDomain(),
|
||||
)
|
||||
suite.Require().EqualValues(
|
||||
fmt.Sprintf("%s:v%s", constants.KubeletImage, request.MachineConfig.KubernetesVersion),
|
||||
joinedConfig.Machine().Kubelet().Image(),
|
||||
)
|
||||
suite.Require().EqualValues(request.MachineConfig.InstallConfig.InstallDisk, disk)
|
||||
suite.Require().EqualValues(request.MachineConfig.InstallConfig.InstallImage, joinedConfig.Machine().Install().Image())
|
||||
suite.Require().EqualValues(request.MachineConfig.NetworkConfig.Hostname, joinedConfig.Machine().Network().Hostname())
|
||||
suite.Require().EqualValues(
|
||||
request.MachineConfig.InstallConfig.InstallImage,
|
||||
joinedConfig.Machine().Install().Image(),
|
||||
)
|
||||
suite.Require().EqualValues(
|
||||
request.MachineConfig.NetworkConfig.Hostname,
|
||||
joinedConfig.Machine().Network().Hostname(),
|
||||
)
|
||||
|
||||
suite.Require().EqualValues(config.Machine().Security().CA(), joinedConfig.Machine().Security().CA())
|
||||
suite.Require().EqualValues(config.Machine().Security().Token(), joinedConfig.Machine().Security().Token())
|
||||
suite.Require().EqualValues(config.Cluster().AESCBCEncryptionSecret(), joinedConfig.Cluster().AESCBCEncryptionSecret())
|
||||
suite.Require().EqualValues(
|
||||
config.Cluster().AESCBCEncryptionSecret(),
|
||||
joinedConfig.Cluster().AESCBCEncryptionSecret(),
|
||||
)
|
||||
suite.Require().EqualValues(config.Cluster().CA(), joinedConfig.Cluster().CA())
|
||||
suite.Require().EqualValues(config.Cluster().Token(), joinedConfig.Cluster().Token())
|
||||
suite.Require().EqualValues(config.Cluster().Etcd().CA(), config.Cluster().Etcd().CA())
|
||||
|
@ -25,10 +25,10 @@ import (
|
||||
type LogsSuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
nodeCtx context.Context
|
||||
nodeCtx context.Context //nolint:containedctx
|
||||
}
|
||||
|
||||
// SuiteName ...
|
||||
@ -167,7 +167,11 @@ func (suite *LogsSuite) testStreaming(tailLines int32) {
|
||||
// invoke machined enough times to generate
|
||||
// some logs
|
||||
for i := int32(0); i < tailLines; i++ {
|
||||
_, err := suite.Client.Stats(suite.nodeCtx, constants.SystemContainerdNamespace, common.ContainerDriver_CONTAINERD)
|
||||
_, err := suite.Client.Stats(
|
||||
suite.nodeCtx,
|
||||
constants.SystemContainerdNamespace,
|
||||
common.ContainerDriver_CONTAINERD,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
type RebootSuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -62,9 +62,11 @@ func (suite *RebootSuite) TestRebootNodeByNode() {
|
||||
for _, node := range nodes {
|
||||
suite.T().Log("rebooting node", node)
|
||||
|
||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
return base.IgnoreGRPCUnavailable(suite.Client.Reboot(nodeCtx))
|
||||
}, 10*time.Minute)
|
||||
suite.AssertRebooted(
|
||||
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
return base.IgnoreGRPCUnavailable(suite.Client.Reboot(nodeCtx))
|
||||
}, 10*time.Minute,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,23 +125,32 @@ func (suite *RebootSuite) TestRebootAllNodes() {
|
||||
|
||||
nodeCtx := client.WithNodes(suite.ctx, node)
|
||||
|
||||
return retry.Constant(10 * time.Minute).Retry(func() error {
|
||||
requestCtx, requestCtxCancel := context.WithTimeout(nodeCtx, 5*time.Second)
|
||||
defer requestCtxCancel()
|
||||
return retry.Constant(10 * time.Minute).Retry(
|
||||
func() error {
|
||||
requestCtx, requestCtxCancel := context.WithTimeout(nodeCtx, 5*time.Second)
|
||||
defer requestCtxCancel()
|
||||
|
||||
bootIDAfter, err := suite.ReadBootID(requestCtx)
|
||||
if err != nil {
|
||||
// API might be unresponsive during reboot
|
||||
return retry.ExpectedError(fmt.Errorf("error reading bootID for node %q: %w", node, err))
|
||||
}
|
||||
bootIDAfter, err := suite.ReadBootID(requestCtx)
|
||||
if err != nil {
|
||||
// API might be unresponsive during reboot
|
||||
return retry.ExpectedError(fmt.Errorf("error reading bootID for node %q: %w", node, err))
|
||||
}
|
||||
|
||||
if bootIDAfter == bootIDBefore {
|
||||
// bootID should be different after reboot
|
||||
return retry.ExpectedError(fmt.Errorf("bootID didn't change for node %q: before %s, after %s", node, bootIDBefore, bootIDAfter))
|
||||
}
|
||||
if bootIDAfter == bootIDBefore {
|
||||
// bootID should be different after reboot
|
||||
return retry.ExpectedError(
|
||||
fmt.Errorf(
|
||||
"bootID didn't change for node %q: before %s, after %s",
|
||||
node,
|
||||
bootIDBefore,
|
||||
bootIDAfter,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}()
|
||||
}(node)
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
type ResetSuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -88,10 +88,12 @@ func (suite *ResetSuite) TestResetNodeByNode() {
|
||||
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
// force reboot after reset, as this is the only mode we can test
|
||||
return base.IgnoreGRPCUnavailable(suite.Client.Reset(nodeCtx, true, true))
|
||||
}, 10*time.Minute)
|
||||
suite.AssertRebooted(
|
||||
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
// force reboot after reset, as this is the only mode we can test
|
||||
return base.IgnoreGRPCUnavailable(suite.Client.Reset(nodeCtx, true, true))
|
||||
}, 10*time.Minute,
|
||||
)
|
||||
|
||||
suite.ClearConnectionRefused(suite.ctx, node)
|
||||
|
||||
@ -118,10 +120,12 @@ func (suite *ResetSuite) testResetNoGraceful(nodeType machine.Type) {
|
||||
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
// force reboot after reset, as this is the only mode we can test
|
||||
return base.IgnoreGRPCUnavailable(suite.Client.Reset(nodeCtx, false, true))
|
||||
}, 5*time.Minute)
|
||||
suite.AssertRebooted(
|
||||
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
// force reboot after reset, as this is the only mode we can test
|
||||
return base.IgnoreGRPCUnavailable(suite.Client.Reset(nodeCtx, false, true))
|
||||
}, 5*time.Minute,
|
||||
)
|
||||
|
||||
suite.ClearConnectionRefused(suite.ctx, node)
|
||||
|
||||
@ -162,19 +166,25 @@ func (suite *ResetSuite) TestResetWithSpecEphemeral() {
|
||||
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
// force reboot after reset, as this is the only mode we can test
|
||||
return base.IgnoreGRPCUnavailable(suite.Client.ResetGeneric(nodeCtx, &machineapi.ResetRequest{
|
||||
Reboot: true,
|
||||
Graceful: true,
|
||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||
{
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
Wipe: true,
|
||||
},
|
||||
},
|
||||
}))
|
||||
}, 5*time.Minute)
|
||||
suite.AssertRebooted(
|
||||
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
// force reboot after reset, as this is the only mode we can test
|
||||
return base.IgnoreGRPCUnavailable(
|
||||
suite.Client.ResetGeneric(
|
||||
nodeCtx, &machineapi.ResetRequest{
|
||||
Reboot: true,
|
||||
Graceful: true,
|
||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||
{
|
||||
Label: constants.EphemeralPartitionLabel,
|
||||
Wipe: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
}, 5*time.Minute,
|
||||
)
|
||||
|
||||
suite.ClearConnectionRefused(suite.ctx, node)
|
||||
|
||||
@ -205,19 +215,25 @@ func (suite *ResetSuite) TestResetWithSpecState() {
|
||||
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
// force reboot after reset, as this is the only mode we can test
|
||||
return base.IgnoreGRPCUnavailable(suite.Client.ResetGeneric(nodeCtx, &machineapi.ResetRequest{
|
||||
Reboot: true,
|
||||
Graceful: true,
|
||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||
{
|
||||
Label: constants.StatePartitionLabel,
|
||||
Wipe: true,
|
||||
},
|
||||
},
|
||||
}))
|
||||
}, 5*time.Minute)
|
||||
suite.AssertRebooted(
|
||||
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||
// force reboot after reset, as this is the only mode we can test
|
||||
return base.IgnoreGRPCUnavailable(
|
||||
suite.Client.ResetGeneric(
|
||||
nodeCtx, &machineapi.ResetRequest{
|
||||
Reboot: true,
|
||||
Graceful: true,
|
||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||
{
|
||||
Label: constants.StatePartitionLabel,
|
||||
Wipe: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
}, 5*time.Minute,
|
||||
)
|
||||
|
||||
suite.ClearConnectionRefused(suite.ctx, node)
|
||||
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
type VersionSuite struct {
|
||||
base.APISuite
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
|
@ -87,8 +87,13 @@ func upgradePreviousToStable() upgradeSpec {
|
||||
return upgradeSpec{
|
||||
ShortName: fmt.Sprintf("%s-%s", previousRelease, stableRelease),
|
||||
|
||||
SourceKernelPath: helpers.ArtifactPath(filepath.Join(trimVersion(previousRelease), constants.KernelAsset)),
|
||||
SourceInitramfsPath: helpers.ArtifactPath(filepath.Join(trimVersion(previousRelease), constants.InitramfsAsset)),
|
||||
SourceKernelPath: helpers.ArtifactPath(filepath.Join(trimVersion(previousRelease), constants.KernelAsset)),
|
||||
SourceInitramfsPath: helpers.ArtifactPath(
|
||||
filepath.Join(
|
||||
trimVersion(previousRelease),
|
||||
constants.InitramfsAsset,
|
||||
),
|
||||
),
|
||||
SourceInstallerImage: fmt.Sprintf("%s:%s", "ghcr.io/siderolabs/installer", previousRelease),
|
||||
SourceVersion: previousRelease,
|
||||
SourceK8sVersion: previousK8sVersion,
|
||||
@ -116,9 +121,14 @@ func upgradeStableToCurrent() upgradeSpec {
|
||||
SourceVersion: stableRelease,
|
||||
SourceK8sVersion: stableK8sVersion,
|
||||
|
||||
TargetInstallerImage: fmt.Sprintf("%s/%s:%s", DefaultSettings.TargetInstallImageRegistry, images.DefaultInstallerImageName, DefaultSettings.CurrentVersion),
|
||||
TargetVersion: DefaultSettings.CurrentVersion,
|
||||
TargetK8sVersion: currentK8sVersion,
|
||||
TargetInstallerImage: fmt.Sprintf(
|
||||
"%s/%s:%s",
|
||||
DefaultSettings.TargetInstallImageRegistry,
|
||||
images.DefaultInstallerImageName,
|
||||
DefaultSettings.CurrentVersion,
|
||||
),
|
||||
TargetVersion: DefaultSettings.CurrentVersion,
|
||||
TargetK8sVersion: currentK8sVersion,
|
||||
|
||||
MasterNodes: DefaultSettings.MasterNodes,
|
||||
WorkerNodes: DefaultSettings.WorkerNodes,
|
||||
@ -127,7 +137,12 @@ func upgradeStableToCurrent() upgradeSpec {
|
||||
|
||||
// upgradeCurrentToCurrent upgrades the current version to itself.
|
||||
func upgradeCurrentToCurrent() upgradeSpec {
|
||||
installerImage := fmt.Sprintf("%s/%s:%s", DefaultSettings.TargetInstallImageRegistry, images.DefaultInstallerImageName, DefaultSettings.CurrentVersion)
|
||||
installerImage := fmt.Sprintf(
|
||||
"%s/%s:%s",
|
||||
DefaultSettings.TargetInstallImageRegistry,
|
||||
images.DefaultInstallerImageName,
|
||||
DefaultSettings.CurrentVersion,
|
||||
)
|
||||
|
||||
return upgradeSpec{
|
||||
ShortName: fmt.Sprintf("%s-%s", DefaultSettings.CurrentVersion, DefaultSettings.CurrentVersion),
|
||||
@ -160,9 +175,14 @@ func upgradeStableToCurrentPreserve() upgradeSpec {
|
||||
SourceVersion: stableRelease,
|
||||
SourceK8sVersion: stableK8sVersion,
|
||||
|
||||
TargetInstallerImage: fmt.Sprintf("%s/%s:%s", DefaultSettings.TargetInstallImageRegistry, images.DefaultInstallerImageName, DefaultSettings.CurrentVersion),
|
||||
TargetVersion: DefaultSettings.CurrentVersion,
|
||||
TargetK8sVersion: currentK8sVersion,
|
||||
TargetInstallerImage: fmt.Sprintf(
|
||||
"%s/%s:%s",
|
||||
DefaultSettings.TargetInstallImageRegistry,
|
||||
images.DefaultInstallerImageName,
|
||||
DefaultSettings.CurrentVersion,
|
||||
),
|
||||
TargetVersion: DefaultSettings.CurrentVersion,
|
||||
TargetK8sVersion: currentK8sVersion,
|
||||
|
||||
MasterNodes: 1,
|
||||
WorkerNodes: 0,
|
||||
@ -181,9 +201,14 @@ func upgradeStableToCurrentPreserveStage() upgradeSpec {
|
||||
SourceVersion: stableRelease,
|
||||
SourceK8sVersion: stableK8sVersion,
|
||||
|
||||
TargetInstallerImage: fmt.Sprintf("%s/%s:%s", DefaultSettings.TargetInstallImageRegistry, images.DefaultInstallerImageName, DefaultSettings.CurrentVersion),
|
||||
TargetVersion: DefaultSettings.CurrentVersion,
|
||||
TargetK8sVersion: currentK8sVersion,
|
||||
TargetInstallerImage: fmt.Sprintf(
|
||||
"%s/%s:%s",
|
||||
DefaultSettings.TargetInstallImageRegistry,
|
||||
images.DefaultInstallerImageName,
|
||||
DefaultSettings.CurrentVersion,
|
||||
),
|
||||
TargetVersion: DefaultSettings.CurrentVersion,
|
||||
TargetK8sVersion: currentK8sVersion,
|
||||
|
||||
MasterNodes: 1,
|
||||
WorkerNodes: 0,
|
||||
@ -209,6 +234,7 @@ type UpgradeSuite struct {
|
||||
clusterAccess *access.Adapter
|
||||
controlPlaneEndpoint string
|
||||
|
||||
//nolint:containedctx
|
||||
ctx context.Context
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
@ -333,55 +359,67 @@ func (suite *UpgradeSuite) setupCluster() {
|
||||
}
|
||||
|
||||
if DefaultSettings.CustomCNIURL != "" {
|
||||
genOptions = append(genOptions, generate.WithClusterCNIConfig(&v1alpha1.CNIConfig{
|
||||
CNIName: constants.CustomCNI,
|
||||
CNIUrls: []string{DefaultSettings.CustomCNIURL},
|
||||
}))
|
||||
genOptions = append(
|
||||
genOptions, generate.WithClusterCNIConfig(
|
||||
&v1alpha1.CNIConfig{
|
||||
CNIName: constants.CustomCNI,
|
||||
CNIUrls: []string{DefaultSettings.CustomCNIURL},
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if suite.spec.WithEncryption {
|
||||
genOptions = append(genOptions, generate.WithSystemDiskEncryption(&v1alpha1.SystemDiskEncryptionConfig{
|
||||
StatePartition: &v1alpha1.EncryptionConfig{
|
||||
EncryptionProvider: encryption.LUKS2,
|
||||
EncryptionKeys: []*v1alpha1.EncryptionKey{
|
||||
{
|
||||
KeyNodeID: &v1alpha1.EncryptionKeyNodeID{},
|
||||
KeySlot: 0,
|
||||
genOptions = append(
|
||||
genOptions, generate.WithSystemDiskEncryption(
|
||||
&v1alpha1.SystemDiskEncryptionConfig{
|
||||
StatePartition: &v1alpha1.EncryptionConfig{
|
||||
EncryptionProvider: encryption.LUKS2,
|
||||
EncryptionKeys: []*v1alpha1.EncryptionKey{
|
||||
{
|
||||
KeyNodeID: &v1alpha1.EncryptionKeyNodeID{},
|
||||
KeySlot: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
EphemeralPartition: &v1alpha1.EncryptionConfig{
|
||||
EncryptionProvider: encryption.LUKS2,
|
||||
EncryptionKeys: []*v1alpha1.EncryptionKey{
|
||||
{
|
||||
KeyNodeID: &v1alpha1.EncryptionKeyNodeID{},
|
||||
KeySlot: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
EphemeralPartition: &v1alpha1.EncryptionConfig{
|
||||
EncryptionProvider: encryption.LUKS2,
|
||||
EncryptionKeys: []*v1alpha1.EncryptionKey{
|
||||
{
|
||||
KeyNodeID: &v1alpha1.EncryptionKeyNodeID{},
|
||||
KeySlot: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
versionContract, err := config.ParseContractFromVersion(suite.spec.SourceVersion)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
suite.configBundle, err = bundle.NewConfigBundle(bundle.WithInputOptions(
|
||||
&bundle.InputOptions{
|
||||
ClusterName: clusterName,
|
||||
Endpoint: suite.controlPlaneEndpoint,
|
||||
KubeVersion: suite.spec.SourceK8sVersion,
|
||||
GenOptions: append(
|
||||
genOptions,
|
||||
generate.WithEndpointList(masterEndpoints),
|
||||
generate.WithInstallImage(suite.spec.SourceInstallerImage),
|
||||
generate.WithDNSDomain("cluster.local"),
|
||||
generate.WithVersionContract(versionContract),
|
||||
),
|
||||
}))
|
||||
suite.configBundle, err = bundle.NewConfigBundle(
|
||||
bundle.WithInputOptions(
|
||||
&bundle.InputOptions{
|
||||
ClusterName: clusterName,
|
||||
Endpoint: suite.controlPlaneEndpoint,
|
||||
KubeVersion: suite.spec.SourceK8sVersion,
|
||||
GenOptions: append(
|
||||
genOptions,
|
||||
generate.WithEndpointList(masterEndpoints),
|
||||
generate.WithInstallImage(suite.spec.SourceInstallerImage),
|
||||
generate.WithDNSDomain("cluster.local"),
|
||||
generate.WithVersionContract(versionContract),
|
||||
),
|
||||
},
|
||||
),
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
for i := 0; i < suite.spec.MasterNodes; i++ {
|
||||
request.Nodes = append(request.Nodes,
|
||||
request.Nodes = append(
|
||||
request.Nodes,
|
||||
provision.NodeRequest{
|
||||
Name: fmt.Sprintf("master-%d", i+1),
|
||||
Type: machine.TypeControlPlane,
|
||||
@ -394,11 +432,13 @@ func (suite *UpgradeSuite) setupCluster() {
|
||||
},
|
||||
},
|
||||
Config: suite.configBundle.ControlPlane(),
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
for i := 1; i <= suite.spec.WorkerNodes; i++ {
|
||||
request.Nodes = append(request.Nodes,
|
||||
request.Nodes = append(
|
||||
request.Nodes,
|
||||
provision.NodeRequest{
|
||||
Name: fmt.Sprintf("worker-%d", i),
|
||||
Type: machine.TypeWorker,
|
||||
@ -411,10 +451,12 @@ func (suite *UpgradeSuite) setupCluster() {
|
||||
},
|
||||
},
|
||||
Config: suite.configBundle.Worker(),
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
suite.Cluster, err = suite.provisioner.Create(suite.ctx, request,
|
||||
suite.Cluster, err = suite.provisioner.Create(
|
||||
suite.ctx, request,
|
||||
provision.WithBootlader(true),
|
||||
provision.WithUEFI(true),
|
||||
provision.WithTalosConfig(suite.configBundle.TalosConfig()),
|
||||
@ -457,7 +499,14 @@ func (suite *UpgradeSuite) waitForClusterHealth() {
|
||||
checkCtx, checkCtxCancel := context.WithTimeout(suite.ctx, 15*time.Minute)
|
||||
defer checkCtxCancel()
|
||||
|
||||
suite.Require().NoError(check.Wait(checkCtx, suite.clusterAccess, check.DefaultClusterChecks(), check.StderrReporter()))
|
||||
suite.Require().NoError(
|
||||
check.Wait(
|
||||
checkCtx,
|
||||
suite.clusterAccess,
|
||||
check.DefaultClusterChecks(),
|
||||
check.StderrReporter(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,12 +536,14 @@ func (suite *UpgradeSuite) assertSameVersionCluster(client *talosclient.Client,
|
||||
|
||||
err := retry.Constant(
|
||||
time.Minute,
|
||||
).Retry(func() error {
|
||||
var e error
|
||||
v, e = client.Version(ctx)
|
||||
).Retry(
|
||||
func() error {
|
||||
var e error
|
||||
v, e = client.Version(ctx)
|
||||
|
||||
return retry.ExpectedError(e)
|
||||
})
|
||||
return retry.ExpectedError(e)
|
||||
},
|
||||
)
|
||||
|
||||
suite.Require().NoError(err)
|
||||
|
||||
@ -503,7 +554,10 @@ func (suite *UpgradeSuite) assertSameVersionCluster(client *talosclient.Client,
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *UpgradeSuite) readVersion(nodeCtx context.Context, client *talosclient.Client) (version string, err error) {
|
||||
func (suite *UpgradeSuite) readVersion(nodeCtx context.Context, client *talosclient.Client) (
|
||||
version string,
|
||||
err error,
|
||||
) {
|
||||
var v *machineapi.VersionResponse
|
||||
|
||||
v, err = client.Version(nodeCtx)
|
||||
@ -526,22 +580,30 @@ func (suite *UpgradeSuite) upgradeNode(client *talosclient.Client, node provisio
|
||||
err error
|
||||
)
|
||||
|
||||
err = retry.Constant(time.Minute, retry.WithUnits(10*time.Second)).Retry(func() error {
|
||||
resp, err = client.Upgrade(nodeCtx, suite.spec.TargetInstallerImage, suite.spec.UpgradePreserve, suite.spec.UpgradeStage, false)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "leader changed") {
|
||||
return retry.ExpectedError(err)
|
||||
err = retry.Constant(time.Minute, retry.WithUnits(10*time.Second)).Retry(
|
||||
func() error {
|
||||
resp, err = client.Upgrade(
|
||||
nodeCtx,
|
||||
suite.spec.TargetInstallerImage,
|
||||
suite.spec.UpgradePreserve,
|
||||
suite.spec.UpgradeStage,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "leader changed") {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "failed to acquire upgrade lock") {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "failed to acquire upgrade lock") {
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
err = base.IgnoreGRPCUnavailable(err)
|
||||
suite.Require().NoError(err)
|
||||
@ -554,22 +616,33 @@ func (suite *UpgradeSuite) upgradeNode(client *talosclient.Client, node provisio
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
// wait for the version to be equal to target version
|
||||
suite.Require().NoError(retry.Constant(10 * time.Minute).Retry(func() error {
|
||||
var version string
|
||||
suite.Require().NoError(
|
||||
retry.Constant(10 * time.Minute).Retry(
|
||||
func() error {
|
||||
var version string
|
||||
|
||||
version, err = suite.readVersion(nodeCtx, client)
|
||||
if err != nil {
|
||||
// API might be unresponsive during upgrade
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
version, err = suite.readVersion(nodeCtx, client)
|
||||
if err != nil {
|
||||
// API might be unresponsive during upgrade
|
||||
return retry.ExpectedError(err)
|
||||
}
|
||||
|
||||
if version != suite.spec.TargetVersion {
|
||||
// upgrade not finished yet
|
||||
return retry.ExpectedError(fmt.Errorf("node %q version doesn't match expected: expected %q, got %q", node.IPs[0].String(), suite.spec.TargetVersion, version))
|
||||
}
|
||||
if version != suite.spec.TargetVersion {
|
||||
// upgrade not finished yet
|
||||
return retry.ExpectedError(
|
||||
fmt.Errorf(
|
||||
"node %q version doesn't match expected: expected %q, got %q",
|
||||
node.IPs[0].String(),
|
||||
suite.spec.TargetVersion,
|
||||
version,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}))
|
||||
return nil
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suite.waitForClusterHealth()
|
||||
}
|
||||
@ -622,7 +695,13 @@ func (suite *UpgradeSuite) untaint(name string) {
|
||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, corev1.Node{})
|
||||
suite.Require().NoError(err)
|
||||
|
||||
_, err = client.CoreV1().Nodes().Patch(suite.ctx, n.Name, types.StrategicMergePatchType, patchBytes, metav1.PatchOptions{})
|
||||
_, err = client.CoreV1().Nodes().Patch(
|
||||
suite.ctx,
|
||||
n.Name,
|
||||
types.StrategicMergePatchType,
|
||||
patchBytes,
|
||||
metav1.PatchOptions{},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
@ -670,7 +749,8 @@ func (suite *UpgradeSuite) SuiteName() string {
|
||||
}
|
||||
|
||||
func init() {
|
||||
allSuites = append(allSuites,
|
||||
allSuites = append(
|
||||
allSuites,
|
||||
&UpgradeSuite{specGen: upgradePreviousToStable, track: 0},
|
||||
&UpgradeSuite{specGen: upgradeStableToCurrent, track: 1},
|
||||
&UpgradeSuite{specGen: upgradeCurrentToCurrent, track: 2},
|
||||
|
@ -29,7 +29,8 @@ import (
|
||||
|
||||
type inspector struct {
|
||||
client *containerd.Client
|
||||
nsctx context.Context
|
||||
//nolint:containedctx
|
||||
nsctx context.Context
|
||||
}
|
||||
|
||||
type inspectorOptions struct {
|
||||
@ -97,7 +98,11 @@ func (i *inspector) Images() (map[string]string, error) {
|
||||
}
|
||||
|
||||
//nolint:gocyclo,cyclop
|
||||
func (i *inspector) containerInfo(cntr containerd.Container, imageList map[string]string, singleLookup bool) (*ctrs.Container, error) {
|
||||
func (i *inspector) containerInfo(
|
||||
cntr containerd.Container,
|
||||
imageList map[string]string,
|
||||
singleLookup bool,
|
||||
) (*ctrs.Container, error) {
|
||||
cp := &ctrs.Container{}
|
||||
|
||||
info, err := cntr.Info(i.nsctx)
|
||||
@ -222,7 +227,11 @@ func (i *inspector) containerInfo(cntr containerd.Container, imageList map[strin
|
||||
cp.IsPodSandbox = true
|
||||
} else if singleLookup && cns != "" && cname != "" {
|
||||
// try to find matching infrastructure container and pull sandbox from it
|
||||
query := fmt.Sprintf("labels.\"io.kubernetes.pod.namespace\"==%q,labels.\"io.kubernetes.pod.name\"==%q", cns, cname)
|
||||
query := fmt.Sprintf(
|
||||
"labels.\"io.kubernetes.pod.namespace\"==%q,labels.\"io.kubernetes.pod.name\"==%q",
|
||||
cns,
|
||||
cname,
|
||||
)
|
||||
|
||||
infraContainers, err := i.client.Containers(i.nsctx, query)
|
||||
if err == nil {
|
||||
@ -274,7 +283,11 @@ func (i *inspector) Container(id string) (*ctrs.Container, error) {
|
||||
pod = pod[:semicolonIdx]
|
||||
}
|
||||
|
||||
query = fmt.Sprintf("labels.\"io.kubernetes.pod.namespace\"==%q,labels.\"io.kubernetes.pod.name\"==%q", namespace, pod)
|
||||
query = fmt.Sprintf(
|
||||
"labels.\"io.kubernetes.pod.namespace\"==%q,labels.\"io.kubernetes.pod.name\"==%q",
|
||||
namespace,
|
||||
pod,
|
||||
)
|
||||
|
||||
if name != "" {
|
||||
query += fmt.Sprintf(",labels.\"io.kubernetes.container.name\"==%q", name)
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
|
||||
type inspector struct {
|
||||
client *criclient.Client
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
}
|
||||
|
||||
type inspectorOptions struct {
|
||||
@ -112,15 +112,17 @@ func (i *inspector) Container(id string) (*ctrs.Container, error) {
|
||||
}
|
||||
|
||||
if name == "" { // request for a pod sandbox
|
||||
sandboxes, err := i.client.ListPodSandbox(i.ctx, &runtimeapi.PodSandboxFilter{
|
||||
State: &runtimeapi.PodSandboxStateValue{
|
||||
State: runtimeapi.PodSandboxState_SANDBOX_READY,
|
||||
sandboxes, err := i.client.ListPodSandbox(
|
||||
i.ctx, &runtimeapi.PodSandboxFilter{
|
||||
State: &runtimeapi.PodSandboxStateValue{
|
||||
State: runtimeapi.PodSandboxState_SANDBOX_READY,
|
||||
},
|
||||
LabelSelector: map[string]string{
|
||||
"io.kubernetes.pod.name": pod,
|
||||
"io.kubernetes.pod.namespace": namespace,
|
||||
},
|
||||
},
|
||||
LabelSelector: map[string]string{
|
||||
"io.kubernetes.pod.name": pod,
|
||||
"io.kubernetes.pod.namespace": namespace,
|
||||
},
|
||||
})
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -138,13 +140,15 @@ func (i *inspector) Container(id string) (*ctrs.Container, error) {
|
||||
}
|
||||
|
||||
// request for a container
|
||||
containers, err := i.client.ListContainers(i.ctx, &runtimeapi.ContainerFilter{
|
||||
LabelSelector: map[string]string{
|
||||
"io.kubernetes.pod.name": pod,
|
||||
"io.kubernetes.pod.namespace": namespace,
|
||||
"io.kubernetes.container.name": name,
|
||||
containers, err := i.client.ListContainers(
|
||||
i.ctx, &runtimeapi.ContainerFilter{
|
||||
LabelSelector: map[string]string{
|
||||
"io.kubernetes.pod.name": pod,
|
||||
"io.kubernetes.pod.namespace": namespace,
|
||||
"io.kubernetes.container.name": name,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -242,11 +246,13 @@ func (i *inspector) buildContainer(container *runtimeapi.Container) (*ctrs.Conta
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func (i *inspector) Pods() ([]*ctrs.Pod, error) {
|
||||
sandboxes, err := i.client.ListPodSandbox(i.ctx, &runtimeapi.PodSandboxFilter{
|
||||
State: &runtimeapi.PodSandboxStateValue{
|
||||
State: runtimeapi.PodSandboxState_SANDBOX_READY,
|
||||
sandboxes, err := i.client.ListPodSandbox(
|
||||
i.ctx, &runtimeapi.PodSandboxFilter{
|
||||
State: &runtimeapi.PodSandboxStateValue{
|
||||
State: runtimeapi.PodSandboxState_SANDBOX_READY,
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ type CRISuite struct {
|
||||
containerdAddress string
|
||||
|
||||
client *criclient.Client
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
inspector ctrs.Inspector
|
||||
@ -175,12 +175,15 @@ func (suite *CRISuite) SetupTest() {
|
||||
suite.pods = append(suite.pods, podSandboxID)
|
||||
suite.Require().Len(podSandboxID, 64)
|
||||
|
||||
imageRef, err := suite.client.PullImage(suite.ctx, &runtimeapi.ImageSpec{
|
||||
Image: busyboxImage,
|
||||
}, podSandboxConfig)
|
||||
imageRef, err := suite.client.PullImage(
|
||||
suite.ctx, &runtimeapi.ImageSpec{
|
||||
Image: busyboxImage,
|
||||
}, podSandboxConfig,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
ctrID, err := suite.client.CreateContainer(suite.ctx, podSandboxID,
|
||||
ctrID, err := suite.client.CreateContainer(
|
||||
suite.ctx, podSandboxID,
|
||||
&runtimeapi.ContainerConfig{
|
||||
Metadata: &runtimeapi.ContainerMetadata{
|
||||
Name: "etcd",
|
||||
@ -197,7 +200,8 @@ func (suite *CRISuite) SetupTest() {
|
||||
Image: imageRef,
|
||||
},
|
||||
Command: []string{"/bin/sh", "-c", "sleep 3600"},
|
||||
}, podSandboxConfig)
|
||||
}, podSandboxConfig,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Len(ctrID, 64)
|
||||
|
||||
|
@ -47,7 +47,7 @@ type CRISuite struct {
|
||||
containerdAddress string
|
||||
|
||||
client *cri.Client
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
ctxCancel context.CancelFunc
|
||||
}
|
||||
|
||||
@ -165,17 +165,22 @@ func (suite *CRISuite) TestRunSandboxContainer() {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Len(podSandboxID, 64)
|
||||
|
||||
imageRef, err := suite.client.PullImage(suite.ctx, &runtimeapi.ImageSpec{
|
||||
Image: busyboxImage,
|
||||
}, podSandboxConfig)
|
||||
imageRef, err := suite.client.PullImage(
|
||||
suite.ctx, &runtimeapi.ImageSpec{
|
||||
Image: busyboxImage,
|
||||
}, podSandboxConfig,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
_, err = suite.client.ImageStatus(suite.ctx, &runtimeapi.ImageSpec{
|
||||
Image: imageRef,
|
||||
})
|
||||
_, err = suite.client.ImageStatus(
|
||||
suite.ctx, &runtimeapi.ImageSpec{
|
||||
Image: imageRef,
|
||||
},
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
ctrID, err := suite.client.CreateContainer(suite.ctx, podSandboxID,
|
||||
ctrID, err := suite.client.CreateContainer(
|
||||
suite.ctx, podSandboxID,
|
||||
&runtimeapi.ContainerConfig{
|
||||
Metadata: &runtimeapi.ContainerMetadata{
|
||||
Name: "etcd",
|
||||
@ -192,7 +197,8 @@ func (suite *CRISuite) TestRunSandboxContainer() {
|
||||
Image: imageRef,
|
||||
},
|
||||
Command: []string{"/bin/sh", "-c", "sleep 3600"},
|
||||
}, podSandboxConfig)
|
||||
}, podSandboxConfig,
|
||||
)
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Len(ctrID, 64)
|
||||
|
||||
|
@ -25,12 +25,15 @@ type Connection struct {
|
||||
bootstrapEndpoint string
|
||||
nodeClient *client.Client
|
||||
bootstrapClient *client.Client
|
||||
nodeCtx context.Context
|
||||
bootstrapCtx context.Context
|
||||
nodeCtx context.Context //nolint:containedctx
|
||||
bootstrapCtx context.Context //nolint:containedctx
|
||||
}
|
||||
|
||||
// NewConnection creates new installer connection.
|
||||
func NewConnection(ctx context.Context, nodeClient *client.Client, endpoint string, options ...Option) (*Connection, error) {
|
||||
func NewConnection(ctx context.Context, nodeClient *client.Client, endpoint string, options ...Option) (
|
||||
*Connection,
|
||||
error,
|
||||
) {
|
||||
c := &Connection{
|
||||
nodeEndpoint: endpoint,
|
||||
nodeClient: nodeClient,
|
||||
@ -48,7 +51,10 @@ func NewConnection(ctx context.Context, nodeClient *client.Client, endpoint stri
|
||||
}
|
||||
|
||||
// GenerateConfiguration calls GenerateConfiguration on the target/bootstrap node.
|
||||
func (c *Connection) GenerateConfiguration(req *machine.GenerateConfigurationRequest, callOptions ...grpc.CallOption) (*machine.GenerateConfigurationResponse, error) {
|
||||
func (c *Connection) GenerateConfiguration(
|
||||
req *machine.GenerateConfigurationRequest,
|
||||
callOptions ...grpc.CallOption,
|
||||
) (*machine.GenerateConfigurationResponse, error) {
|
||||
if c.bootstrapClient != nil {
|
||||
return c.bootstrapClient.GenerateConfiguration(c.bootstrapCtx, req, callOptions...)
|
||||
}
|
||||
@ -57,7 +63,10 @@ func (c *Connection) GenerateConfiguration(req *machine.GenerateConfigurationReq
|
||||
}
|
||||
|
||||
// ApplyConfiguration calls ApplyConfiguration on the target node using appropriate node context.
|
||||
func (c *Connection) ApplyConfiguration(req *machine.ApplyConfigurationRequest, callOptions ...grpc.CallOption) (*machine.ApplyConfigurationResponse, error) {
|
||||
func (c *Connection) ApplyConfiguration(
|
||||
req *machine.ApplyConfigurationRequest,
|
||||
callOptions ...grpc.CallOption,
|
||||
) (*machine.ApplyConfigurationResponse, error) {
|
||||
return c.nodeClient.ApplyConfiguration(c.nodeCtx, req, callOptions...)
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ type Installer struct {
|
||||
app *tview.Application
|
||||
wg sync.WaitGroup
|
||||
err error
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
cancel context.CancelFunc
|
||||
addedPages map[string]bool
|
||||
state *State
|
||||
@ -204,30 +204,32 @@ func (installer *Installer) configure() error {
|
||||
}
|
||||
|
||||
capture := installer.app.GetInputCapture()
|
||||
installer.app.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
||||
//nolint:exhaustive
|
||||
switch e.Key() {
|
||||
case tcell.KeyCtrlN:
|
||||
setPage(currentPage + 1)
|
||||
case tcell.KeyCtrlB:
|
||||
setPage(currentPage - 1)
|
||||
}
|
||||
|
||||
// page jump by ctrl/alt + N
|
||||
if e.Rune() >= '1' && e.Rune() < '9' {
|
||||
if e.Modifiers()&(tcell.ModAlt|tcell.ModCtrl) != 0 {
|
||||
setPage(int(e.Rune()) - 49)
|
||||
|
||||
return nil
|
||||
installer.app.SetInputCapture(
|
||||
func(e *tcell.EventKey) *tcell.EventKey {
|
||||
//nolint:exhaustive
|
||||
switch e.Key() {
|
||||
case tcell.KeyCtrlN:
|
||||
setPage(currentPage + 1)
|
||||
case tcell.KeyCtrlB:
|
||||
setPage(currentPage - 1)
|
||||
}
|
||||
}
|
||||
|
||||
if capture != nil {
|
||||
return capture(e)
|
||||
}
|
||||
// page jump by ctrl/alt + N
|
||||
if e.Rune() >= '1' && e.Rune() < '9' {
|
||||
if e.Modifiers()&(tcell.ModAlt|tcell.ModCtrl) != 0 {
|
||||
setPage(int(e.Rune()) - 49)
|
||||
|
||||
return e
|
||||
})
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if capture != nil {
|
||||
return capture(e)
|
||||
}
|
||||
|
||||
return e
|
||||
},
|
||||
)
|
||||
|
||||
defer installer.app.SetInputCapture(capture)
|
||||
|
||||
@ -240,9 +242,11 @@ func (installer *Installer) configure() error {
|
||||
button.SetInactiveColors(inactiveColor, tcell.ColorIvory)
|
||||
|
||||
func(page int) {
|
||||
button.SetSelectedFunc(func() {
|
||||
setPage(page)
|
||||
})
|
||||
button.SetSelectedFunc(
|
||||
func() {
|
||||
setPage(page)
|
||||
},
|
||||
)
|
||||
}(index)
|
||||
|
||||
menu.AddItem(button, len(name)+4, 1, false)
|
||||
@ -267,9 +271,11 @@ func (installer *Installer) configure() error {
|
||||
|
||||
if index > 0 {
|
||||
back := form.AddMenuButton("[::u]B[::-]ack", false)
|
||||
back.SetSelectedFunc(func() {
|
||||
setPage(index - 1)
|
||||
})
|
||||
back.SetSelectedFunc(
|
||||
func() {
|
||||
setPage(index - 1)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
addMenuItem(p.name, index)
|
||||
@ -278,15 +284,19 @@ func (installer *Installer) configure() error {
|
||||
|
||||
if index < len(state.pages)-1 {
|
||||
next := form.AddMenuButton("[::u]N[::-]ext", index == 0)
|
||||
next.SetSelectedFunc(func() {
|
||||
setPage(index + 1)
|
||||
})
|
||||
next.SetSelectedFunc(
|
||||
func() {
|
||||
setPage(index + 1)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
install := form.AddMenuButton("Install", false)
|
||||
install.SetBackgroundColor(tcell.ColorGreen)
|
||||
install.SetSelectedFunc(func() {
|
||||
close(done)
|
||||
})
|
||||
install.SetSelectedFunc(
|
||||
func() {
|
||||
close(done)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
installer.addPage(p.name, form, index == 0, menu)
|
||||
@ -362,9 +372,11 @@ func (installer *Installer) apply(conn *Connection) error {
|
||||
|
||||
// TODO: progress bar, logs?
|
||||
list.AddItem(s, 1, 1, false)
|
||||
_, err = conn.ApplyConfiguration(&machineapi.ApplyConfigurationRequest{
|
||||
Data: config,
|
||||
})
|
||||
_, err = conn.ApplyConfiguration(
|
||||
&machineapi.ApplyConfigurationRequest{
|
||||
Data: config,
|
||||
},
|
||||
)
|
||||
|
||||
s.Stop(err == nil)
|
||||
|
||||
@ -453,19 +465,21 @@ func (installer *Installer) writeTalosconfig(list *tview.Flex, talosconfig *clie
|
||||
func (installer *Installer) awaitKey(keys ...tcell.Key) {
|
||||
done := make(chan struct{})
|
||||
|
||||
installer.app.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
||||
for _, key := range keys {
|
||||
if e.Key() == key {
|
||||
installer.app.SetInputCapture(
|
||||
func(e *tcell.EventKey) *tcell.EventKey {
|
||||
for _, key := range keys {
|
||||
if e.Key() == key {
|
||||
close(done)
|
||||
}
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
close(done)
|
||||
}
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
close(done)
|
||||
}
|
||||
|
||||
return e
|
||||
})
|
||||
return e
|
||||
},
|
||||
)
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
@ -482,10 +496,12 @@ func (installer *Installer) showModal(title, text string, buttons ...string) int
|
||||
modal := tview.NewModal().
|
||||
SetText(text).
|
||||
AddButtons(buttons).
|
||||
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
index = buttonIndex
|
||||
close(done)
|
||||
})
|
||||
SetDoneFunc(
|
||||
func(buttonIndex int, buttonLabel string) {
|
||||
index = buttonIndex
|
||||
close(done)
|
||||
},
|
||||
)
|
||||
|
||||
installer.addPage(title, modal, true, nil)
|
||||
installer.app.SetFocus(modal)
|
||||
@ -524,8 +540,10 @@ func (installer *Installer) addPage(name string, primitive tview.Primitive, swit
|
||||
if switchToPage {
|
||||
installer.pages.AddAndSwitchToPage(name, frame, true)
|
||||
} else {
|
||||
installer.pages.AddPage(name,
|
||||
frame, true, false)
|
||||
installer.pages.AddPage(
|
||||
name,
|
||||
frame, true, false,
|
||||
)
|
||||
}
|
||||
} else if switchToPage {
|
||||
installer.pages.SwitchToPage(name)
|
||||
|
@ -32,7 +32,7 @@ type Stream struct {
|
||||
source Source
|
||||
options *Options
|
||||
|
||||
ctx context.Context
|
||||
ctx context.Context //nolint:containedctx
|
||||
}
|
||||
|
||||
// Source is an interface describing the source of a Stream.
|
||||
|
@ -184,9 +184,11 @@ func upgradeKubeletOnNode(ctx context.Context, cluster UpgradeProvider, options
|
||||
|
||||
options.Log(" > %q: waiting for node update", node)
|
||||
|
||||
if err = retry.Constant(3*time.Minute, retry.WithUnits(10*time.Second)).Retry(func() error {
|
||||
return checkNodeKubeletVersion(ctx, cluster, node, "v"+options.ToVersion)
|
||||
}); err != nil {
|
||||
if err = retry.Constant(3*time.Minute, retry.WithUnits(10*time.Second)).Retry(
|
||||
func() error {
|
||||
return checkNodeKubeletVersion(ctx, cluster, node, "v"+options.ToVersion)
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -195,7 +197,10 @@ func upgradeKubeletOnNode(ctx context.Context, cluster UpgradeProvider, options
|
||||
return nil
|
||||
}
|
||||
|
||||
func upgradeKubeletPatcher(options UpgradeOptions, kubeletSpec resource.Resource) func(config *v1alpha1config.Config) error {
|
||||
func upgradeKubeletPatcher(
|
||||
options UpgradeOptions,
|
||||
kubeletSpec resource.Resource,
|
||||
) func(config *v1alpha1config.Config) error {
|
||||
return func(config *v1alpha1config.Config) error {
|
||||
if config.MachineConfig == nil {
|
||||
config.MachineConfig = &v1alpha1config.MachineConfig{}
|
||||
@ -206,15 +211,15 @@ func upgradeKubeletPatcher(options UpgradeOptions, kubeletSpec resource.Resource
|
||||
}
|
||||
|
||||
var (
|
||||
any *resource.Any
|
||||
ok bool
|
||||
anyResource *resource.Any
|
||||
ok bool
|
||||
)
|
||||
|
||||
if any, ok = kubeletSpec.(*resource.Any); !ok {
|
||||
if anyResource, ok = kubeletSpec.(*resource.Any); !ok {
|
||||
return fmt.Errorf("unexpected resource type")
|
||||
}
|
||||
|
||||
oldImage := any.Value().(map[string]interface{})["image"].(string) //nolint:errcheck,forcetypeassert
|
||||
oldImage := anyResource.Value().(map[string]interface{})["image"].(string) //nolint:errcheck,forcetypeassert
|
||||
|
||||
logUpdate := func(oldImage string) {
|
||||
parts := strings.Split(oldImage, ":")
|
||||
@ -287,7 +292,13 @@ func checkNodeKubeletVersion(ctx context.Context, cluster UpgradeProvider, nodeT
|
||||
nodeFound = true
|
||||
|
||||
if node.Status.NodeInfo.KubeletVersion != version {
|
||||
return retry.ExpectedError(fmt.Errorf("node version mismatch: got %q, expected %q", node.Status.NodeInfo.KubeletVersion, version))
|
||||
return retry.ExpectedError(
|
||||
fmt.Errorf(
|
||||
"node version mismatch: got %q, expected %q",
|
||||
node.Status.NodeInfo.KubeletVersion,
|
||||
version,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
ready := false
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
type Reader struct {
|
||||
source *os.File
|
||||
|
||||
//nolint:containedctx
|
||||
ctx context.Context
|
||||
ctxCancel context.CancelFunc
|
||||
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/grpc/status"
|
||||
|
||||
_ "github.com/talos-systems/talos/pkg/grpc/codec" //nolint:gci // register codec
|
||||
_ "github.com/talos-systems/talos/pkg/grpc/codec" // register codec
|
||||
grpclog "github.com/talos-systems/talos/pkg/grpc/middleware/log"
|
||||
)
|
||||
|
||||
@ -150,19 +150,32 @@ func NewDefaultOptions(setters ...Option) *Options {
|
||||
|
||||
// Recovery is installed as the the first middleware in the chain to handle panics (via defer and recover()) in all subsequent middlewares.
|
||||
recoveryOpt := grpc_recovery.WithRecoveryHandler(recoveryHandler(logger))
|
||||
opts.UnaryInterceptors = append([]grpc.UnaryServerInterceptor{grpc_recovery.UnaryServerInterceptor(recoveryOpt)}, opts.UnaryInterceptors...)
|
||||
opts.StreamInterceptors = append([]grpc.StreamServerInterceptor{grpc_recovery.StreamServerInterceptor(recoveryOpt)}, opts.StreamInterceptors...)
|
||||
opts.UnaryInterceptors = append(
|
||||
[]grpc.UnaryServerInterceptor{grpc_recovery.UnaryServerInterceptor(recoveryOpt)},
|
||||
opts.UnaryInterceptors...,
|
||||
)
|
||||
opts.StreamInterceptors = append(
|
||||
[]grpc.StreamServerInterceptor{grpc_recovery.StreamServerInterceptor(recoveryOpt)},
|
||||
opts.StreamInterceptors...,
|
||||
)
|
||||
|
||||
if logger != nil {
|
||||
// Logging is installed as the first middleware (even before recovery middleware) in the chain
|
||||
// so that request in the form it was received and status sent on the wire is logged (error/success).
|
||||
// It also tracks the whole duration of the request, including other middleware overhead.
|
||||
logMiddleware := grpclog.NewMiddleware(logger)
|
||||
opts.UnaryInterceptors = append([]grpc.UnaryServerInterceptor{logMiddleware.UnaryInterceptor()}, opts.UnaryInterceptors...)
|
||||
opts.StreamInterceptors = append([]grpc.StreamServerInterceptor{logMiddleware.StreamInterceptor()}, opts.StreamInterceptors...)
|
||||
opts.UnaryInterceptors = append(
|
||||
[]grpc.UnaryServerInterceptor{logMiddleware.UnaryInterceptor()},
|
||||
opts.UnaryInterceptors...,
|
||||
)
|
||||
opts.StreamInterceptors = append(
|
||||
[]grpc.StreamServerInterceptor{logMiddleware.StreamInterceptor()},
|
||||
opts.StreamInterceptors...,
|
||||
)
|
||||
}
|
||||
|
||||
opts.ServerOptions = append(opts.ServerOptions,
|
||||
opts.ServerOptions = append(
|
||||
opts.ServerOptions,
|
||||
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(opts.UnaryInterceptors...)),
|
||||
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(opts.StreamInterceptors...)),
|
||||
)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user