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
|
range-loops: true # Report preallocation suggestions on range loops, true by default
|
||||||
for-loops: false # Report preallocation suggestions on for loops, false by default
|
for-loops: false # Report preallocation suggestions on for loops, false by default
|
||||||
gci:
|
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:
|
cyclop:
|
||||||
# the maximal code complexity to report
|
# the maximal code complexity to report
|
||||||
max-complexity: 20
|
max-complexity: 20
|
||||||
@ -138,6 +141,7 @@ linters:
|
|||||||
- errorlint
|
- errorlint
|
||||||
- exhaustivestruct
|
- exhaustivestruct
|
||||||
- forbidigo
|
- forbidigo
|
||||||
|
- forcetypeassert
|
||||||
- funlen
|
- funlen
|
||||||
- gas
|
- gas
|
||||||
- gochecknoglobals
|
- gochecknoglobals
|
||||||
@ -148,6 +152,7 @@ linters:
|
|||||||
- gomnd
|
- gomnd
|
||||||
- ifshort
|
- ifshort
|
||||||
- ireturn # we return interfaces
|
- ireturn # we return interfaces
|
||||||
|
- maintidx
|
||||||
- nestif
|
- nestif
|
||||||
- nilnil # we return "nil, nil"
|
- nilnil # we return "nil, nil"
|
||||||
- paralleltest
|
- paralleltest
|
||||||
@ -199,10 +204,10 @@ issues:
|
|||||||
exclude-use-default: false
|
exclude-use-default: false
|
||||||
|
|
||||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
# 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.
|
# 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,
|
# Show only new issues: if there are unstaged changes or untracked files,
|
||||||
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
|
# 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"]
|
RUN ["/toolchain/bin/ln", "-svf", "/toolchain/etc/ssl", "/etc/ssl"]
|
||||||
ARG GOLANGCILINT_VERSION
|
ARG GOLANGCILINT_VERSION
|
||||||
RUN curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/${GOLANGCILINT_VERSION}/install.sh | bash -s -- -b /toolchain/bin ${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
|
ARG GOFUMPT_VERSION
|
||||||
RUN go install mvdan.cc/gofumpt/gofumports@${GOFUMPT_VERSION} \
|
RUN go install mvdan.cc/gofumpt@${GOFUMPT_VERSION} \
|
||||||
&& mv /go/bin/gofumports /toolchain/go/bin/gofumports
|
&& mv /go/bin/gofumpt /toolchain/go/bin/gofumpt
|
||||||
ARG STRINGER_VERSION
|
ARG STRINGER_VERSION
|
||||||
RUN go install golang.org/x/tools/cmd/stringer@${STRINGER_VERSION} \
|
RUN go install golang.org/x/tools/cmd/stringer@${STRINGER_VERSION} \
|
||||||
&& mv /go/bin/stringer /toolchain/go/bin/stringer
|
&& 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
|
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
|
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
|
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
|
# Goimports and gofumpt generated files to adjust import order
|
||||||
RUN gofumports -w -local github.com/talos-systems/talos /api/
|
RUN goimports -w -local github.com/talos-systems/talos /api/
|
||||||
|
RUN gofumpt -w /api/
|
||||||
|
|
||||||
# run docgen for machinery config
|
# run docgen for machinery config
|
||||||
FROM build-go AS go-generate
|
FROM build-go AS go-generate
|
||||||
COPY ./pkg ./pkg
|
COPY ./pkg ./pkg
|
||||||
COPY ./hack/boilerplate.txt ./hack/boilerplate.txt
|
COPY ./hack/boilerplate.txt ./hack/boilerplate.txt
|
||||||
RUN --mount=type=cache,target=/.cache go generate ./pkg/...
|
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
|
WORKDIR /src/pkg/machinery
|
||||||
RUN --mount=type=cache,target=/.cache go generate ./...
|
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
|
FROM --platform=${BUILDPLATFORM} scratch AS generate
|
||||||
COPY --from=proto-format-build /src/api /api/
|
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
|
RUN --mount=type=cache,target=/.cache golangci-lint run --config ../../.golangci.yml
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
RUN --mount=type=cache,target=/.cache importvet github.com/talos-systems/talos/...
|
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.
|
# 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
|
PKGS ?= v1.1.0-alpha.0-5-g58603ba
|
||||||
EXTRAS ?= v1.0.0
|
EXTRAS ?= v1.0.0
|
||||||
GO_VERSION ?= 1.17
|
GO_VERSION ?= 1.17
|
||||||
GOFUMPT_VERSION ?= v0.1.1
|
GOIMPORTS_VERSION ?= v0.1.10
|
||||||
GOLANGCILINT_VERSION ?= v1.43.0
|
GOFUMPT_VERSION ?= v0.3.0
|
||||||
|
GOLANGCILINT_VERSION ?= v1.45.0
|
||||||
STRINGER_VERSION ?= v0.1.5
|
STRINGER_VERSION ?= v0.1.5
|
||||||
ENUMER_VERSION ?= v1.1.2
|
ENUMER_VERSION ?= v1.1.2
|
||||||
DEEPCOPY_GEN_VERSION ?= v0.21.3
|
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=PKGS=$(PKGS)
|
||||||
COMMON_ARGS += --build-arg=EXTRAS=$(EXTRAS)
|
COMMON_ARGS += --build-arg=EXTRAS=$(EXTRAS)
|
||||||
COMMON_ARGS += --build-arg=GOFUMPT_VERSION=$(GOFUMPT_VERSION)
|
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=STRINGER_VERSION=$(STRINGER_VERSION)
|
||||||
COMMON_ARGS += --build-arg=ENUMER_VERSION=$(ENUMER_VERSION)
|
COMMON_ARGS += --build-arg=ENUMER_VERSION=$(ENUMER_VERSION)
|
||||||
COMMON_ARGS += --build-arg=DEEPCOPY_GEN_VERSION=$(DEEPCOPY_GEN_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
|
@$(MAKE) local-api-descriptors DEST=./ PLATFORM=linux/amd64
|
||||||
|
|
||||||
fmt-go: ## Formats the source code.
|
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.
|
fmt-protobuf: ## Formats protobuf files.
|
||||||
@$(MAKE) local-fmt-protobuf DEST=./ PLATFORM=linux/amd64
|
@$(MAKE) local-fmt-protobuf DEST=./ PLATFORM=linux/amd64
|
||||||
|
@ -123,7 +123,8 @@ func GenV1Alpha1Config(genOptions []generate.GenOption,
|
|||||||
kubernetesVersion string,
|
kubernetesVersion string,
|
||||||
configPatch []string,
|
configPatch []string,
|
||||||
configPatchControlPlane []string,
|
configPatchControlPlane []string,
|
||||||
configPatchWorker []string) (*v1alpha1.ConfigBundle, error) {
|
configPatchWorker []string,
|
||||||
|
) (*v1alpha1.ConfigBundle, error) {
|
||||||
configBundleOpts := []bundle.Option{
|
configBundleOpts := []bundle.Option{
|
||||||
bundle.WithInputOptions(
|
bundle.WithInputOptions(
|
||||||
&bundle.InputOptions{
|
&bundle.InputOptions{
|
||||||
|
@ -22,7 +22,7 @@ type APISource struct {
|
|||||||
|
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
"google.golang.org/grpc/peer"
|
"google.golang.org/grpc/peer"
|
||||||
|
|
||||||
"github.com/talos-systems/talos/pkg/cli"
|
"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"
|
"github.com/talos-systems/talos/pkg/machinery/api/common"
|
||||||
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
|
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
|
||||||
"github.com/talos-systems/talos/pkg/machinery/client"
|
"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.
|
// WithClientNoNodes doesn't set any node information on request context.
|
||||||
func WithClientNoNodes(action func(context.Context, *client.Client) error) error {
|
func WithClientNoNodes(action func(context.Context, *client.Client) error) error {
|
||||||
return cli.WithContext(context.Background(), func(ctx context.Context) error {
|
return cli.WithContext(
|
||||||
cfg, err := clientconfig.Open(Talosconfig)
|
context.Background(), func(ctx context.Context) error {
|
||||||
if err != nil {
|
cfg, err := clientconfig.Open(Talosconfig)
|
||||||
return fmt.Errorf("failed to open config file %q: %w", Talosconfig, err)
|
if err != nil {
|
||||||
}
|
return fmt.Errorf("failed to open config file %q: %w", Talosconfig, err)
|
||||||
|
}
|
||||||
|
|
||||||
opts := []client.OptionFunc{
|
opts := []client.OptionFunc{
|
||||||
client.WithConfig(cfg),
|
client.WithConfig(cfg),
|
||||||
}
|
}
|
||||||
|
|
||||||
if Cmdcontext != "" {
|
if Cmdcontext != "" {
|
||||||
opts = append(opts, client.WithContextName(Cmdcontext))
|
opts = append(opts, client.WithContextName(Cmdcontext))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(Endpoints) > 0 {
|
if len(Endpoints) > 0 {
|
||||||
// override endpoints from command-line flags
|
// override endpoints from command-line flags
|
||||||
opts = append(opts, client.WithEndpoints(Endpoints...))
|
opts = append(opts, client.WithEndpoints(Endpoints...))
|
||||||
}
|
}
|
||||||
|
|
||||||
c, err := client.New(ctx, opts...)
|
c, err := client.New(ctx, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error constructing client: %w", err)
|
return fmt.Errorf("error constructing client: %w", err)
|
||||||
}
|
}
|
||||||
//nolint:errcheck
|
//nolint:errcheck
|
||||||
defer c.Close()
|
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.
|
// 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 {
|
func WithClient(action func(context.Context, *client.Client) error) error {
|
||||||
return WithClientNoNodes(func(ctx context.Context, c *client.Client) error {
|
return WithClientNoNodes(
|
||||||
if len(Nodes) < 1 {
|
func(ctx context.Context, c *client.Client) error {
|
||||||
configContext := c.GetConfigContext()
|
if len(Nodes) < 1 {
|
||||||
if configContext == nil {
|
configContext := c.GetConfigContext()
|
||||||
return fmt.Errorf("failed to resolve config context")
|
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 {
|
ctx = client.WithNodes(ctx, Nodes...)
|
||||||
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...)
|
return action(ctx, c)
|
||||||
|
},
|
||||||
return action(ctx, c)
|
)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithClientMaintenance wraps common code to initialize Talos client in maintenance (insecure mode).
|
// WithClientMaintenance wraps common code to initialize Talos client in maintenance (insecure mode).
|
||||||
func WithClientMaintenance(enforceFingerprints []string, action func(context.Context, *client.Client) error) error {
|
func WithClientMaintenance(enforceFingerprints []string, action func(context.Context, *client.Client) error) error {
|
||||||
return cli.WithContext(context.Background(), func(ctx context.Context) error {
|
return cli.WithContext(
|
||||||
tlsConfig := &tls.Config{
|
context.Background(), func(ctx context.Context) error {
|
||||||
InsecureSkipVerify: true,
|
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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...))
|
for i, stringFingerprint := range enforceFingerprints {
|
||||||
if err != nil {
|
var err error
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
//nolint:errcheck
|
fingerprints[i], err = x509.ParseFingerprint(stringFingerprint)
|
||||||
defer c.Close()
|
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.
|
// 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{} {
|
func getPathFromNode(path, filter string) map[string]struct{} {
|
||||||
paths := make(map[string]struct{})
|
paths := make(map[string]struct{})
|
||||||
|
|
||||||
WithClient(func(ctx context.Context, c *client.Client) error { //nolint:errcheck
|
//nolint:errcheck
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
WithClient(
|
||||||
defer cancel()
|
func(ctx context.Context, c *client.Client) error {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
stream, err := c.LS(ctx, &machineapi.ListRequest{
|
stream, err := c.LS(
|
||||||
Root: path,
|
ctx, &machineapi.ListRequest{
|
||||||
})
|
Root: path,
|
||||||
if err != nil {
|
},
|
||||||
return err
|
)
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
resp, err := stream.Recv()
|
|
||||||
if err != nil {
|
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 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 != "" {
|
if relativeTo(fullPath, filter) {
|
||||||
continue
|
paths[fullPath] = struct{}{}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fullPath := path + resp.RelativeName
|
||||||
|
|
||||||
if resp.Error != "" {
|
if relativeTo(fullPath, filter) {
|
||||||
continue
|
paths[fullPath] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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{}{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
@ -232,23 +243,26 @@ func getPathFromNode(path, filter string) map[string]struct{} {
|
|||||||
func getServiceFromNode() []string {
|
func getServiceFromNode() []string {
|
||||||
var svcIds []string
|
var svcIds []string
|
||||||
|
|
||||||
WithClient(func(ctx context.Context, c *client.Client) error { //nolint:errcheck
|
//nolint:errcheck
|
||||||
var remotePeer peer.Peer
|
WithClient(
|
||||||
|
func(ctx context.Context, c *client.Client) error {
|
||||||
|
var remotePeer peer.Peer
|
||||||
|
|
||||||
resp, err := c.ServiceList(ctx, grpc.Peer(&remotePeer))
|
resp, err := c.ServiceList(ctx, grpc.Peer(&remotePeer))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
for _, msg := range resp.Messages {
|
|
||||||
for _, s := range msg.Services {
|
|
||||||
svc := cli.ServiceInfoWrapper{ServiceInfo: s}
|
|
||||||
svcIds = append(svcIds, svc.Id)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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
|
return svcIds
|
||||||
}
|
}
|
||||||
@ -256,41 +270,44 @@ func getServiceFromNode() []string {
|
|||||||
func getContainersFromNode(kubernetes bool) []string {
|
func getContainersFromNode(kubernetes bool) []string {
|
||||||
var containerIds []string
|
var containerIds []string
|
||||||
|
|
||||||
WithClient(func(ctx context.Context, c *client.Client) error { //nolint:errcheck
|
//nolint:errcheck
|
||||||
var (
|
WithClient(
|
||||||
namespace string
|
func(ctx context.Context, c *client.Client) error {
|
||||||
driver common.ContainerDriver
|
var (
|
||||||
)
|
namespace string
|
||||||
|
driver common.ContainerDriver
|
||||||
|
)
|
||||||
|
|
||||||
if kubernetes {
|
if kubernetes {
|
||||||
namespace = criconstants.K8sContainerdNamespace
|
namespace = criconstants.K8sContainerdNamespace
|
||||||
driver = common.ContainerDriver_CRI
|
driver = common.ContainerDriver_CRI
|
||||||
} else {
|
} else {
|
||||||
namespace = constants.SystemContainerdNamespace
|
namespace = constants.SystemContainerdNamespace
|
||||||
driver = common.ContainerDriver_CONTAINERD
|
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)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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
|
return containerIds
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
"github.com/talos-systems/grpc-proxy/proxy"
|
"github.com/talos-systems/grpc-proxy/proxy"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
"google.golang.org/grpc/metadata"
|
"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/reflect/protoreflect"
|
||||||
"google.golang.org/protobuf/types/descriptorpb"
|
"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{"127.0.0.2"}, mdOut1.Get("proxyfrom"))
|
||||||
suite.Assert().Equal([]string{"os:admin"}, mdOut1.Get("talos-role"))
|
suite.Assert().Equal([]string{"os:admin"}, mdOut1.Get("talos-role"))
|
||||||
|
|
||||||
suite.Run("Same context", func() {
|
suite.Run(
|
||||||
ctx2 := ctx1
|
"Same context", func() {
|
||||||
outCtx2, conn2, err2 := suite.b.GetConnection(ctx2)
|
ctx2 := ctx1
|
||||||
suite.Require().NoError(err2)
|
outCtx2, conn2, err2 := suite.b.GetConnection(ctx2)
|
||||||
suite.Assert().Equal(conn1, conn2) // connection is cached
|
suite.Require().NoError(err2)
|
||||||
suite.Assert().Equal(role.MakeSet(role.Admin), authz.GetRoles(outCtx2))
|
suite.Assert().Equal(conn1, conn2) // connection is cached
|
||||||
|
suite.Assert().Equal(role.MakeSet(role.Admin), authz.GetRoles(outCtx2))
|
||||||
|
|
||||||
mdOut2, ok2 := metadata.FromOutgoingContext(outCtx2)
|
mdOut2, ok2 := metadata.FromOutgoingContext(outCtx2)
|
||||||
suite.Require().True(ok2)
|
suite.Require().True(ok2)
|
||||||
suite.Assert().Equal([]string{"value1", "value2"}, mdOut2.Get("key"))
|
suite.Assert().Equal([]string{"value1", "value2"}, mdOut2.Get("key"))
|
||||||
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut2.Get("proxyfrom"))
|
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut2.Get("proxyfrom"))
|
||||||
suite.Assert().Equal([]string{"os:admin"}, mdOut2.Get("talos-role"))
|
suite.Assert().Equal([]string{"os:admin"}, mdOut2.Get("talos-role"))
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.Run("Other context", func() {
|
suite.Run(
|
||||||
md3 := metadata.New(nil)
|
"Other context", func() {
|
||||||
md3.Set(":authority", "127.0.0.2")
|
md3 := metadata.New(nil)
|
||||||
md3.Set("nodes", "127.0.0.1")
|
md3.Set(":authority", "127.0.0.2")
|
||||||
md3.Set("key", "value3", "value4")
|
md3.Set("nodes", "127.0.0.1")
|
||||||
ctx3 := metadata.NewIncomingContext(authz.ContextWithRoles(context.Background(), role.MakeSet(role.Reader)), md3)
|
md3.Set("key", "value3", "value4")
|
||||||
|
ctx3 := metadata.NewIncomingContext(
|
||||||
|
authz.ContextWithRoles(context.Background(), role.MakeSet(role.Reader)),
|
||||||
|
md3,
|
||||||
|
)
|
||||||
|
|
||||||
outCtx3, conn3, err3 := suite.b.GetConnection(ctx3)
|
outCtx3, conn3, err3 := suite.b.GetConnection(ctx3)
|
||||||
suite.Require().NoError(err3)
|
suite.Require().NoError(err3)
|
||||||
suite.Assert().Equal(conn1, conn3) // connection is cached
|
suite.Assert().Equal(conn1, conn3) // connection is cached
|
||||||
suite.Assert().Equal(role.MakeSet(role.Reader), authz.GetRoles(outCtx3))
|
suite.Assert().Equal(role.MakeSet(role.Reader), authz.GetRoles(outCtx3))
|
||||||
|
|
||||||
mdOut3, ok3 := metadata.FromOutgoingContext(outCtx3)
|
mdOut3, ok3 := metadata.FromOutgoingContext(outCtx3)
|
||||||
suite.Require().True(ok3)
|
suite.Require().True(ok3)
|
||||||
suite.Assert().Equal([]string{"value3", "value4"}, mdOut3.Get("key"))
|
suite.Assert().Equal([]string{"value3", "value4"}, mdOut3.Get("key"))
|
||||||
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut3.Get("proxyfrom"))
|
suite.Assert().Equal([]string{"127.0.0.2"}, mdOut3.Get("proxyfrom"))
|
||||||
suite.Assert().Equal([]string{"os:reader"}, mdOut3.Get("talos-role"))
|
suite.Assert().Equal([]string{"os:reader"}, mdOut3.Get("talos-role"))
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *APIDSuite) TestAppendInfoUnary() {
|
func (suite *APIDSuite) TestAppendInfoUnary() {
|
||||||
@ -221,30 +228,37 @@ func TestAPIIdiosyncrasies(t *testing.T) {
|
|||||||
for j := 0; j < methods.Len(); j++ {
|
for j := 0; j < methods.Len(); j++ {
|
||||||
method := methods.Get(j)
|
method := methods.Get(j)
|
||||||
|
|
||||||
t.Run(string(method.FullName()), func(t *testing.T) {
|
t.Run(
|
||||||
response := method.Output()
|
string(method.FullName()), func(t *testing.T) {
|
||||||
responseFields := response.Fields()
|
response := method.Output()
|
||||||
|
responseFields := response.Fields()
|
||||||
|
|
||||||
if method.IsStreamingServer() {
|
if method.IsStreamingServer() {
|
||||||
metadata := responseFields.Get(0)
|
metadata := responseFields.Get(0)
|
||||||
assert.Equal(t, "metadata", metadata.TextName())
|
assert.Equal(t, "metadata", metadata.TextName())
|
||||||
assert.Equal(t, 1, int(metadata.Number()))
|
assert.Equal(t, 1, int(metadata.Number()))
|
||||||
} else {
|
} else {
|
||||||
require.Equal(t, 1, responseFields.Len(), "unary responses should have exactly one field")
|
require.Equal(t, 1, responseFields.Len(), "unary responses should have exactly one field")
|
||||||
|
|
||||||
messages := responseFields.Get(0)
|
messages := responseFields.Get(0)
|
||||||
assert.Equal(t, "messages", messages.TextName())
|
assert.Equal(t, "messages", messages.TextName())
|
||||||
assert.Equal(t, 1, int(messages.Number()))
|
assert.Equal(t, 1, int(messages.Number()))
|
||||||
|
|
||||||
reply := messages.Message()
|
reply := messages.Message()
|
||||||
replyFields := reply.Fields()
|
replyFields := reply.Fields()
|
||||||
require.GreaterOrEqual(t, replyFields.Len(), 1, "unary replies should have at least one field")
|
require.GreaterOrEqual(
|
||||||
|
t,
|
||||||
|
replyFields.Len(),
|
||||||
|
1,
|
||||||
|
"unary replies should have at least one field",
|
||||||
|
)
|
||||||
|
|
||||||
metadata := replyFields.Get(0)
|
metadata := replyFields.Get(0)
|
||||||
assert.Equal(t, "metadata", metadata.TextName())
|
assert.Equal(t, "metadata", metadata.TextName())
|
||||||
assert.Equal(t, 1, int(metadata.Number()))
|
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) {
|
func testDeprecated(t *testing.T, descriptor protoreflect.Descriptor, currentVersion *config.VersionContract) {
|
||||||
deprecated, version := getOptions(t, descriptor)
|
deprecated, version := getOptions(t, descriptor)
|
||||||
|
|
||||||
assert.Equal(t, deprecated, version != "",
|
assert.Equal(
|
||||||
"%s: `deprecated` and `remove_deprecated_XXX_in` options should be used together", descriptor.FullName())
|
t, deprecated, version != "",
|
||||||
|
"%s: `deprecated` and `remove_deprecated_XXX_in` options should be used together", descriptor.FullName(),
|
||||||
|
)
|
||||||
|
|
||||||
if !deprecated || version == "" {
|
if !deprecated || version == "" {
|
||||||
return
|
return
|
||||||
|
@ -47,7 +47,6 @@ func (s *InspectServer) ControllerRuntimeDependencies(ctx context.Context, in *e
|
|||||||
}
|
}
|
||||||
|
|
||||||
edges = append(edges, &inspectapi.ControllerDependencyEdge{
|
edges = append(edges, &inspectapi.ControllerDependencyEdge{
|
||||||
|
|
||||||
ControllerName: graph.Edges[i].ControllerName,
|
ControllerName: graph.Edges[i].ControllerName,
|
||||||
|
|
||||||
EdgeType: edgeType,
|
EdgeType: edgeType,
|
||||||
|
@ -263,25 +263,32 @@ func run() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Watch and handle runtime events.
|
// Watch and handle runtime events.
|
||||||
_ = c.Runtime().Events().Watch(func(events <-chan runtime.EventInfo) { //nolint:errcheck
|
//nolint:errcheck
|
||||||
for {
|
_ = c.Runtime().Events().Watch(
|
||||||
for event := range events {
|
func(events <-chan runtime.EventInfo) {
|
||||||
switch msg := event.Payload.(type) {
|
for {
|
||||||
case *machine.SequenceEvent:
|
for event := range events {
|
||||||
if msg.Error != nil {
|
switch msg := event.Payload.(type) {
|
||||||
if msg.Error.GetCode() == common.Code_LOCKED {
|
case *machine.SequenceEvent:
|
||||||
// ignore sequence lock errors, they're not fatal
|
if msg.Error != nil {
|
||||||
continue
|
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
|
return <-errCh
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ type ClusterSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +96,14 @@ func (suite *ClusterSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ type K8sAddressFilterSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
|
//nolint:containedctx
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
ctxCancel context.CancelFunc
|
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 {
|
return func() error {
|
||||||
r, err := suite.state.Get(suite.ctx, md)
|
r, err := suite.state.Get(suite.ctx, md)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -86,56 +90,78 @@ func (suite *K8sAddressFilterSuite) TestReconcile() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
||||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
ServiceSubnet: []string{
|
||||||
ServiceSubnet: []string{
|
"10.200.0.0/22",
|
||||||
"10.200.0.0/22",
|
"fd40:10:200::/112",
|
||||||
"fd40:10:200::/112",
|
},
|
||||||
},
|
PodSubnet: []string{
|
||||||
PodSubnet: []string{
|
"10.32.0.0/12",
|
||||||
"10.32.0.0/12",
|
"fd00:10:32::/102",
|
||||||
"fd00:10:32::/102",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
suite.assertResource(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(network.NamespaceName, network.NodeAddressFilterType, k8s.NodeAddressFilterOnlyK8s, resource.VersionUndefined),
|
suite.assertResource(
|
||||||
func(res resource.Resource) error {
|
resource.NewMetadata(
|
||||||
spec := res.(*network.NodeAddressFilter).TypedSpec()
|
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().Equal(
|
||||||
suite.Assert().Empty(spec.ExcludeSubnets)
|
"[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.Assert().NoError(
|
||||||
suite.assertResource(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(network.NamespaceName, network.NodeAddressFilterType, k8s.NodeAddressFilterNoK8s, resource.VersionUndefined),
|
suite.assertResource(
|
||||||
func(res resource.Resource) error {
|
resource.NewMetadata(
|
||||||
spec := res.(*network.NodeAddressFilter).TypedSpec()
|
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().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().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() {
|
func (suite *K8sAddressFilterSuite) TearDownTest() {
|
||||||
|
@ -40,7 +40,7 @@ type K8sControlPlaneSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,10 @@ func (suite *K8sControlPlaneSuite) startRuntime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *K8sControlPlaneSuite) assertK8sControlPlanes(manifests []string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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, machineType))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertK8sControlPlanes(
|
func() error {
|
||||||
[]string{
|
return suite.assertK8sControlPlanes(
|
||||||
config.K8sAdmissionControlID,
|
[]string{
|
||||||
config.K8sExtraManifestsID,
|
config.K8sAdmissionControlID,
|
||||||
config.K8sControlPlaneAPIServerID,
|
config.K8sExtraManifestsID,
|
||||||
config.K8sControlPlaneControllerManagerID,
|
config.K8sControlPlaneAPIServerID,
|
||||||
config.K8sControlPlaneSchedulerID,
|
config.K8sControlPlaneControllerManagerID,
|
||||||
config.K8sManifestsID,
|
config.K8sControlPlaneSchedulerID,
|
||||||
},
|
config.K8sManifestsID,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
r, err := suite.state.Get(suite.ctx, config.NewK8sControlPlaneAPIServer().Metadata())
|
r, err := suite.state.Get(suite.ctx, config.NewK8sControlPlaneAPIServer().Metadata())
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -125,17 +130,19 @@ func (suite *K8sControlPlaneSuite) TestReconcileDefaults() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
apiServerCfg := suite.setupMachine(cfg)
|
apiServerCfg := suite.setupMachine(cfg)
|
||||||
suite.Assert().Empty(apiServerCfg.CloudProvider)
|
suite.Assert().Empty(apiServerCfg.CloudProvider)
|
||||||
@ -149,86 +156,96 @@ func (suite *K8sControlPlaneSuite) TestReconcileExtraVolumes() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
APIServerConfig: &v1alpha1.APIServerConfig{
|
||||||
APIServerConfig: &v1alpha1.APIServerConfig{
|
ExtraVolumesConfig: []v1alpha1.VolumeMountConfig{
|
||||||
ExtraVolumesConfig: []v1alpha1.VolumeMountConfig{
|
{
|
||||||
{
|
VolumeHostPath: "/var/lib",
|
||||||
VolumeHostPath: "/var/lib",
|
VolumeMountPath: "/var/foo/",
|
||||||
VolumeMountPath: "/var/foo/",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
apiServerCfg := suite.setupMachine(cfg)
|
apiServerCfg := suite.setupMachine(cfg)
|
||||||
suite.Assert().Equal([]config.K8sExtraVolume{
|
suite.Assert().Equal(
|
||||||
{
|
[]config.K8sExtraVolume{
|
||||||
Name: "var-foo",
|
{
|
||||||
HostPath: "/var/lib",
|
Name: "var-foo",
|
||||||
MountPath: "/var/foo/",
|
HostPath: "/var/lib",
|
||||||
ReadOnly: false,
|
MountPath: "/var/foo/",
|
||||||
},
|
ReadOnly: false,
|
||||||
}, apiServerCfg.ExtraVolumes)
|
},
|
||||||
|
}, apiServerCfg.ExtraVolumes,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *K8sControlPlaneSuite) TestReconcileEnvironment() {
|
func (suite *K8sControlPlaneSuite) TestReconcileEnvironment() {
|
||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
APIServerConfig: &v1alpha1.APIServerConfig{
|
||||||
APIServerConfig: &v1alpha1.APIServerConfig{
|
EnvConfig: v1alpha1.Env{
|
||||||
EnvConfig: v1alpha1.Env{
|
"HTTP_PROXY": "foo",
|
||||||
"HTTP_PROXY": "foo",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
apiServerCfg := suite.setupMachine(cfg)
|
apiServerCfg := suite.setupMachine(cfg)
|
||||||
suite.Assert().Equal(map[string]string{
|
suite.Assert().Equal(
|
||||||
"HTTP_PROXY": "foo",
|
map[string]string{
|
||||||
}, apiServerCfg.EnvironmentVariables)
|
"HTTP_PROXY": "foo",
|
||||||
|
}, apiServerCfg.EnvironmentVariables,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *K8sControlPlaneSuite) TestReconcileExternalCloudProvider() {
|
func (suite *K8sControlPlaneSuite) TestReconcileExternalCloudProvider() {
|
||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
ExternalCloudProviderConfig: &v1alpha1.ExternalCloudProviderConfig{
|
||||||
ExternalCloudProviderConfig: &v1alpha1.ExternalCloudProviderConfig{
|
ExternalEnabled: true,
|
||||||
ExternalEnabled: true,
|
ExternalManifests: []string{
|
||||||
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/rbac.yaml",
|
"https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/aws-cloud-controller-manager-daemonset.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)
|
apiServerCfg := suite.setupMachine(cfg)
|
||||||
suite.Assert().Equal("external", apiServerCfg.CloudProvider)
|
suite.Assert().Equal("external", apiServerCfg.CloudProvider)
|
||||||
@ -240,63 +257,71 @@ func (suite *K8sControlPlaneSuite) TestReconcileExternalCloudProvider() {
|
|||||||
r, err = suite.state.Get(suite.ctx, config.NewK8sExtraManifests().Metadata())
|
r, err = suite.state.Get(suite.ctx, config.NewK8sExtraManifests().Metadata())
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().Equal(config.K8sExtraManifestsSpec{
|
suite.Assert().Equal(
|
||||||
ExtraManifests: []config.ExtraManifest{
|
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",
|
Name: "https://raw.githubusercontent.com/kubernetes/cloud-provider-aws/v1.20.0-alpha.0/manifests/rbac.yaml",
|
||||||
Priority: "30",
|
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",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
}, r.(*config.K8sControlPlane).ExtraManifests(),
|
||||||
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())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *K8sControlPlaneSuite) TestReconcileInlineManifests() {
|
func (suite *K8sControlPlaneSuite) TestReconcileInlineManifests() {
|
||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterInlineManifests: v1alpha1.ClusterInlineManifests{
|
||||||
ClusterInlineManifests: v1alpha1.ClusterInlineManifests{
|
{
|
||||||
{
|
InlineManifestName: "namespace-ci",
|
||||||
InlineManifestName: "namespace-ci",
|
InlineManifestContents: strings.TrimSpace(
|
||||||
InlineManifestContents: strings.TrimSpace(`
|
`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: ci
|
name: ci
|
||||||
`),
|
`,
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.setupMachine(cfg)
|
suite.setupMachine(cfg)
|
||||||
|
|
||||||
r, err := suite.state.Get(suite.ctx, config.NewK8sExtraManifests().Metadata())
|
r, err := suite.state.Get(suite.ctx, config.NewK8sExtraManifests().Metadata())
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().Equal(config.K8sExtraManifestsSpec{
|
suite.Assert().Equal(
|
||||||
ExtraManifests: []config.ExtraManifest{
|
config.K8sExtraManifestsSpec{
|
||||||
{
|
ExtraManifests: []config.ExtraManifest{
|
||||||
Name: "namespace-ci",
|
{
|
||||||
Priority: "99",
|
Name: "namespace-ci",
|
||||||
InlineManifest: "apiVersion: v1\nkind: Namespace\nmetadata:\n\tname: ci",
|
Priority: "99",
|
||||||
|
InlineManifest: "apiVersion: v1\nkind: Namespace\nmetadata:\n\tname: ci",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}, r.(*config.K8sControlPlane).ExtraManifests(),
|
||||||
}, r.(*config.K8sControlPlane).ExtraManifests())
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *K8sControlPlaneSuite) TearDownTest() {
|
func (suite *K8sControlPlaneSuite) TearDownTest() {
|
||||||
@ -307,8 +332,19 @@ func (suite *K8sControlPlaneSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
suite.Assert().NoError(suite.state.Create(context.Background(), k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, "-")))
|
suite.Assert().NoError(
|
||||||
suite.Assert().NoError(suite.state.Destroy(context.Background(), config.NewK8sControlPlaneAPIServer().Metadata(), state.WithDestroyOwner("config.K8sControlPlaneController")))
|
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) {
|
func TestK8sControlPlaneSuite(t *testing.T) {
|
||||||
|
@ -35,7 +35,7 @@ type EtcFileSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
etcPath string
|
etcPath string
|
||||||
@ -57,10 +57,14 @@ func (suite *EtcFileSuite) SetupTest() {
|
|||||||
suite.etcPath = suite.T().TempDir()
|
suite.etcPath = suite.T().TempDir()
|
||||||
suite.shadowPath = suite.T().TempDir()
|
suite.shadowPath = suite.T().TempDir()
|
||||||
|
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&filesctrl.EtcFileController{
|
suite.Require().NoError(
|
||||||
EtcPath: suite.etcPath,
|
suite.runtime.RegisterController(
|
||||||
ShadowPath: suite.shadowPath,
|
&filesctrl.EtcFileController{
|
||||||
}))
|
EtcPath: suite.etcPath,
|
||||||
|
ShadowPath: suite.shadowPath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *EtcFileSuite) startRuntime() {
|
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)
|
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 err != nil {
|
||||||
if state.IsNotFoundError(err) {
|
if state.IsNotFoundError(err) {
|
||||||
return retry.ExpectedError(err)
|
return retry.ExpectedError(err)
|
||||||
@ -118,10 +125,13 @@ func (suite *EtcFileSuite) TestFiles() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, etcFileSpec))
|
suite.Require().NoError(suite.state.Create(suite.ctx, etcFileSpec))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertEtcFile("test1", "foo", etcFileSpec.Metadata().Version())
|
func() error {
|
||||||
}))
|
return suite.assertEtcFile("test1", "foo", etcFileSpec.Metadata().Version())
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
for _, r := range []resource.Resource{etcFileSpec} {
|
for _, r := range []resource.Resource{etcFileSpec} {
|
||||||
for {
|
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,
|
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()
|
cfg := configResource.APIServer()
|
||||||
|
|
||||||
enabledAdmissionPlugins := []string{"NodeRestriction"}
|
enabledAdmissionPlugins := []string{"NodeRestriction"}
|
||||||
@ -465,7 +466,8 @@ func (ctrl *ControlPlaneStaticPodController) manageAPIServer(ctx context.Context
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ctrl *ControlPlaneStaticPodController) manageControllerManager(ctx context.Context, r controller.Runtime,
|
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()
|
cfg := configResource.ControllerManager()
|
||||||
|
|
||||||
if !cfg.Enabled {
|
if !cfg.Enabled {
|
||||||
@ -594,7 +596,8 @@ func (ctrl *ControlPlaneStaticPodController) manageControllerManager(ctx context
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ctrl *ControlPlaneStaticPodController) manageScheduler(ctx context.Context, r controller.Runtime,
|
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()
|
cfg := configResource.Scheduler()
|
||||||
|
|
||||||
if !cfg.Enabled {
|
if !cfg.Enabled {
|
||||||
|
@ -41,7 +41,7 @@ type ControlPlaneStaticPodSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,10 @@ func (suite *ControlPlaneStaticPodSuite) startRuntime() {
|
|||||||
|
|
||||||
//nolint:dupl
|
//nolint:dupl
|
||||||
func (suite *ControlPlaneStaticPodSuite) assertControlPlaneStaticPods(manifests []string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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, configControllerManager))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertControlPlaneStaticPods(
|
func() error {
|
||||||
[]string{
|
return suite.assertControlPlaneStaticPods(
|
||||||
"kube-apiserver",
|
[]string{
|
||||||
"kube-controller-manager",
|
"kube-apiserver",
|
||||||
"kube-scheduler",
|
"kube-controller-manager",
|
||||||
},
|
"kube-scheduler",
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// tear down etcd service
|
// tear down etcd service
|
||||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, v1alpha1.NewService("etcd").Metadata()))
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
list, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
list, err := suite.state.List(
|
||||||
return err
|
suite.ctx,
|
||||||
}
|
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(list.Items) > 0 {
|
if len(list.Items) > 0 {
|
||||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
))
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraMounts() {
|
func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraMounts() {
|
||||||
secretStatus := k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, k8s.StaticPodSecretsStaticPodID)
|
secretStatus := k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, k8s.StaticPodSecretsStaticPodID)
|
||||||
configStatus := k8s.NewConfigStatus(k8s.ControlPlaneNamespaceName, k8s.ConfigStatusStaticPodID)
|
configStatus := k8s.NewConfigStatus(k8s.ControlPlaneNamespaceName, k8s.ConfigStatusStaticPodID)
|
||||||
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
||||||
configAPIServer.SetAPIServer(config.K8sControlPlaneAPIServerSpec{
|
configAPIServer.SetAPIServer(
|
||||||
ExtraVolumes: []config.K8sExtraVolume{
|
config.K8sControlPlaneAPIServerSpec{
|
||||||
{
|
ExtraVolumes: []config.K8sExtraVolume{
|
||||||
Name: "foo",
|
{
|
||||||
HostPath: "/var/lib",
|
Name: "foo",
|
||||||
MountPath: "/var/foo",
|
HostPath: "/var/lib",
|
||||||
ReadOnly: true,
|
MountPath: "/var/foo",
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
configControllerManager := config.NewK8sControlPlaneControllerManager()
|
configControllerManager := config.NewK8sControlPlaneControllerManager()
|
||||||
configScheduler := config.NewK8sControlPlaneScheduler()
|
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, configControllerManager))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertControlPlaneStaticPods(
|
func() error {
|
||||||
[]string{
|
return suite.assertControlPlaneStaticPods(
|
||||||
"kube-apiserver",
|
[]string{
|
||||||
"kube-controller-manager",
|
"kube-apiserver",
|
||||||
"kube-scheduler",
|
"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)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
apiServerPod, err := k8sadapter.StaticPod(r.(*k8s.StaticPod)).Pod()
|
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.Volumes, 4)
|
||||||
suite.Assert().Len(apiServerPod.Spec.Containers[0].VolumeMounts, 4)
|
suite.Assert().Len(apiServerPod.Spec.Containers[0].VolumeMounts, 4)
|
||||||
|
|
||||||
suite.Assert().Equal(v1.Volume{
|
suite.Assert().Equal(
|
||||||
Name: "secrets",
|
v1.Volume{
|
||||||
VolumeSource: v1.VolumeSource{
|
Name: "secrets",
|
||||||
HostPath: &v1.HostPathVolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
Path: constants.KubernetesAPIServerSecretsDir,
|
HostPath: &v1.HostPathVolumeSource{
|
||||||
|
Path: constants.KubernetesAPIServerSecretsDir,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}, apiServerPod.Spec.Volumes[0],
|
||||||
}, apiServerPod.Spec.Volumes[0])
|
)
|
||||||
|
|
||||||
suite.Assert().Equal(v1.Volume{
|
suite.Assert().Equal(
|
||||||
Name: "config",
|
v1.Volume{
|
||||||
VolumeSource: v1.VolumeSource{
|
Name: "config",
|
||||||
HostPath: &v1.HostPathVolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
Path: constants.KubernetesAPIServerConfigDir,
|
HostPath: &v1.HostPathVolumeSource{
|
||||||
|
Path: constants.KubernetesAPIServerConfigDir,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}, apiServerPod.Spec.Volumes[1],
|
||||||
}, apiServerPod.Spec.Volumes[1])
|
)
|
||||||
|
|
||||||
suite.Assert().Equal(v1.Volume{
|
suite.Assert().Equal(
|
||||||
Name: "audit",
|
v1.Volume{
|
||||||
VolumeSource: v1.VolumeSource{
|
Name: "audit",
|
||||||
HostPath: &v1.HostPathVolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
Path: constants.KubernetesAuditLogDir,
|
HostPath: &v1.HostPathVolumeSource{
|
||||||
|
Path: constants.KubernetesAuditLogDir,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}, apiServerPod.Spec.Volumes[2],
|
||||||
}, apiServerPod.Spec.Volumes[2])
|
)
|
||||||
|
|
||||||
suite.Assert().Equal(v1.Volume{
|
suite.Assert().Equal(
|
||||||
Name: "foo",
|
v1.Volume{
|
||||||
VolumeSource: v1.VolumeSource{
|
Name: "foo",
|
||||||
HostPath: &v1.HostPathVolumeSource{
|
VolumeSource: v1.VolumeSource{
|
||||||
Path: "/var/lib",
|
HostPath: &v1.HostPathVolumeSource{
|
||||||
|
Path: "/var/lib",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}, apiServerPod.Spec.Volumes[3],
|
||||||
}, apiServerPod.Spec.Volumes[3])
|
)
|
||||||
|
|
||||||
suite.Assert().Equal(v1.VolumeMount{
|
suite.Assert().Equal(
|
||||||
Name: "secrets",
|
v1.VolumeMount{
|
||||||
MountPath: constants.KubernetesAPIServerSecretsDir,
|
Name: "secrets",
|
||||||
ReadOnly: true,
|
MountPath: constants.KubernetesAPIServerSecretsDir,
|
||||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[0])
|
ReadOnly: true,
|
||||||
|
}, apiServerPod.Spec.Containers[0].VolumeMounts[0],
|
||||||
|
)
|
||||||
|
|
||||||
suite.Assert().Equal(v1.VolumeMount{
|
suite.Assert().Equal(
|
||||||
Name: "config",
|
v1.VolumeMount{
|
||||||
MountPath: constants.KubernetesAPIServerConfigDir,
|
Name: "config",
|
||||||
ReadOnly: true,
|
MountPath: constants.KubernetesAPIServerConfigDir,
|
||||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[1])
|
ReadOnly: true,
|
||||||
|
}, apiServerPod.Spec.Containers[0].VolumeMounts[1],
|
||||||
|
)
|
||||||
|
|
||||||
suite.Assert().Equal(v1.VolumeMount{
|
suite.Assert().Equal(
|
||||||
Name: "audit",
|
v1.VolumeMount{
|
||||||
MountPath: constants.KubernetesAuditLogDir,
|
Name: "audit",
|
||||||
ReadOnly: false,
|
MountPath: constants.KubernetesAuditLogDir,
|
||||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[2])
|
ReadOnly: false,
|
||||||
|
}, apiServerPod.Spec.Containers[0].VolumeMounts[2],
|
||||||
|
)
|
||||||
|
|
||||||
suite.Assert().Equal(v1.VolumeMount{
|
suite.Assert().Equal(
|
||||||
Name: "foo",
|
v1.VolumeMount{
|
||||||
MountPath: "/var/foo",
|
Name: "foo",
|
||||||
ReadOnly: true,
|
MountPath: "/var/foo",
|
||||||
}, apiServerPod.Spec.Containers[0].VolumeMounts[3])
|
ReadOnly: true,
|
||||||
|
}, apiServerPod.Spec.Containers[0].VolumeMounts[3],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraArgs() {
|
func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraArgs() {
|
||||||
@ -278,9 +311,11 @@ func (suite *ControlPlaneStaticPodSuite) TestReconcileExtraArgs() {
|
|||||||
secretStatus := k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, k8s.StaticPodSecretsStaticPodID)
|
secretStatus := k8s.NewSecretsStatus(k8s.ControlPlaneNamespaceName, k8s.StaticPodSecretsStaticPodID)
|
||||||
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
||||||
|
|
||||||
configAPIServer.SetAPIServer(config.K8sControlPlaneAPIServerSpec{
|
configAPIServer.SetAPIServer(
|
||||||
ExtraArgs: test.args,
|
config.K8sControlPlaneAPIServerSpec{
|
||||||
})
|
ExtraArgs: test.args,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, configStatus))
|
suite.Require().NoError(suite.state.Create(suite.ctx, configStatus))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, secretStatus))
|
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
|
// wait for some time to ensure that controller has picked the input
|
||||||
time.Sleep(500 * time.Millisecond)
|
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)
|
suite.Require().Error(err)
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertControlPlaneStaticPods(
|
func() error {
|
||||||
[]string{
|
return suite.assertControlPlaneStaticPods(
|
||||||
"kube-apiserver",
|
[]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)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
apiServerPod, err := k8sadapter.StaticPod(r.(*k8s.StaticPod)).Pod()
|
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, secretStatus.Metadata()))
|
||||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, configAPIServer.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
list, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
list, err := suite.state.List(
|
||||||
return err
|
suite.ctx,
|
||||||
}
|
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(list.Items) > 0 {
|
if len(list.Items) > 0 {
|
||||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
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 {
|
for _, test := range tests {
|
||||||
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
configAPIServer := config.NewK8sControlPlaneAPIServer()
|
||||||
|
|
||||||
configAPIServer.SetAPIServer(config.K8sControlPlaneAPIServerSpec{
|
configAPIServer.SetAPIServer(
|
||||||
EnvironmentVariables: test.env,
|
config.K8sControlPlaneAPIServerSpec{
|
||||||
})
|
EnvironmentVariables: test.env,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, configAPIServer))
|
suite.Require().NoError(suite.state.Create(suite.ctx, configAPIServer))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertControlPlaneStaticPods(
|
func() error {
|
||||||
[]string{
|
return suite.assertControlPlaneStaticPods(
|
||||||
"kube-apiserver",
|
[]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)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
apiServerPod, err := k8sadapter.StaticPod(r.(*k8s.StaticPod)).Pod()
|
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.Require().NoError(suite.state.Destroy(suite.ctx, configAPIServer.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
list, err := suite.state.List(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
list, err := suite.state.List(
|
||||||
return err
|
suite.ctx,
|
||||||
}
|
resource.NewMetadata(k8s.NamespaceName, k8s.StaticPodType, "", resource.VersionUndefined),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(list.Items) > 0 {
|
if len(list.Items) > 0 {
|
||||||
return retry.ExpectedErrorf("expected no pods, got %d", len(list.Items))
|
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, configControllerManager))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
suite.Require().NoError(suite.state.Create(suite.ctx, configScheduler))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertControlPlaneStaticPods(
|
func() error {
|
||||||
[]string{
|
return suite.assertControlPlaneStaticPods(
|
||||||
"kube-apiserver",
|
[]string{
|
||||||
"kube-controller-manager",
|
"kube-apiserver",
|
||||||
"kube-scheduler",
|
"kube-controller-manager",
|
||||||
},
|
"kube-scheduler",
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// flip enabled to disable scheduler
|
// flip enabled to disable scheduler
|
||||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, configScheduler.Metadata(), func(r resource.Resource) error {
|
_, err := suite.state.UpdateWithConflicts(
|
||||||
spec := r.(*config.K8sControlPlane).Scheduler()
|
suite.ctx, configScheduler.Metadata(), func(r resource.Resource) error {
|
||||||
spec.Enabled = false
|
spec := r.(*config.K8sControlPlane).Scheduler()
|
||||||
r.(*config.K8sControlPlane).SetScheduler(spec)
|
spec.Enabled = false
|
||||||
|
r.(*config.K8sControlPlane).SetScheduler(spec)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
configScheduler.SetScheduler(config.K8sControlPlaneSchedulerSpec{Enabled: false})
|
configScheduler.SetScheduler(config.K8sControlPlaneSchedulerSpec{Enabled: false})
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertControlPlaneStaticPods(
|
func() error {
|
||||||
[]string{
|
return suite.assertControlPlaneStaticPods(
|
||||||
"kube-apiserver",
|
[]string{
|
||||||
"kube-controller-manager",
|
"kube-apiserver",
|
||||||
},
|
"kube-controller-manager",
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ControlPlaneStaticPodSuite) TearDownTest() {
|
func (suite *ControlPlaneStaticPodSuite) TearDownTest() {
|
||||||
@ -503,7 +569,12 @@ func (suite *ControlPlaneStaticPodSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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()))
|
suite.Assert().NoError(suite.state.Create(context.Background(), config.NewK8sManifests()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ type ExtraManifestSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,10 @@ func (suite *ExtraManifestSuite) startRuntime() {
|
|||||||
|
|
||||||
//nolint:dupl
|
//nolint:dupl
|
||||||
func (suite *ExtraManifestSuite) assertExtraManifests(manifests []string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -91,12 +94,14 @@ func (suite *ExtraManifestSuite) assertExtraManifests(manifests []string) error
|
|||||||
|
|
||||||
func (suite *ExtraManifestSuite) TestReconcileInlineManifests() {
|
func (suite *ExtraManifestSuite) TestReconcileInlineManifests() {
|
||||||
configExtraManifests := config.NewK8sExtraManifests()
|
configExtraManifests := config.NewK8sExtraManifests()
|
||||||
configExtraManifests.SetExtraManifests(config.K8sExtraManifestsSpec{
|
configExtraManifests.SetExtraManifests(
|
||||||
ExtraManifests: []config.ExtraManifest{
|
config.K8sExtraManifestsSpec{
|
||||||
{
|
ExtraManifests: []config.ExtraManifest{
|
||||||
Name: "namespaces",
|
{
|
||||||
Priority: "99",
|
Name: "namespaces",
|
||||||
InlineManifest: strings.TrimSpace(`
|
Priority: "99",
|
||||||
|
InlineManifest: strings.TrimSpace(
|
||||||
|
`
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
@ -106,10 +111,12 @@ apiVersion: v1
|
|||||||
kind: Namespace
|
kind: Namespace
|
||||||
metadata:
|
metadata:
|
||||||
name: build
|
name: build
|
||||||
`),
|
`,
|
||||||
|
),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
statusNetwork := network.NewStatus(network.NamespaceName, network.StatusID)
|
statusNetwork := network.NewStatus(network.NamespaceName, network.StatusID)
|
||||||
statusNetwork.TypedSpec().AddressReady = true
|
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, configExtraManifests))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, statusNetwork))
|
suite.Require().NoError(suite.state.Create(suite.ctx, statusNetwork))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertExtraManifests(
|
func() error {
|
||||||
[]string{
|
return suite.assertExtraManifests(
|
||||||
"99-namespaces",
|
[]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)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
manifest := r.(*k8s.Manifest) //nolint:errcheck,forcetypeassert
|
manifest := r.(*k8s.Manifest) //nolint:errcheck,forcetypeassert
|
||||||
|
@ -38,7 +38,7 @@ type KubeletConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,139 +71,165 @@ func (suite *KubeletConfigSuite) TestReconcile() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
KubeletImage: "kubelet",
|
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||||
KubeletClusterDNS: []string{"10.0.0.1"},
|
KubeletImage: "kubelet",
|
||||||
KubeletExtraArgs: map[string]string{
|
KubeletClusterDNS: []string{"10.0.0.1"},
|
||||||
"enable-feature": "foo",
|
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{
|
},
|
||||||
{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Mount: specs.Mount{
|
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",
|
Destination: "/tmp",
|
||||||
Source: "/var",
|
Source: "/var",
|
||||||
Type: "tmpfs",
|
Type: "tmpfs",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
spec.ExtraMounts,
|
||||||
KubeletExtraConfig: v1alpha1.Unstructured{
|
)
|
||||||
Object: map[string]interface{}{
|
suite.Assert().Equal(
|
||||||
|
map[string]interface{}{
|
||||||
"serverTLSBootstrap": true,
|
"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() {
|
func (suite *KubeletConfigSuite) TestReconcileDefaults() {
|
||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
KubeletImage: "kubelet",
|
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||||
},
|
KubeletImage: "kubelet",
|
||||||
},
|
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
|
||||||
URL: u,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ClusterNetwork: &v1alpha1.ClusterNetworkConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ServiceSubnet: []string{constants.DefaultIPv4ServiceNet},
|
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.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
kubeletConfig, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletConfigType, k8s.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
kubeletConfig, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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)
|
return nil
|
||||||
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
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KubeletConfigSuite) TearDownTest() {
|
func (suite *KubeletConfigSuite) TearDownTest() {
|
||||||
|
@ -43,7 +43,7 @@ type KubeletSpecSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,41 +99,52 @@ func (suite *KubeletSpecSuite) TestReconcileDefault() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodename))
|
suite.Require().NoError(suite.state.Create(suite.ctx, nodename))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
kubeletSpec, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletSpecType, k8s.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
kubeletSpec, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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([]interface{}{"10.96.0.10"}, spec.Config["clusterDNS"])
|
||||||
suite.Assert().Equal(
|
suite.Assert().Equal("cluster.local", spec.Config["clusterDomain"])
|
||||||
[]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"])
|
return nil
|
||||||
suite.Assert().Equal("cluster.local", spec.Config["clusterDomain"])
|
},
|
||||||
|
),
|
||||||
return nil
|
)
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KubeletSpecSuite) TestReconcileWithExplicitNodeIP() {
|
func (suite *KubeletSpecSuite) TestReconcileWithExplicitNodeIP() {
|
||||||
@ -150,35 +161,46 @@ func (suite *KubeletSpecSuite) TestReconcileWithExplicitNodeIP() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodename))
|
suite.Require().NoError(suite.state.Create(suite.ctx, nodename))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
kubeletSpec, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletSpecType, k8s.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
kubeletSpec, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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)
|
return nil
|
||||||
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
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KubeletSpecSuite) TestReconcileWithExtraConfig() {
|
func (suite *KubeletSpecSuite) TestReconcileWithExtraConfig() {
|
||||||
@ -202,32 +224,45 @@ func (suite *KubeletSpecSuite) TestReconcileWithExtraConfig() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodeIP))
|
suite.Require().NoError(suite.state.Create(suite.ctx, nodeIP))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
kubeletSpec, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.KubeletSpecType, k8s.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
kubeletSpec, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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 {
|
suite.Assert().Equal("/", kubeletConfiguration.CgroupRoot)
|
||||||
return err
|
suite.Assert().Equal(cfg.TypedSpec().ClusterDomain, kubeletConfiguration.ClusterDomain)
|
||||||
}
|
suite.Assert().True(kubeletConfiguration.ServerTLSBootstrap)
|
||||||
|
|
||||||
suite.Assert().Equal("/", kubeletConfiguration.CgroupRoot)
|
return nil
|
||||||
suite.Assert().Equal(cfg.TypedSpec().ClusterDomain, kubeletConfiguration.ClusterDomain)
|
},
|
||||||
suite.Assert().True(kubeletConfiguration.ServerTLSBootstrap)
|
),
|
||||||
|
)
|
||||||
return nil
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KubeletSpecSuite) TearDownTest() {
|
func (suite *KubeletSpecSuite) TearDownTest() {
|
||||||
@ -276,68 +311,74 @@ func TestNewKubeletConfigurationFail(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
tt := tt
|
tt := tt
|
||||||
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(
|
||||||
_, err := k8sctrl.NewKubeletConfiguration([]string{"10.96.0.10"}, "cluster.svc", tt.extraConfig)
|
tt.name, func(t *testing.T) {
|
||||||
require.Error(t, err)
|
_, 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) {
|
func TestNewKubeletConfigurationSuccess(t *testing.T) {
|
||||||
config, err := k8sctrl.NewKubeletConfiguration([]string{"10.0.0.5"}, "cluster.local", map[string]interface{}{
|
config, err := k8sctrl.NewKubeletConfiguration(
|
||||||
"oomScoreAdj": -300,
|
[]string{"10.0.0.5"}, "cluster.local", map[string]interface{}{
|
||||||
"enableDebuggingHandlers": true,
|
"oomScoreAdj": -300,
|
||||||
})
|
"enableDebuggingHandlers": true,
|
||||||
|
},
|
||||||
|
)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, &kubeletconfig.KubeletConfiguration{
|
assert.Equal(
|
||||||
TypeMeta: metav1.TypeMeta{
|
t, &kubeletconfig.KubeletConfiguration{
|
||||||
APIVersion: kubeletconfig.SchemeGroupVersion.String(),
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: "KubeletConfiguration",
|
APIVersion: kubeletconfig.SchemeGroupVersion.String(),
|
||||||
},
|
Kind: "KubeletConfiguration",
|
||||||
StaticPodPath: constants.ManifestsDirectory,
|
|
||||||
Port: constants.KubeletPort,
|
|
||||||
Authentication: kubeletconfig.KubeletAuthentication{
|
|
||||||
X509: kubeletconfig.KubeletX509Authentication{
|
|
||||||
ClientCAFile: constants.KubernetesCACert,
|
|
||||||
},
|
},
|
||||||
Webhook: kubeletconfig.KubeletWebhookAuthentication{
|
StaticPodPath: constants.ManifestsDirectory,
|
||||||
Enabled: pointer.ToBool(true),
|
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{
|
Authorization: kubeletconfig.KubeletAuthorization{
|
||||||
Enabled: pointer.ToBool(false),
|
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{
|
config,
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ type ManifestSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,10 @@ func (suite *ManifestSuite) startRuntime() {
|
|||||||
|
|
||||||
//nolint:dupl
|
//nolint:dupl
|
||||||
func (suite *ManifestSuite) assertManifests(manifests []string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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, rootSecrets))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertManifests(
|
func() error {
|
||||||
[]string{
|
return suite.assertManifests(
|
||||||
"00-kubelet-bootstrapping-token",
|
[]string{
|
||||||
"01-csr-approver-role-binding",
|
"00-kubelet-bootstrapping-token",
|
||||||
"01-csr-node-bootstrap",
|
"01-csr-approver-role-binding",
|
||||||
"01-csr-renewal-role-binding",
|
"01-csr-node-bootstrap",
|
||||||
"02-kube-system-sa-role-binding",
|
"01-csr-renewal-role-binding",
|
||||||
"03-default-pod-security-policy",
|
"02-kube-system-sa-role-binding",
|
||||||
"05-flannel",
|
"03-default-pod-security-policy",
|
||||||
"10-kube-proxy",
|
"05-flannel",
|
||||||
"11-core-dns",
|
"10-kube-proxy",
|
||||||
"11-core-dns-svc",
|
"11-core-dns",
|
||||||
"11-kube-config-in-cluster",
|
"11-core-dns-svc",
|
||||||
},
|
"11-kube-config-in-cluster",
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ManifestSuite) TestReconcileDisableKubeProxy() {
|
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, rootSecrets))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertManifests(
|
func() error {
|
||||||
[]string{
|
return suite.assertManifests(
|
||||||
"00-kubelet-bootstrapping-token",
|
[]string{
|
||||||
"01-csr-approver-role-binding",
|
"00-kubelet-bootstrapping-token",
|
||||||
"01-csr-node-bootstrap",
|
"01-csr-approver-role-binding",
|
||||||
"01-csr-renewal-role-binding",
|
"01-csr-node-bootstrap",
|
||||||
"02-kube-system-sa-role-binding",
|
"01-csr-renewal-role-binding",
|
||||||
"03-default-pod-security-policy",
|
"02-kube-system-sa-role-binding",
|
||||||
"05-flannel",
|
"03-default-pod-security-policy",
|
||||||
"11-core-dns",
|
"05-flannel",
|
||||||
"11-core-dns-svc",
|
"11-core-dns",
|
||||||
"11-kube-config-in-cluster",
|
"11-core-dns-svc",
|
||||||
},
|
"11-kube-config-in-cluster",
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ManifestSuite) TestReconcileKubeProxyExtraArgs() {
|
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, rootSecrets))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertManifests(
|
func() error {
|
||||||
[]string{
|
return suite.assertManifests(
|
||||||
"00-kubelet-bootstrapping-token",
|
[]string{
|
||||||
"01-csr-approver-role-binding",
|
"00-kubelet-bootstrapping-token",
|
||||||
"01-csr-node-bootstrap",
|
"01-csr-approver-role-binding",
|
||||||
"01-csr-renewal-role-binding",
|
"01-csr-node-bootstrap",
|
||||||
"02-kube-system-sa-role-binding",
|
"01-csr-renewal-role-binding",
|
||||||
"03-default-pod-security-policy",
|
"02-kube-system-sa-role-binding",
|
||||||
"05-flannel",
|
"03-default-pod-security-policy",
|
||||||
"10-kube-proxy",
|
"05-flannel",
|
||||||
"11-core-dns",
|
"10-kube-proxy",
|
||||||
"11-core-dns-svc",
|
"11-core-dns",
|
||||||
"11-kube-config-in-cluster",
|
"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)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
manifest := r.(*k8s.Manifest) //nolint:errcheck,forcetypeassert
|
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, rootSecrets))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
suite.Require().NoError(suite.state.Create(suite.ctx, manifestConfig))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertManifests(
|
func() error {
|
||||||
[]string{
|
return suite.assertManifests(
|
||||||
"00-kubelet-bootstrapping-token",
|
[]string{
|
||||||
"01-csr-approver-role-binding",
|
"00-kubelet-bootstrapping-token",
|
||||||
"01-csr-node-bootstrap",
|
"01-csr-approver-role-binding",
|
||||||
"01-csr-renewal-role-binding",
|
"01-csr-node-bootstrap",
|
||||||
"02-kube-system-sa-role-binding",
|
"01-csr-renewal-role-binding",
|
||||||
"05-flannel",
|
"02-kube-system-sa-role-binding",
|
||||||
"10-kube-proxy",
|
"05-flannel",
|
||||||
"11-core-dns",
|
"10-kube-proxy",
|
||||||
"11-core-dns-svc",
|
"11-core-dns",
|
||||||
"11-kube-config-in-cluster",
|
"11-core-dns-svc",
|
||||||
},
|
"11-kube-config-in-cluster",
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ManifestSuite) TearDownTest() {
|
func (suite *ManifestSuite) TearDownTest() {
|
||||||
|
@ -37,7 +37,7 @@ type NodeIPConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,109 +70,139 @@ func (suite *NodeIPConfigSuite) TestReconcileWithSubnets() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
KubeletNodeIP: v1alpha1.KubeletNodeIPConfig{
|
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||||
KubeletNodeIPValidSubnets: []string{"10.0.0.0/24"},
|
KubeletNodeIP: v1alpha1.KubeletNodeIPConfig{
|
||||||
|
KubeletNodeIPValidSubnets: []string{"10.0.0.0/24"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
NetworkInterfaces: []*v1alpha1.Device{
|
||||||
NetworkInterfaces: []*v1alpha1.Device{
|
{
|
||||||
{
|
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
SharedIP: "1.2.3.4",
|
||||||
SharedIP: "1.2.3.4",
|
},
|
||||||
},
|
DeviceVlans: []*v1alpha1.Vlan{
|
||||||
DeviceVlans: []*v1alpha1.Vlan{
|
{
|
||||||
{
|
VlanID: 100,
|
||||||
VlanID: 100,
|
VlanVIP: &v1alpha1.DeviceVIPConfig{
|
||||||
VlanVIP: &v1alpha1.DeviceVIPConfig{
|
SharedIP: "5.6.7.8",
|
||||||
SharedIP: "5.6.7.8",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
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.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
NodeIPConfig, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPConfigType, k8s.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
NodeIPConfig, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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)
|
return nil
|
||||||
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
|
)
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *NodeIPConfigSuite) TestReconcileDefaults() {
|
func (suite *NodeIPConfigSuite) TestReconcileDefaults() {
|
||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
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.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
NodeIPConfig, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPConfigType, k8s.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
NodeIPConfig, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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)
|
return nil
|
||||||
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
|
)
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *NodeIPConfigSuite) TearDownTest() {
|
func (suite *NodeIPConfigSuite) TearDownTest() {
|
||||||
|
@ -36,7 +36,7 @@ type NodeIPSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,10 @@ func (suite *NodeIPSuite) TestReconcileIPv4() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
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{
|
addresses.TypedSpec().Addresses = []netaddr.IPPrefix{
|
||||||
netaddr.MustParseIPPrefix("10.0.0.2/32"), // excluded explicitly
|
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.Require().NoError(suite.state.Create(suite.ctx, addresses))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
NodeIP, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPType, k8s.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
NodeIP, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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() {
|
func (suite *NodeIPSuite) TestReconcileDefaultSubnets() {
|
||||||
@ -114,7 +122,10 @@ func (suite *NodeIPSuite) TestReconcileDefaultSubnets() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
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{
|
addresses.TypedSpec().Addresses = []netaddr.IPPrefix{
|
||||||
netaddr.MustParseIPPrefix("10.0.0.5/24"),
|
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.Require().NoError(suite.state.Create(suite.ctx, addresses))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
NodeIP, err := suite.state.Get(suite.ctx, resource.NewMetadata(k8s.NamespaceName, k8s.NodeIPType, k8s.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
NodeIP, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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() {
|
func (suite *NodeIPSuite) TearDownTest() {
|
||||||
|
@ -38,7 +38,7 @@ type NodenameSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +69,10 @@ func (suite *NodenameSuite) startRuntime() {
|
|||||||
|
|
||||||
//nolint:dupl
|
//nolint:dupl
|
||||||
func (suite *NodenameSuite) assertNodename(expected string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -83,7 +86,11 @@ func (suite *NodenameSuite) assertNodename(expected string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resources.Items[0].(*k8s.Nodename).TypedSpec().Nodename != expected {
|
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
|
return nil
|
||||||
@ -93,17 +100,19 @@ func (suite *NodenameSuite) TestDefault() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
|
URL: u,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
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.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNodename("foo")
|
func() error {
|
||||||
},
|
return suite.assertNodename("foo")
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *NodenameSuite) TestFQDN() {
|
func (suite *NodenameSuite) TestFQDN() {
|
||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineKubelet: &v1alpha1.KubeletConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
KubeletRegisterWithFQDN: true,
|
MachineKubelet: &v1alpha1.KubeletConfig{
|
||||||
|
KubeletRegisterWithFQDN: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
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.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNodename("foo.bar.ltd")
|
func() error {
|
||||||
},
|
return suite.assertNodename("foo.bar.ltd")
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *NodenameSuite) TearDownTest() {
|
func (suite *NodenameSuite) TearDownTest() {
|
||||||
@ -163,17 +178,26 @@ func (suite *NodenameSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().NoError(err)
|
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) {
|
func TestNodenameSuite(t *testing.T) {
|
||||||
|
@ -36,7 +36,7 @@ type StaticPodConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
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 {
|
return func() error {
|
||||||
r, err := suite.state.Get(suite.ctx, md)
|
r, err := suite.state.Get(suite.ctx, md)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -96,47 +99,51 @@ func (suite *StaticPodConfigSuite) assertNoResource(md resource.Metadata) func()
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StaticPodConfigSuite) TestReconcile() {
|
func (suite *StaticPodConfigSuite) TestReconcile() {
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachinePods: []v1alpha1.Unstructured{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
{
|
MachinePods: []v1alpha1.Unstructured{
|
||||||
Object: map[string]interface{}{
|
{
|
||||||
"apiVersion": "v1",
|
Object: map[string]interface{}{
|
||||||
"kind": "pod",
|
"apiVersion": "v1",
|
||||||
"metadata": map[string]interface{}{
|
"kind": "pod",
|
||||||
"name": "nginx",
|
"metadata": map[string]interface{}{
|
||||||
},
|
"name": "nginx",
|
||||||
"spec": map[string]interface{}{
|
},
|
||||||
"containers": []interface{}{
|
"spec": map[string]interface{}{
|
||||||
map[string]interface{}{
|
"containers": []interface{}{
|
||||||
"name": "nginx",
|
map[string]interface{}{
|
||||||
"image": "nginx",
|
"name": "nginx",
|
||||||
|
"image": "nginx",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||||
},
|
},
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
)
|
||||||
})
|
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
suite.assertResource(
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
*k8s.NewStaticPod(k8s.NamespaceName, "default-nginx").Metadata(),
|
suite.assertResource(
|
||||||
func(res resource.Resource) error {
|
*k8s.NewStaticPod(k8s.NamespaceName, "default-nginx").Metadata(),
|
||||||
v, ok, err := unstructured.NestedString(res.(*k8s.StaticPod).TypedSpec().Pod, "kind")
|
func(res resource.Resource) error {
|
||||||
suite.Require().NoError(err)
|
v, ok, err := unstructured.NestedString(res.(*k8s.StaticPod).TypedSpec().Pod, "kind")
|
||||||
suite.Assert().True(ok)
|
suite.Require().NoError(err)
|
||||||
suite.Assert().Equal("pod", v)
|
suite.Assert().True(ok)
|
||||||
|
suite.Assert().Equal("pod", v)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
))
|
)
|
||||||
|
|
||||||
// update the pod changing the namespace
|
// update the pod changing the namespace
|
||||||
cfg.Config().Raw().(*v1alpha1.Config).MachineConfig.MachinePods[0].Object["metadata"].(map[string]interface{})["namespace"] = "custom"
|
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()
|
cfg.Metadata().BumpVersion()
|
||||||
suite.Require().NoError(suite.state.Update(suite.ctx, oldVersion, cfg))
|
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.Assert().NoError(
|
||||||
suite.assertNoResource(
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
*k8s.NewStaticPod(k8s.NamespaceName, "default-nginx").Metadata(),
|
suite.assertNoResource(
|
||||||
|
*k8s.NewStaticPod(k8s.NamespaceName, "default-nginx").Metadata(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
))
|
)
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
suite.assertResource(
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
*k8s.NewStaticPod(k8s.NamespaceName, "custom-nginx").Metadata(),
|
suite.assertResource(
|
||||||
func(res resource.Resource) error {
|
*k8s.NewStaticPod(k8s.NamespaceName, "custom-nginx").Metadata(),
|
||||||
v, ok, err := unstructured.NestedString(res.(*k8s.StaticPod).TypedSpec().Pod, "metadata", "namespace")
|
func(res resource.Resource) error {
|
||||||
suite.Require().NoError(err)
|
v, ok, err := unstructured.NestedString(
|
||||||
suite.Assert().True(ok)
|
res.(*k8s.StaticPod).TypedSpec().Pod,
|
||||||
suite.Assert().Equal("custom", v)
|
"metadata",
|
||||||
|
"namespace",
|
||||||
|
)
|
||||||
|
suite.Require().NoError(err)
|
||||||
|
suite.Assert().True(ok)
|
||||||
|
suite.Assert().Equal("custom", v)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
))
|
)
|
||||||
|
|
||||||
// remove all pods
|
// remove all pods
|
||||||
cfg.Config().Raw().(*v1alpha1.Config).MachineConfig.MachinePods = nil
|
cfg.Config().Raw().(*v1alpha1.Config).MachineConfig.MachinePods = nil
|
||||||
@ -169,11 +184,13 @@ func (suite *StaticPodConfigSuite) TestReconcile() {
|
|||||||
cfg.Metadata().BumpVersion()
|
cfg.Metadata().BumpVersion()
|
||||||
suite.Require().NoError(suite.state.Update(suite.ctx, oldVersion, cfg))
|
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.Assert().NoError(
|
||||||
suite.assertNoResource(
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
*k8s.NewStaticPod(k8s.NamespaceName, "custom-nginx").Metadata(),
|
suite.assertNoResource(
|
||||||
|
*k8s.NewStaticPod(k8s.NamespaceName, "custom-nginx").Metadata(),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StaticPodConfigSuite) TearDownTest() {
|
func (suite *StaticPodConfigSuite) TearDownTest() {
|
||||||
|
@ -33,7 +33,7 @@ type KubeSpanSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,10 +136,14 @@ func (suite *KubeSpanSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
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.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
suite.assertNoResourceType(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, "", resource.VersionUndefined),
|
suite.assertNoResourceType(
|
||||||
)),
|
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, "", resource.VersionUndefined),
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,18 +116,22 @@ func (suite *ManagerSuite) TestReconcile() {
|
|||||||
mockWireguard := &mockWireguardClient{}
|
mockWireguard := &mockWireguardClient{}
|
||||||
mockNfTables := &mockNftablesManager{}
|
mockNfTables := &mockNftablesManager{}
|
||||||
|
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&kubespanctrl.ManagerController{
|
suite.Require().NoError(
|
||||||
WireguardClientFactory: func() (kubespanctrl.WireguardClient, error) {
|
suite.runtime.RegisterController(
|
||||||
return mockWireguard, nil
|
&kubespanctrl.ManagerController{
|
||||||
},
|
WireguardClientFactory: func() (kubespanctrl.WireguardClient, error) {
|
||||||
RulesManagerFactory: func(_, _ int) kubespanctrl.RulesManager {
|
return mockWireguard, nil
|
||||||
return mockRulesManager{}
|
},
|
||||||
},
|
RulesManagerFactory: func(_, _ int) kubespanctrl.RulesManager {
|
||||||
NfTablesManagerFactory: func(_, _ uint32) kubespanctrl.NfTablesManager {
|
return mockRulesManager{}
|
||||||
return mockNfTables
|
},
|
||||||
},
|
NfTablesManagerFactory: func(_, _ uint32) kubespanctrl.NfTablesManager {
|
||||||
PeerReconcileInterval: time.Second,
|
return mockNfTables
|
||||||
}))
|
},
|
||||||
|
PeerReconcileInterval: time.Second,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -140,82 +146,116 @@ func (suite *ManagerSuite) TestReconcile() {
|
|||||||
|
|
||||||
localIdentity := kubespan.NewIdentity(kubespan.NamespaceName, kubespan.LocalIdentity)
|
localIdentity := kubespan.NewIdentity(kubespan.NamespaceName, kubespan.LocalIdentity)
|
||||||
suite.Require().NoError(kubespanadapter.IdentitySpec(localIdentity.TypedSpec()).GenerateKey())
|
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))
|
suite.Require().NoError(suite.state.Create(suite.ctx, localIdentity))
|
||||||
|
|
||||||
// initial setup: link should be created without any peers
|
// initial setup: link should be created without any peers
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
suite.assertResource(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(
|
suite.assertResource(
|
||||||
network.ConfigNamespaceName,
|
resource.NewMetadata(
|
||||||
network.LinkSpecType,
|
network.ConfigNamespaceName,
|
||||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
network.LinkSpecType,
|
||||||
resource.VersionUndefined,
|
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.Assert().NoError(
|
||||||
suite.assertResource(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(
|
suite.assertResource(
|
||||||
network.ConfigNamespaceName,
|
resource.NewMetadata(
|
||||||
network.AddressSpecType,
|
network.ConfigNamespaceName,
|
||||||
network.LayeredID(network.ConfigOperator, network.AddressID(constants.KubeSpanLinkName, localIdentity.TypedSpec().Address)),
|
network.AddressSpecType,
|
||||||
resource.VersionUndefined,
|
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.Assert().NoError(
|
||||||
suite.assertResourceIDs(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(
|
suite.assertResourceIDs(
|
||||||
network.ConfigNamespaceName,
|
resource.NewMetadata(
|
||||||
network.RouteSpecType,
|
network.ConfigNamespaceName,
|
||||||
"",
|
network.RouteSpecType,
|
||||||
resource.VersionUndefined,
|
"",
|
||||||
|
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.Assert().NoError(
|
||||||
suite.assertNoResourceType(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, "", resource.VersionUndefined),
|
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
|
// 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=")
|
peer1 := kubespan.NewPeerSpec(kubespan.NamespaceName, "3FxU7UuwektMjbyuJBs7i1hDj2rQA6tHnbNB6WrQxww=")
|
||||||
@ -246,72 +286,83 @@ func (suite *ManagerSuite) TestReconcile() {
|
|||||||
key2, err := wgtypes.ParseKey(peer2.Metadata().ID())
|
key2, err := wgtypes.ParseKey(peer2.Metadata().ID())
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
suite.assertResource(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(
|
suite.assertResource(
|
||||||
network.ConfigNamespaceName,
|
resource.NewMetadata(
|
||||||
network.LinkSpecType,
|
network.ConfigNamespaceName,
|
||||||
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
network.LinkSpecType,
|
||||||
resource.VersionUndefined,
|
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
||||||
),
|
resource.VersionUndefined,
|
||||||
func(res resource.Resource) error {
|
),
|
||||||
spec := res.(*network.LinkSpec).TypedSpec()
|
func(res resource.Resource) error {
|
||||||
|
spec := res.(*network.LinkSpec).TypedSpec()
|
||||||
|
|
||||||
if len(spec.Wireguard.Peers) != 2 {
|
if len(spec.Wireguard.Peers) != 2 {
|
||||||
return retry.ExpectedErrorf("peers not set up yet")
|
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} {
|
ranges := fmt.Sprintf("%v", ipSet.Ranges())
|
||||||
suite.Assert().Equal(peer.Metadata().ID(), spec.Wireguard.Peers[i].PublicKey)
|
expected := "[10.244.1.0-10.244.2.255]"
|
||||||
suite.Assert().Equal(cfg.TypedSpec().SharedSecret, spec.Wireguard.Peers[i].PresharedKey)
|
|
||||||
suite.Assert().Equal(peer.TypedSpec().AllowedIPs, spec.Wireguard.Peers[i].AllowedIPs)
|
if ranges != expected {
|
||||||
suite.Assert().Equal(peer.TypedSpec().Endpoints[0].String(), spec.Wireguard.Peers[i].Endpoint)
|
return retry.ExpectedErrorf("ranges %s != expected %s", ranges, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
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
|
// update config and disable force routing, nothing should be routed
|
||||||
oldVersion := cfg.Metadata().Version()
|
oldVersion := cfg.Metadata().Version()
|
||||||
@ -319,76 +370,89 @@ func (suite *ManagerSuite) TestReconcile() {
|
|||||||
cfg.Metadata().BumpVersion()
|
cfg.Metadata().BumpVersion()
|
||||||
suite.Require().NoError(suite.state.Update(suite.ctx, oldVersion, cfg))
|
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.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
ipSet := mockNfTables.IPSet()
|
func() error {
|
||||||
|
ipSet := mockNfTables.IPSet()
|
||||||
|
|
||||||
if ipSet == nil {
|
if ipSet == nil {
|
||||||
return retry.ExpectedErrorf("ipset is nil")
|
return retry.ExpectedErrorf("ipset is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ipSet.Prefixes()) != 0 {
|
if len(ipSet.Prefixes()) != 0 {
|
||||||
return retry.ExpectedErrorf("expected empty ipset: %v", ipSet.Ranges())
|
return retry.ExpectedErrorf("expected empty ipset: %v", ipSet.Ranges())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// report up status via wireguard mock
|
// report up status via wireguard mock
|
||||||
mockWireguard.update(&wgtypes.Device{
|
mockWireguard.update(
|
||||||
Peers: []wgtypes.Peer{
|
&wgtypes.Device{
|
||||||
{
|
Peers: []wgtypes.Peer{
|
||||||
PublicKey: key1,
|
{
|
||||||
Endpoint: peer1.TypedSpec().Endpoints[0].UDPAddr(),
|
PublicKey: key1,
|
||||||
LastHandshakeTime: time.Now(),
|
Endpoint: peer1.TypedSpec().Endpoints[0].UDPAddr(),
|
||||||
},
|
LastHandshakeTime: time.Now(),
|
||||||
{
|
},
|
||||||
PublicKey: key2,
|
{
|
||||||
Endpoint: peer2.TypedSpec().Endpoints[0].UDPAddr(),
|
PublicKey: key2,
|
||||||
LastHandshakeTime: time.Now(),
|
Endpoint: peer2.TypedSpec().Endpoints[0].UDPAddr(),
|
||||||
|
LastHandshakeTime: time.Now(),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
for _, peer := range []*kubespan.PeerSpec{peer1, peer2} {
|
for _, peer := range []*kubespan.PeerSpec{peer1, peer2} {
|
||||||
peer := peer
|
peer := peer
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
suite.assertResource(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(kubespan.NamespaceName, kubespan.PeerStatusType, peer.Metadata().ID(), resource.VersionUndefined),
|
suite.assertResource(
|
||||||
func(res resource.Resource) error {
|
resource.NewMetadata(
|
||||||
spec := res.(*kubespan.PeerStatus).TypedSpec()
|
kubespan.NamespaceName,
|
||||||
|
kubespan.PeerStatusType,
|
||||||
|
peer.Metadata().ID(),
|
||||||
|
resource.VersionUndefined,
|
||||||
|
),
|
||||||
|
func(res resource.Resource) error {
|
||||||
|
spec := res.(*kubespan.PeerStatus).TypedSpec()
|
||||||
|
|
||||||
if spec.State != kubespan.PeerStateUp {
|
if spec.State != kubespan.PeerStateUp {
|
||||||
return retry.ExpectedErrorf("peer state is not up yet: %s", spec.State)
|
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
|
// 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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
ipSet := mockNfTables.IPSet()
|
func() error {
|
||||||
|
ipSet := mockNfTables.IPSet()
|
||||||
|
|
||||||
if ipSet == nil {
|
if ipSet == nil {
|
||||||
return retry.ExpectedErrorf("ipset is nil")
|
return retry.ExpectedErrorf("ipset is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
ranges := fmt.Sprintf("%v", ipSet.Ranges())
|
ranges := fmt.Sprintf("%v", ipSet.Ranges())
|
||||||
expected := "[10.244.1.0-10.244.2.255]"
|
expected := "[10.244.1.0-10.244.2.255]"
|
||||||
|
|
||||||
if ranges != expected {
|
if ranges != expected {
|
||||||
return retry.ExpectedErrorf("ranges %s != expected %s", 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
|
// update config and disable wireguard, everything should be cleaned up
|
||||||
oldVersion = cfg.Metadata().Version()
|
oldVersion = cfg.Metadata().Version()
|
||||||
@ -396,11 +460,18 @@ func (suite *ManagerSuite) TestReconcile() {
|
|||||||
cfg.Metadata().BumpVersion()
|
cfg.Metadata().BumpVersion()
|
||||||
suite.Require().NoError(suite.state.Update(suite.ctx, oldVersion, cfg))
|
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.Assert().NoError(
|
||||||
suite.assertNoResource(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
resource.NewMetadata(network.ConfigNamespaceName, network.LinkSpecType, network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)), resource.VersionUndefined),
|
suite.assertNoResource(
|
||||||
|
resource.NewMetadata(
|
||||||
|
network.ConfigNamespaceName,
|
||||||
|
network.LinkSpecType,
|
||||||
|
network.LayeredID(network.ConfigOperator, network.LinkID(constants.KubeSpanLinkName)),
|
||||||
|
resource.VersionUndefined,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestManagerSuite(t *testing.T) {
|
func TestManagerSuite(t *testing.T) {
|
||||||
|
@ -41,7 +41,7 @@ type AddressConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,10 @@ func (suite *AddressConfigSuite) assertAddresses(requiredIDs []string, check fun
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -103,42 +106,60 @@ func (suite *AddressConfigSuite) TestLoopback() {
|
|||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
"default/lo/127.0.0.1/8",
|
return suite.assertAddresses(
|
||||||
}, func(r *network.AddressSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("lo", r.TypedSpec().LinkName)
|
"default/lo/127.0.0.1/8",
|
||||||
suite.Assert().Equal(nethelpers.ScopeHost, r.TypedSpec().Scope)
|
}, 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() {
|
func (suite *AddressConfigSuite) TestCmdline() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.AddressConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
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.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
"cmdline/eth1/172.20.0.2/24",
|
return suite.assertAddresses(
|
||||||
}, func(r *network.AddressSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
"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() {
|
func (suite *AddressConfigSuite) TestCmdlineNoNetmask() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.AddressConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1"),
|
suite.runtime.RegisterController(
|
||||||
}))
|
&netctrl.AddressConfigController{
|
||||||
|
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -160,17 +181,22 @@ func (suite *AddressConfigSuite) TestCmdlineNoNetmask() {
|
|||||||
|
|
||||||
suite.Assert().NotEmpty(ifaceName)
|
suite.Assert().NotEmpty(ifaceName)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
fmt.Sprintf("cmdline/%s/172.20.0.2/32", ifaceName),
|
return suite.assertAddresses(
|
||||||
}, func(r *network.AddressSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal(ifaceName, r.TypedSpec().LinkName)
|
fmt.Sprintf("cmdline/%s/172.20.0.2/32", ifaceName),
|
||||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
}, 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() {
|
func (suite *AddressConfigSuite) TestMachineConfiguration() {
|
||||||
@ -181,78 +207,85 @@ func (suite *AddressConfigSuite) TestMachineConfiguration() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NetworkInterfaces: []*v1alpha1.Device{
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
{
|
NetworkInterfaces: []*v1alpha1.Device{
|
||||||
DeviceInterface: "eth3",
|
{
|
||||||
DeviceCIDR: "192.168.0.24/28",
|
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",
|
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
DeviceIgnore: true,
|
||||||
DeviceInterface: "eth0",
|
DeviceInterface: "eth4",
|
||||||
DeviceVlans: []*v1alpha1.Vlan{
|
DeviceCIDR: "192.168.0.24/28",
|
||||||
{
|
},
|
||||||
VlanID: 24,
|
{
|
||||||
VlanCIDR: "10.0.0.1/8",
|
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{
|
DeviceInterface: "eth0",
|
||||||
"11.0.0.1/8",
|
DeviceVlans: []*v1alpha1.Vlan{
|
||||||
|
{
|
||||||
|
VlanID: 24,
|
||||||
|
VlanCIDR: "10.0.0.1/8",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
VlanID: 25,
|
||||||
|
VlanAddresses: []string{
|
||||||
|
"11.0.0.1/8",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
"configuration/eth2/2001:470:6d:30e:8ed2:b60c:9d2f:803a/64",
|
return suite.assertAddresses(
|
||||||
"configuration/eth3/192.168.0.24/28",
|
[]string{
|
||||||
"configuration/eth5/10.5.0.7/32",
|
"configuration/eth2/2001:470:6d:30e:8ed2:b60c:9d2f:803a/64",
|
||||||
"configuration/eth6/10.5.0.8/32",
|
"configuration/eth3/192.168.0.24/28",
|
||||||
"configuration/eth6/2001:470:6d:30e:8ed2:b60c:9d2f:803b/64",
|
"configuration/eth5/10.5.0.7/32",
|
||||||
"configuration/eth0.24/10.0.0.1/8",
|
"configuration/eth6/10.5.0.8/32",
|
||||||
"configuration/eth0.25/11.0.0.1/8",
|
"configuration/eth6/2001:470:6d:30e:8ed2:b60c:9d2f:803b/64",
|
||||||
}, func(r *network.AddressSpec) error {
|
"configuration/eth0.24/10.0.0.1/8",
|
||||||
return nil
|
"configuration/eth0.25/11.0.0.1/8",
|
||||||
})
|
}, func(r *network.AddressSpec) error {
|
||||||
}))
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AddressConfigSuite) TearDownTest() {
|
func (suite *AddressConfigSuite) TearDownTest() {
|
||||||
@ -263,10 +296,14 @@ func (suite *AddressConfigSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ type AddressEventsSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,9 +67,13 @@ func (suite *AddressEventsSuite) SetupTest() {
|
|||||||
suite.runtime, err = runtime.NewRuntime(suite.state, logging.Wrap(log.Writer()))
|
suite.runtime, err = runtime.NewRuntime(suite.state, logging.Wrap(log.Writer()))
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&network.AddressEventController{
|
suite.Require().NoError(
|
||||||
V1Alpha1Events: suite.events,
|
suite.runtime.RegisterController(
|
||||||
}))
|
&network.AddressEventController{
|
||||||
|
V1Alpha1Events: suite.events,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
}
|
}
|
||||||
@ -92,38 +96,42 @@ func (suite *AddressEventsSuite) TestReconcile() {
|
|||||||
|
|
||||||
var event *machine.AddressEvent
|
var event *machine.AddressEvent
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
suite.events.messagesMu.Lock()
|
func() error {
|
||||||
defer suite.events.messagesMu.Unlock()
|
suite.events.messagesMu.Lock()
|
||||||
|
defer suite.events.messagesMu.Unlock()
|
||||||
|
|
||||||
if len(suite.events.messages) == 0 {
|
if len(suite.events.messages) == 0 {
|
||||||
return retry.ExpectedError(fmt.Errorf("no events created"))
|
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)
|
event, ok = m.(*machine.AddressEvent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("not an endpoint event")
|
return fmt.Errorf("not an endpoint event")
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.Hostname == "" {
|
if event.Hostname == "" {
|
||||||
return retry.ExpectedError(fmt.Errorf("expected hostname to be set"))
|
return retry.ExpectedError(fmt.Errorf("expected hostname to be set"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().Equal(hostname.TypedSpec().Hostname, event.Hostname)
|
suite.Require().Equal(hostname.TypedSpec().Hostname, event.Hostname)
|
||||||
suite.Require().Empty(event.Addresses)
|
suite.Require().Empty(event.Addresses)
|
||||||
|
|
||||||
nodeAddress := networkresource.NewNodeAddress(networkresource.NamespaceName, networkresource.FilteredNodeAddressID(
|
nodeAddress := networkresource.NewNodeAddress(
|
||||||
networkresource.NodeAddressCurrentID,
|
networkresource.NamespaceName, networkresource.FilteredNodeAddressID(
|
||||||
k8s.NodeAddressFilterNoK8s),
|
networkresource.NodeAddressCurrentID,
|
||||||
|
k8s.NodeAddressFilterNoK8s,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
addrs := []string{
|
addrs := []string{
|
||||||
@ -139,31 +147,33 @@ func (suite *AddressEventsSuite) TestReconcile() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodeAddress))
|
suite.Require().NoError(suite.state.Create(suite.ctx, nodeAddress))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
suite.events.messagesMu.Lock()
|
func() error {
|
||||||
defer suite.events.messagesMu.Unlock()
|
suite.events.messagesMu.Lock()
|
||||||
|
defer suite.events.messagesMu.Unlock()
|
||||||
|
|
||||||
if len(suite.events.messages) == 0 {
|
if len(suite.events.messages) == 0 {
|
||||||
return retry.ExpectedError(fmt.Errorf("no events created"))
|
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)
|
event, ok = m.(*machine.AddressEvent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("not an address event")
|
return fmt.Errorf("not an address event")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(event.Addresses) == 0 {
|
if len(event.Addresses) == 0 {
|
||||||
return retry.ExpectedError(fmt.Errorf("expected addresses to be set"))
|
return retry.ExpectedError(fmt.Errorf("expected addresses to be set"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().Equal(addrs, event.Addresses)
|
suite.Require().Equal(addrs, event.Addresses)
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ type AddressMergeSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,10 @@ func (suite *AddressMergeSuite) assertAddresses(requiredIDs []string, check func
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -99,7 +102,10 @@ func (suite *AddressMergeSuite) assertAddresses(requiredIDs []string, check func
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AddressMergeSuite) assertNoAddress(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -154,41 +160,54 @@ func (suite *AddressMergeSuite) TestMerge() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
"lo/127.0.0.1/8",
|
return suite.assertAddresses(
|
||||||
"eth0/10.0.0.1/8",
|
[]string{
|
||||||
"eth0/10.0.0.35/32",
|
"lo/127.0.0.1/8",
|
||||||
}, func(r *network.AddressSpec) error {
|
"eth0/10.0.0.1/8",
|
||||||
switch r.Metadata().ID() {
|
"eth0/10.0.0.35/32",
|
||||||
case "lo/127.0.0.1/8":
|
}, func(r *network.AddressSpec) error {
|
||||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
switch r.Metadata().ID() {
|
||||||
case "eth0/10.0.0.1/8":
|
case "lo/127.0.0.1/8":
|
||||||
suite.Assert().Equal(*override.TypedSpec(), *r.TypedSpec())
|
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
||||||
case "eth0/10.0.0.35/32":
|
case "eth0/10.0.0.1/8":
|
||||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
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.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
"lo/127.0.0.1/8",
|
return suite.assertAddresses(
|
||||||
"eth0/10.0.0.35/32",
|
[]string{
|
||||||
}, func(r *network.AddressSpec) error {
|
"lo/127.0.0.1/8",
|
||||||
return nil
|
"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.assertNoAddress("eth0/10.0.0.35/32")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
@ -236,50 +255,75 @@ func (suite *AddressMergeSuite) TestMergeFlapping() {
|
|||||||
|
|
||||||
eg.Go(flipflop(0))
|
eg.Go(flipflop(0))
|
||||||
eg.Go(flipflop(1))
|
eg.Go(flipflop(1))
|
||||||
eg.Go(func() error {
|
eg.Go(
|
||||||
// add/remove finalizer to the merged resource
|
func() error {
|
||||||
for i := 0; i < 1000; i++ {
|
// add/remove finalizer to the merged resource
|
||||||
if err := suite.state.AddFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.AddressSpecType, "eth0/10.0.0.1/8", resource.VersionUndefined), "foo"); err != nil {
|
for i := 0; i < 1000; i++ {
|
||||||
if !state.IsNotFoundError(err) {
|
if err := suite.state.AddFinalizer(
|
||||||
return err
|
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
|
time.Sleep(10 * time.Millisecond)
|
||||||
} else {
|
|
||||||
suite.T().Log("finalizer added")
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
if err := suite.state.RemoveFinalizer(
|
||||||
|
suite.ctx,
|
||||||
if err := suite.state.RemoveFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.AddressSpecType, "eth0/10.0.0.1/8", resource.VersionUndefined), "foo"); err != nil {
|
resource.NewMetadata(
|
||||||
if err != nil && !state.IsNotFoundError(err) {
|
network.NamespaceName,
|
||||||
return err
|
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.Require().NoError(eg.Wait())
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
"eth0/10.0.0.1/8",
|
return suite.assertAddresses(
|
||||||
}, func(r *network.AddressSpec) error {
|
[]string{
|
||||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
"eth0/10.0.0.1/8",
|
||||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
}, 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() {
|
if *override.TypedSpec() != *r.TypedSpec() {
|
||||||
// using retry here, as it might not be reconciled immediately
|
// using retry here, as it might not be reconciled immediately
|
||||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AddressMergeSuite) TearDownTest() {
|
func (suite *AddressMergeSuite) TearDownTest() {
|
||||||
@ -290,7 +334,12 @@ func (suite *AddressMergeSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestAddressMergeSuite(t *testing.T) {
|
||||||
|
@ -146,7 +146,8 @@ func findAddress(addrs []rtnetlink.AddressMessage, linkIndex uint32, ipPrefix ne
|
|||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func (ctrl *AddressSpecController) syncAddress(ctx context.Context, r controller.Runtime, logger *zap.Logger, conn *rtnetlink.Conn,
|
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)
|
linkIndex := resolveLinkName(links, address.TypedSpec().LinkName)
|
||||||
|
|
||||||
switch address.Metadata().Phase() {
|
switch address.Metadata().Phase() {
|
||||||
|
@ -40,7 +40,7 @@ type AddressSpecSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,10 +144,13 @@ func (suite *AddressSpecSuite) TestLoopback() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinkAddress("lo", "127.11.0.1/32")
|
func() error {
|
||||||
}))
|
return suite.assertLinkAddress("lo", "127.11.0.1/32")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// teardown the address
|
// teardown the address
|
||||||
for {
|
for {
|
||||||
@ -191,26 +194,33 @@ func (suite *AddressSpecSuite) TestDummy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create dummy interface
|
// create dummy interface
|
||||||
suite.Require().NoError(conn.Link.New(&rtnetlink.LinkMessage{
|
suite.Require().NoError(
|
||||||
Type: unix.ARPHRD_ETHER,
|
conn.Link.New(
|
||||||
Attributes: &rtnetlink.LinkAttributes{
|
&rtnetlink.LinkMessage{
|
||||||
Name: dummyInterface,
|
Type: unix.ARPHRD_ETHER,
|
||||||
MTU: 1400,
|
Attributes: &rtnetlink.LinkAttributes{
|
||||||
Info: &rtnetlink.LinkInfo{
|
Name: dummyInterface,
|
||||||
Kind: "dummy",
|
MTU: 1400,
|
||||||
|
Info: &rtnetlink.LinkInfo{
|
||||||
|
Kind: "dummy",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
}))
|
)
|
||||||
|
|
||||||
iface, err := net.InterfaceByName(dummyInterface)
|
iface, err := net.InterfaceByName(dummyInterface)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
defer conn.Link.Delete(uint32(iface.Index)) //nolint:errcheck
|
defer conn.Link.Delete(uint32(iface.Index)) //nolint:errcheck
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinkAddress(dummyInterface, "10.0.0.1/8")
|
func() error {
|
||||||
}))
|
return suite.assertLinkAddress(dummyInterface, "10.0.0.1/8")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// delete dummy interface, address should be unassigned automatically
|
// delete dummy interface, address should be unassigned automatically
|
||||||
suite.Require().NoError(conn.Link.Delete(uint32(iface.Index)))
|
suite.Require().NoError(conn.Link.Delete(uint32(iface.Index)))
|
||||||
@ -236,7 +246,12 @@ func (suite *AddressSpecSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestAddressSpecSuite(t *testing.T) {
|
||||||
|
@ -34,7 +34,7 @@ type AddressStatusSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,10 @@ func (suite *AddressStatusSuite) assertAddresses(requiredIDs []string, check fun
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -96,12 +99,17 @@ func (suite *AddressStatusSuite) assertAddresses(requiredIDs []string, check fun
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AddressStatusSuite) TestLoopback() {
|
func (suite *AddressStatusSuite) TestLoopback() {
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{"lo/127.0.0.1/8"}, func(r *network.AddressStatus) error {
|
func() error {
|
||||||
return nil
|
return suite.assertAddresses(
|
||||||
})
|
[]string{"lo/127.0.0.1/8"}, func(r *network.AddressStatus) error {
|
||||||
}))
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *AddressStatusSuite) TearDownTest() {
|
func (suite *AddressStatusSuite) TearDownTest() {
|
||||||
|
@ -39,7 +39,7 @@ type EtcFileConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
cfg *config.MachineConfig
|
cfg *config.MachineConfig
|
||||||
@ -65,30 +65,32 @@ func (suite *EtcFileConfigSuite) SetupTest() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.cfg = config.NewMachineConfig(&v1alpha1.Config{
|
suite.cfg = config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
ExtraHostEntries: []*v1alpha1.ExtraHost{
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
{
|
ExtraHostEntries: []*v1alpha1.ExtraHost{
|
||||||
HostIP: "10.0.0.1",
|
{
|
||||||
HostAliases: []string{"a", "b"},
|
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 = network.NewNodeAddress(network.NamespaceName, network.NodeAddressDefaultID)
|
||||||
suite.defaultAddress.TypedSpec().Addresses = []netaddr.IPPrefix{netaddr.MustParseIPPrefix("33.11.22.44/32")}
|
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.hostnameStatus.TypedSpec().Domainname = "example.com"
|
||||||
|
|
||||||
suite.resolverStatus = network.NewResolverStatus(network.NamespaceName, network.ResolverID)
|
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() {
|
func (suite *EtcFileConfigSuite) startRuntime() {
|
||||||
@ -118,7 +125,10 @@ func (suite *EtcFileConfigSuite) assertEtcFiles(requiredIDs []string, check func
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -144,7 +154,10 @@ func (suite *EtcFileConfigSuite) assertEtcFiles(requiredIDs []string, check func
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *EtcFileConfigSuite) assertNoEtcFile(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -177,41 +190,50 @@ func (suite *EtcFileConfigSuite) testFiles(resources []resource.Resource, resolv
|
|||||||
unexpectedIds = append(unexpectedIds, "hosts")
|
unexpectedIds = append(unexpectedIds, "hosts")
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertEtcFiles(
|
func() error {
|
||||||
expectedIds,
|
return suite.assertEtcFiles(
|
||||||
func(r *files.EtcFileSpec) error {
|
expectedIds,
|
||||||
switch r.Metadata().ID() {
|
func(r *files.EtcFileSpec) error {
|
||||||
case "hosts":
|
switch r.Metadata().ID() {
|
||||||
suite.Assert().Equal(hosts, string(r.TypedSpec().Contents))
|
case "hosts":
|
||||||
case "resolv.conf":
|
suite.Assert().Equal(hosts, string(r.TypedSpec().Contents))
|
||||||
suite.Assert().Equal(resolvConf, string(r.TypedSpec().Contents))
|
case "resolv.conf":
|
||||||
}
|
suite.Assert().Equal(resolvConf, string(r.TypedSpec().Contents))
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
for _, id := range unexpectedIds {
|
for _, id := range unexpectedIds {
|
||||||
id := id
|
id := id
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(1*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(1*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoEtcFile(id)
|
func() error {
|
||||||
}))
|
return suite.assertNoEtcFile(id)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *EtcFileConfigSuite) TestComplete() {
|
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",
|
"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
|
"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() {
|
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",
|
"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",
|
"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() {
|
func (suite *EtcFileConfigSuite) TestNoDomainname() {
|
||||||
suite.hostnameStatus.TypedSpec().Domainname = ""
|
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",
|
"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",
|
"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() {
|
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",
|
"nameserver 1.1.1.1\nnameserver 2.2.2.2\nnameserver 3.3.3.3\n",
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *EtcFileConfigSuite) TestOnlyHostname() {
|
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",
|
"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()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewHostnameStatus(network.NamespaceName, "bar")))
|
suite.Assert().NoError(
|
||||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewResolverStatus(network.NamespaceName, "bar")))
|
suite.state.Create(
|
||||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewNodeAddress(network.NamespaceName, "bar")))
|
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) {
|
func TestEtcFileConfigSuite(t *testing.T) {
|
||||||
|
@ -36,7 +36,7 @@ type HardwareAddrSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,10 @@ func (suite *HardwareAddrSuite) assertHWAddr(requiredIDs []string, check func(*n
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -98,7 +101,10 @@ func (suite *HardwareAddrSuite) assertHWAddr(requiredIDs []string, check func(*n
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *HardwareAddrSuite) assertNoHWAddr(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
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, bond0))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, eth1))
|
suite.Require().NoError(suite.state.Create(suite.ctx, eth1))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertHWAddr([]string{network.FirstHardwareAddr}, func(r *network.HardwareAddr) error {
|
func() error {
|
||||||
if r.TypedSpec().Name != eth1.Metadata().ID() && net.HardwareAddr(r.TypedSpec().HardwareAddr).String() != "6a:2b:bd:b2:fc:e0" {
|
return suite.assertHWAddr(
|
||||||
return retry.ExpectedErrorf("should be eth1")
|
[]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.Require().NoError(suite.state.Create(suite.ctx, eth0))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertHWAddr([]string{network.FirstHardwareAddr}, func(r *network.HardwareAddr) error {
|
func() error {
|
||||||
if r.TypedSpec().Name != eth0.Metadata().ID() && net.HardwareAddr(r.TypedSpec().HardwareAddr).String() != "56:a0:a0:87:1c:fa" {
|
return suite.assertHWAddr(
|
||||||
return retry.ExpectedErrorf("should be eth0")
|
[]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, eth0.Metadata()))
|
||||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, eth1.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoHWAddr(network.FirstHardwareAddr)
|
func() error {
|
||||||
}))
|
return suite.assertNoHWAddr(network.FirstHardwareAddr)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *HardwareAddrSuite) TearDownTest() {
|
func (suite *HardwareAddrSuite) TearDownTest() {
|
||||||
@ -177,7 +196,12 @@ func (suite *HardwareAddrSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestHardwareAddrSuite(t *testing.T) {
|
||||||
|
@ -40,7 +40,7 @@ type HostnameConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,10 @@ func (suite *HostnameConfigSuite) assertHostnames(requiredIDs []string, check fu
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -98,7 +101,10 @@ func (suite *HostnameConfigSuite) assertHostnames(requiredIDs []string, check fu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *HostnameConfigSuite) assertNoHostname(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -122,39 +128,53 @@ func (suite *HostnameConfigSuite) TestDefaults() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, defaultAddress))
|
suite.Require().NoError(suite.state.Create(suite.ctx, defaultAddress))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertHostnames([]string{
|
func() error {
|
||||||
"default/hostname",
|
return suite.assertHostnames(
|
||||||
}, func(r *network.HostnameSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("talos-33-11-22-44", r.TypedSpec().Hostname)
|
"default/hostname",
|
||||||
suite.Assert().Equal("", r.TypedSpec().Domainname)
|
}, func(r *network.HostnameSpec) error {
|
||||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
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() {
|
func (suite *HostnameConfigSuite) TestCmdline() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.HostnameConfigController{
|
suite.Require().NoError(
|
||||||
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.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.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertHostnames([]string{
|
func() error {
|
||||||
"cmdline/hostname",
|
return suite.assertHostnames(
|
||||||
}, func(r *network.HostnameSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("master1", r.TypedSpec().Hostname)
|
"cmdline/hostname",
|
||||||
suite.Assert().Equal("domain.tld", r.TypedSpec().Domainname)
|
}, func(r *network.HostnameSpec) error {
|
||||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
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() {
|
func (suite *HostnameConfigSuite) TestMachineConfiguration() {
|
||||||
@ -165,48 +185,63 @@ func (suite *HostnameConfigSuite) TestMachineConfiguration() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NetworkHostname: "foo",
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
|
NetworkHostname: "foo",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertHostnames([]string{
|
func() error {
|
||||||
"configuration/hostname",
|
return suite.assertHostnames(
|
||||||
}, func(r *network.HostnameSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("foo", r.TypedSpec().Hostname)
|
"configuration/hostname",
|
||||||
suite.Assert().Equal("", r.TypedSpec().Domainname)
|
}, func(r *network.HostnameSpec) error {
|
||||||
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
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 {
|
_, err = suite.state.UpdateWithConflicts(
|
||||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineNetwork.NetworkHostname = strings.Repeat("a", 128)
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoHostname("configuration/hostname")
|
func() error {
|
||||||
}))
|
return suite.assertNoHostname("configuration/hostname")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *HostnameConfigSuite) TearDownTest() {
|
func (suite *HostnameConfigSuite) TearDownTest() {
|
||||||
@ -217,17 +252,26 @@ func (suite *HostnameConfigSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().NoError(err)
|
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) {
|
func TestHostnameConfigSuite(t *testing.T) {
|
||||||
|
@ -34,7 +34,7 @@ type HostnameMergeSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,7 +70,10 @@ func (suite *HostnameMergeSuite) assertHostnames(requiredIDs []string, check fun
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -126,33 +129,43 @@ func (suite *HostnameMergeSuite) TestMerge() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertHostnames([]string{
|
func() error {
|
||||||
"hostname",
|
return suite.assertHostnames(
|
||||||
}, func(r *network.HostnameSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("bar.com", r.TypedSpec().FQDN())
|
"hostname",
|
||||||
suite.Assert().Equal("bar", r.TypedSpec().Hostname)
|
}, func(r *network.HostnameSpec) error {
|
||||||
suite.Assert().Equal("com", r.TypedSpec().Domainname)
|
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.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertHostnames([]string{
|
func() error {
|
||||||
"hostname",
|
return suite.assertHostnames(
|
||||||
}, func(r *network.HostnameSpec) error {
|
[]string{
|
||||||
if r.TypedSpec().FQDN() != "eth-0" {
|
"hostname",
|
||||||
return retry.ExpectedErrorf("unexpected hostname %q", r.TypedSpec().FQDN())
|
}, 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() {
|
func (suite *HostnameMergeSuite) TearDownTest() {
|
||||||
@ -163,7 +176,12 @@ func (suite *HostnameMergeSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestHostnameMergeSuite(t *testing.T) {
|
||||||
|
@ -33,7 +33,7 @@ type HostnameSpecSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,9 +47,13 @@ func (suite *HostnameSpecSuite) SetupTest() {
|
|||||||
suite.runtime, err = runtime.NewRuntime(suite.state, logging.Wrap(log.Writer()))
|
suite.runtime, err = runtime.NewRuntime(suite.state, logging.Wrap(log.Writer()))
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.HostnameSpecController{
|
suite.Require().NoError(
|
||||||
V1Alpha1Mode: v1alpha1runtime.ModeContainer, // run in container mode to skip _actually_ setting hostname
|
suite.runtime.RegisterController(
|
||||||
}))
|
&netctrl.HostnameSpecController{
|
||||||
|
V1Alpha1Mode: v1alpha1runtime.ModeContainer, // run in container mode to skip _actually_ setting hostname
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
}
|
}
|
||||||
@ -65,7 +69,10 @@ func (suite *HostnameSpecSuite) startRuntime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *HostnameSpecSuite) assertStatus(id string, fqdn string) error {
|
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 err != nil {
|
||||||
if state.IsNotFoundError(err) {
|
if state.IsNotFoundError(err) {
|
||||||
return retry.ExpectedError(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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertStatus("hostname", "foo.bar")
|
func() error {
|
||||||
}))
|
return suite.assertStatus("hostname", "foo.bar")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *HostnameSpecSuite) TearDownTest() {
|
func (suite *HostnameSpecSuite) TearDownTest() {
|
||||||
@ -109,7 +119,12 @@ func (suite *HostnameSpecSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestHostnameSpecSuite(t *testing.T) {
|
||||||
|
@ -40,7 +40,7 @@ type LinkConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,10 @@ func (suite *LinkConfigSuite) assertLinks(requiredIDs []string, check func(*netw
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -104,7 +107,10 @@ func (suite *LinkConfigSuite) assertNoLinks(unexpectedIDs []string) error {
|
|||||||
unexpIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -124,41 +130,55 @@ func (suite *LinkConfigSuite) TestLoopback() {
|
|||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"default/lo",
|
return suite.assertLinks(
|
||||||
}, func(r *network.LinkSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("lo", r.TypedSpec().Name)
|
"default/lo",
|
||||||
suite.Assert().True(r.TypedSpec().Up)
|
}, func(r *network.LinkSpec) error {
|
||||||
suite.Assert().False(r.TypedSpec().Logical)
|
suite.Assert().Equal("lo", r.TypedSpec().Name)
|
||||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
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() {
|
func (suite *LinkConfigSuite) TestCmdline() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
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.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"cmdline/eth1",
|
return suite.assertLinks(
|
||||||
}, func(r *network.LinkSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("eth1", r.TypedSpec().Name)
|
"cmdline/eth1",
|
||||||
suite.Assert().True(r.TypedSpec().Up)
|
}, func(r *network.LinkSpec) error {
|
||||||
suite.Assert().False(r.TypedSpec().Logical)
|
suite.Assert().Equal("eth1", r.TypedSpec().Name)
|
||||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
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() {
|
func (suite *LinkConfigSuite) TestMachineConfiguration() {
|
||||||
@ -169,67 +189,69 @@ func (suite *LinkConfigSuite) TestMachineConfiguration() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NetworkInterfaces: []*v1alpha1.Device{
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
{
|
NetworkInterfaces: []*v1alpha1.Device{
|
||||||
DeviceInterface: "eth0",
|
{
|
||||||
DeviceVlans: []*v1alpha1.Vlan{
|
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{
|
|
||||||
{
|
{
|
||||||
WireguardPublicKey: "DEF",
|
VlanID: 24,
|
||||||
WireguardEndpoint: "10.0.0.1:3000",
|
VlanMTU: 1000,
|
||||||
WireguardAllowedIPs: []string{
|
VlanAddresses: []string{
|
||||||
"10.2.3.0/24",
|
"10.0.0.1/8",
|
||||||
"10.2.4.0/24",
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"configuration/eth0",
|
return suite.assertLinks(
|
||||||
"configuration/eth0.24",
|
[]string{
|
||||||
"configuration/eth0.48",
|
"configuration/eth0",
|
||||||
"configuration/eth1",
|
"configuration/eth0.24",
|
||||||
"configuration/eth2",
|
"configuration/eth0.48",
|
||||||
"configuration/eth3",
|
"configuration/eth1",
|
||||||
"configuration/bond0",
|
"configuration/eth2",
|
||||||
"configuration/dummy0",
|
"configuration/eth3",
|
||||||
"configuration/wireguard0",
|
"configuration/bond0",
|
||||||
}, func(r *network.LinkSpec) error {
|
"configuration/dummy0",
|
||||||
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
"configuration/wireguard0",
|
||||||
|
}, func(r *network.LinkSpec) error {
|
||||||
|
suite.Assert().Equal(network.ConfigMachineConfiguration, r.TypedSpec().ConfigLayer)
|
||||||
|
|
||||||
switch r.TypedSpec().Name {
|
switch r.TypedSpec().Name {
|
||||||
case "eth0", "eth1":
|
case "eth0", "eth1":
|
||||||
suite.Assert().True(r.TypedSpec().Up)
|
suite.Assert().True(r.TypedSpec().Up)
|
||||||
suite.Assert().False(r.TypedSpec().Logical)
|
suite.Assert().False(r.TypedSpec().Logical)
|
||||||
|
|
||||||
if r.TypedSpec().Name == "eth0" {
|
if r.TypedSpec().Name == "eth0" {
|
||||||
suite.Assert().EqualValues(0, r.TypedSpec().MTU)
|
suite.Assert().EqualValues(0, r.TypedSpec().MTU)
|
||||||
} else {
|
} else {
|
||||||
suite.Assert().EqualValues(9001, r.TypedSpec().MTU)
|
suite.Assert().EqualValues(9001, r.TypedSpec().MTU)
|
||||||
}
|
}
|
||||||
case "eth0.24", "eth0.48":
|
case "eth0.24", "eth0.48":
|
||||||
suite.Assert().True(r.TypedSpec().Up)
|
suite.Assert().True(r.TypedSpec().Up)
|
||||||
suite.Assert().True(r.TypedSpec().Logical)
|
suite.Assert().True(r.TypedSpec().Logical)
|
||||||
suite.Assert().Equal(nethelpers.LinkEther, r.TypedSpec().Type)
|
suite.Assert().Equal(nethelpers.LinkEther, r.TypedSpec().Type)
|
||||||
suite.Assert().Equal(network.LinkKindVLAN, r.TypedSpec().Kind)
|
suite.Assert().Equal(network.LinkKindVLAN, r.TypedSpec().Kind)
|
||||||
suite.Assert().Equal("eth0", r.TypedSpec().ParentName)
|
suite.Assert().Equal("eth0", r.TypedSpec().ParentName)
|
||||||
suite.Assert().Equal(nethelpers.VLANProtocol8021Q, r.TypedSpec().VLAN.Protocol)
|
suite.Assert().Equal(nethelpers.VLANProtocol8021Q, r.TypedSpec().VLAN.Protocol)
|
||||||
|
|
||||||
if r.TypedSpec().Name == "eth0.24" {
|
if r.TypedSpec().Name == "eth0.24" {
|
||||||
suite.Assert().EqualValues(24, r.TypedSpec().VLAN.VID)
|
suite.Assert().EqualValues(24, r.TypedSpec().VLAN.VID)
|
||||||
suite.Assert().EqualValues(1000, r.TypedSpec().MTU)
|
suite.Assert().EqualValues(1000, r.TypedSpec().MTU)
|
||||||
} else {
|
} else {
|
||||||
suite.Assert().EqualValues(48, r.TypedSpec().VLAN.VID)
|
suite.Assert().EqualValues(48, r.TypedSpec().VLAN.VID)
|
||||||
suite.Assert().EqualValues(0, r.TypedSpec().MTU)
|
suite.Assert().EqualValues(0, r.TypedSpec().MTU)
|
||||||
}
|
}
|
||||||
case "eth2", "eth3":
|
case "eth2", "eth3":
|
||||||
suite.Assert().True(r.TypedSpec().Up)
|
suite.Assert().True(r.TypedSpec().Up)
|
||||||
suite.Assert().False(r.TypedSpec().Logical)
|
suite.Assert().False(r.TypedSpec().Logical)
|
||||||
suite.Assert().Equal("bond0", r.TypedSpec().MasterName)
|
suite.Assert().Equal("bond0", r.TypedSpec().MasterName)
|
||||||
case "bond0":
|
case "bond0":
|
||||||
suite.Assert().True(r.TypedSpec().Up)
|
suite.Assert().True(r.TypedSpec().Up)
|
||||||
suite.Assert().True(r.TypedSpec().Logical)
|
suite.Assert().True(r.TypedSpec().Logical)
|
||||||
suite.Assert().Equal(nethelpers.LinkEther, r.TypedSpec().Type)
|
suite.Assert().Equal(nethelpers.LinkEther, r.TypedSpec().Type)
|
||||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
||||||
suite.Assert().Equal(nethelpers.BondModeXOR, r.TypedSpec().BondMaster.Mode)
|
suite.Assert().Equal(nethelpers.BondModeXOR, r.TypedSpec().BondMaster.Mode)
|
||||||
suite.Assert().True(r.TypedSpec().BondMaster.UseCarrier)
|
suite.Assert().True(r.TypedSpec().BondMaster.UseCarrier)
|
||||||
case "wireguard0":
|
case "wireguard0":
|
||||||
suite.Assert().True(r.TypedSpec().Up)
|
suite.Assert().True(r.TypedSpec().Up)
|
||||||
suite.Assert().True(r.TypedSpec().Logical)
|
suite.Assert().True(r.TypedSpec().Logical)
|
||||||
suite.Assert().Equal(nethelpers.LinkNone, r.TypedSpec().Type)
|
suite.Assert().Equal(nethelpers.LinkNone, r.TypedSpec().Type)
|
||||||
suite.Assert().Equal(network.LinkKindWireguard, r.TypedSpec().Kind)
|
suite.Assert().Equal(network.LinkKindWireguard, r.TypedSpec().Kind)
|
||||||
suite.Assert().Equal(network.WireguardSpec{
|
suite.Assert().Equal(
|
||||||
PrivateKey: "ABC",
|
network.WireguardSpec{
|
||||||
Peers: []network.WireguardPeer{
|
PrivateKey: "ABC",
|
||||||
{
|
Peers: []network.WireguardPeer{
|
||||||
PublicKey: "DEF",
|
{
|
||||||
Endpoint: "10.0.0.1:3000",
|
PublicKey: "DEF",
|
||||||
AllowedIPs: []netaddr.IPPrefix{
|
Endpoint: "10.0.0.1:3000",
|
||||||
netaddr.MustParseIPPrefix("10.2.3.0/24"),
|
AllowedIPs: []netaddr.IPPrefix{
|
||||||
netaddr.MustParseIPPrefix("10.2.4.0/24"),
|
netaddr.MustParseIPPrefix("10.2.3.0/24"),
|
||||||
},
|
netaddr.MustParseIPPrefix("10.2.4.0/24"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, r.TypedSpec().Wireguard)
|
},
|
||||||
}
|
}, r.TypedSpec().Wireguard,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkConfigSuite) TestDefaultUp() {
|
func (suite *LinkConfigSuite) TestDefaultUp() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
suite.runtime.RegisterController(
|
||||||
}))
|
&netctrl.LinkConfigController{
|
||||||
|
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
for _, link := range []string{"eth0", "eth1", "eth2", "eth3", "eth4"} {
|
for _, link := range []string{"eth0", "eth1", "eth2", "eth3", "eth4"} {
|
||||||
linkStatus := network.NewLinkStatus(network.NamespaceName, link)
|
linkStatus := network.NewLinkStatus(network.NamespaceName, link)
|
||||||
@ -341,74 +374,86 @@ func (suite *LinkConfigSuite) TestDefaultUp() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NetworkInterfaces: []*v1alpha1.Device{
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
{
|
NetworkInterfaces: []*v1alpha1.Device{
|
||||||
DeviceInterface: "eth0",
|
{
|
||||||
DeviceVlans: []*v1alpha1.Vlan{
|
DeviceInterface: "eth0",
|
||||||
{
|
DeviceVlans: []*v1alpha1.Vlan{
|
||||||
VlanID: 24,
|
{
|
||||||
VlanAddresses: []string{
|
VlanID: 24,
|
||||||
"10.0.0.1/8",
|
VlanAddresses: []string{
|
||||||
|
"10.0.0.1/8",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
VlanID: 48,
|
||||||
VlanID: 48,
|
VlanAddresses: []string{
|
||||||
VlanAddresses: []string{
|
"10.0.0.2/8",
|
||||||
"10.0.0.2/8",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
DeviceInterface: "bond0",
|
||||||
DeviceInterface: "bond0",
|
DeviceBond: &v1alpha1.Bond{
|
||||||
DeviceBond: &v1alpha1.Bond{
|
BondInterfaces: []string{
|
||||||
BondInterfaces: []string{
|
"eth3",
|
||||||
"eth3",
|
"eth4",
|
||||||
"eth4",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"default/eth1",
|
return suite.assertLinks(
|
||||||
}, func(r *network.LinkSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
"default/eth1",
|
||||||
suite.Assert().True(r.TypedSpec().Up)
|
}, 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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoLinks([]string{
|
func() error {
|
||||||
"default/eth0",
|
return suite.assertNoLinks(
|
||||||
"default/eth2",
|
[]string{
|
||||||
"default/eth3",
|
"default/eth0",
|
||||||
"default/eth4",
|
"default/eth2",
|
||||||
})
|
"default/eth3",
|
||||||
}))
|
"default/eth4",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkConfigSuite) TearDownTest() {
|
func (suite *LinkConfigSuite) TearDownTest() {
|
||||||
@ -419,17 +464,26 @@ func (suite *LinkConfigSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().NoError(err)
|
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) {
|
func TestLinkConfigSuite(t *testing.T) {
|
||||||
|
@ -36,7 +36,7 @@ type LinkMergeSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,10 @@ func (suite *LinkMergeSuite) assertLinks(requiredIDs []string, check func(*netwo
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -98,7 +101,10 @@ func (suite *LinkMergeSuite) assertLinks(requiredIDs []string, check func(*netwo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkMergeSuite) assertNoLinks(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -140,51 +146,64 @@ func (suite *LinkMergeSuite) TestMerge() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"lo",
|
return suite.assertLinks(
|
||||||
"eth0",
|
[]string{
|
||||||
}, func(r *network.LinkSpec) error {
|
"lo",
|
||||||
switch r.Metadata().ID() {
|
"eth0",
|
||||||
case "lo":
|
}, func(r *network.LinkSpec) error {
|
||||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
switch r.Metadata().ID() {
|
||||||
case "eth0":
|
case "lo":
|
||||||
suite.Assert().EqualValues(1500, r.TypedSpec().MTU) // static should override dhcp
|
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.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"lo",
|
return suite.assertLinks(
|
||||||
"eth0",
|
[]string{
|
||||||
}, func(r *network.LinkSpec) error {
|
"lo",
|
||||||
switch r.Metadata().ID() {
|
"eth0",
|
||||||
case "lo":
|
}, func(r *network.LinkSpec) error {
|
||||||
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
switch r.Metadata().ID() {
|
||||||
case "eth0":
|
case "lo":
|
||||||
// reconcile happens eventually, so give it some time
|
suite.Assert().Equal(*loopback.TypedSpec(), *r.TypedSpec())
|
||||||
if r.TypedSpec().MTU != 1450 {
|
case "eth0":
|
||||||
return retry.ExpectedErrorf("MTU %d != 1450", r.TypedSpec().MTU)
|
// 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.Require().NoError(suite.state.Destroy(suite.ctx, loopback.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoLinks("lo")
|
func() error {
|
||||||
}))
|
return suite.assertNoLinks("lo")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkMergeSuite) TestMergeLogicalLink() {
|
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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"bond0",
|
return suite.assertLinks(
|
||||||
}, func(r *network.LinkSpec) error {
|
[]string{
|
||||||
if r.TypedSpec().MTU != 1450 {
|
"bond0",
|
||||||
return retry.ExpectedErrorf("not merged yet")
|
}, func(r *network.LinkSpec) error {
|
||||||
}
|
if r.TypedSpec().MTU != 1450 {
|
||||||
|
return retry.ExpectedErrorf("not merged yet")
|
||||||
|
}
|
||||||
|
|
||||||
suite.Assert().True(r.TypedSpec().Logical)
|
suite.Assert().True(r.TypedSpec().Logical)
|
||||||
suite.Assert().EqualValues(1450, r.TypedSpec().MTU)
|
suite.Assert().EqualValues(1450, r.TypedSpec().MTU)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
@ -271,49 +295,74 @@ func (suite *LinkMergeSuite) TestMergeFlapping() {
|
|||||||
|
|
||||||
eg.Go(flipflop(0))
|
eg.Go(flipflop(0))
|
||||||
eg.Go(flipflop(1))
|
eg.Go(flipflop(1))
|
||||||
eg.Go(func() error {
|
eg.Go(
|
||||||
// add/remove finalizer to the merged resource
|
func() error {
|
||||||
for i := 0; i < 1000; i++ {
|
// add/remove finalizer to the merged resource
|
||||||
if err := suite.state.AddFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkSpecType, "eth0", resource.VersionUndefined), "foo"); err != nil {
|
for i := 0; i < 1000; i++ {
|
||||||
if !state.IsNotFoundError(err) {
|
if err := suite.state.AddFinalizer(
|
||||||
return err
|
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
|
time.Sleep(10 * time.Millisecond)
|
||||||
} else {
|
|
||||||
suite.T().Log("finalizer added")
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
if err := suite.state.RemoveFinalizer(
|
||||||
|
suite.ctx,
|
||||||
if err := suite.state.RemoveFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.LinkSpecType, "eth0", resource.VersionUndefined), "foo"); err != nil {
|
resource.NewMetadata(
|
||||||
if err != nil && !state.IsNotFoundError(err) {
|
network.NamespaceName,
|
||||||
return err
|
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.Require().NoError(eg.Wait())
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"eth0",
|
return suite.assertLinks(
|
||||||
}, func(r *network.LinkSpec) error {
|
[]string{
|
||||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
"eth0",
|
||||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
}, 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 {
|
if r.TypedSpec().MTU != 1500 {
|
||||||
return retry.ExpectedErrorf("MTU %d != 1500", r.TypedSpec().MTU)
|
return retry.ExpectedErrorf("MTU %d != 1500", r.TypedSpec().MTU)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkMergeSuite) TestMergeWireguard() {
|
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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertLinks([]string{
|
func() error {
|
||||||
"kubespan",
|
return suite.assertLinks(
|
||||||
}, func(r *network.LinkSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("IG9MqCII7z54Ysof1fQ9a7WcMNG+qNJRMyRCQz3JTUY=", r.TypedSpec().Wireguard.PrivateKey)
|
"kubespan",
|
||||||
suite.Assert().Equal(1234, r.TypedSpec().Wireguard.ListenPort)
|
}, func(r *network.LinkSpec) error {
|
||||||
suite.Assert().Len(r.TypedSpec().Wireguard.Peers, 2)
|
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(
|
suite.Assert().Equal(
|
||||||
network.WireguardPeer{
|
network.WireguardPeer{
|
||||||
PublicKey: "RXdQkMTD1Jcxd/Wizr9k8syw8ANs57l5jTormDVHAVs=",
|
PublicKey: "RXdQkMTD1Jcxd/Wizr9k8syw8ANs57l5jTormDVHAVs=",
|
||||||
Endpoint: "127.0.0.1:1234",
|
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.Require().NoError(suite.state.Destroy(suite.ctx, kubespanOperator.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoLinks("kubespan")
|
func() error {
|
||||||
}))
|
return suite.assertNoLinks("kubespan")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkMergeSuite) TearDownTest() {
|
func (suite *LinkMergeSuite) TearDownTest() {
|
||||||
@ -397,7 +457,12 @@ func (suite *LinkMergeSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestLinkMergeSuite(t *testing.T) {
|
||||||
|
@ -160,7 +160,8 @@ func findLink(links []rtnetlink.LinkMessage, name string) *rtnetlink.LinkMessage
|
|||||||
//
|
//
|
||||||
//nolint:gocyclo,cyclop
|
//nolint:gocyclo,cyclop
|
||||||
func (ctrl *LinkSpecController) syncLink(ctx context.Context, r controller.Runtime, logger *zap.Logger, conn *rtnetlink.Conn, wgClient *wgctrl.Client,
|
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))
|
logger = logger.With(zap.String("link", link.TypedSpec().Name))
|
||||||
|
|
||||||
switch link.Metadata().Phase() {
|
switch link.Metadata().Phase() {
|
||||||
|
@ -39,7 +39,7 @@ type LinkSpecSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,10 @@ func (suite *LinkSpecSuite) assertInterfaces(requiredIDs []string, check func(*n
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -104,7 +107,10 @@ func (suite *LinkSpecSuite) assertInterfaces(requiredIDs []string, check func(*n
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkSpecSuite) assertNoInterface(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -134,12 +140,17 @@ func (suite *LinkSpecSuite) TestLoopback() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{"lo"}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
return nil
|
return suite.assertInterfaces(
|
||||||
})
|
[]string{"lo"}, func(r *network.LinkStatus) error {
|
||||||
}))
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkSpecSuite) TestDummy() {
|
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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{dummyInterface}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
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 {
|
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||||
return retry.ExpectedErrorf("link is not up")
|
return retry.ExpectedErrorf("link is not up")
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.TypedSpec().MTU != 1400 {
|
if r.TypedSpec().MTU != 1400 {
|
||||||
return retry.ExpectedErrorf("unexpected MTU %d", r.TypedSpec().MTU)
|
return retry.ExpectedErrorf("unexpected MTU %d", r.TypedSpec().MTU)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// teardown the link
|
// teardown the link
|
||||||
for {
|
for {
|
||||||
@ -189,10 +205,13 @@ func (suite *LinkSpecSuite) TestDummy() {
|
|||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoInterface(dummyInterface)
|
func() error {
|
||||||
}))
|
return suite.assertNoInterface(dummyInterface)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
@ -245,49 +264,61 @@ func (suite *LinkSpecSuite) TestVLAN() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{dummyInterface, vlanName1, vlanName2}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
switch r.Metadata().ID() {
|
return suite.assertInterfaces(
|
||||||
case dummyInterface:
|
[]string{dummyInterface, vlanName1, vlanName2}, func(r *network.LinkStatus) error {
|
||||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
switch r.Metadata().ID() {
|
||||||
case vlanName1, vlanName2:
|
case dummyInterface:
|
||||||
suite.Assert().Equal(network.LinkKindVLAN, r.TypedSpec().Kind)
|
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||||
suite.Assert().Equal(nethelpers.VLANProtocol8021Q, r.TypedSpec().VLAN.Protocol)
|
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 {
|
if r.Metadata().ID() == vlanName1 {
|
||||||
suite.Assert().EqualValues(2, r.TypedSpec().VLAN.VID)
|
suite.Assert().EqualValues(2, r.TypedSpec().VLAN.VID)
|
||||||
} else {
|
} else {
|
||||||
suite.Assert().EqualValues(4, r.TypedSpec().VLAN.VID)
|
suite.Assert().EqualValues(4, r.TypedSpec().VLAN.VID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||||
return retry.ExpectedErrorf("link is not up")
|
return retry.ExpectedErrorf("link is not up")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// attempt to change VLAN ID
|
// attempt to change VLAN ID
|
||||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, vlan1.Metadata(), func(r resource.Resource) error {
|
_, err := suite.state.UpdateWithConflicts(
|
||||||
r.(*network.LinkSpec).TypedSpec().VLAN.VID = 42
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{vlanName1}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
if r.TypedSpec().VLAN.VID != 42 {
|
return suite.assertInterfaces(
|
||||||
return retry.ExpectedErrorf("vlan ID is not 42: %d", r.TypedSpec().VLAN.VID)
|
[]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
|
// teardown the links
|
||||||
for _, r := range []resource.Resource{vlan1, vlan2, dummy} {
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoInterface(dummyInterface)
|
func() error {
|
||||||
}))
|
return suite.assertNoInterface(dummyInterface)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
@ -362,69 +396,92 @@ func (suite *LinkSpecSuite) TestBond() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{dummy0Name, dummy1Name, bondName}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
switch r.Metadata().ID() {
|
return suite.assertInterfaces(
|
||||||
case bondName:
|
[]string{dummy0Name, dummy1Name, bondName}, func(r *network.LinkStatus) error {
|
||||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
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 {
|
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||||
}
|
}
|
||||||
case dummy0Name, dummy1Name:
|
case dummy0Name, dummy1Name:
|
||||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||||
|
|
||||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
||||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.TypedSpec().MasterIndex == 0 {
|
if r.TypedSpec().MasterIndex == 0 {
|
||||||
return retry.ExpectedErrorf("masterIndex should be non-zero")
|
return retry.ExpectedErrorf("masterIndex should be non-zero")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// attempt to change bond type
|
// attempt to change bond type
|
||||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, bond.Metadata(), func(r resource.Resource) error {
|
_, err := suite.state.UpdateWithConflicts(
|
||||||
r.(*network.LinkSpec).TypedSpec().BondMaster.Mode = nethelpers.BondModeRoundrobin
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{bondName}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
if r.TypedSpec().BondMaster.Mode != nethelpers.BondModeRoundrobin {
|
return suite.assertInterfaces(
|
||||||
return retry.ExpectedErrorf("bond mode is not %s: %s", nethelpers.BondModeRoundrobin, r.TypedSpec().BondMaster.Mode)
|
[]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
|
// unslave one of the interfaces
|
||||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, dummy0.Metadata(), func(r resource.Resource) error {
|
_, err = suite.state.UpdateWithConflicts(
|
||||||
r.(*network.LinkSpec).TypedSpec().MasterName = ""
|
suite.ctx, dummy0.Metadata(), func(r resource.Resource) error {
|
||||||
|
r.(*network.LinkSpec).TypedSpec().MasterName = ""
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{dummy0Name}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
if r.TypedSpec().MasterIndex != 0 {
|
return suite.assertInterfaces(
|
||||||
return retry.ExpectedErrorf("iface not unslaved yet")
|
[]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
|
// teardown the links
|
||||||
for _, r := range []resource.Resource{dummy0, dummy1, bond} {
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoInterface(bondName)
|
func() error {
|
||||||
}))
|
return suite.assertNoInterface(bondName)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
@ -490,32 +550,37 @@ func (suite *LinkSpecSuite) TestBond8023ad() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces(append(dummyNames, bondName), func(r *network.LinkStatus) error {
|
func() error {
|
||||||
if r.Metadata().ID() == bondName {
|
return suite.assertInterfaces(
|
||||||
// master
|
append(dummyNames, bondName), func(r *network.LinkStatus) error {
|
||||||
suite.Assert().Equal(network.LinkKindBond, r.TypedSpec().Kind)
|
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 {
|
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// slaves
|
// slaves
|
||||||
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
suite.Assert().Equal("dummy", r.TypedSpec().Kind)
|
||||||
|
|
||||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
||||||
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
return retry.ExpectedErrorf("link is not up: %s", r.TypedSpec().OperationalState)
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.TypedSpec().MasterIndex == 0 {
|
if r.TypedSpec().MasterIndex == 0 {
|
||||||
return retry.ExpectedErrorf("masterIndex should be non-zero")
|
return retry.ExpectedErrorf("masterIndex should be non-zero")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// teardown the links
|
// teardown the links
|
||||||
for _, r := range append(dummies, bond) {
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoInterface(bondName)
|
func() error {
|
||||||
}))
|
return suite.assertNoInterface(bondName)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkSpecSuite) TestWireguard() {
|
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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{wgInterface}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
suite.Assert().Equal("wireguard", r.TypedSpec().Kind)
|
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() {
|
if r.TypedSpec().Wireguard.PublicKey != priv.PublicKey().String() {
|
||||||
return retry.ExpectedErrorf("private key not set")
|
return retry.ExpectedErrorf("private key not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.TypedSpec().Wireguard.Peers) != 2 {
|
if len(r.TypedSpec().Wireguard.Peers) != 2 {
|
||||||
return retry.ExpectedErrorf("peers are not set up")
|
return retry.ExpectedErrorf("peers are not set up")
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
if r.TypedSpec().OperationalState != nethelpers.OperStateUnknown && r.TypedSpec().OperationalState != nethelpers.OperStateUp {
|
||||||
return retry.ExpectedErrorf("link is not up")
|
return retry.ExpectedErrorf("link is not up")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// attempt to change wireguard private key
|
// attempt to change wireguard private key
|
||||||
priv2, err := wgtypes.GeneratePrivateKey()
|
priv2, err := wgtypes.GeneratePrivateKey()
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, wg.Metadata(), func(r resource.Resource) error {
|
_, err = suite.state.UpdateWithConflicts(
|
||||||
r.(*network.LinkSpec).TypedSpec().Wireguard.PrivateKey = priv2.String()
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{wgInterface}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
if r.TypedSpec().Wireguard.PublicKey != priv2.PublicKey().String() {
|
return suite.assertInterfaces(
|
||||||
return retry.ExpectedErrorf("private key was not updated")
|
[]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
|
// teardown the links
|
||||||
for _, r := range []resource.Resource{wg} {
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoInterface(wgInterface)
|
func() error {
|
||||||
}))
|
return suite.assertNoInterface(wgInterface)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkSpecSuite) TearDownTest() {
|
func (suite *LinkSpecSuite) TearDownTest() {
|
||||||
|
@ -39,7 +39,7 @@ type LinkStatusSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +79,10 @@ func (suite *LinkStatusSuite) assertInterfaces(requiredIDs []string, check func(
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -105,7 +108,10 @@ func (suite *LinkStatusSuite) assertInterfaces(requiredIDs []string, check func(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkStatusSuite) assertNoInterface(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -120,15 +126,20 @@ func (suite *LinkStatusSuite) assertNoInterface(id string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkStatusSuite) TestLoopbackInterface() {
|
func (suite *LinkStatusSuite) TestLoopbackInterface() {
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{"lo"}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
suite.Assert().Equal("loopback", r.TypedSpec().Type.String())
|
return suite.assertInterfaces(
|
||||||
suite.Assert().EqualValues(65536, r.TypedSpec().MTU)
|
[]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() {
|
func (suite *LinkStatusSuite) TestDummyInterface() {
|
||||||
@ -139,57 +150,83 @@ func (suite *LinkStatusSuite) TestDummyInterface() {
|
|||||||
|
|
||||||
defer conn.Close() //nolint:errcheck
|
defer conn.Close() //nolint:errcheck
|
||||||
|
|
||||||
suite.Require().NoError(conn.Link.New(&rtnetlink.LinkMessage{
|
suite.Require().NoError(
|
||||||
Type: unix.ARPHRD_ETHER,
|
conn.Link.New(
|
||||||
Attributes: &rtnetlink.LinkAttributes{
|
&rtnetlink.LinkMessage{
|
||||||
Name: dummyInterface,
|
Type: unix.ARPHRD_ETHER,
|
||||||
MTU: 1400,
|
Attributes: &rtnetlink.LinkAttributes{
|
||||||
Info: &rtnetlink.LinkInfo{
|
Name: dummyInterface,
|
||||||
Kind: "dummy",
|
MTU: 1400,
|
||||||
|
Info: &rtnetlink.LinkInfo{
|
||||||
|
Kind: "dummy",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
}))
|
)
|
||||||
|
|
||||||
iface, err := net.InterfaceByName(dummyInterface)
|
iface, err := net.InterfaceByName(dummyInterface)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
defer conn.Link.Delete(uint32(iface.Index)) //nolint:errcheck
|
defer conn.Link.Delete(uint32(iface.Index)) //nolint:errcheck
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{dummyInterface}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
suite.Assert().Equal("ether", r.TypedSpec().Type.String())
|
return suite.assertInterfaces(
|
||||||
suite.Assert().EqualValues(1400, r.TypedSpec().MTU)
|
[]string{dummyInterface}, func(r *network.LinkStatus) error {
|
||||||
suite.Assert().Equal(nethelpers.OperStateDown, r.TypedSpec().OperationalState)
|
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{
|
suite.Require().NoError(
|
||||||
Type: unix.ARPHRD_ETHER,
|
conn.Link.Set(
|
||||||
Index: uint32(iface.Index),
|
&rtnetlink.LinkMessage{
|
||||||
Flags: unix.IFF_UP,
|
Type: unix.ARPHRD_ETHER,
|
||||||
Change: unix.IFF_UP,
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertInterfaces([]string{dummyInterface}, func(r *network.LinkStatus) error {
|
func() error {
|
||||||
if r.TypedSpec().OperationalState != nethelpers.OperStateUp && r.TypedSpec().OperationalState != nethelpers.OperStateUnknown {
|
return suite.assertInterfaces(
|
||||||
return retry.ExpectedError(fmt.Errorf("operational state is not up: %s", r.TypedSpec().OperationalState))
|
[]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.Require().NoError(conn.Link.Delete(uint32(iface.Index)))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoInterface(dummyInterface)
|
func() error {
|
||||||
}))
|
return suite.assertNoInterface(dummyInterface)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *LinkStatusSuite) TearDownTest() {
|
func (suite *LinkStatusSuite) TearDownTest() {
|
||||||
@ -200,7 +237,12 @@ func (suite *LinkStatusSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestLinkStatusSuite(t *testing.T) {
|
||||||
|
@ -39,7 +39,7 @@ type NodeAddressSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +75,10 @@ func (suite *NodeAddressSuite) assertAddresses(requiredIDs []string, check func(
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
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.AddressStatusController{}))
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkStatusController{}))
|
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkStatusController{}))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
network.NodeAddressDefaultID,
|
return suite.assertAddresses(
|
||||||
network.NodeAddressCurrentID,
|
[]string{
|
||||||
network.NodeAddressAccumulativeID,
|
network.NodeAddressDefaultID,
|
||||||
}, func(r *network.NodeAddress) error {
|
network.NodeAddressCurrentID,
|
||||||
addrs := r.TypedSpec().Addresses
|
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 {
|
suite.Assert().True(
|
||||||
return addrs[i].IP().Compare(addrs[j].IP()) < 0
|
sort.SliceIsSorted(
|
||||||
}), "addresses %s", addrs)
|
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 r.Metadata().ID() == network.NodeAddressDefaultID {
|
||||||
if len(addrs) != 1 {
|
if len(addrs) != 1 {
|
||||||
return fmt.Errorf("there should be only one default address")
|
return fmt.Errorf("there should be only one default address")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(addrs) == 0 {
|
if len(addrs) == 0 {
|
||||||
return fmt.Errorf("there should be some addresses")
|
return fmt.Errorf("there should be some addresses")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
@ -158,17 +170,34 @@ func (suite *NodeAddressSuite) TestFilters() {
|
|||||||
addressStatus.TypedSpec().Address = addr
|
addressStatus.TypedSpec().Address = addr
|
||||||
addressStatus.TypedSpec().LinkName = link.Metadata().ID()
|
addressStatus.TypedSpec().LinkName = link.Metadata().ID()
|
||||||
addressStatus.TypedSpec().LinkIndex = link.TypedSpec().Index
|
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) {
|
newExternalAddress := func(addr netaddr.IPPrefix) {
|
||||||
addressStatus := network.NewAddressStatus(network.NamespaceName, network.AddressID("external", addr))
|
addressStatus := network.NewAddressStatus(network.NamespaceName, network.AddressID("external", addr))
|
||||||
addressStatus.TypedSpec().Address = addr
|
addressStatus.TypedSpec().Address = addr
|
||||||
addressStatus.TypedSpec().LinkName = "external"
|
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)
|
newAddress(netaddr.MustParseIPPrefix(addr), linkUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,56 +214,76 @@ func (suite *NodeAddressSuite) TestFilters() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, filter1))
|
suite.Require().NoError(suite.state.Create(suite.ctx, filter1))
|
||||||
|
|
||||||
filter2 := network.NewNodeAddressFilter(network.NamespaceName, "only-k8s")
|
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.Require().NoError(suite.state.Create(suite.ctx, filter2))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertAddresses([]string{
|
func() error {
|
||||||
network.NodeAddressDefaultID,
|
return suite.assertAddresses(
|
||||||
network.NodeAddressCurrentID,
|
[]string{
|
||||||
network.NodeAddressAccumulativeID,
|
network.NodeAddressDefaultID,
|
||||||
network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter1.Metadata().ID()),
|
network.NodeAddressCurrentID,
|
||||||
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter1.Metadata().ID()),
|
network.NodeAddressAccumulativeID,
|
||||||
network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter2.Metadata().ID()),
|
network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter1.Metadata().ID()),
|
||||||
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter2.Metadata().ID()),
|
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter1.Metadata().ID()),
|
||||||
}, func(r *network.NodeAddress) error {
|
network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter2.Metadata().ID()),
|
||||||
addrs := r.TypedSpec().Addresses
|
network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter2.Metadata().ID()),
|
||||||
|
}, func(r *network.NodeAddress) error {
|
||||||
|
addrs := r.TypedSpec().Addresses
|
||||||
|
|
||||||
switch r.Metadata().ID() {
|
switch r.Metadata().ID() {
|
||||||
case network.NodeAddressDefaultID:
|
case network.NodeAddressDefaultID:
|
||||||
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8")) {
|
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8")) {
|
||||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||||
}
|
}
|
||||||
case network.NodeAddressCurrentID:
|
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")) {
|
if !reflect.DeepEqual(
|
||||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
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"),
|
||||||
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)
|
||||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
}
|
||||||
}
|
case network.NodeAddressAccumulativeID:
|
||||||
case network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter1.Metadata().ID()):
|
if !reflect.DeepEqual(
|
||||||
if !reflect.DeepEqual(addrs, ipList("1.2.3.4/32 25.3.7.9/32 2001:470:6d:30e:4a62:b3ba:180b:b5b8/64")) {
|
addrs,
|
||||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), 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"),
|
||||||
}
|
) {
|
||||||
case network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter1.Metadata().ID()):
|
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
||||||
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, filter1.Metadata().ID()):
|
||||||
}
|
if !reflect.DeepEqual(
|
||||||
case network.FilteredNodeAddressID(network.NodeAddressCurrentID, filter2.Metadata().ID()):
|
addrs,
|
||||||
if !reflect.DeepEqual(addrs, ipList("10.0.0.1/8")) {
|
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)
|
) {
|
||||||
}
|
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")) {
|
case network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, filter1.Metadata().ID()):
|
||||||
return fmt.Errorf("unexpected %q: %s", r.Metadata().ID(), addrs)
|
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() {
|
func (suite *NodeAddressSuite) TearDownTest() {
|
||||||
@ -245,8 +294,18 @@ func (suite *NodeAddressSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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.Assert().NoError(suite.state.Create(context.Background(), network.NewLinkStatus(network.NamespaceName, "bar")))
|
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) {
|
func TestNodeAddressSuite(t *testing.T) {
|
||||||
|
@ -40,7 +40,7 @@ type OperatorConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,10 @@ func (suite *OperatorConfigSuite) assertOperators(requiredIDs []string, check fu
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -104,7 +107,10 @@ func (suite *OperatorConfigSuite) assertNoOperators(unexpectedIDs []string) erro
|
|||||||
unexpIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -120,9 +126,13 @@ func (suite *OperatorConfigSuite) assertNoOperators(unexpectedIDs []string) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorConfigSuite) TestDefaultDHCP() {
|
func (suite *OperatorConfigSuite) TestDefaultDHCP() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.OperatorConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
suite.runtime.RegisterController(
|
||||||
}))
|
&netctrl.OperatorConfigController{
|
||||||
|
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth2"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -134,32 +144,41 @@ func (suite *OperatorConfigSuite) TestDefaultDHCP() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkStatus))
|
suite.Require().NoError(suite.state.Create(suite.ctx, linkStatus))
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertOperators([]string{
|
func() error {
|
||||||
"default/dhcp4/eth0",
|
return suite.assertOperators(
|
||||||
"default/dhcp4/eth1",
|
[]string{
|
||||||
}, func(r *network.OperatorSpec) error {
|
"default/dhcp4/eth0",
|
||||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
"default/dhcp4/eth1",
|
||||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
}, func(r *network.OperatorSpec) error {
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
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() {
|
switch r.Metadata().ID() {
|
||||||
case "default/dhcp4/eth0":
|
case "default/dhcp4/eth0":
|
||||||
suite.Assert().Equal("eth0", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth0", r.TypedSpec().LinkName)
|
||||||
case "default/dhcp4/eth1":
|
case "default/dhcp4/eth1":
|
||||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorConfigSuite) TestDefaultDHCPCmdline() {
|
func (suite *OperatorConfigSuite) TestDefaultDHCPCmdline() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.OperatorConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
suite.runtime.RegisterController(
|
||||||
}))
|
&netctrl.OperatorConfigController{
|
||||||
|
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -171,46 +190,69 @@ func (suite *OperatorConfigSuite) TestDefaultDHCPCmdline() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkStatus))
|
suite.Require().NoError(suite.state.Create(suite.ctx, linkStatus))
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertOperators([]string{
|
func() error {
|
||||||
"default/dhcp4/eth0",
|
return suite.assertOperators(
|
||||||
"default/dhcp4/eth2",
|
[]string{
|
||||||
}, func(r *network.OperatorSpec) error {
|
"default/dhcp4/eth0",
|
||||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
"default/dhcp4/eth2",
|
||||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
}, func(r *network.OperatorSpec) error {
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
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() {
|
switch r.Metadata().ID() {
|
||||||
case "default/dhcp4/eth0":
|
case "default/dhcp4/eth0":
|
||||||
suite.Assert().Equal("eth0", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth0", r.TypedSpec().LinkName)
|
||||||
case "default/dhcp4/eth2":
|
case "default/dhcp4/eth2":
|
||||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// remove link
|
// 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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoOperators([]string{
|
func() error {
|
||||||
"default/dhcp4/eth2",
|
return suite.assertNoOperators(
|
||||||
})
|
[]string{
|
||||||
}))
|
"default/dhcp4/eth2",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP4() {
|
func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP4() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.OperatorConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth5"),
|
suite.runtime.RegisterController(
|
||||||
}))
|
&netctrl.OperatorConfigController{
|
||||||
|
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth5"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
// add LinkConfig controller to produce link specs based on machine configuration
|
// add LinkConfig controller to produce link specs based on machine configuration
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.LinkConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth5"),
|
suite.runtime.RegisterController(
|
||||||
}))
|
&netctrl.LinkConfigController{
|
||||||
|
Cmdline: procfs.NewCmdline("talos.network.interface.ignore=eth5"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -225,97 +267,109 @@ func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP4() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NetworkInterfaces: []*v1alpha1.Device{
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
{
|
NetworkInterfaces: []*v1alpha1.Device{
|
||||||
DeviceInterface: "eth0",
|
{
|
||||||
},
|
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,
|
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
DeviceInterface: "eth1",
|
||||||
DeviceInterface: "eth4",
|
DeviceDHCP: true,
|
||||||
DeviceVlans: []*v1alpha1.Vlan{
|
},
|
||||||
{
|
{
|
||||||
VlanID: 25,
|
DeviceIgnore: true,
|
||||||
VlanDHCP: true,
|
DeviceInterface: "eth2",
|
||||||
},
|
DeviceDHCP: true,
|
||||||
{
|
},
|
||||||
VlanID: 26,
|
{
|
||||||
|
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.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertOperators([]string{
|
func() error {
|
||||||
"configuration/dhcp4/eth1",
|
return suite.assertOperators(
|
||||||
"configuration/dhcp4/eth3",
|
[]string{
|
||||||
"configuration/dhcp4/eth4.25",
|
"configuration/dhcp4/eth1",
|
||||||
}, func(r *network.OperatorSpec) error {
|
"configuration/dhcp4/eth3",
|
||||||
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
"configuration/dhcp4/eth4.25",
|
||||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
}, func(r *network.OperatorSpec) error {
|
||||||
|
suite.Assert().Equal(network.OperatorDHCP4, r.TypedSpec().Operator)
|
||||||
|
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||||
|
|
||||||
switch r.Metadata().ID() {
|
switch r.Metadata().ID() {
|
||||||
case "configuration/dhcp4/eth1":
|
case "configuration/dhcp4/eth1":
|
||||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
||||||
case "configuration/dhcp4/eth3":
|
case "configuration/dhcp4/eth3":
|
||||||
suite.Assert().Equal("eth3", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth3", r.TypedSpec().LinkName)
|
||||||
suite.Assert().EqualValues(256, r.TypedSpec().DHCP4.RouteMetric)
|
suite.Assert().EqualValues(256, r.TypedSpec().DHCP4.RouteMetric)
|
||||||
case "configuration/dhcp4/eth4.25":
|
case "configuration/dhcp4/eth4.25":
|
||||||
suite.Assert().Equal("eth4.25", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth4.25", r.TypedSpec().LinkName)
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP4.RouteMetric)
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoOperators([]string{
|
func() error {
|
||||||
"configuration/dhcp4/eth0",
|
return suite.assertNoOperators(
|
||||||
"default/dhcp4/eth0",
|
[]string{
|
||||||
"configuration/dhcp4/eth2",
|
"configuration/dhcp4/eth0",
|
||||||
"default/dhcp4/eth2",
|
"default/dhcp4/eth0",
|
||||||
"configuration/dhcp4/eth4.26",
|
"configuration/dhcp4/eth2",
|
||||||
})
|
"default/dhcp4/eth2",
|
||||||
}))
|
"configuration/dhcp4/eth4.26",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP6() {
|
func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP6() {
|
||||||
@ -326,75 +380,87 @@ func (suite *OperatorConfigSuite) TestMachineConfigurationDHCP6() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NetworkInterfaces: []*v1alpha1.Device{
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
{
|
NetworkInterfaces: []*v1alpha1.Device{
|
||||||
DeviceInterface: "eth1",
|
{
|
||||||
DeviceDHCP: true,
|
DeviceInterface: "eth1",
|
||||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
DeviceDHCP: true,
|
||||||
DHCPIPv4: pointer.ToBool(true),
|
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||||
|
DHCPIPv4: pointer.ToBool(true),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
DeviceInterface: "eth2",
|
||||||
DeviceInterface: "eth2",
|
DeviceDHCP: true,
|
||||||
DeviceDHCP: true,
|
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
DHCPIPv6: pointer.ToBool(true),
|
||||||
DHCPIPv6: pointer.ToBool(true),
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
DeviceInterface: "eth3",
|
||||||
DeviceInterface: "eth3",
|
DeviceDHCP: true,
|
||||||
DeviceDHCP: true,
|
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
||||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{
|
DHCPIPv6: pointer.ToBool(true),
|
||||||
DHCPIPv6: pointer.ToBool(true),
|
DHCPRouteMetric: 512,
|
||||||
DHCPRouteMetric: 512,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertOperators([]string{
|
func() error {
|
||||||
"configuration/dhcp6/eth2",
|
return suite.assertOperators(
|
||||||
"configuration/dhcp6/eth3",
|
[]string{
|
||||||
}, func(r *network.OperatorSpec) error {
|
"configuration/dhcp6/eth2",
|
||||||
suite.Assert().Equal(network.OperatorDHCP6, r.TypedSpec().Operator)
|
"configuration/dhcp6/eth3",
|
||||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
}, func(r *network.OperatorSpec) error {
|
||||||
|
suite.Assert().Equal(network.OperatorDHCP6, r.TypedSpec().Operator)
|
||||||
|
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||||
|
|
||||||
switch r.Metadata().ID() {
|
switch r.Metadata().ID() {
|
||||||
case "configuration/dhcp6/eth2":
|
case "configuration/dhcp6/eth2":
|
||||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP6.RouteMetric)
|
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().DHCP6.RouteMetric)
|
||||||
case "configuration/dhcp6/eth3":
|
case "configuration/dhcp6/eth3":
|
||||||
suite.Assert().Equal("eth3", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth3", r.TypedSpec().LinkName)
|
||||||
suite.Assert().EqualValues(512, r.TypedSpec().DHCP6.RouteMetric)
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoOperators([]string{
|
func() error {
|
||||||
"configuration/dhcp6/eth1",
|
return suite.assertNoOperators(
|
||||||
})
|
[]string{
|
||||||
}))
|
"configuration/dhcp6/eth1",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorConfigSuite) TearDownTest() {
|
func (suite *OperatorConfigSuite) TearDownTest() {
|
||||||
@ -405,17 +471,26 @@ func (suite *OperatorConfigSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().NoError(err)
|
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) {
|
func TestOperatorConfigSuite(t *testing.T) {
|
||||||
|
@ -35,7 +35,7 @@ type OperatorMergeSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,10 @@ func (suite *OperatorMergeSuite) assertOperators(requiredIDs []string, check fun
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -97,7 +100,10 @@ func (suite *OperatorMergeSuite) assertOperators(requiredIDs []string, check fun
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorMergeSuite) assertNoOperator(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -139,37 +145,50 @@ func (suite *OperatorMergeSuite) TestMerge() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertOperators([]string{
|
func() error {
|
||||||
"dhcp4/eth0",
|
return suite.assertOperators(
|
||||||
"dhcp6/eth0",
|
[]string{
|
||||||
}, func(r *network.OperatorSpec) error {
|
"dhcp4/eth0",
|
||||||
switch r.Metadata().ID() {
|
"dhcp6/eth0",
|
||||||
case "dhcp4/eth0":
|
}, func(r *network.OperatorSpec) error {
|
||||||
suite.Assert().Equal(*dhcp2.TypedSpec(), *r.TypedSpec())
|
switch r.Metadata().ID() {
|
||||||
case "dhcp6/eth0":
|
case "dhcp4/eth0":
|
||||||
suite.Assert().Equal(*dhcp6.TypedSpec(), *r.TypedSpec())
|
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.Require().NoError(suite.state.Destroy(suite.ctx, dhcp6.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertOperators([]string{
|
func() error {
|
||||||
"dhcp4/eth0",
|
return suite.assertOperators(
|
||||||
}, func(r *network.OperatorSpec) error {
|
[]string{
|
||||||
return nil
|
"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.assertNoOperator("dhcp6/eth0")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
@ -214,50 +233,75 @@ func (suite *OperatorMergeSuite) TestMergeFlapping() {
|
|||||||
|
|
||||||
eg.Go(flipflop(0))
|
eg.Go(flipflop(0))
|
||||||
eg.Go(flipflop(1))
|
eg.Go(flipflop(1))
|
||||||
eg.Go(func() error {
|
eg.Go(
|
||||||
// add/remove finalizer to the merged resource
|
func() error {
|
||||||
for i := 0; i < 1000; i++ {
|
// add/remove finalizer to the merged resource
|
||||||
if err := suite.state.AddFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.OperatorSpecType, "dhcp4/eth0", resource.VersionUndefined), "foo"); err != nil {
|
for i := 0; i < 1000; i++ {
|
||||||
if !state.IsNotFoundError(err) {
|
if err := suite.state.AddFinalizer(
|
||||||
return err
|
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
|
time.Sleep(10 * time.Millisecond)
|
||||||
} else {
|
|
||||||
suite.T().Log("finalizer added")
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
if err := suite.state.RemoveFinalizer(
|
||||||
|
suite.ctx,
|
||||||
if err := suite.state.RemoveFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.OperatorSpecType, "dhcp4/eth0", resource.VersionUndefined), "foo"); err != nil {
|
resource.NewMetadata(
|
||||||
if err != nil && !state.IsNotFoundError(err) {
|
network.NamespaceName,
|
||||||
return err
|
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.Require().NoError(eg.Wait())
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertOperators([]string{
|
func() error {
|
||||||
"dhcp4/eth0",
|
return suite.assertOperators(
|
||||||
}, func(r *network.OperatorSpec) error {
|
[]string{
|
||||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
"dhcp4/eth0",
|
||||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
}, 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() {
|
if *override.TypedSpec() != *r.TypedSpec() {
|
||||||
// using retry here, as it might not be reconciled immediately
|
// using retry here, as it might not be reconciled immediately
|
||||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorMergeSuite) TearDownTest() {
|
func (suite *OperatorMergeSuite) TearDownTest() {
|
||||||
@ -268,7 +312,12 @@ func (suite *OperatorMergeSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestOperatorMergeSuite(t *testing.T) {
|
||||||
|
@ -37,7 +37,7 @@ type OperatorSpecSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,9 +155,13 @@ func (suite *OperatorSpecSuite) SetupTest() {
|
|||||||
|
|
||||||
runningOperators = map[string]*mockOperator{}
|
runningOperators = map[string]*mockOperator{}
|
||||||
|
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.OperatorSpecController{
|
suite.Require().NoError(
|
||||||
Factory: suite.newOperator,
|
suite.runtime.RegisterController(
|
||||||
}))
|
&netctrl.OperatorSpecController{
|
||||||
|
Factory: suite.newOperator,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
}
|
}
|
||||||
@ -214,7 +218,10 @@ func (suite *OperatorSpecSuite) assertResources(resourceType resource.Type, requ
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -255,12 +262,17 @@ func (suite *OperatorSpecSuite) TestScheduling() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, specVIP))
|
suite.Require().NoError(suite.state.Create(suite.ctx, specVIP))
|
||||||
|
|
||||||
// operators shouldn't be running yet, as link state is not known yet
|
// 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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRunning(nil, func(op *mockOperator) error {
|
func() error {
|
||||||
return nil
|
return suite.assertRunning(
|
||||||
})
|
nil, func(op *mockOperator) error {
|
||||||
}))
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
linkState := network.NewLinkStatus(network.NamespaceName, "eth0")
|
linkState := network.NewLinkStatus(network.NamespaceName, "eth0")
|
||||||
*linkState.TypedSpec() = network.LinkStatusSpec{
|
*linkState.TypedSpec() = network.LinkStatusSpec{
|
||||||
@ -270,79 +282,105 @@ func (suite *OperatorSpecSuite) TestScheduling() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkState))
|
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
|
// 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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRunning([]string{"vip/eth0"}, func(op *mockOperator) error {
|
func() error {
|
||||||
suite.Assert().Equal(netaddr.MustParseIP("1.2.3.4"), op.spec.VIP.IP)
|
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 {
|
_, err := suite.state.UpdateWithConflicts(
|
||||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateUp
|
suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
||||||
|
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateUp
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// now all operators should be scheduled
|
// now all operators should be scheduled
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRunning([]string{"dhcp4/eth0", "vip/eth0"}, func(op *mockOperator) error {
|
func() error {
|
||||||
switch op.spec.Operator { //nolint:exhaustive
|
return suite.assertRunning(
|
||||||
case network.OperatorDHCP4:
|
[]string{"dhcp4/eth0", "vip/eth0"}, func(op *mockOperator) error {
|
||||||
suite.Assert().EqualValues(1024, op.spec.DHCP4.RouteMetric)
|
switch op.spec.Operator { //nolint:exhaustive
|
||||||
case network.OperatorVIP:
|
case network.OperatorDHCP4:
|
||||||
suite.Assert().Equal(netaddr.MustParseIP("1.2.3.4"), op.spec.VIP.IP)
|
suite.Assert().EqualValues(1024, op.spec.DHCP4.RouteMetric)
|
||||||
default:
|
case network.OperatorVIP:
|
||||||
panic("unreachable")
|
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
|
// change the spec, operator should be rescheduled
|
||||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, specVIP.Metadata(), func(r resource.Resource) error {
|
_, err = suite.state.UpdateWithConflicts(
|
||||||
r.(*network.OperatorSpec).TypedSpec().VIP.IP = netaddr.MustParseIP("3.4.5.6")
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRunning([]string{"dhcp4/eth0", "vip/eth0"}, func(op *mockOperator) error {
|
func() error {
|
||||||
switch op.spec.Operator { //nolint:exhaustive
|
return suite.assertRunning(
|
||||||
case network.OperatorDHCP4:
|
[]string{"dhcp4/eth0", "vip/eth0"}, func(op *mockOperator) error {
|
||||||
suite.Assert().EqualValues(1024, op.spec.DHCP4.RouteMetric)
|
switch op.spec.Operator { //nolint:exhaustive
|
||||||
case network.OperatorVIP:
|
case network.OperatorDHCP4:
|
||||||
if op.spec.VIP.IP.Compare(netaddr.MustParseIP("3.4.5.6")) != 0 {
|
suite.Assert().EqualValues(1024, op.spec.DHCP4.RouteMetric)
|
||||||
return retry.ExpectedErrorf("unexpected vip: %s", op.spec.VIP.IP)
|
case network.OperatorVIP:
|
||||||
}
|
if op.spec.VIP.IP.Compare(netaddr.MustParseIP("3.4.5.6")) != 0 {
|
||||||
default:
|
return retry.ExpectedErrorf("unexpected vip: %s", op.spec.VIP.IP)
|
||||||
panic("unreachable")
|
}
|
||||||
}
|
default:
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// bring down the interface, operator should be stopped
|
// bring down the interface, operator should be stopped
|
||||||
_, err = suite.state.UpdateWithConflicts(suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
_, err = suite.state.UpdateWithConflicts(
|
||||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateDown
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRunning([]string{"vip/eth0"}, func(op *mockOperator) error {
|
func() error {
|
||||||
return nil
|
return suite.assertRunning(
|
||||||
})
|
[]string{"vip/eth0"}, func(op *mockOperator) error {
|
||||||
}))
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorSpecSuite) TestPanic() {
|
func (suite *OperatorSpecSuite) TestPanic() {
|
||||||
@ -366,25 +404,35 @@ func (suite *OperatorSpecSuite) TestPanic() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkState))
|
suite.Require().NoError(suite.state.Create(suite.ctx, linkState))
|
||||||
|
|
||||||
// DHCP6 operator should panic and then restart
|
// DHCP6 operator should panic and then restart
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRunning([]string{"dhcp6/eth0"}, func(op *mockOperator) error { return nil })
|
func() error {
|
||||||
}))
|
return suite.assertRunning([]string{"dhcp6/eth0"}, func(op *mockOperator) error { return nil })
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// bring down the interface, operator should be stopped
|
// bring down the interface, operator should be stopped
|
||||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, linkState.Metadata(), func(r resource.Resource) error {
|
_, err := suite.state.UpdateWithConflicts(
|
||||||
r.(*network.LinkStatus).TypedSpec().OperationalState = nethelpers.OperStateDown
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRunning(nil, func(op *mockOperator) error {
|
func() error {
|
||||||
return nil
|
return suite.assertRunning(
|
||||||
})
|
nil, func(op *mockOperator) error {
|
||||||
}))
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
||||||
@ -407,12 +455,17 @@ func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, linkState))
|
suite.Require().NoError(suite.state.Create(suite.ctx, linkState))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRunning([]string{"dhcp4/eth0"}, func(op *mockOperator) error {
|
func() error {
|
||||||
return nil
|
return suite.assertRunning(
|
||||||
})
|
[]string{"dhcp4/eth0"}, func(op *mockOperator) error {
|
||||||
}))
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// pretend dhcp has some specs ready
|
// pretend dhcp has some specs ready
|
||||||
runningOperatorsMu.Lock()
|
runningOperatorsMu.Lock()
|
||||||
@ -447,18 +500,27 @@ func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
|||||||
|
|
||||||
dhcpMock.notify()
|
dhcpMock.notify()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.AddressSpecType, []string{"dhcp4/eth0/eth0/10.5.0.2/24"})
|
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(
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
func() error {
|
func() error {
|
||||||
return suite.assertResources(network.HostnameSpecType, []string{"dhcp4/eth0/hostname"})
|
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
|
// update specs
|
||||||
dhcpMock.mu.Lock()
|
dhcpMock.mu.Lock()
|
||||||
@ -476,10 +538,13 @@ func (suite *OperatorSpecSuite) TestOperatorOutputs() {
|
|||||||
|
|
||||||
dhcpMock.notify()
|
dhcpMock.notify()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.AddressSpecType, []string{"dhcp4/eth0/eth0/10.5.0.3/24"})
|
func() error {
|
||||||
}))
|
return suite.assertResources(network.AddressSpecType, []string{"dhcp4/eth0/eth0/10.5.0.3/24"})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *OperatorSpecSuite) TearDownTest() {
|
func (suite *OperatorSpecSuite) TearDownTest() {
|
||||||
@ -490,7 +555,12 @@ func (suite *OperatorSpecSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestOperatorSpecSuite(t *testing.T) {
|
||||||
|
@ -38,7 +38,7 @@ type OperatorVIPConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
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))
|
missingIDs := make(map[string]struct{}, len(requiredIDs))
|
||||||
|
|
||||||
for _, id := range requiredIDs {
|
for _, id := range requiredIDs {
|
||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -103,76 +109,86 @@ func (suite *OperatorVIPConfigSuite) TestMachineConfigurationVIP() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NetworkInterfaces: []*v1alpha1.Device{
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
{
|
NetworkInterfaces: []*v1alpha1.Device{
|
||||||
DeviceInterface: "eth1",
|
{
|
||||||
DeviceDHCP: true,
|
DeviceInterface: "eth1",
|
||||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
DeviceDHCP: true,
|
||||||
SharedIP: "2.3.4.5",
|
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||||
|
SharedIP: "2.3.4.5",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
DeviceInterface: "eth2",
|
||||||
DeviceInterface: "eth2",
|
DeviceDHCP: true,
|
||||||
DeviceDHCP: true,
|
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
||||||
DeviceVIPConfig: &v1alpha1.DeviceVIPConfig{
|
SharedIP: "fd7a:115c:a1e0:ab12:4843:cd96:6277:2302",
|
||||||
SharedIP: "fd7a:115c:a1e0:ab12:4843:cd96:6277:2302",
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
DeviceInterface: "eth3",
|
||||||
DeviceInterface: "eth3",
|
DeviceDHCP: true,
|
||||||
DeviceDHCP: true,
|
DeviceVlans: []*v1alpha1.Vlan{
|
||||||
DeviceVlans: []*v1alpha1.Vlan{
|
{
|
||||||
{
|
VlanID: 26,
|
||||||
VlanID: 26,
|
VlanVIP: &v1alpha1.DeviceVIPConfig{
|
||||||
VlanVIP: &v1alpha1.DeviceVIPConfig{
|
SharedIP: "5.5.4.4",
|
||||||
SharedIP: "5.5.4.4",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertOperators([]string{
|
func() error {
|
||||||
"configuration/vip/eth1",
|
return suite.assertOperators(
|
||||||
"configuration/vip/eth2",
|
[]string{
|
||||||
"configuration/vip/eth3.26",
|
"configuration/vip/eth1",
|
||||||
}, func(r *network.OperatorSpec) error {
|
"configuration/vip/eth2",
|
||||||
suite.Assert().Equal(network.OperatorVIP, r.TypedSpec().Operator)
|
"configuration/vip/eth3.26",
|
||||||
suite.Assert().True(r.TypedSpec().RequireUp)
|
}, func(r *network.OperatorSpec) error {
|
||||||
|
suite.Assert().Equal(network.OperatorVIP, r.TypedSpec().Operator)
|
||||||
|
suite.Assert().True(r.TypedSpec().RequireUp)
|
||||||
|
|
||||||
switch r.Metadata().ID() {
|
switch r.Metadata().ID() {
|
||||||
case "configuration/vip/eth1":
|
case "configuration/vip/eth1":
|
||||||
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth1", r.TypedSpec().LinkName)
|
||||||
suite.Assert().EqualValues(netaddr.MustParseIP("2.3.4.5"), r.TypedSpec().VIP.IP)
|
suite.Assert().EqualValues(netaddr.MustParseIP("2.3.4.5"), r.TypedSpec().VIP.IP)
|
||||||
case "configuration/vip/eth2":
|
case "configuration/vip/eth2":
|
||||||
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
suite.Assert().Equal("eth2", r.TypedSpec().LinkName)
|
||||||
suite.Assert().EqualValues(netaddr.MustParseIP("fd7a:115c:a1e0:ab12:4843:cd96:6277:2302"), r.TypedSpec().VIP.IP)
|
suite.Assert().EqualValues(
|
||||||
case "configuration/vip/eth3.26":
|
netaddr.MustParseIP("fd7a:115c:a1e0:ab12:4843:cd96:6277:2302"),
|
||||||
suite.Assert().Equal("eth3.26", r.TypedSpec().LinkName)
|
r.TypedSpec().VIP.IP,
|
||||||
suite.Assert().EqualValues(netaddr.MustParseIP("5.5.4.4"), 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() {
|
func (suite *OperatorVIPConfigSuite) TearDownTest() {
|
||||||
@ -183,17 +199,26 @@ func (suite *OperatorVIPConfigSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().NoError(err)
|
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) {
|
func TestOperatorVIPConfigSuite(t *testing.T) {
|
||||||
|
@ -45,7 +45,7 @@ type PlatformConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
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))
|
missingIDs := make(map[string]struct{}, len(requiredIDs))
|
||||||
|
|
||||||
for _, id := range requiredIDs {
|
for _, id := range requiredIDs {
|
||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -102,7 +110,10 @@ func (suite *PlatformConfigSuite) assertResources(resourceNamespace resource.Nam
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) assertNoResource(resourceType resource.Type, id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -121,261 +132,360 @@ func (suite *PlatformConfigSuite) TestNoPlatform() {
|
|||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoResource(network.HostnameSpecType, "platform/hostname")
|
func() error {
|
||||||
}))
|
return suite.assertNoResource(network.HostnameSpecType, "platform/hostname")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TestPlatformMockHostname() {
|
func (suite *PlatformConfigSuite) TestPlatformMockHostname() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl.c.talos-testbed.internal")},
|
suite.runtime.RegisterController(
|
||||||
StatePath: suite.statePath,
|
&netctrl.PlatformConfigController{
|
||||||
}))
|
V1alpha1Platform: &platformMock{hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl.c.talos-testbed.internal")},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
func() error {
|
||||||
"platform/hostname",
|
return suite.assertResources(
|
||||||
}, func(r resource.Resource) error {
|
network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
"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("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||||
suite.Assert().Equal("c.talos-testbed.internal", spec.Domainname)
|
suite.Assert().Equal("c.talos-testbed.internal", spec.Domainname)
|
||||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TestPlatformMockHostnameNoDomain() {
|
func (suite *PlatformConfigSuite) TestPlatformMockHostnameNoDomain() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl")},
|
suite.runtime.RegisterController(
|
||||||
StatePath: suite.statePath,
|
&netctrl.PlatformConfigController{
|
||||||
}))
|
V1alpha1Platform: &platformMock{hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl")},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
func() error {
|
||||||
"platform/hostname",
|
return suite.assertResources(
|
||||||
}, func(r resource.Resource) error {
|
network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
"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("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||||
suite.Assert().Equal("", spec.Domainname)
|
suite.Assert().Equal("", spec.Domainname)
|
||||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TestPlatformMockAddresses() {
|
func (suite *PlatformConfigSuite) TestPlatformMockAddresses() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{
|
suite.runtime.RegisterController(
|
||||||
addresses: []netaddr.IPPrefix{netaddr.MustParseIPPrefix("192.168.1.24/24"), netaddr.MustParseIPPrefix("2001:fd::3/64")},
|
&netctrl.PlatformConfigController{
|
||||||
},
|
V1alpha1Platform: &platformMock{
|
||||||
StatePath: suite.statePath,
|
addresses: []netaddr.IPPrefix{
|
||||||
}))
|
netaddr.MustParseIPPrefix("192.168.1.24/24"),
|
||||||
|
netaddr.MustParseIPPrefix("2001:fd::3/64"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.AddressSpecType, []string{
|
func() error {
|
||||||
"platform/eth0/192.168.1.24/24",
|
return suite.assertResources(
|
||||||
"platform/eth0/2001:fd::3/64",
|
network.ConfigNamespaceName, network.AddressSpecType, []string{
|
||||||
}, func(r resource.Resource) error {
|
"platform/eth0/192.168.1.24/24",
|
||||||
spec := r.(*network.AddressSpec).TypedSpec()
|
"platform/eth0/2001:fd::3/64",
|
||||||
|
}, func(r resource.Resource) error {
|
||||||
|
spec := r.(*network.AddressSpec).TypedSpec()
|
||||||
|
|
||||||
switch r.Metadata().ID() {
|
switch r.Metadata().ID() {
|
||||||
case "platform/eth0/192.168.1.24/24":
|
case "platform/eth0/192.168.1.24/24":
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||||
suite.Assert().Equal("192.168.1.24/24", spec.Address.String())
|
suite.Assert().Equal("192.168.1.24/24", spec.Address.String())
|
||||||
case "platform/eth0/2001:fd::3/64":
|
case "platform/eth0/2001:fd::3/64":
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
||||||
suite.Assert().Equal("2001:fd::3/64", spec.Address.String())
|
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() {
|
func (suite *PlatformConfigSuite) TestPlatformMockLinks() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{
|
suite.runtime.RegisterController(
|
||||||
linksUp: []string{"eth0", "eth1"},
|
&netctrl.PlatformConfigController{
|
||||||
},
|
V1alpha1Platform: &platformMock{
|
||||||
StatePath: suite.statePath,
|
linksUp: []string{"eth0", "eth1"},
|
||||||
}))
|
},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.LinkSpecType, []string{
|
func() error {
|
||||||
"platform/eth0",
|
return suite.assertResources(
|
||||||
"platform/eth1",
|
network.ConfigNamespaceName, network.LinkSpecType, []string{
|
||||||
}, func(r resource.Resource) error {
|
"platform/eth0",
|
||||||
spec := r.(*network.LinkSpec).TypedSpec()
|
"platform/eth1",
|
||||||
|
}, func(r resource.Resource) error {
|
||||||
|
spec := r.(*network.LinkSpec).TypedSpec()
|
||||||
|
|
||||||
suite.Assert().True(spec.Up)
|
suite.Assert().True(spec.Up)
|
||||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TestPlatformMockRoutes() {
|
func (suite *PlatformConfigSuite) TestPlatformMockRoutes() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{
|
suite.runtime.RegisterController(
|
||||||
defaultRoutes: []netaddr.IP{netaddr.MustParseIP("10.0.0.1")},
|
&netctrl.PlatformConfigController{
|
||||||
},
|
V1alpha1Platform: &platformMock{
|
||||||
StatePath: suite.statePath,
|
defaultRoutes: []netaddr.IP{netaddr.MustParseIP("10.0.0.1")},
|
||||||
}))
|
},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.RouteSpecType, []string{
|
func() error {
|
||||||
"platform/inet4/10.0.0.1//1024",
|
return suite.assertResources(
|
||||||
}, func(r resource.Resource) error {
|
network.ConfigNamespaceName, network.RouteSpecType, []string{
|
||||||
spec := r.(*network.RouteSpec).TypedSpec()
|
"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("10.0.0.1", spec.Gateway.String())
|
||||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TestPlatformMockOperators() {
|
func (suite *PlatformConfigSuite) TestPlatformMockOperators() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{
|
suite.runtime.RegisterController(
|
||||||
dhcp4Links: []string{"eth1", "eth2"},
|
&netctrl.PlatformConfigController{
|
||||||
},
|
V1alpha1Platform: &platformMock{
|
||||||
StatePath: suite.statePath,
|
dhcp4Links: []string{"eth1", "eth2"},
|
||||||
}))
|
},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.OperatorSpecType, []string{
|
func() error {
|
||||||
"platform/dhcp4/eth1",
|
return suite.assertResources(
|
||||||
"platform/dhcp4/eth2",
|
network.ConfigNamespaceName, network.OperatorSpecType, []string{
|
||||||
}, func(r resource.Resource) error {
|
"platform/dhcp4/eth1",
|
||||||
spec := r.(*network.OperatorSpec).TypedSpec()
|
"platform/dhcp4/eth2",
|
||||||
|
}, func(r resource.Resource) error {
|
||||||
|
spec := r.(*network.OperatorSpec).TypedSpec()
|
||||||
|
|
||||||
suite.Assert().Equal(network.OperatorDHCP4, spec.Operator)
|
suite.Assert().Equal(network.OperatorDHCP4, spec.Operator)
|
||||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TestPlatformMockResolvers() {
|
func (suite *PlatformConfigSuite) TestPlatformMockResolvers() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{
|
suite.runtime.RegisterController(
|
||||||
resolvers: []netaddr.IP{netaddr.MustParseIP("1.1.1.1")},
|
&netctrl.PlatformConfigController{
|
||||||
},
|
V1alpha1Platform: &platformMock{
|
||||||
StatePath: suite.statePath,
|
resolvers: []netaddr.IP{netaddr.MustParseIP("1.1.1.1")},
|
||||||
}))
|
},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.ResolverSpecType, []string{
|
func() error {
|
||||||
"platform/resolvers",
|
return suite.assertResources(
|
||||||
}, func(r resource.Resource) error {
|
network.ConfigNamespaceName, network.ResolverSpecType, []string{
|
||||||
spec := r.(*network.ResolverSpec).TypedSpec()
|
"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("[1.1.1.1]", fmt.Sprintf("%s", spec.DNSServers))
|
||||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TestPlatformMockTimeServers() {
|
func (suite *PlatformConfigSuite) TestPlatformMockTimeServers() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{
|
suite.runtime.RegisterController(
|
||||||
timeServers: []string{"pool.ntp.org"},
|
&netctrl.PlatformConfigController{
|
||||||
},
|
V1alpha1Platform: &platformMock{
|
||||||
StatePath: suite.statePath,
|
timeServers: []string{"pool.ntp.org"},
|
||||||
}))
|
},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.TimeServerSpecType, []string{
|
func() error {
|
||||||
"platform/timeservers",
|
return suite.assertResources(
|
||||||
}, func(r resource.Resource) error {
|
network.ConfigNamespaceName, network.TimeServerSpecType, []string{
|
||||||
spec := r.(*network.TimeServerSpec).TypedSpec()
|
"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("[pool.ntp.org]", fmt.Sprintf("%s", spec.NTPServers))
|
||||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TestPlatformMockExternalIPs() {
|
func (suite *PlatformConfigSuite) TestPlatformMockExternalIPs() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{externalIPs: []netaddr.IP{netaddr.MustParseIP("10.3.4.5"), netaddr.MustParseIP("2001:470:6d:30e:96f4:4219:5733:b860")}},
|
suite.runtime.RegisterController(
|
||||||
StatePath: suite.statePath,
|
&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.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.NamespaceName, network.AddressStatusType, []string{
|
func() error {
|
||||||
"external/10.3.4.5/32",
|
return suite.assertResources(
|
||||||
"external/2001:470:6d:30e:96f4:4219:5733:b860/128",
|
network.NamespaceName, network.AddressStatusType, []string{
|
||||||
}, func(r resource.Resource) error {
|
"external/10.3.4.5/32",
|
||||||
spec := r.(*network.AddressStatus).TypedSpec()
|
"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("external", spec.LinkName)
|
||||||
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
||||||
|
|
||||||
if r.Metadata().ID() == "external/10.3.4.5/32" {
|
if r.Metadata().ID() == "external/10.3.4.5/32" {
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||||
} else {
|
} else {
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
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
|
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() {
|
func (suite *PlatformConfigSuite) TestStoreConfig() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{
|
suite.runtime.RegisterController(
|
||||||
hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl"),
|
&netctrl.PlatformConfigController{
|
||||||
externalIPs: []netaddr.IP{netaddr.MustParseIP("10.3.4.5"), netaddr.MustParseIP("2001:470:6d:30e:96f4:4219:5733:b860")},
|
V1alpha1Platform: &platformMock{
|
||||||
},
|
hostname: []byte("talos-e2e-897b4e49-gcp-controlplane-jvcnl"),
|
||||||
StatePath: suite.statePath,
|
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.startRuntime()
|
||||||
|
|
||||||
@ -383,75 +493,98 @@ func (suite *PlatformConfigSuite) TestStoreConfig() {
|
|||||||
|
|
||||||
suite.Assert().NoError(suite.state.Create(suite.ctx, stateMount))
|
suite.Assert().NoError(suite.state.Create(suite.ctx, stateMount))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
contents, err := os.ReadFile(filepath.Join(suite.statePath, constants.PlatformNetworkConfigFilename))
|
func() error {
|
||||||
if err != nil {
|
contents, err := os.ReadFile(filepath.Join(suite.statePath, constants.PlatformNetworkConfigFilename))
|
||||||
if os.IsNotExist(err) {
|
if err != nil {
|
||||||
return retry.ExpectedError(err)
|
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() {
|
func (suite *PlatformConfigSuite) TestLoadConfig() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.PlatformConfigController{
|
suite.Require().NoError(
|
||||||
V1alpha1Platform: &platformMock{
|
suite.runtime.RegisterController(
|
||||||
noData: true,
|
&netctrl.PlatformConfigController{
|
||||||
},
|
V1alpha1Platform: &platformMock{
|
||||||
StatePath: suite.statePath,
|
noData: true,
|
||||||
}))
|
},
|
||||||
|
StatePath: suite.statePath,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
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)
|
stateMount := runtimeres.NewMountStatus(v1alpha1.NamespaceName, constants.StatePartitionLabel)
|
||||||
|
|
||||||
suite.Assert().NoError(suite.state.Create(suite.ctx, stateMount))
|
suite.Assert().NoError(suite.state.Create(suite.ctx, stateMount))
|
||||||
|
|
||||||
// controller should pick up cached network configuration
|
// controller should pick up cached network configuration
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.NamespaceName, network.AddressStatusType, []string{
|
func() error {
|
||||||
"external/10.3.4.5/32",
|
return suite.assertResources(
|
||||||
"external/2001:470:6d:30e:96f4:4219:5733:b860/128",
|
network.NamespaceName, network.AddressStatusType, []string{
|
||||||
}, func(r resource.Resource) error {
|
"external/10.3.4.5/32",
|
||||||
spec := r.(*network.AddressStatus).TypedSpec()
|
"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("external", spec.LinkName)
|
||||||
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
suite.Assert().Equal(nethelpers.ScopeGlobal, spec.Scope)
|
||||||
|
|
||||||
if r.Metadata().ID() == "external/10.3.4.5/32" {
|
if r.Metadata().ID() == "external/10.3.4.5/32" {
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
suite.Assert().Equal(nethelpers.FamilyInet4, spec.Family)
|
||||||
} else {
|
} else {
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet6, spec.Family)
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResources(network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
func() error {
|
||||||
"platform/hostname",
|
return suite.assertResources(
|
||||||
}, func(r resource.Resource) error {
|
network.ConfigNamespaceName, network.HostnameSpecType, []string{
|
||||||
spec := r.(*network.HostnameSpec).TypedSpec()
|
"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("talos-e2e-897b4e49-gcp-controlplane-jvcnl", spec.Hostname)
|
||||||
suite.Assert().Equal("", spec.Domainname)
|
suite.Assert().Equal("", spec.Domainname)
|
||||||
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
suite.Assert().Equal(network.ConfigPlatform, spec.ConfigLayer)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlatformConfigSuite) TearDownTest() {
|
func (suite *PlatformConfigSuite) TearDownTest() {
|
||||||
@ -496,7 +629,10 @@ func (mock *platformMock) KernelArgs() procfs.Parameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//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 {
|
if mock.noData {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -520,7 +656,8 @@ func (mock *platformMock) NetworkConfiguration(ctx context.Context, ch chan<- *v
|
|||||||
family = nethelpers.FamilyInet6
|
family = nethelpers.FamilyInet6
|
||||||
}
|
}
|
||||||
|
|
||||||
networkConfig.Addresses = append(networkConfig.Addresses,
|
networkConfig.Addresses = append(
|
||||||
|
networkConfig.Addresses,
|
||||||
network.AddressSpecSpec{
|
network.AddressSpecSpec{
|
||||||
ConfigLayer: network.ConfigPlatform,
|
ConfigLayer: network.ConfigPlatform,
|
||||||
LinkName: "eth0",
|
LinkName: "eth0",
|
||||||
@ -528,7 +665,8 @@ func (mock *platformMock) NetworkConfiguration(ctx context.Context, ch chan<- *v
|
|||||||
Scope: nethelpers.ScopeGlobal,
|
Scope: nethelpers.ScopeGlobal,
|
||||||
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
|
Flags: nethelpers.AddressFlags(nethelpers.AddressPermanent),
|
||||||
Family: family,
|
Family: family,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, gw := range mock.defaultRoutes {
|
for _, gw := range mock.defaultRoutes {
|
||||||
@ -554,34 +692,42 @@ func (mock *platformMock) NetworkConfiguration(ctx context.Context, ch chan<- *v
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, link := range mock.linksUp {
|
for _, link := range mock.linksUp {
|
||||||
networkConfig.Links = append(networkConfig.Links, network.LinkSpecSpec{
|
networkConfig.Links = append(
|
||||||
ConfigLayer: network.ConfigPlatform,
|
networkConfig.Links, network.LinkSpecSpec{
|
||||||
Name: link,
|
ConfigLayer: network.ConfigPlatform,
|
||||||
Up: true,
|
Name: link,
|
||||||
})
|
Up: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(mock.resolvers) > 0 {
|
if len(mock.resolvers) > 0 {
|
||||||
networkConfig.Resolvers = append(networkConfig.Resolvers, network.ResolverSpecSpec{
|
networkConfig.Resolvers = append(
|
||||||
ConfigLayer: network.ConfigPlatform,
|
networkConfig.Resolvers, network.ResolverSpecSpec{
|
||||||
DNSServers: mock.resolvers,
|
ConfigLayer: network.ConfigPlatform,
|
||||||
})
|
DNSServers: mock.resolvers,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(mock.timeServers) > 0 {
|
if len(mock.timeServers) > 0 {
|
||||||
networkConfig.TimeServers = append(networkConfig.TimeServers, network.TimeServerSpecSpec{
|
networkConfig.TimeServers = append(
|
||||||
ConfigLayer: network.ConfigPlatform,
|
networkConfig.TimeServers, network.TimeServerSpecSpec{
|
||||||
NTPServers: mock.timeServers,
|
ConfigLayer: network.ConfigPlatform,
|
||||||
})
|
NTPServers: mock.timeServers,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, link := range mock.dhcp4Links {
|
for _, link := range mock.dhcp4Links {
|
||||||
networkConfig.Operators = append(networkConfig.Operators, network.OperatorSpecSpec{
|
networkConfig.Operators = append(
|
||||||
ConfigLayer: network.ConfigPlatform,
|
networkConfig.Operators, network.OperatorSpecSpec{
|
||||||
LinkName: link,
|
ConfigLayer: network.ConfigPlatform,
|
||||||
Operator: network.OperatorDHCP4,
|
LinkName: link,
|
||||||
DHCP4: network.DHCP4OperatorSpec{},
|
Operator: network.OperatorDHCP4,
|
||||||
})
|
DHCP4: network.DHCP4OperatorSpec{},
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
@ -40,7 +40,7 @@ type ResolverConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,10 @@ func (suite *ResolverConfigSuite) assertResolvers(requiredIDs []string, check fu
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -98,7 +101,10 @@ func (suite *ResolverConfigSuite) assertResolvers(requiredIDs []string, check fu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ResolverConfigSuite) assertNoResolver(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -117,36 +123,60 @@ func (suite *ResolverConfigSuite) TestDefaults() {
|
|||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResolvers([]string{
|
func() error {
|
||||||
"default/resolvers",
|
return suite.assertResolvers(
|
||||||
}, func(r *network.ResolverSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal([]netaddr.IP{netaddr.MustParseIP(constants.DefaultPrimaryResolver), netaddr.MustParseIP(constants.DefaultSecondaryResolver)}, r.TypedSpec().DNSServers)
|
"default/resolvers",
|
||||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
}, 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() {
|
func (suite *ResolverConfigSuite) TestCmdline() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.ResolverConfigController{
|
suite.Require().NoError(
|
||||||
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.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.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResolvers([]string{
|
func() error {
|
||||||
"cmdline/resolvers",
|
return suite.assertResolvers(
|
||||||
}, func(r *network.ResolverSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal([]netaddr.IP{netaddr.MustParseIP("10.0.0.1"), netaddr.MustParseIP("10.0.0.2")}, r.TypedSpec().DNSServers)
|
"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() {
|
func (suite *ResolverConfigSuite) TestMachineConfiguration() {
|
||||||
@ -157,46 +187,63 @@ func (suite *ResolverConfigSuite) TestMachineConfiguration() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NameServers: []string{"2.2.2.2", "3.3.3.3"},
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
|
NameServers: []string{"2.2.2.2", "3.3.3.3"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResolvers([]string{
|
func() error {
|
||||||
"configuration/resolvers",
|
return suite.assertResolvers(
|
||||||
}, func(r *network.ResolverSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal([]netaddr.IP{netaddr.MustParseIP("2.2.2.2"), netaddr.MustParseIP("3.3.3.3")}, r.TypedSpec().DNSServers)
|
"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 {
|
_, err = suite.state.UpdateWithConflicts(
|
||||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineNetwork.NameServers = nil
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoResolver("configuration/resolvers")
|
func() error {
|
||||||
}))
|
return suite.assertNoResolver("configuration/resolvers")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ResolverConfigSuite) TearDownTest() {
|
func (suite *ResolverConfigSuite) TearDownTest() {
|
||||||
@ -207,10 +254,14 @@ func (suite *ResolverConfigSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ type ResolverMergeSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,10 @@ func (suite *ResolverMergeSuite) assertResolvers(requiredIDs []string, check fun
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -101,7 +104,10 @@ func (suite *ResolverMergeSuite) assertResolvers(requiredIDs []string, check fun
|
|||||||
func (suite *ResolverMergeSuite) TestMerge() {
|
func (suite *ResolverMergeSuite) TestMerge() {
|
||||||
def := network.NewResolverSpec(network.ConfigNamespaceName, "default/resolvers")
|
def := network.NewResolverSpec(network.ConfigNamespaceName, "default/resolvers")
|
||||||
*def.TypedSpec() = network.ResolverSpecSpec{
|
*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,
|
ConfigLayer: network.ConfigDefault,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,31 +133,44 @@ func (suite *ResolverMergeSuite) TestMerge() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResolvers([]string{
|
func() error {
|
||||||
"resolvers",
|
return suite.assertResolvers(
|
||||||
}, func(r *network.ResolverSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
"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.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertResolvers([]string{
|
func() error {
|
||||||
"resolvers",
|
return suite.assertResolvers(
|
||||||
}, func(r *network.ResolverSpec) error {
|
[]string{
|
||||||
if !reflect.DeepEqual(r.TypedSpec().DNSServers, []netaddr.IP{netaddr.MustParseIP("1.1.2.0"), netaddr.MustParseIP("1.1.2.1")}) {
|
"resolvers",
|
||||||
return retry.ExpectedErrorf("unexpected servers %q", r.TypedSpec().DNSServers)
|
}, 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() {
|
func (suite *ResolverMergeSuite) TearDownTest() {
|
||||||
@ -162,7 +181,12 @@ func (suite *ResolverMergeSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestResolverMergeSuite(t *testing.T) {
|
||||||
|
@ -36,7 +36,7 @@ type ResolverSpecSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,10 @@ func (suite *ResolverSpecSuite) startRuntime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ResolverSpecSuite) assertStatus(id string, servers ...netaddr.IP) error {
|
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 err != nil {
|
||||||
if state.IsNotFoundError(err) {
|
if state.IsNotFoundError(err) {
|
||||||
return retry.ExpectedError(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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertStatus("resolvers", netaddr.MustParseIP(constants.DefaultPrimaryResolver))
|
func() error {
|
||||||
}))
|
return suite.assertStatus("resolvers", netaddr.MustParseIP(constants.DefaultPrimaryResolver))
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ResolverSpecSuite) TearDownTest() {
|
func (suite *ResolverSpecSuite) TearDownTest() {
|
||||||
@ -109,7 +115,12 @@ func (suite *ResolverSpecSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestResolverSpecSuite(t *testing.T) {
|
||||||
|
@ -40,7 +40,7 @@ type RouteConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,10 @@ func (suite *RouteConfigSuite) assertRoutes(requiredIDs []string, check func(*ne
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -98,25 +101,34 @@ func (suite *RouteConfigSuite) assertRoutes(requiredIDs []string, check func(*ne
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *RouteConfigSuite) TestCmdline() {
|
func (suite *RouteConfigSuite) TestCmdline() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.RouteConfigController{
|
suite.Require().NoError(
|
||||||
Cmdline: procfs.NewCmdline("ip=172.20.0.2::172.20.0.1:255.255.255.0::eth1:::::"),
|
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.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoutes([]string{
|
func() error {
|
||||||
"cmdline/inet4/172.20.0.1//1024",
|
return suite.assertRoutes(
|
||||||
}, func(r *network.RouteSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal("eth1", r.TypedSpec().OutLinkName)
|
"cmdline/inet4/172.20.0.1//1024",
|
||||||
suite.Assert().Equal(network.ConfigCmdline, r.TypedSpec().ConfigLayer)
|
}, func(r *network.RouteSpec) error {
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
suite.Assert().Equal("eth1", r.TypedSpec().OutLinkName)
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
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() {
|
func (suite *RouteConfigSuite) TestMachineConfiguration() {
|
||||||
@ -127,127 +139,134 @@ func (suite *RouteConfigSuite) TestMachineConfiguration() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
NetworkInterfaces: []*v1alpha1.Device{
|
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||||
{
|
NetworkInterfaces: []*v1alpha1.Device{
|
||||||
DeviceInterface: "eth3",
|
{
|
||||||
DeviceAddresses: []string{"192.168.0.24/28"},
|
DeviceInterface: "eth3",
|
||||||
DeviceRoutes: []*v1alpha1.Route{
|
DeviceAddresses: []string{"192.168.0.24/28"},
|
||||||
{
|
DeviceRoutes: []*v1alpha1.Route{
|
||||||
RouteNetwork: "192.168.0.0/18",
|
{
|
||||||
RouteGateway: "192.168.0.25",
|
RouteNetwork: "192.168.0.0/18",
|
||||||
RouteMetric: 25,
|
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",
|
|
||||||
},
|
},
|
||||||
VlanRoutes: []*v1alpha1.Route{
|
{
|
||||||
{
|
RouteNetwork: "169.254.254.254/32",
|
||||||
RouteNetwork: "10.0.3.0/24",
|
},
|
||||||
RouteGateway: "10.0.3.1",
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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",
|
||||||
DeviceInterface: "eth1",
|
DeviceRoutes: []*v1alpha1.Route{
|
||||||
DeviceRoutes: []*v1alpha1.Route{
|
{
|
||||||
{
|
RouteNetwork: "192.244.0.0/24",
|
||||||
RouteNetwork: "192.244.0.0/24",
|
RouteGateway: "192.244.0.1",
|
||||||
RouteGateway: "192.244.0.1",
|
RouteSource: "192.244.0.10",
|
||||||
RouteSource: "192.244.0.10",
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoutes([]string{
|
func() error {
|
||||||
"configuration/inet6/2001:470:6d:30e:8ed2:b60c:9d2f:803b//1024",
|
return suite.assertRoutes(
|
||||||
"configuration/inet4/10.0.3.1/10.0.3.0/24/1024",
|
[]string{
|
||||||
"configuration/inet4/192.168.0.25/192.168.0.0/18/25",
|
"configuration/inet6/2001:470:6d:30e:8ed2:b60c:9d2f:803b//1024",
|
||||||
"configuration/inet4/192.244.0.1/192.244.0.0/24/1024",
|
"configuration/inet4/10.0.3.1/10.0.3.0/24/1024",
|
||||||
"configuration/inet4//169.254.254.254/32/1024",
|
"configuration/inet4/192.168.0.25/192.168.0.0/18/25",
|
||||||
}, func(r *network.RouteSpec) error {
|
"configuration/inet4/192.244.0.1/192.244.0.0/24/1024",
|
||||||
switch r.Metadata().ID() {
|
"configuration/inet4//169.254.254.254/32/1024",
|
||||||
case "configuration/inet6/2001:470:6d:30e:8ed2:b60c:9d2f:803b//1024":
|
}, func(r *network.RouteSpec) error {
|
||||||
suite.Assert().Equal("eth2", r.TypedSpec().OutLinkName)
|
switch r.Metadata().ID() {
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet6, r.TypedSpec().Family)
|
case "configuration/inet6/2001:470:6d:30e:8ed2:b60c:9d2f:803b//1024":
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
suite.Assert().Equal("eth2", r.TypedSpec().OutLinkName)
|
||||||
case "configuration/inet4/10.0.3.1/10.0.3.0/24/1024":
|
suite.Assert().Equal(nethelpers.FamilyInet6, r.TypedSpec().Family)
|
||||||
suite.Assert().Equal("eth0.24", r.TypedSpec().OutLinkName)
|
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
case "configuration/inet4/10.0.3.1/10.0.3.0/24/1024":
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
suite.Assert().Equal("eth0.24", r.TypedSpec().OutLinkName)
|
||||||
case "configuration/inet4/192.168.0.25/192.168.0.0/18/25":
|
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||||
suite.Assert().Equal("eth3", r.TypedSpec().OutLinkName)
|
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
case "configuration/inet4/192.168.0.25/192.168.0.0/18/25":
|
||||||
suite.Assert().EqualValues(25, r.TypedSpec().Priority)
|
suite.Assert().Equal("eth3", r.TypedSpec().OutLinkName)
|
||||||
case "configuration/inet4/192.244.0.1/192.244.0.0/24/1024":
|
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||||
suite.Assert().Equal("eth1", r.TypedSpec().OutLinkName)
|
suite.Assert().EqualValues(25, r.TypedSpec().Priority)
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
case "configuration/inet4/192.244.0.1/192.244.0.0/24/1024":
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
suite.Assert().Equal("eth1", r.TypedSpec().OutLinkName)
|
||||||
suite.Assert().EqualValues(netaddr.MustParseIP("192.244.0.10"), r.TypedSpec().Source)
|
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||||
case "configuration/inet4//169.254.254.254/32/1024":
|
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
||||||
suite.Assert().Equal("eth3", r.TypedSpec().OutLinkName)
|
suite.Assert().EqualValues(netaddr.MustParseIP("192.244.0.10"), r.TypedSpec().Source)
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
case "configuration/inet4//169.254.254.254/32/1024":
|
||||||
suite.Assert().EqualValues(netctrl.DefaultRouteMetric, r.TypedSpec().Priority)
|
suite.Assert().Equal("eth3", r.TypedSpec().OutLinkName)
|
||||||
suite.Assert().Equal(nethelpers.ScopeLink, r.TypedSpec().Scope)
|
suite.Assert().Equal(nethelpers.FamilyInet4, r.TypedSpec().Family)
|
||||||
suite.Assert().Equal("169.254.254.254/32", r.TypedSpec().Destination.String())
|
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() {
|
func (suite *RouteConfigSuite) TearDownTest() {
|
||||||
@ -258,10 +277,14 @@ func (suite *RouteConfigSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ type RouteMergeSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +73,10 @@ func (suite *RouteMergeSuite) assertRoutes(requiredIDs []string, check func(*net
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -99,7 +102,10 @@ func (suite *RouteMergeSuite) assertRoutes(requiredIDs []string, check func(*net
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *RouteMergeSuite) assertNoRoute(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -155,55 +161,68 @@ func (suite *RouteMergeSuite) TestMerge() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoutes([]string{
|
func() error {
|
||||||
"inet4/10.5.0.3//50",
|
return suite.assertRoutes(
|
||||||
"inet4/10.0.0.34/10.0.0.35/32/1024",
|
[]string{
|
||||||
}, func(r *network.RouteSpec) error {
|
"inet4/10.5.0.3//50",
|
||||||
suite.Assert().Equal(resource.PhaseRunning, r.Metadata().Phase())
|
"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() {
|
switch r.Metadata().ID() {
|
||||||
case "inet4/10.5.0.3//50":
|
case "inet4/10.5.0.3//50":
|
||||||
suite.Assert().Equal(*dhcp.TypedSpec(), *r.TypedSpec())
|
suite.Assert().Equal(*dhcp.TypedSpec(), *r.TypedSpec())
|
||||||
case "inet4/10.0.0.34/10.0.0.35/32/1024":
|
case "inet4/10.0.0.34/10.0.0.35/32/1024":
|
||||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, dhcp.Metadata()))
|
suite.Require().NoError(suite.state.Destroy(suite.ctx, dhcp.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoutes([]string{
|
func() error {
|
||||||
"inet4/10.5.0.3//50",
|
return suite.assertRoutes(
|
||||||
"inet4/10.0.0.34/10.0.0.35/32/1024",
|
[]string{
|
||||||
}, func(r *network.RouteSpec) error {
|
"inet4/10.5.0.3//50",
|
||||||
suite.Assert().Equal(resource.PhaseRunning, r.Metadata().Phase())
|
"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() {
|
switch r.Metadata().ID() {
|
||||||
case "inet4/10.5.0.3//50":
|
case "inet4/10.5.0.3//50":
|
||||||
if *cmdline.TypedSpec() != *r.TypedSpec() {
|
if *cmdline.TypedSpec() != *r.TypedSpec() {
|
||||||
// using retry here, as it might not be reconciled immediately
|
// using retry here, as it might not be reconciled immediately
|
||||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||||
}
|
}
|
||||||
case "inet4/10.0.0.34/10.0.0.35/32/1024":
|
case "inet4/10.0.0.34/10.0.0.35/32/1024":
|
||||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
suite.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoRoute("inet4/10.0.0.34/10.0.0.35/32/1024")
|
func() error {
|
||||||
}))
|
return suite.assertNoRoute("inet4/10.0.0.34/10.0.0.35/32/1024")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
@ -257,50 +276,75 @@ func (suite *RouteMergeSuite) TestMergeFlapping() {
|
|||||||
|
|
||||||
eg.Go(flipflop(0))
|
eg.Go(flipflop(0))
|
||||||
eg.Go(flipflop(1))
|
eg.Go(flipflop(1))
|
||||||
eg.Go(func() error {
|
eg.Go(
|
||||||
// add/remove finalizer to the merged resource
|
func() error {
|
||||||
for i := 0; i < 1000; i++ {
|
// add/remove finalizer to the merged resource
|
||||||
if err := suite.state.AddFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.RouteSpecType, "inet4/10.5.0.3//50", resource.VersionUndefined), "foo"); err != nil {
|
for i := 0; i < 1000; i++ {
|
||||||
if !state.IsNotFoundError(err) {
|
if err := suite.state.AddFinalizer(
|
||||||
return err
|
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
|
time.Sleep(10 * time.Millisecond)
|
||||||
} else {
|
|
||||||
suite.T().Log("finalizer added")
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(10 * time.Millisecond)
|
if err := suite.state.RemoveFinalizer(
|
||||||
|
suite.ctx,
|
||||||
if err := suite.state.RemoveFinalizer(suite.ctx, resource.NewMetadata(network.NamespaceName, network.RouteSpecType, "inet4/10.5.0.3//50", resource.VersionUndefined), "foo"); err != nil {
|
resource.NewMetadata(
|
||||||
if err != nil && !state.IsNotFoundError(err) {
|
network.NamespaceName,
|
||||||
return err
|
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.Require().NoError(eg.Wait())
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(15*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoutes([]string{
|
func() error {
|
||||||
"inet4/10.5.0.3//50",
|
return suite.assertRoutes(
|
||||||
}, func(r *network.RouteSpec) error {
|
[]string{
|
||||||
if r.Metadata().Phase() != resource.PhaseRunning {
|
"inet4/10.5.0.3//50",
|
||||||
return retry.ExpectedErrorf("resource phase is %s", r.Metadata().Phase())
|
}, 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() {
|
if *dhcp.TypedSpec() != *r.TypedSpec() {
|
||||||
// using retry here, as it might not be reconciled immediately
|
// using retry here, as it might not be reconciled immediately
|
||||||
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
return retry.ExpectedError(fmt.Errorf("not equal yet"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *RouteMergeSuite) TearDownTest() {
|
func (suite *RouteMergeSuite) TearDownTest() {
|
||||||
@ -311,7 +355,12 @@ func (suite *RouteMergeSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestRouteMergeSuite(t *testing.T) {
|
||||||
|
@ -149,7 +149,8 @@ func findRoutes(routes []rtnetlink.RouteMessage, family nethelpers.Family, desti
|
|||||||
|
|
||||||
//nolint:gocyclo,cyclop
|
//nolint:gocyclo,cyclop
|
||||||
func (ctrl *RouteSpecController) syncRoute(ctx context.Context, r controller.Runtime, logger *zap.Logger, conn *rtnetlink.Conn,
|
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)
|
linkIndex := resolveLinkName(links, route.TypedSpec().OutLinkName)
|
||||||
|
|
||||||
destinationStr := route.TypedSpec().Destination.String()
|
destinationStr := route.TypedSpec().Destination.String()
|
||||||
|
@ -40,7 +40,7 @@ type RouteSpecSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
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)
|
conn, err := rtnetlink.Dial(nil)
|
||||||
suite.Require().NoError(err)
|
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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoute(netaddr.MustParseIPPrefix("127.0.11.0/24"), netaddr.MustParseIP("127.0.11.1"), func(route rtnetlink.RouteMessage) error {
|
func() error {
|
||||||
suite.Assert().EqualValues(0, route.Attributes.Priority)
|
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
|
// teardown the route
|
||||||
for {
|
for {
|
||||||
@ -172,7 +183,12 @@ func (suite *RouteSpecSuite) TestLoopback() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// torn down address should be removed immediately
|
// 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()))
|
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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoute(netaddr.IPPrefix{}, netaddr.MustParseIP("127.0.11.2"), func(route rtnetlink.RouteMessage) error {
|
func() error {
|
||||||
suite.Assert().Nil(route.Attributes.Dst)
|
return suite.assertRoute(
|
||||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
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
|
// update the route metric
|
||||||
_, err := suite.state.UpdateWithConflicts(suite.ctx, def.Metadata(), func(r resource.Resource) error {
|
_, err := suite.state.UpdateWithConflicts(
|
||||||
defR := r.(*network.RouteSpec) //nolint:forcetypeassert,errcheck
|
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(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoute(netaddr.IPPrefix{}, netaddr.MustParseIP("127.0.11.2"), func(route rtnetlink.RouteMessage) error {
|
func() error {
|
||||||
suite.Assert().Nil(route.Attributes.Dst)
|
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 {
|
if route.Attributes.Priority != 1048577 {
|
||||||
return fmt.Errorf("route metric wasn't updated: %d", route.Attributes.Priority)
|
return fmt.Errorf("route metric wasn't updated: %d", route.Attributes.Priority)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// teardown the route
|
// teardown the route
|
||||||
for {
|
for {
|
||||||
@ -256,18 +284,22 @@ func (suite *RouteSpecSuite) TestDefaultAndInterfaceRoutes() {
|
|||||||
|
|
||||||
defer conn.Close() //nolint:errcheck
|
defer conn.Close() //nolint:errcheck
|
||||||
|
|
||||||
suite.Require().NoError(conn.Link.New(&rtnetlink.LinkMessage{
|
suite.Require().NoError(
|
||||||
Type: unix.ARPHRD_ETHER,
|
conn.Link.New(
|
||||||
Flags: unix.IFF_UP,
|
&rtnetlink.LinkMessage{
|
||||||
Change: unix.IFF_UP,
|
Type: unix.ARPHRD_ETHER,
|
||||||
Attributes: &rtnetlink.LinkAttributes{
|
Flags: unix.IFF_UP,
|
||||||
Name: dummyInterface,
|
Change: unix.IFF_UP,
|
||||||
MTU: 1400,
|
Attributes: &rtnetlink.LinkAttributes{
|
||||||
Info: &rtnetlink.LinkInfo{
|
Name: dummyInterface,
|
||||||
Kind: "dummy",
|
MTU: 1400,
|
||||||
|
Info: &rtnetlink.LinkInfo{
|
||||||
|
Kind: "dummy",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
}))
|
)
|
||||||
|
|
||||||
iface, err := net.InterfaceByName(dummyInterface)
|
iface, err := net.InterfaceByName(dummyInterface)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -276,16 +308,20 @@ func (suite *RouteSpecSuite) TestDefaultAndInterfaceRoutes() {
|
|||||||
|
|
||||||
localIP := net.ParseIP("10.28.0.27").To4()
|
localIP := net.ParseIP("10.28.0.27").To4()
|
||||||
|
|
||||||
suite.Require().NoError(conn.Address.New(&rtnetlink.AddressMessage{
|
suite.Require().NoError(
|
||||||
Family: unix.AF_INET,
|
conn.Address.New(
|
||||||
PrefixLength: 32,
|
&rtnetlink.AddressMessage{
|
||||||
Scope: unix.RT_SCOPE_UNIVERSE,
|
Family: unix.AF_INET,
|
||||||
Index: uint32(iface.Index),
|
PrefixLength: 32,
|
||||||
Attributes: &rtnetlink.AddressAttributes{
|
Scope: unix.RT_SCOPE_UNIVERSE,
|
||||||
Address: localIP,
|
Index: uint32(iface.Index),
|
||||||
Local: localIP,
|
Attributes: &rtnetlink.AddressAttributes{
|
||||||
},
|
Address: localIP,
|
||||||
}))
|
Local: localIP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
def := network.NewRouteSpec(network.NamespaceName, "default")
|
def := network.NewRouteSpec(network.NamespaceName, "default")
|
||||||
*def.TypedSpec() = network.RouteSpecSpec{
|
*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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
if err := suite.assertRoute(netaddr.IPPrefix{}, netaddr.MustParseIP("10.28.0.1"), func(route rtnetlink.RouteMessage) error {
|
func() error {
|
||||||
suite.Assert().Nil(route.Attributes.Dst)
|
if err := suite.assertRoute(
|
||||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
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
|
return nil
|
||||||
}); err != nil {
|
},
|
||||||
return err
|
); err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return suite.assertRoute(netaddr.MustParseIPPrefix("10.28.0.1/32"), netaddr.IP{}, func(route rtnetlink.RouteMessage) error {
|
return suite.assertRoute(
|
||||||
suite.Assert().Nil(route.Attributes.Gateway)
|
netaddr.MustParseIPPrefix("10.28.0.1/32"), netaddr.IP{}, func(route rtnetlink.RouteMessage) error {
|
||||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
suite.Assert().Nil(route.Attributes.Gateway)
|
||||||
|
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
}))
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
// teardown the routes
|
// teardown the routes
|
||||||
for {
|
for {
|
||||||
@ -378,18 +421,22 @@ func (suite *RouteSpecSuite) TestLinkLocalRoute() {
|
|||||||
|
|
||||||
defer conn.Close() //nolint:errcheck
|
defer conn.Close() //nolint:errcheck
|
||||||
|
|
||||||
suite.Require().NoError(conn.Link.New(&rtnetlink.LinkMessage{
|
suite.Require().NoError(
|
||||||
Type: unix.ARPHRD_ETHER,
|
conn.Link.New(
|
||||||
Flags: unix.IFF_UP,
|
&rtnetlink.LinkMessage{
|
||||||
Change: unix.IFF_UP,
|
Type: unix.ARPHRD_ETHER,
|
||||||
Attributes: &rtnetlink.LinkAttributes{
|
Flags: unix.IFF_UP,
|
||||||
Name: dummyInterface,
|
Change: unix.IFF_UP,
|
||||||
MTU: 1500,
|
Attributes: &rtnetlink.LinkAttributes{
|
||||||
Info: &rtnetlink.LinkInfo{
|
Name: dummyInterface,
|
||||||
Kind: "dummy",
|
MTU: 1500,
|
||||||
|
Info: &rtnetlink.LinkInfo{
|
||||||
|
Kind: "dummy",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
}))
|
)
|
||||||
|
|
||||||
iface, err := net.InterfaceByName(dummyInterface)
|
iface, err := net.InterfaceByName(dummyInterface)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -398,16 +445,20 @@ func (suite *RouteSpecSuite) TestLinkLocalRoute() {
|
|||||||
|
|
||||||
localIP := net.ParseIP("10.28.0.27").To4()
|
localIP := net.ParseIP("10.28.0.27").To4()
|
||||||
|
|
||||||
suite.Require().NoError(conn.Address.New(&rtnetlink.AddressMessage{
|
suite.Require().NoError(
|
||||||
Family: unix.AF_INET,
|
conn.Address.New(
|
||||||
PrefixLength: 24,
|
&rtnetlink.AddressMessage{
|
||||||
Scope: unix.RT_SCOPE_UNIVERSE,
|
Family: unix.AF_INET,
|
||||||
Index: uint32(iface.Index),
|
PrefixLength: 24,
|
||||||
Attributes: &rtnetlink.AddressAttributes{
|
Scope: unix.RT_SCOPE_UNIVERSE,
|
||||||
Address: localIP,
|
Index: uint32(iface.Index),
|
||||||
Local: localIP,
|
Attributes: &rtnetlink.AddressAttributes{
|
||||||
},
|
Address: localIP,
|
||||||
}))
|
Local: localIP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
ll := network.NewRouteSpec(network.NamespaceName, "ll")
|
ll := network.NewRouteSpec(network.NamespaceName, "ll")
|
||||||
*ll.TypedSpec() = network.RouteSpecSpec{
|
*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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoute(netaddr.MustParseIPPrefix("169.254.169.254/32"), netaddr.MustParseIP("10.28.0.1"), func(route rtnetlink.RouteMessage) error {
|
func() error {
|
||||||
suite.Assert().EqualValues(1048576, route.Attributes.Priority)
|
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
|
// teardown the routes
|
||||||
for {
|
for {
|
||||||
@ -450,7 +508,12 @@ func (suite *RouteSpecSuite) TestLinkLocalRoute() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// torn down route should be removed immediately
|
// 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()))
|
suite.Require().NoError(suite.state.Destroy(suite.ctx, ll.Metadata()))
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ type RouteStatusSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +71,10 @@ func (suite *RouteStatusSuite) assertRoutes(requiredIDs []string, check func(*ne
|
|||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -97,19 +100,24 @@ func (suite *RouteStatusSuite) assertRoutes(requiredIDs []string, check func(*ne
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *RouteStatusSuite) TestRoutes() {
|
func (suite *RouteStatusSuite) TestRoutes() {
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertRoutes([]string{"local/inet4//127.0.0.0/8/0"}, func(r *network.RouteStatus) error {
|
func() error {
|
||||||
suite.Assert().True(r.TypedSpec().Source.IsLoopback())
|
return suite.assertRoutes(
|
||||||
suite.Assert().Equal("lo", r.TypedSpec().OutLinkName)
|
[]string{"local/inet4//127.0.0.0/8/0"}, func(r *network.RouteStatus) error {
|
||||||
suite.Assert().Equal(nethelpers.TableLocal, r.TypedSpec().Table)
|
suite.Assert().True(r.TypedSpec().Source.IsLoopback())
|
||||||
suite.Assert().Equal(nethelpers.ScopeHost, r.TypedSpec().Scope)
|
suite.Assert().Equal("lo", r.TypedSpec().OutLinkName)
|
||||||
suite.Assert().Equal(nethelpers.TypeLocal, r.TypedSpec().Type)
|
suite.Assert().Equal(nethelpers.TableLocal, r.TypedSpec().Table)
|
||||||
suite.Assert().Equal(nethelpers.ProtocolKernel, r.TypedSpec().Protocol)
|
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() {
|
func (suite *RouteStatusSuite) TearDownTest() {
|
||||||
|
@ -35,7 +35,7 @@ type StatusSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,10 @@ func (suite *StatusSuite) startRuntime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StatusSuite) assertStatus(expected network.StatusSpec) error {
|
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 err != nil {
|
||||||
if !state.IsNotFoundError(err) {
|
if !state.IsNotFoundError(err) {
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -82,10 +85,13 @@ func (suite *StatusSuite) assertStatus(expected network.StatusSpec) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StatusSuite) TestNone() {
|
func (suite *StatusSuite) TestNone() {
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertStatus(network.StatusSpec{})
|
func() error {
|
||||||
}))
|
return suite.assertStatus(network.StatusSpec{})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StatusSuite) TestAddresses() {
|
func (suite *StatusSuite) TestAddresses() {
|
||||||
@ -94,10 +100,13 @@ func (suite *StatusSuite) TestAddresses() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, nodeAddress))
|
suite.Require().NoError(suite.state.Create(suite.ctx, nodeAddress))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertStatus(network.StatusSpec{AddressReady: true})
|
func() error {
|
||||||
}))
|
return suite.assertStatus(network.StatusSpec{AddressReady: true})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StatusSuite) TestRoutes() {
|
func (suite *StatusSuite) TestRoutes() {
|
||||||
@ -106,10 +115,13 @@ func (suite *StatusSuite) TestRoutes() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, route))
|
suite.Require().NoError(suite.state.Create(suite.ctx, route))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertStatus(network.StatusSpec{ConnectivityReady: true})
|
func() error {
|
||||||
}))
|
return suite.assertStatus(network.StatusSpec{ConnectivityReady: true})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StatusSuite) TestHostname() {
|
func (suite *StatusSuite) TestHostname() {
|
||||||
@ -118,10 +130,13 @@ func (suite *StatusSuite) TestHostname() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostname))
|
suite.Require().NoError(suite.state.Create(suite.ctx, hostname))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertStatus(network.StatusSpec{HostnameReady: true})
|
func() error {
|
||||||
}))
|
return suite.assertStatus(network.StatusSpec{HostnameReady: true})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StatusSuite) TestEtcFiles() {
|
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, hosts))
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, resolv))
|
suite.Require().NoError(suite.state.Create(suite.ctx, resolv))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertStatus(network.StatusSpec{EtcFilesReady: true})
|
func() error {
|
||||||
}))
|
return suite.assertStatus(network.StatusSpec{EtcFilesReady: true})
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StatusSuite) TearDownTest() {
|
func (suite *StatusSuite) TearDownTest() {
|
||||||
@ -145,9 +163,24 @@ func (suite *StatusSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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.Assert().NoError(suite.state.Create(context.Background(), network.NewResolverStatus(network.NamespaceName, "bar")))
|
suite.state.Create(
|
||||||
suite.Assert().NoError(suite.state.Create(context.Background(), network.NewHostnameStatus(network.NamespaceName, "bar")))
|
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")))
|
suite.Assert().NoError(suite.state.Create(context.Background(), files.NewEtcFileStatus(files.NamespaceName, "bar")))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ type TimeServerConfigSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
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))
|
missingIDs := make(map[string]struct{}, len(requiredIDs))
|
||||||
|
|
||||||
for _, id := range requiredIDs {
|
for _, id := range requiredIDs {
|
||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -97,7 +103,10 @@ func (suite *TimeServerConfigSuite) assertTimeServers(requiredIDs []string, chec
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *TimeServerConfigSuite) assertNoTimeServer(id string) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -116,36 +125,50 @@ func (suite *TimeServerConfigSuite) TestDefaults() {
|
|||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeServers([]string{
|
func() error {
|
||||||
"default/timeservers",
|
return suite.assertTimeServers(
|
||||||
}, func(r *network.TimeServerSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal([]string{constants.DefaultNTPServer}, r.TypedSpec().NTPServers)
|
"default/timeservers",
|
||||||
suite.Assert().Equal(network.ConfigDefault, r.TypedSpec().ConfigLayer)
|
}, 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() {
|
func (suite *TimeServerConfigSuite) TestCmdline() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&netctrl.TimeServerConfigController{
|
suite.Require().NoError(
|
||||||
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.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.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeServers([]string{
|
func() error {
|
||||||
"cmdline/timeservers",
|
return suite.assertTimeServers(
|
||||||
}, func(r *network.TimeServerSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal([]string{"10.0.0.1"}, r.TypedSpec().NTPServers)
|
"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() {
|
func (suite *TimeServerConfigSuite) TestMachineConfiguration() {
|
||||||
@ -156,46 +179,58 @@ func (suite *TimeServerConfigSuite) TestMachineConfiguration() {
|
|||||||
u, err := url.Parse("https://foo:6443")
|
u, err := url.Parse("https://foo:6443")
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
ConfigVersion: "v1alpha1",
|
||||||
MachineTime: &v1alpha1.TimeConfig{
|
MachineConfig: &v1alpha1.MachineConfig{
|
||||||
TimeServers: []string{"za.pool.ntp.org", "pool.ntp.org"},
|
MachineTime: &v1alpha1.TimeConfig{
|
||||||
|
TimeServers: []string{"za.pool.ntp.org", "pool.ntp.org"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
Endpoint: &v1alpha1.Endpoint{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
URL: u,
|
||||||
URL: u,
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeServers([]string{
|
func() error {
|
||||||
"configuration/timeservers",
|
return suite.assertTimeServers(
|
||||||
}, func(r *network.TimeServerSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal([]string{"za.pool.ntp.org", "pool.ntp.org"}, r.TypedSpec().NTPServers)
|
"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 {
|
_, err = suite.state.UpdateWithConflicts(
|
||||||
r.(*config.MachineConfig).Config().(*v1alpha1.Config).MachineConfig.MachineTime = nil
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertNoTimeServer("configuration/timeservers")
|
func() error {
|
||||||
}))
|
return suite.assertNoTimeServer("configuration/timeservers")
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *TimeServerConfigSuite) TearDownTest() {
|
func (suite *TimeServerConfigSuite) TearDownTest() {
|
||||||
@ -206,10 +241,14 @@ func (suite *TimeServerConfigSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ type TimeServerMergeSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
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))
|
missingIDs := make(map[string]struct{}, len(requiredIDs))
|
||||||
|
|
||||||
for _, id := range requiredIDs {
|
for _, id := range requiredIDs {
|
||||||
missingIDs[id] = struct{}{}
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -126,31 +132,41 @@ func (suite *TimeServerMergeSuite) TestMerge() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, res), "%v", res.Spec())
|
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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeServers([]string{
|
func() error {
|
||||||
"timeservers",
|
return suite.assertTimeServers(
|
||||||
}, func(r *network.TimeServerSpec) error {
|
[]string{
|
||||||
suite.Assert().Equal(*static.TypedSpec(), *r.TypedSpec())
|
"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.Require().NoError(suite.state.Destroy(suite.ctx, static.Metadata()))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeServers([]string{
|
func() error {
|
||||||
"timeservers",
|
return suite.assertTimeServers(
|
||||||
}, func(r *network.TimeServerSpec) error {
|
[]string{
|
||||||
if !reflect.DeepEqual(r.TypedSpec().NTPServers, []string{"ntp.eth0", "ntp.eth1"}) {
|
"timeservers",
|
||||||
return retry.ExpectedErrorf("unexpected servers %q", r.TypedSpec().NTPServers)
|
}, 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() {
|
func (suite *TimeServerMergeSuite) TearDownTest() {
|
||||||
@ -161,7 +177,12 @@ func (suite *TimeServerMergeSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestTimeServerMergeSuite(t *testing.T) {
|
||||||
|
@ -35,7 +35,7 @@ type TimeServerSpecSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,10 @@ func (suite *TimeServerSpecSuite) startRuntime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *TimeServerSpecSuite) assertStatus(id string, servers ...string) error {
|
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 err != nil {
|
||||||
if state.IsNotFoundError(err) {
|
if state.IsNotFoundError(err) {
|
||||||
return retry.ExpectedError(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.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(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(3*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertStatus("timeservers", constants.DefaultNTPServer)
|
func() error {
|
||||||
}))
|
return suite.assertStatus("timeservers", constants.DefaultNTPServer)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *TimeServerSpecSuite) TearDownTest() {
|
func (suite *TimeServerSpecSuite) TearDownTest() {
|
||||||
@ -108,7 +114,12 @@ func (suite *TimeServerSpecSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// 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) {
|
func TestTimeServerSpecSuite(t *testing.T) {
|
||||||
|
@ -33,6 +33,7 @@ type PerfSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
|
//nolint:containedctx
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
@ -65,36 +66,54 @@ func (suite *PerfSuite) TestReconcile() {
|
|||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
cpu, err := suite.state.Get(suite.ctx, resource.NewMetadata(perfresource.NamespaceName, perfresource.CPUType, perfresource.CPUID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
cpu, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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))
|
return err
|
||||||
if err != nil {
|
|
||||||
if state.IsNotFoundError(err) {
|
|
||||||
return retry.ExpectedError(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
|
if len(cpuSpec.CPU) == 0 || memSpec.MemTotal == 0 {
|
||||||
memSpec := mem.Spec().(*perfresource.MemorySpec) //nolint:errcheck,forcetypeassert
|
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 nil
|
||||||
return retry.ExpectedError(fmt.Errorf("cpu spec does not contain any CPU or Total memory is zero"))
|
},
|
||||||
}
|
),
|
||||||
|
)
|
||||||
return nil
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PerfSuite) TearDownTest() {
|
func (suite *PerfSuite) TearDownTest() {
|
||||||
|
@ -38,7 +38,7 @@ type RuntimeSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,10 +92,14 @@ func (suite *RuntimeSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ type EventsSinkSuite struct {
|
|||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
eg errgroup.Group
|
eg errgroup.Group
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,11 +84,15 @@ func (suite *EventsSinkSuite) SetupTest() {
|
|||||||
suite.cmdline = procfs.NewCmdline(fmt.Sprintf("%s=%s", constants.KernelParamEventsSink, "localhost"))
|
suite.cmdline = procfs.NewCmdline(fmt.Sprintf("%s=%s", constants.KernelParamEventsSink, "localhost"))
|
||||||
suite.drainer = talosruntime.NewDrainer()
|
suite.drainer = talosruntime.NewDrainer()
|
||||||
|
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&controllerruntime.EventsSinkController{
|
suite.Require().NoError(
|
||||||
V1Alpha1Events: suite.events,
|
suite.runtime.RegisterController(
|
||||||
Cmdline: suite.cmdline,
|
&controllerruntime.EventsSinkController{
|
||||||
Drainer: suite.drainer,
|
V1Alpha1Events: suite.events,
|
||||||
}))
|
Cmdline: suite.cmdline,
|
||||||
|
Drainer: suite.drainer,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
}
|
}
|
||||||
@ -121,46 +125,56 @@ func (suite *EventsSinkSuite) startServer(ctx context.Context) {
|
|||||||
suite.server = grpc.NewServer()
|
suite.server = grpc.NewServer()
|
||||||
eventsapi.RegisterEventSinkServiceServer(suite.server, suite.sink)
|
eventsapi.RegisterEventSinkServiceServer(suite.server, suite.sink)
|
||||||
|
|
||||||
suite.eg.Go(func() error {
|
suite.eg.Go(
|
||||||
<-ctx.Done()
|
func() error {
|
||||||
|
<-ctx.Done()
|
||||||
|
|
||||||
suite.server.Stop()
|
suite.server.Stop()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.eg.Go(func() error {
|
suite.eg.Go(
|
||||||
return suite.server.Serve(lis)
|
func() error {
|
||||||
})
|
return suite.server.Serve(lis)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *EventsSinkSuite) TestPublish() {
|
func (suite *EventsSinkSuite) TestPublish() {
|
||||||
ctx, cancel := context.WithCancel(suite.ctx)
|
ctx, cancel := context.WithCancel(suite.ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
suite.events.Publish(&machine.AddressEvent{
|
suite.events.Publish(
|
||||||
Hostname: "localhost",
|
&machine.AddressEvent{
|
||||||
})
|
Hostname: "localhost",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.events.Publish(&machine.PhaseEvent{
|
suite.events.Publish(
|
||||||
Phase: "test",
|
&machine.PhaseEvent{
|
||||||
Action: machine.PhaseEvent_START,
|
Phase: "test",
|
||||||
})
|
Action: machine.PhaseEvent_START,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().Equal(0, len(suite.handler.events))
|
suite.Require().Equal(0, len(suite.handler.events))
|
||||||
|
|
||||||
suite.startServer(ctx)
|
suite.startServer(ctx)
|
||||||
|
|
||||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(func() error {
|
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(
|
||||||
suite.handler.eventsMu.Lock()
|
func() error {
|
||||||
defer suite.handler.eventsMu.Unlock()
|
suite.handler.eventsMu.Lock()
|
||||||
|
defer suite.handler.eventsMu.Unlock()
|
||||||
|
|
||||||
if len(suite.handler.events) != 2 {
|
if len(suite.handler.events) != 2 {
|
||||||
return retry.ExpectedErrorf("expected 2 events")
|
return retry.ExpectedErrorf("expected 2 events")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,14 +183,18 @@ func (suite *EventsSinkSuite) TestDrain() {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
suite.events.Publish(&machine.PhaseEvent{
|
suite.events.Publish(
|
||||||
Phase: "test",
|
&machine.PhaseEvent{
|
||||||
Action: machine.PhaseEvent_START,
|
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_STOP,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.Require().Equal(0, len(suite.handler.events))
|
suite.Require().Equal(0, len(suite.handler.events))
|
||||||
@ -188,28 +206,34 @@ func (suite *EventsSinkSuite) TestDrain() {
|
|||||||
|
|
||||||
var eg errgroup.Group
|
var eg errgroup.Group
|
||||||
|
|
||||||
eg.Go(func() error {
|
eg.Go(
|
||||||
return suite.drainer.Drain(c)
|
func() error {
|
||||||
})
|
return suite.drainer.Drain(c)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
eg.Go(func() error {
|
eg.Go(
|
||||||
time.Sleep(time.Millisecond * 300)
|
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 {
|
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(
|
||||||
suite.handler.eventsMu.Lock()
|
func() error {
|
||||||
defer suite.handler.eventsMu.Unlock()
|
suite.handler.eventsMu.Lock()
|
||||||
|
defer suite.handler.eventsMu.Unlock()
|
||||||
|
|
||||||
if len(suite.handler.events) != 20 {
|
if len(suite.handler.events) != 20 {
|
||||||
return retry.ExpectedErrorf("expected 20 events, got %d", len(suite.handler.events))
|
return retry.ExpectedErrorf("expected 20 events, got %d", len(suite.handler.events))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.Require().NoError(eg.Wait())
|
suite.Require().NoError(eg.Wait())
|
||||||
|
@ -60,7 +60,7 @@ type KmsgLogDeliverySuite struct {
|
|||||||
drainer *talosruntime.Drainer
|
drainer *talosruntime.Drainer
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
handler *logHandler
|
handler *logHandler
|
||||||
@ -92,13 +92,23 @@ func (suite *KmsgLogDeliverySuite) SetupTest() {
|
|||||||
suite.srv.Serve() //nolint:errcheck
|
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.drainer = talosruntime.NewDrainer()
|
||||||
|
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&controllerruntime.KmsgLogDeliveryController{
|
suite.Require().NoError(
|
||||||
Cmdline: suite.cmdline,
|
suite.runtime.RegisterController(
|
||||||
Drainer: suite.drainer,
|
&controllerruntime.KmsgLogDeliveryController{
|
||||||
}))
|
Cmdline: suite.cmdline,
|
||||||
|
Drainer: suite.drainer,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
status := network.NewStatus(network.NamespaceName, network.StatusID)
|
status := network.NewStatus(network.NamespaceName, network.StatusID)
|
||||||
status.TypedSpec().AddressReady = true
|
status.TypedSpec().AddressReady = true
|
||||||
@ -120,13 +130,15 @@ func (suite *KmsgLogDeliverySuite) TestDelivery() {
|
|||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
// controller should deliver some kernel logs from host's kmsg buffer
|
// 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 {
|
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(
|
||||||
if suite.handler.getCount() == 0 {
|
func() error {
|
||||||
return retry.ExpectedErrorf("no logs received")
|
if suite.handler.getCount() == 0 {
|
||||||
}
|
return retry.ExpectedErrorf("no logs received")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,13 +146,15 @@ func (suite *KmsgLogDeliverySuite) TestDrain() {
|
|||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
// wait for controller to start delivering some logs
|
// wait for controller to start delivering some logs
|
||||||
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(func() error {
|
err := retry.Constant(time.Second*5, retry.WithUnits(time.Millisecond*100)).Retry(
|
||||||
if suite.handler.getCount() == 0 {
|
func() error {
|
||||||
return retry.ExpectedErrorf("no logs received")
|
if suite.handler.getCount() == 0 {
|
||||||
}
|
return retry.ExpectedErrorf("no logs received")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
// drain should be successful, i.e. controller should stop on its own before context is canceled
|
// 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,
|
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)
|
remoteGen, err := gen.NewRemoteGenerator(rootSpec.Token, endpointsStr, rootSpec.CA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed creating trustd client: %w", err)
|
return fmt.Errorf("failed creating trustd client: %w", err)
|
||||||
|
@ -37,7 +37,7 @@ type APICertSANsSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,30 +78,46 @@ func (suite *APICertSANsSuite) TestReconcileControlPlane() {
|
|||||||
hostnameStatus.TypedSpec().Domainname = "some.org"
|
hostnameStatus.TypedSpec().Domainname = "some.org"
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||||
|
|
||||||
nodeAddresses := network.NewNodeAddress(network.NamespaceName, network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, k8s.NodeAddressFilterNoK8s))
|
nodeAddresses := network.NewNodeAddress(
|
||||||
nodeAddresses.TypedSpec().Addresses = []netaddr.IPPrefix{netaddr.MustParseIPPrefix("10.2.1.3/24"), netaddr.MustParseIPPrefix("172.16.0.1/32")}
|
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.Require().NoError(suite.state.Create(suite.ctx, nodeAddresses))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
certSANs, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.CertSANType, secrets.CertSANAPIID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
certSANs, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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)
|
return nil
|
||||||
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
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *APICertSANsSuite) TearDownTest() {
|
func (suite *APICertSANsSuite) TearDownTest() {
|
||||||
|
@ -41,7 +41,7 @@ type APISuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,49 +110,65 @@ func (suite *APISuite) TestReconcileControlPlane() {
|
|||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, certSANs))
|
suite.Require().NoError(suite.state.Create(suite.ctx, certSANs))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
certs, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.APIType, secrets.APIID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
certs, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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)
|
serverCert, err := apiCerts.Server.GetCert()
|
||||||
suite.Assert().Nil(apiCerts.CA.Key)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
serverCert, err := apiCerts.Server.GetCert()
|
suite.Assert().Equal([]string{"example.com", "foo", "foo.example.com"}, serverCert.DNSNames)
|
||||||
suite.Require().NoError(err)
|
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("foo.example.com", serverCert.Subject.CommonName)
|
||||||
suite.Assert().Equal("[10.2.1.3 10.4.3.2 172.16.0.1]", fmt.Sprintf("%v", serverCert.IPAddresses))
|
suite.Assert().Empty(serverCert.Subject.Organization)
|
||||||
|
|
||||||
suite.Assert().Equal("foo.example.com", serverCert.Subject.CommonName)
|
suite.Assert().Equal(
|
||||||
suite.Assert().Empty(serverCert.Subject.Organization)
|
stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment,
|
||||||
|
serverCert.KeyUsage,
|
||||||
|
)
|
||||||
|
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageServerAuth}, serverCert.ExtKeyUsage)
|
||||||
|
|
||||||
suite.Assert().Equal(stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment, serverCert.KeyUsage)
|
clientCert, err := apiCerts.Client.GetCert()
|
||||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageServerAuth}, serverCert.ExtKeyUsage)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
clientCert, err := apiCerts.Client.GetCert()
|
suite.Assert().Empty(clientCert.DNSNames)
|
||||||
suite.Require().NoError(err)
|
suite.Assert().Empty(clientCert.IPAddresses)
|
||||||
|
|
||||||
suite.Assert().Empty(clientCert.DNSNames)
|
suite.Assert().Equal("foo.example.com", clientCert.Subject.CommonName)
|
||||||
suite.Assert().Empty(clientCert.IPAddresses)
|
suite.Assert().Equal([]string{string(role.Impersonator)}, clientCert.Subject.Organization)
|
||||||
|
|
||||||
suite.Assert().Equal("foo.example.com", clientCert.Subject.CommonName)
|
suite.Assert().Equal(
|
||||||
suite.Assert().Equal([]string{string(role.Impersonator)}, clientCert.Subject.Organization)
|
stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment,
|
||||||
|
clientCert.KeyUsage,
|
||||||
|
)
|
||||||
|
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageClientAuth}, clientCert.ExtKeyUsage)
|
||||||
|
|
||||||
suite.Assert().Equal(stdlibx509.KeyUsageDigitalSignature|stdlibx509.KeyUsageKeyEncipherment, clientCert.KeyUsage)
|
return nil
|
||||||
suite.Assert().Equal([]stdlibx509.ExtKeyUsage{stdlibx509.ExtKeyUsageClientAuth}, clientCert.ExtKeyUsage)
|
},
|
||||||
|
),
|
||||||
return nil
|
)
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *APISuite) TearDownTest() {
|
func (suite *APISuite) TearDownTest() {
|
||||||
|
@ -37,7 +37,7 @@ type KubeletSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,43 +75,55 @@ func (suite *KubeletSuite) TestReconcile() {
|
|||||||
|
|
||||||
k8sCA := x509.NewCertificateAndKeyFromCertificateAuthority(ca)
|
k8sCA := x509.NewCertificateAndKeyFromCertificateAuthority(ca)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||||
Endpoint: &v1alpha1.Endpoint{
|
ControlPlane: &v1alpha1.ControlPlaneConfig{
|
||||||
URL: u,
|
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.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
kubeletSecrets, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubeletType, secrets.KubeletID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
kubeletSecrets, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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())
|
return nil
|
||||||
suite.Assert().Equal(k8sCA, spec.CA)
|
},
|
||||||
suite.Assert().Equal("abc", spec.BootstrapTokenID)
|
),
|
||||||
suite.Assert().Equal("def", spec.BootstrapTokenSecret)
|
)
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KubeletSuite) TearDownTest() {
|
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,
|
func (ctrl *KubernetesController) updateSecrets(k8sRoot *secrets.KubernetesRootSpec, k8sSecrets *secrets.KubernetesCertsSpec,
|
||||||
certSANs *secrets.CertSANSpec) error {
|
certSANs *secrets.CertSANSpec,
|
||||||
|
) error {
|
||||||
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(k8sRoot.CA)
|
ca, err := x509.NewCertificateAuthorityFromCertificateAndKey(k8sRoot.CA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse CA certificate: %w", err)
|
return fmt.Errorf("failed to parse CA certificate: %w", err)
|
||||||
|
@ -39,7 +39,7 @@ type KubernetesCertSANsSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,40 +86,57 @@ func (suite *KubernetesCertSANsSuite) TestReconcile() {
|
|||||||
hostnameStatus.TypedSpec().Domainname = "example.com"
|
hostnameStatus.TypedSpec().Domainname = "example.com"
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
suite.Require().NoError(suite.state.Create(suite.ctx, hostnameStatus))
|
||||||
|
|
||||||
nodeAddresses := network.NewNodeAddress(network.NamespaceName, network.FilteredNodeAddressID(network.NodeAddressAccumulativeID, k8s.NodeAddressFilterNoK8s))
|
nodeAddresses := network.NewNodeAddress(
|
||||||
nodeAddresses.TypedSpec().Addresses = []netaddr.IPPrefix{netaddr.MustParseIPPrefix("10.2.1.3/24"), netaddr.MustParseIPPrefix("172.16.0.1/32")}
|
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.Require().NoError(suite.state.Create(suite.ctx, nodeAddresses))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
certSANs, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.CertSANType, secrets.CertSANKubernetesID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
certSANs, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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(
|
return nil
|
||||||
[]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
|
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *KubernetesCertSANsSuite) TearDownTest() {
|
func (suite *KubernetesCertSANsSuite) TearDownTest() {
|
||||||
|
@ -44,7 +44,7 @@ type KubernetesSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,81 +138,116 @@ func (suite *KubernetesSuite) TestReconcile() {
|
|||||||
suite.Require().NoError(suite.state.Create(suite.ctx, certSANs))
|
suite.Require().NoError(suite.state.Create(suite.ctx, certSANs))
|
||||||
|
|
||||||
timeSync := timeresource.NewStatus()
|
timeSync := timeresource.NewStatus()
|
||||||
timeSync.SetStatus(timeresource.StatusSpec{
|
timeSync.SetStatus(
|
||||||
Synced: true,
|
timeresource.StatusSpec{
|
||||||
})
|
Synced: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeSync))
|
suite.Require().NoError(suite.state.Create(suite.ctx, timeSync))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
certs, err := suite.state.Get(suite.ctx, resource.NewMetadata(secrets.NamespaceName, secrets.KubernetesType, secrets.KubernetesID, resource.VersionUndefined))
|
func() error {
|
||||||
if err != nil {
|
certs, err := suite.state.Get(
|
||||||
if state.IsNotFoundError(err) {
|
suite.ctx,
|
||||||
return retry.ExpectedError(err)
|
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()
|
||||||
|
|
||||||
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))
|
|
||||||
suite.Require().NoError(err)
|
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() {
|
func (suite *KubernetesSuite) TearDownTest() {
|
||||||
|
@ -40,7 +40,7 @@ type ManagerSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
s *grpc.Server
|
s *grpc.Server
|
||||||
@ -90,9 +90,13 @@ func (suite *ManagerSuite) SetupTest() {
|
|||||||
|
|
||||||
cmdline := procfs.NewCmdline(fmt.Sprintf("%s=%s", constants.KernelParamSideroLink, lis.Addr().String()))
|
cmdline := procfs.NewCmdline(fmt.Sprintf("%s=%s", constants.KernelParamSideroLink, lis.Addr().String()))
|
||||||
|
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&siderolinkctrl.ManagerController{
|
suite.Require().NoError(
|
||||||
Cmdline: cmdline,
|
suite.runtime.RegisterController(
|
||||||
}))
|
&siderolinkctrl.ManagerController{
|
||||||
|
Cmdline: cmdline,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ManagerSuite) startRuntime() {
|
func (suite *ManagerSuite) startRuntime() {
|
||||||
@ -113,56 +117,76 @@ func (suite *ManagerSuite) TestReconcile() {
|
|||||||
|
|
||||||
nodeAddress := netaddr.MustParseIPPrefix(mockNodeAddressPrefix)
|
nodeAddress := netaddr.MustParseIPPrefix(mockNodeAddressPrefix)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(5*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
addressResource, err := suite.state.Get(suite.ctx, resource.NewMetadata(
|
func() error {
|
||||||
network.ConfigNamespaceName,
|
addressResource, err := suite.state.Get(
|
||||||
network.AddressSpecType,
|
suite.ctx, resource.NewMetadata(
|
||||||
network.LayeredID(network.ConfigOperator, network.AddressID(constants.SideroLinkName, nodeAddress)),
|
network.ConfigNamespaceName,
|
||||||
resource.VersionUndefined,
|
network.AddressSpecType,
|
||||||
))
|
network.LayeredID(
|
||||||
if err != nil {
|
network.ConfigOperator,
|
||||||
if state.IsNotFoundError(err) {
|
network.AddressID(constants.SideroLinkName, nodeAddress),
|
||||||
return retry.ExpectedError(err)
|
),
|
||||||
|
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)
|
linkResource, err := suite.state.Get(
|
||||||
suite.Assert().Equal(network.ConfigOperator, address.ConfigLayer)
|
suite.ctx, resource.NewMetadata(
|
||||||
suite.Assert().Equal(nethelpers.FamilyInet6, address.Family)
|
network.ConfigNamespaceName,
|
||||||
suite.Assert().Equal(constants.SideroLinkName, address.LinkName)
|
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(
|
return err
|
||||||
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
|
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)
|
return nil
|
||||||
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
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *ManagerSuite) TearDownTest() {
|
func (suite *ManagerSuite) TearDownTest() {
|
||||||
|
@ -41,7 +41,7 @@ type SyncSuite struct {
|
|||||||
runtime *runtime.Runtime
|
runtime *runtime.Runtime
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
syncerMu sync.Mutex
|
syncerMu sync.Mutex
|
||||||
@ -72,7 +72,15 @@ func (suite *SyncSuite) startRuntime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SyncSuite) assertTimeStatus(spec timeresource.StatusSpec) error {
|
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 err != nil {
|
||||||
if state.IsNotFoundError(err) {
|
if state.IsNotFoundError(err) {
|
||||||
return retry.ExpectedError(err)
|
return retry.ExpectedError(err)
|
||||||
@ -91,10 +99,14 @@ func (suite *SyncSuite) assertTimeStatus(spec timeresource.StatusSpec) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SyncSuite) TestReconcileContainerMode() {
|
func (suite *SyncSuite) TestReconcileContainerMode() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
suite.Require().NoError(
|
||||||
V1Alpha1Mode: v1alpha1runtime.ModeContainer,
|
suite.runtime.RegisterController(
|
||||||
NewNTPSyncer: suite.newMockSyncer,
|
&timectrl.SyncController{
|
||||||
}))
|
V1Alpha1Mode: v1alpha1runtime.ModeContainer,
|
||||||
|
NewNTPSyncer: suite.newMockSyncer,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
timeServers := network.NewTimeServerStatus(network.NamespaceName, network.TimeServerID)
|
timeServers := network.NewTimeServerStatus(network.NamespaceName, network.TimeServerID)
|
||||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||||
@ -102,24 +114,30 @@ func (suite *SyncSuite) TestReconcileContainerMode() {
|
|||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: true,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: true,
|
||||||
SyncDisabled: true,
|
Epoch: 0,
|
||||||
},
|
SyncDisabled: true,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SyncSuite) TestReconcileSyncDisabled() {
|
func (suite *SyncSuite) TestReconcileSyncDisabled() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
suite.Require().NoError(
|
||||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
suite.runtime.RegisterController(
|
||||||
NewNTPSyncer: suite.newMockSyncer,
|
&timectrl.SyncController{
|
||||||
}))
|
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||||
|
NewNTPSyncer: suite.newMockSyncer,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -127,48 +145,58 @@ func (suite *SyncSuite) TestReconcileSyncDisabled() {
|
|||||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: false,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: false,
|
||||||
SyncDisabled: false,
|
Epoch: 0,
|
||||||
},
|
SyncDisabled: false,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
|
||||||
ConfigVersion: "v1alpha1",
|
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
|
||||||
MachineTime: &v1alpha1.TimeConfig{
|
|
||||||
TimeDisabled: true,
|
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
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.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: true,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: true,
|
||||||
SyncDisabled: true,
|
Epoch: 0,
|
||||||
},
|
SyncDisabled: true,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SyncSuite) TestReconcileSyncDefaultConfig() {
|
func (suite *SyncSuite) TestReconcileSyncDefaultConfig() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
suite.Require().NoError(
|
||||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
suite.runtime.RegisterController(
|
||||||
NewNTPSyncer: suite.newMockSyncer,
|
&timectrl.SyncController{
|
||||||
}))
|
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||||
|
NewNTPSyncer: suite.newMockSyncer,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -176,32 +204,40 @@ func (suite *SyncSuite) TestReconcileSyncDefaultConfig() {
|
|||||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
})
|
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: false,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: false,
|
||||||
SyncDisabled: false,
|
Epoch: 0,
|
||||||
},
|
SyncDisabled: false,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SyncSuite) TestReconcileSyncChangeConfig() {
|
func (suite *SyncSuite) TestReconcileSyncChangeConfig() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
suite.Require().NoError(
|
||||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
suite.runtime.RegisterController(
|
||||||
NewNTPSyncer: suite.newMockSyncer,
|
&timectrl.SyncController{
|
||||||
}))
|
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||||
|
NewNTPSyncer: suite.newMockSyncer,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -209,126 +245,150 @@ func (suite *SyncSuite) TestReconcileSyncChangeConfig() {
|
|||||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: false,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: false,
|
||||||
SyncDisabled: false,
|
Epoch: 0,
|
||||||
},
|
SyncDisabled: false,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
cfg := config.NewMachineConfig(
|
||||||
ConfigVersion: "v1alpha1",
|
&v1alpha1.Config{
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
ConfigVersion: "v1alpha1",
|
||||||
ClusterConfig: &v1alpha1.ClusterConfig{},
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
})
|
ClusterConfig: &v1alpha1.ClusterConfig{},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
suite.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
var mockSyncer *mockSyncer
|
var mockSyncer *mockSyncer
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
mockSyncer = suite.getMockSyncer()
|
func() error {
|
||||||
|
mockSyncer = suite.getMockSyncer()
|
||||||
|
|
||||||
if mockSyncer == nil {
|
if mockSyncer == nil {
|
||||||
return retry.ExpectedError(fmt.Errorf("syncer not created yet"))
|
return retry.ExpectedError(fmt.Errorf("syncer not created yet"))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
))
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.Assert().Equal([]string{constants.DefaultNTPServer}, mockSyncer.getTimeServers())
|
suite.Assert().Equal([]string{constants.DefaultNTPServer}, mockSyncer.getTimeServers())
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: false,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: false,
|
||||||
SyncDisabled: false,
|
Epoch: 0,
|
||||||
},
|
SyncDisabled: false,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
close(mockSyncer.syncedCh)
|
close(mockSyncer.syncedCh)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: true,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: true,
|
||||||
SyncDisabled: false,
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
if !reflect.DeepEqual(mockSyncer.getTimeServers(), []string{"127.0.0.1"}) {
|
func() error {
|
||||||
return retry.ExpectedError(fmt.Errorf("time servers not updated yet"))
|
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
|
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.Require().NoError(err)
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: true,
|
timeresource.StatusSpec{
|
||||||
Epoch: 1,
|
Synced: true,
|
||||||
SyncDisabled: true,
|
Epoch: 1,
|
||||||
},
|
SyncDisabled: true,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SyncSuite) TestReconcileSyncBootTimeout() {
|
func (suite *SyncSuite) TestReconcileSyncBootTimeout() {
|
||||||
suite.Require().NoError(suite.runtime.RegisterController(&timectrl.SyncController{
|
suite.Require().NoError(
|
||||||
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
suite.runtime.RegisterController(
|
||||||
NewNTPSyncer: suite.newMockSyncer,
|
&timectrl.SyncController{
|
||||||
}))
|
V1Alpha1Mode: v1alpha1runtime.ModeMetal,
|
||||||
|
NewNTPSyncer: suite.newMockSyncer,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
suite.startRuntime()
|
suite.startRuntime()
|
||||||
|
|
||||||
@ -336,41 +396,47 @@ func (suite *SyncSuite) TestReconcileSyncBootTimeout() {
|
|||||||
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
timeServers.TypedSpec().NTPServers = []string{constants.DefaultNTPServer}
|
||||||
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
suite.Require().NoError(suite.state.Create(suite.ctx, timeServers))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: false,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: false,
|
||||||
SyncDisabled: false,
|
Epoch: 0,
|
||||||
},
|
SyncDisabled: false,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
|
||||||
|
|
||||||
cfg := config.NewMachineConfig(&v1alpha1.Config{
|
|
||||||
ConfigVersion: "v1alpha1",
|
|
||||||
MachineConfig: &v1alpha1.MachineConfig{
|
|
||||||
MachineTime: &v1alpha1.TimeConfig{
|
|
||||||
TimeBootTimeout: 5 * time.Second,
|
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
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.Require().NoError(suite.state.Create(suite.ctx, cfg))
|
||||||
|
|
||||||
suite.Assert().NoError(retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
suite.Assert().NoError(
|
||||||
func() error {
|
retry.Constant(10*time.Second, retry.WithUnits(100*time.Millisecond)).Retry(
|
||||||
return suite.assertTimeStatus(
|
func() error {
|
||||||
timeresource.StatusSpec{
|
return suite.assertTimeStatus(
|
||||||
Synced: true,
|
timeresource.StatusSpec{
|
||||||
Epoch: 0,
|
Synced: true,
|
||||||
SyncDisabled: false,
|
Epoch: 0,
|
||||||
},
|
SyncDisabled: false,
|
||||||
)
|
},
|
||||||
},
|
)
|
||||||
))
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *SyncSuite) TearDownTest() {
|
func (suite *SyncSuite) TearDownTest() {
|
||||||
@ -381,10 +447,14 @@ func (suite *SyncSuite) TearDownTest() {
|
|||||||
suite.wg.Wait()
|
suite.wg.Wait()
|
||||||
|
|
||||||
// trigger updates in resources to stop watch loops
|
// trigger updates in resources to stop watch loops
|
||||||
err := suite.state.Create(context.Background(), config.NewMachineConfig(&v1alpha1.Config{
|
err := suite.state.Create(
|
||||||
ConfigVersion: "v1alpha1",
|
context.Background(), config.NewMachineConfig(
|
||||||
MachineConfig: &v1alpha1.MachineConfig{},
|
&v1alpha1.Config{
|
||||||
}))
|
ConfigVersion: "v1alpha1",
|
||||||
|
MachineConfig: &v1alpha1.MachineConfig{},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
if state.IsConflictError(err) {
|
if state.IsConflictError(err) {
|
||||||
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
err = suite.state.Destroy(context.Background(), config.NewMachineConfig(nil).Metadata())
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
package rpi4
|
package rpi4
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed" //nolint:gci
|
_ "embed"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/talos-systems/go-procfs/procfs"
|
"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),
|
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) {
|
return func(seq runtime.Sequence, data interface{}) (runtime.TaskExecutionFunc, string) {
|
||||||
f, name := callback(seq, data)
|
f, name := callback(seq, data)
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ type containerdRunner struct {
|
|||||||
stopped chan struct{}
|
stopped chan struct{}
|
||||||
|
|
||||||
client *containerd.Client
|
client *containerd.Client
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
container containerd.Container
|
container containerd.Container
|
||||||
stdinCloser *StdinCloser
|
stdinCloser *StdinCloser
|
||||||
}
|
}
|
||||||
@ -196,7 +196,13 @@ func (c *containerdRunner) Run(eventSink events.Recorder) error {
|
|||||||
return nil
|
return nil
|
||||||
case <-c.stop:
|
case <-c.stop:
|
||||||
// graceful stop the task
|
// 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 {
|
if err = task.Kill(c.ctx, syscall.SIGTERM, containerd.WithKillAll); err != nil {
|
||||||
return fmt.Errorf("error sending SIGTERM: %w", err)
|
return fmt.Errorf("error sending SIGTERM: %w", err)
|
||||||
@ -209,7 +215,13 @@ func (c *containerdRunner) Run(eventSink events.Recorder) error {
|
|||||||
return nil
|
return nil
|
||||||
case <-time.After(c.opts.GracefulShutdownTimeout):
|
case <-time.After(c.opts.GracefulShutdownTimeout):
|
||||||
// kill the process
|
// 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 {
|
if err = task.Kill(c.ctx, syscall.SIGKILL, containerd.WithKillAll); err != nil {
|
||||||
return fmt.Errorf("error sending SIGKILL: %w", err)
|
return fmt.Errorf("error sending SIGKILL: %w", err)
|
||||||
@ -233,21 +245,27 @@ func (c *containerdRunner) Stop() error {
|
|||||||
return nil
|
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{}
|
containerOpts := []containerd.NewContainerOpts{}
|
||||||
|
|
||||||
if image != nil {
|
if image != nil {
|
||||||
containerOpts = append(containerOpts,
|
containerOpts = append(
|
||||||
|
containerOpts,
|
||||||
containerd.WithImage(image),
|
containerd.WithImage(image),
|
||||||
containerd.WithNewSnapshot(c.args.ID, image),
|
containerd.WithNewSnapshot(c.args.ID, image),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
containerOpts = append(containerOpts,
|
containerOpts = append(
|
||||||
|
containerOpts,
|
||||||
containerd.WithNewSpec(specOpts...),
|
containerd.WithNewSpec(specOpts...),
|
||||||
)
|
)
|
||||||
|
|
||||||
containerOpts = append(containerOpts,
|
containerOpts = append(
|
||||||
|
containerOpts,
|
||||||
c.opts.ContainerOpts...,
|
c.opts.ContainerOpts...,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -258,12 +276,14 @@ func (c *containerdRunner) newOCISpecOpts(image oci.Image) []oci.SpecOpts {
|
|||||||
specOpts := []oci.SpecOpts{}
|
specOpts := []oci.SpecOpts{}
|
||||||
|
|
||||||
if image != nil {
|
if image != nil {
|
||||||
specOpts = append(specOpts,
|
specOpts = append(
|
||||||
|
specOpts,
|
||||||
oci.WithImageConfig(image),
|
oci.WithImageConfig(image),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
specOpts = append(specOpts,
|
specOpts = append(
|
||||||
|
specOpts,
|
||||||
oci.WithProcessArgs(c.args.ProcessArgs...),
|
oci.WithProcessArgs(c.args.ProcessArgs...),
|
||||||
oci.WithEnv(c.opts.Env),
|
oci.WithEnv(c.opts.Env),
|
||||||
oci.WithHostHostsFile,
|
oci.WithHostHostsFile,
|
||||||
@ -272,27 +292,32 @@ func (c *containerdRunner) newOCISpecOpts(image oci.Image) []oci.SpecOpts {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if c.opts.OOMScoreAdj != 0 {
|
if c.opts.OOMScoreAdj != 0 {
|
||||||
specOpts = append(specOpts,
|
specOpts = append(
|
||||||
|
specOpts,
|
||||||
WithOOMScoreAdj(c.opts.OOMScoreAdj),
|
WithOOMScoreAdj(c.opts.OOMScoreAdj),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.opts.CgroupPath != "" {
|
if c.opts.CgroupPath != "" {
|
||||||
specOpts = append(specOpts,
|
specOpts = append(
|
||||||
|
specOpts,
|
||||||
oci.WithCgroup(c.opts.CgroupPath),
|
oci.WithCgroup(c.opts.CgroupPath),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
specOpts = append(specOpts,
|
specOpts = append(
|
||||||
|
specOpts,
|
||||||
c.opts.OCISpecOpts...,
|
c.opts.OCISpecOpts...,
|
||||||
)
|
)
|
||||||
|
|
||||||
if c.opts.OverrideSeccompProfile != nil {
|
if c.opts.OverrideSeccompProfile != nil {
|
||||||
specOpts = append(specOpts,
|
specOpts = append(
|
||||||
|
specOpts,
|
||||||
WithCustomSeccompProfile(c.opts.OverrideSeccompProfile),
|
WithCustomSeccompProfile(c.opts.OverrideSeccompProfile),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
specOpts = append(specOpts,
|
specOpts = append(
|
||||||
|
specOpts,
|
||||||
seccomp.WithDefaultProfile(), // add seccomp profile last, as it depends on process capabilities
|
seccomp.WithDefaultProfile(), // add seccomp profile last, as it depends on process capabilities
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ type goroutineRunner struct {
|
|||||||
|
|
||||||
opts *runner.Options
|
opts *runner.Options
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
@ -41,7 +41,7 @@ type ServiceRunner struct {
|
|||||||
stateSubscribers map[StateEvent][]chan<- struct{}
|
stateSubscribers map[StateEvent][]chan<- struct{}
|
||||||
|
|
||||||
ctxMu sync.Mutex
|
ctxMu sync.Mutex
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +291,12 @@ func (svcrunner *ServiceRunner) run(ctx context.Context, runnr runner.Runner) er
|
|||||||
defer healthWg.Done()
|
defer healthWg.Done()
|
||||||
|
|
||||||
//nolint:errcheck
|
//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)
|
notifyCh := make(chan health.StateChange, 2)
|
||||||
|
@ -51,7 +51,7 @@ const assertRebootedRebootTimeout = 10 * time.Minute
|
|||||||
type ApplyConfigSuite struct {
|
type ApplyConfigSuite struct {
|
||||||
base.K8sSuite
|
base.K8sSuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,30 +109,38 @@ func (suite *ApplyConfigSuite) TestApply() {
|
|||||||
cfgDataOut, err := cfg.Bytes()
|
cfgDataOut, err := cfg.Bytes()
|
||||||
suite.Assert().Nilf(err, "failed to marshal updated machine config data (node %q): %w", node, err)
|
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 {
|
suite.AssertRebooted(
|
||||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||||
Data: cfgDataOut,
|
_, err = suite.Client.ApplyConfiguration(
|
||||||
Mode: machineapi.ApplyConfigurationRequest_REBOOT,
|
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||||
})
|
Data: cfgDataOut,
|
||||||
if err != nil {
|
Mode: machineapi.ApplyConfigurationRequest_REBOOT,
|
||||||
// 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)
|
)
|
||||||
}
|
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
|
return nil
|
||||||
}, assertRebootedRebootTimeout)
|
}, assertRebootedRebootTimeout,
|
||||||
|
)
|
||||||
|
|
||||||
// Verify configuration change
|
// Verify configuration change
|
||||||
var newProvider config.Provider
|
var newProvider config.Provider
|
||||||
|
|
||||||
suite.Require().Nilf(retry.Constant(time.Minute, retry.WithUnits(time.Second)).Retry(func() error {
|
suite.Require().Nilf(
|
||||||
newProvider, err = suite.ReadConfigFromNode(nodeCtx)
|
retry.Constant(time.Minute, retry.WithUnits(time.Second)).Retry(
|
||||||
if err != nil {
|
func() error {
|
||||||
return retry.ExpectedError(err)
|
newProvider, err = suite.ReadConfigFromNode(nodeCtx)
|
||||||
}
|
if err != nil {
|
||||||
|
return retry.ExpectedError(err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}), "failed to read updated configuration from node %q: %w", node, err)
|
},
|
||||||
|
), "failed to read updated configuration from node %q: %w", node, err,
|
||||||
|
)
|
||||||
|
|
||||||
suite.Assert().Equal(
|
suite.Assert().Equal(
|
||||||
newProvider.Machine().Sysctls()[applyConfigTestSysctl],
|
newProvider.Machine().Sysctls()[applyConfigTestSysctl],
|
||||||
@ -168,10 +176,12 @@ func (suite *ApplyConfigSuite) TestApplyWithoutReboot() {
|
|||||||
cfgDataOut, err := cfg.Bytes()
|
cfgDataOut, err := cfg.Bytes()
|
||||||
suite.Require().NoError(err, "failed to marshal updated machine config data (node %q)", node)
|
suite.Require().NoError(err, "failed to marshal updated machine config data (node %q)", node)
|
||||||
|
|
||||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
_, err = suite.Client.ApplyConfiguration(
|
||||||
Data: cfgDataOut,
|
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||||
Mode: mode,
|
Data: cfgDataOut,
|
||||||
})
|
Mode: mode,
|
||||||
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err, "failed to apply deferred configuration (node %q): %w", node)
|
suite.Require().NoError(err, "failed to apply deferred configuration (node %q): %w", node)
|
||||||
|
|
||||||
// Verify configuration change
|
// Verify configuration change
|
||||||
@ -195,10 +205,12 @@ func (suite *ApplyConfigSuite) TestApplyWithoutReboot() {
|
|||||||
cfgDataOut, err = cfg.Bytes()
|
cfgDataOut, err = cfg.Bytes()
|
||||||
suite.Require().NoError(err, "failed to marshal updated machine config data (node %q)", node)
|
suite.Require().NoError(err, "failed to marshal updated machine config data (node %q)", node)
|
||||||
|
|
||||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
_, err = suite.Client.ApplyConfiguration(
|
||||||
Data: cfgDataOut,
|
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||||
Mode: mode,
|
Data: cfgDataOut,
|
||||||
})
|
Mode: mode,
|
||||||
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err, "failed to apply deferred configuration (node %q): %w", node)
|
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()
|
data, err := machineConfig.Bytes()
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
suite.AssertRebooted(
|
||||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||||
Data: data,
|
_, err = suite.Client.ApplyConfiguration(
|
||||||
Mode: machineapi.ApplyConfigurationRequest_REBOOT,
|
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||||
})
|
Data: data,
|
||||||
if err != nil {
|
Mode: machineapi.ApplyConfigurationRequest_REBOOT,
|
||||||
// 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)
|
)
|
||||||
}
|
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
|
return nil
|
||||||
}, assertRebootedRebootTimeout)
|
}, assertRebootedRebootTimeout,
|
||||||
|
)
|
||||||
|
|
||||||
suite.ClearConnectionRefused(suite.ctx, node)
|
suite.ClearConnectionRefused(suite.ctx, node)
|
||||||
|
|
||||||
// Verify configuration change
|
// Verify configuration change
|
||||||
var newProvider config.Provider
|
var newProvider config.Provider
|
||||||
|
|
||||||
suite.Require().Nilf(retry.Constant(time.Minute, retry.WithUnits(time.Second)).Retry(func() error {
|
suite.Require().Nilf(
|
||||||
newProvider, err = suite.ReadConfigFromNode(nodeCtx)
|
retry.Constant(time.Minute, retry.WithUnits(time.Second)).Retry(
|
||||||
if err != nil {
|
func() error {
|
||||||
return retry.ExpectedError(err)
|
newProvider, err = suite.ReadConfigFromNode(nodeCtx)
|
||||||
}
|
if err != nil {
|
||||||
|
return retry.ExpectedError(err)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}), "failed to read updated configuration from node %q: %w", node, err)
|
},
|
||||||
|
), "failed to read updated configuration from node %q: %w", node, err,
|
||||||
|
)
|
||||||
|
|
||||||
e := newProvider.Machine().SystemDiskEncryption().Get(constants.EphemeralPartitionLabel)
|
e := newProvider.Machine().SystemDiskEncryption().Get(constants.EphemeralPartitionLabel)
|
||||||
|
|
||||||
@ -370,10 +390,12 @@ func (suite *ApplyConfigSuite) TestApplyNoReboot() {
|
|||||||
cfgDataOut, err := cfg.Bytes()
|
cfgDataOut, err := cfg.Bytes()
|
||||||
suite.Assert().Nilf(err, "failed to marshal updated machine config data (node %q): %w", node, err)
|
suite.Assert().Nilf(err, "failed to marshal updated machine config data (node %q): %w", node, err)
|
||||||
|
|
||||||
_, err = suite.Client.ApplyConfiguration(nodeCtx, &machineapi.ApplyConfigurationRequest{
|
_, err = suite.Client.ApplyConfiguration(
|
||||||
Data: cfgDataOut,
|
nodeCtx, &machineapi.ApplyConfigurationRequest{
|
||||||
Mode: machineapi.ApplyConfigurationRequest_NO_REBOOT,
|
Data: cfgDataOut,
|
||||||
})
|
Mode: machineapi.ApplyConfigurationRequest_NO_REBOOT,
|
||||||
|
},
|
||||||
|
)
|
||||||
suite.Require().Error(err)
|
suite.Require().Error(err)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -28,7 +28,7 @@ import (
|
|||||||
type DiscoverySuite struct {
|
type DiscoverySuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,10 +23,10 @@ import (
|
|||||||
type DiskUsageSuite struct {
|
type DiskUsageSuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
nodeCtx context.Context
|
nodeCtx context.Context //nolint:containedctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// SuiteName ...
|
// SuiteName ...
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
type DmesgSuite struct {
|
type DmesgSuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import (
|
|||||||
type EtcdRecoverSuite struct {
|
type EtcdRecoverSuite struct {
|
||||||
base.K8sSuite
|
base.K8sSuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,39 +112,52 @@ func (suite *EtcdRecoverSuite) TestSnapshotRecover() {
|
|||||||
return fmt.Errorf("error reading pre-reset boot ID: %w", err)
|
return fmt.Errorf("error reading pre-reset boot ID: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = base.IgnoreGRPCUnavailable(suite.Client.ResetGeneric(nodeCtx, &machineapi.ResetRequest{
|
if err = base.IgnoreGRPCUnavailable(
|
||||||
Reboot: true,
|
suite.Client.ResetGeneric(
|
||||||
Graceful: false,
|
nodeCtx, &machineapi.ResetRequest{
|
||||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
Reboot: true,
|
||||||
{
|
Graceful: false,
|
||||||
Label: constants.EphemeralPartitionLabel,
|
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||||
Wipe: true,
|
{
|
||||||
|
Label: constants.EphemeralPartitionLabel,
|
||||||
|
Wipe: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
),
|
||||||
})); err != nil {
|
); err != nil {
|
||||||
return fmt.Errorf("error resetting the node %q: %w", node, err)
|
return fmt.Errorf("error resetting the node %q: %w", node, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var bootIDAfter string
|
var bootIDAfter string
|
||||||
|
|
||||||
return retry.Constant(5 * time.Minute).Retry(func() error {
|
return retry.Constant(5 * time.Minute).Retry(
|
||||||
requestCtx, requestCtxCancel := context.WithTimeout(nodeCtx, 5*time.Second)
|
func() error {
|
||||||
defer requestCtxCancel()
|
requestCtx, requestCtxCancel := context.WithTimeout(nodeCtx, 5*time.Second)
|
||||||
|
defer requestCtxCancel()
|
||||||
|
|
||||||
bootIDAfter, err = suite.ReadBootID(requestCtx)
|
bootIDAfter, err = suite.ReadBootID(requestCtx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// API might be unresponsive during reboot
|
// API might be unresponsive during reboot
|
||||||
return retry.ExpectedError(err)
|
return retry.ExpectedError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if bootIDAfter == bootIDBefore {
|
if bootIDAfter == bootIDBefore {
|
||||||
// bootID should be different after reboot
|
// 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 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")
|
suite.T().Log("uploading the snapshot")
|
||||||
|
|
||||||
if err := retry.Constant(time.Minute, retry.WithUnits(time.Millisecond*200)).RetryWithContext(ctx, func(ctx context.Context) error {
|
if err := retry.Constant(time.Minute, retry.WithUnits(time.Millisecond*200)).RetryWithContext(
|
||||||
_, err := src.Seek(0, io.SeekStart)
|
ctx, func(ctx context.Context) error {
|
||||||
if err != nil {
|
_, 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
|
return err
|
||||||
}
|
},
|
||||||
|
); err != nil {
|
||||||
_, err = suite.Client.EtcdRecover(ctx, src)
|
|
||||||
|
|
||||||
if client.StatusCode(err) == codes.FailedPrecondition {
|
|
||||||
return retry.ExpectedError(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}); err != nil {
|
|
||||||
return fmt.Errorf("error uploading snapshot: %w", err)
|
return fmt.Errorf("error uploading snapshot: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
suite.T().Log("bootstrapping from the snapshot")
|
suite.T().Log("bootstrapping from the snapshot")
|
||||||
|
|
||||||
return retry.Constant(time.Minute, retry.WithUnits(time.Millisecond*200)).RetryWithContext(ctx, func(ctx context.Context) error {
|
return retry.Constant(time.Minute, retry.WithUnits(time.Millisecond*200)).RetryWithContext(
|
||||||
err := suite.Client.Bootstrap(ctx, &machineapi.BootstrapRequest{
|
ctx, func(ctx context.Context) error {
|
||||||
RecoverEtcd: true,
|
err := suite.Client.Bootstrap(
|
||||||
})
|
ctx, &machineapi.BootstrapRequest{
|
||||||
|
RecoverEtcd: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
if client.StatusCode(err) == codes.FailedPrecondition || client.StatusCode(err) == codes.DeadlineExceeded {
|
if client.StatusCode(err) == codes.FailedPrecondition || client.StatusCode(err) == codes.DeadlineExceeded {
|
||||||
return retry.ExpectedError(err)
|
return retry.ExpectedError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
type EtcdSuite struct {
|
type EtcdSuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,10 @@ func (suite *EtcdSuite) TestEtcdForfeitLeadership() {
|
|||||||
var leader string
|
var leader string
|
||||||
|
|
||||||
for _, node := range nodes {
|
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)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
if resp.Messages[0].GetMember() != "" {
|
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
|
// 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.
|
// to check the cluster health and catch any issues in rejoining.
|
||||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
suite.AssertRebooted(
|
||||||
_, err = suite.Client.MachineClient.Reboot(nodeCtx, &machineapi.RebootRequest{})
|
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||||
|
_, err = suite.Client.MachineClient.Reboot(nodeCtx, &machineapi.RebootRequest{})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}, 10*time.Minute)
|
}, 10*time.Minute,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -20,10 +20,10 @@ import (
|
|||||||
type EventsSuite struct {
|
type EventsSuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
nodeCtx context.Context
|
nodeCtx context.Context //nolint:containedctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// SuiteName ...
|
// SuiteName ...
|
||||||
@ -54,25 +54,29 @@ func (suite *EventsSuite) TestEventsWatch() {
|
|||||||
watchCtx, watchCtxCancel := context.WithCancel(suite.nodeCtx)
|
watchCtx, watchCtxCancel := context.WithCancel(suite.nodeCtx)
|
||||||
defer watchCtxCancel()
|
defer watchCtxCancel()
|
||||||
|
|
||||||
suite.Assert().NoError(suite.Client.EventsWatch(watchCtx, func(ch <-chan client.Event) {
|
suite.Assert().NoError(
|
||||||
defer watchCtxCancel()
|
suite.Client.EventsWatch(
|
||||||
|
watchCtx, func(ch <-chan client.Event) {
|
||||||
|
defer watchCtxCancel()
|
||||||
|
|
||||||
timer := time.NewTimer(500 * time.Millisecond)
|
timer := time.NewTimer(500 * time.Millisecond)
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case event, ok := <-ch:
|
case event, ok := <-ch:
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, event)
|
||||||
|
case <-timer.C:
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}, opts...,
|
||||||
result = append(result, event)
|
),
|
||||||
case <-timer.C:
|
)
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, opts...))
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -88,7 +92,10 @@ func (suite *EventsSuite) TestEventsWatch() {
|
|||||||
// (as check excludes that event with picked ID)
|
// (as check excludes that event with picked ID)
|
||||||
id := allEvents[len(allEvents)-15].ID
|
id := allEvents[len(allEvents)-15].ID
|
||||||
eventsSinceID := receiveEvents(client.WithTailID(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() {
|
func init() {
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
type GenerateConfigSuite struct {
|
type GenerateConfigSuite struct {
|
||||||
base.K8sSuite
|
base.K8sSuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
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.Name, config.Cluster().Name())
|
||||||
suite.Require().EqualValues(request.ClusterConfig.ControlPlane.Endpoint, config.Cluster().Endpoint().String())
|
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.DnsDomain, config.Cluster().Network().DNSDomain())
|
||||||
suite.Require().EqualValues(request.ClusterConfig.ClusterNetwork.CniConfig.Name, config.Cluster().Network().CNI().Name())
|
suite.Require().EqualValues(
|
||||||
suite.Require().EqualValues(request.ClusterConfig.ClusterNetwork.CniConfig.Urls, config.Cluster().Network().CNI().URLs())
|
request.ClusterConfig.ClusterNetwork.CniConfig.Name,
|
||||||
suite.Require().EqualValues(fmt.Sprintf("%s:v%s", constants.KubeletImage, request.MachineConfig.KubernetesVersion), config.Machine().Kubelet().Image())
|
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.InstallDisk, disk)
|
||||||
suite.Require().EqualValues(request.MachineConfig.InstallConfig.InstallImage, config.Machine().Install().Image())
|
suite.Require().EqualValues(request.MachineConfig.InstallConfig.InstallImage, config.Machine().Install().Image())
|
||||||
suite.Require().EqualValues(request.MachineConfig.NetworkConfig.Hostname, config.Machine().Network().Hostname())
|
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.ConfigVersion, joinedConfig.Version())
|
||||||
suite.Require().EqualValues(request.ClusterConfig.Name, joinedConfig.Cluster().Name())
|
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.ControlPlane.Endpoint, joinedConfig.Cluster().Endpoint().String())
|
||||||
suite.Require().EqualValues(request.ClusterConfig.ClusterNetwork.DnsDomain, joinedConfig.Cluster().Network().DNSDomain())
|
suite.Require().EqualValues(
|
||||||
suite.Require().EqualValues(fmt.Sprintf("%s:v%s", constants.KubeletImage, request.MachineConfig.KubernetesVersion), joinedConfig.Machine().Kubelet().Image())
|
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.InstallDisk, disk)
|
||||||
suite.Require().EqualValues(request.MachineConfig.InstallConfig.InstallImage, joinedConfig.Machine().Install().Image())
|
suite.Require().EqualValues(
|
||||||
suite.Require().EqualValues(request.MachineConfig.NetworkConfig.Hostname, joinedConfig.Machine().Network().Hostname())
|
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().CA(), joinedConfig.Machine().Security().CA())
|
||||||
suite.Require().EqualValues(config.Machine().Security().Token(), joinedConfig.Machine().Security().Token())
|
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().CA(), joinedConfig.Cluster().CA())
|
||||||
suite.Require().EqualValues(config.Cluster().Token(), joinedConfig.Cluster().Token())
|
suite.Require().EqualValues(config.Cluster().Token(), joinedConfig.Cluster().Token())
|
||||||
suite.Require().EqualValues(config.Cluster().Etcd().CA(), config.Cluster().Etcd().CA())
|
suite.Require().EqualValues(config.Cluster().Etcd().CA(), config.Cluster().Etcd().CA())
|
||||||
|
@ -25,10 +25,10 @@ import (
|
|||||||
type LogsSuite struct {
|
type LogsSuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
nodeCtx context.Context
|
nodeCtx context.Context //nolint:containedctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// SuiteName ...
|
// SuiteName ...
|
||||||
@ -167,7 +167,11 @@ func (suite *LogsSuite) testStreaming(tailLines int32) {
|
|||||||
// invoke machined enough times to generate
|
// invoke machined enough times to generate
|
||||||
// some logs
|
// some logs
|
||||||
for i := int32(0); i < tailLines; i++ {
|
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)
|
suite.Require().NoError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
type RebootSuite struct {
|
type RebootSuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,9 +62,11 @@ func (suite *RebootSuite) TestRebootNodeByNode() {
|
|||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
suite.T().Log("rebooting node", node)
|
suite.T().Log("rebooting node", node)
|
||||||
|
|
||||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
suite.AssertRebooted(
|
||||||
return base.IgnoreGRPCUnavailable(suite.Client.Reboot(nodeCtx))
|
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||||
}, 10*time.Minute)
|
return base.IgnoreGRPCUnavailable(suite.Client.Reboot(nodeCtx))
|
||||||
|
}, 10*time.Minute,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,23 +125,32 @@ func (suite *RebootSuite) TestRebootAllNodes() {
|
|||||||
|
|
||||||
nodeCtx := client.WithNodes(suite.ctx, node)
|
nodeCtx := client.WithNodes(suite.ctx, node)
|
||||||
|
|
||||||
return retry.Constant(10 * time.Minute).Retry(func() error {
|
return retry.Constant(10 * time.Minute).Retry(
|
||||||
requestCtx, requestCtxCancel := context.WithTimeout(nodeCtx, 5*time.Second)
|
func() error {
|
||||||
defer requestCtxCancel()
|
requestCtx, requestCtxCancel := context.WithTimeout(nodeCtx, 5*time.Second)
|
||||||
|
defer requestCtxCancel()
|
||||||
|
|
||||||
bootIDAfter, err := suite.ReadBootID(requestCtx)
|
bootIDAfter, err := suite.ReadBootID(requestCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// API might be unresponsive during reboot
|
// API might be unresponsive during reboot
|
||||||
return retry.ExpectedError(fmt.Errorf("error reading bootID for node %q: %w", node, err))
|
return retry.ExpectedError(fmt.Errorf("error reading bootID for node %q: %w", node, err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if bootIDAfter == bootIDBefore {
|
if bootIDAfter == bootIDBefore {
|
||||||
// bootID should be different after reboot
|
// 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 retry.ExpectedError(
|
||||||
}
|
fmt.Errorf(
|
||||||
|
"bootID didn't change for node %q: before %s, after %s",
|
||||||
|
node,
|
||||||
|
bootIDBefore,
|
||||||
|
bootIDAfter,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}()
|
}()
|
||||||
}(node)
|
}(node)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
type ResetSuite struct {
|
type ResetSuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,10 +88,12 @@ func (suite *ResetSuite) TestResetNodeByNode() {
|
|||||||
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
suite.AssertRebooted(
|
||||||
// force reboot after reset, as this is the only mode we can test
|
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||||
return base.IgnoreGRPCUnavailable(suite.Client.Reset(nodeCtx, true, true))
|
// force reboot after reset, as this is the only mode we can test
|
||||||
}, 10*time.Minute)
|
return base.IgnoreGRPCUnavailable(suite.Client.Reset(nodeCtx, true, true))
|
||||||
|
}, 10*time.Minute,
|
||||||
|
)
|
||||||
|
|
||||||
suite.ClearConnectionRefused(suite.ctx, node)
|
suite.ClearConnectionRefused(suite.ctx, node)
|
||||||
|
|
||||||
@ -118,10 +120,12 @@ func (suite *ResetSuite) testResetNoGraceful(nodeType machine.Type) {
|
|||||||
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
suite.AssertRebooted(
|
||||||
// force reboot after reset, as this is the only mode we can test
|
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||||
return base.IgnoreGRPCUnavailable(suite.Client.Reset(nodeCtx, false, true))
|
// force reboot after reset, as this is the only mode we can test
|
||||||
}, 5*time.Minute)
|
return base.IgnoreGRPCUnavailable(suite.Client.Reset(nodeCtx, false, true))
|
||||||
|
}, 5*time.Minute,
|
||||||
|
)
|
||||||
|
|
||||||
suite.ClearConnectionRefused(suite.ctx, node)
|
suite.ClearConnectionRefused(suite.ctx, node)
|
||||||
|
|
||||||
@ -162,19 +166,25 @@ func (suite *ResetSuite) TestResetWithSpecEphemeral() {
|
|||||||
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
suite.AssertRebooted(
|
||||||
// force reboot after reset, as this is the only mode we can test
|
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||||
return base.IgnoreGRPCUnavailable(suite.Client.ResetGeneric(nodeCtx, &machineapi.ResetRequest{
|
// force reboot after reset, as this is the only mode we can test
|
||||||
Reboot: true,
|
return base.IgnoreGRPCUnavailable(
|
||||||
Graceful: true,
|
suite.Client.ResetGeneric(
|
||||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
nodeCtx, &machineapi.ResetRequest{
|
||||||
{
|
Reboot: true,
|
||||||
Label: constants.EphemeralPartitionLabel,
|
Graceful: true,
|
||||||
Wipe: true,
|
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||||
},
|
{
|
||||||
},
|
Label: constants.EphemeralPartitionLabel,
|
||||||
}))
|
Wipe: true,
|
||||||
}, 5*time.Minute)
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}, 5*time.Minute,
|
||||||
|
)
|
||||||
|
|
||||||
suite.ClearConnectionRefused(suite.ctx, node)
|
suite.ClearConnectionRefused(suite.ctx, node)
|
||||||
|
|
||||||
@ -205,19 +215,25 @@ func (suite *ResetSuite) TestResetWithSpecState() {
|
|||||||
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
preReset, err := suite.HashKubeletCert(suite.ctx, node)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.AssertRebooted(suite.ctx, node, func(nodeCtx context.Context) error {
|
suite.AssertRebooted(
|
||||||
// force reboot after reset, as this is the only mode we can test
|
suite.ctx, node, func(nodeCtx context.Context) error {
|
||||||
return base.IgnoreGRPCUnavailable(suite.Client.ResetGeneric(nodeCtx, &machineapi.ResetRequest{
|
// force reboot after reset, as this is the only mode we can test
|
||||||
Reboot: true,
|
return base.IgnoreGRPCUnavailable(
|
||||||
Graceful: true,
|
suite.Client.ResetGeneric(
|
||||||
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
nodeCtx, &machineapi.ResetRequest{
|
||||||
{
|
Reboot: true,
|
||||||
Label: constants.StatePartitionLabel,
|
Graceful: true,
|
||||||
Wipe: true,
|
SystemPartitionsToWipe: []*machineapi.ResetPartitionSpec{
|
||||||
},
|
{
|
||||||
},
|
Label: constants.StatePartitionLabel,
|
||||||
}))
|
Wipe: true,
|
||||||
}, 5*time.Minute)
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}, 5*time.Minute,
|
||||||
|
)
|
||||||
|
|
||||||
suite.ClearConnectionRefused(suite.ctx, node)
|
suite.ClearConnectionRefused(suite.ctx, node)
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import (
|
|||||||
type VersionSuite struct {
|
type VersionSuite struct {
|
||||||
base.APISuite
|
base.APISuite
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +87,13 @@ func upgradePreviousToStable() upgradeSpec {
|
|||||||
return upgradeSpec{
|
return upgradeSpec{
|
||||||
ShortName: fmt.Sprintf("%s-%s", previousRelease, stableRelease),
|
ShortName: fmt.Sprintf("%s-%s", previousRelease, stableRelease),
|
||||||
|
|
||||||
SourceKernelPath: helpers.ArtifactPath(filepath.Join(trimVersion(previousRelease), constants.KernelAsset)),
|
SourceKernelPath: helpers.ArtifactPath(filepath.Join(trimVersion(previousRelease), constants.KernelAsset)),
|
||||||
SourceInitramfsPath: helpers.ArtifactPath(filepath.Join(trimVersion(previousRelease), constants.InitramfsAsset)),
|
SourceInitramfsPath: helpers.ArtifactPath(
|
||||||
|
filepath.Join(
|
||||||
|
trimVersion(previousRelease),
|
||||||
|
constants.InitramfsAsset,
|
||||||
|
),
|
||||||
|
),
|
||||||
SourceInstallerImage: fmt.Sprintf("%s:%s", "ghcr.io/siderolabs/installer", previousRelease),
|
SourceInstallerImage: fmt.Sprintf("%s:%s", "ghcr.io/siderolabs/installer", previousRelease),
|
||||||
SourceVersion: previousRelease,
|
SourceVersion: previousRelease,
|
||||||
SourceK8sVersion: previousK8sVersion,
|
SourceK8sVersion: previousK8sVersion,
|
||||||
@ -116,9 +121,14 @@ func upgradeStableToCurrent() upgradeSpec {
|
|||||||
SourceVersion: stableRelease,
|
SourceVersion: stableRelease,
|
||||||
SourceK8sVersion: stableK8sVersion,
|
SourceK8sVersion: stableK8sVersion,
|
||||||
|
|
||||||
TargetInstallerImage: fmt.Sprintf("%s/%s:%s", DefaultSettings.TargetInstallImageRegistry, images.DefaultInstallerImageName, DefaultSettings.CurrentVersion),
|
TargetInstallerImage: fmt.Sprintf(
|
||||||
TargetVersion: DefaultSettings.CurrentVersion,
|
"%s/%s:%s",
|
||||||
TargetK8sVersion: currentK8sVersion,
|
DefaultSettings.TargetInstallImageRegistry,
|
||||||
|
images.DefaultInstallerImageName,
|
||||||
|
DefaultSettings.CurrentVersion,
|
||||||
|
),
|
||||||
|
TargetVersion: DefaultSettings.CurrentVersion,
|
||||||
|
TargetK8sVersion: currentK8sVersion,
|
||||||
|
|
||||||
MasterNodes: DefaultSettings.MasterNodes,
|
MasterNodes: DefaultSettings.MasterNodes,
|
||||||
WorkerNodes: DefaultSettings.WorkerNodes,
|
WorkerNodes: DefaultSettings.WorkerNodes,
|
||||||
@ -127,7 +137,12 @@ func upgradeStableToCurrent() upgradeSpec {
|
|||||||
|
|
||||||
// upgradeCurrentToCurrent upgrades the current version to itself.
|
// upgradeCurrentToCurrent upgrades the current version to itself.
|
||||||
func upgradeCurrentToCurrent() upgradeSpec {
|
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{
|
return upgradeSpec{
|
||||||
ShortName: fmt.Sprintf("%s-%s", DefaultSettings.CurrentVersion, DefaultSettings.CurrentVersion),
|
ShortName: fmt.Sprintf("%s-%s", DefaultSettings.CurrentVersion, DefaultSettings.CurrentVersion),
|
||||||
@ -160,9 +175,14 @@ func upgradeStableToCurrentPreserve() upgradeSpec {
|
|||||||
SourceVersion: stableRelease,
|
SourceVersion: stableRelease,
|
||||||
SourceK8sVersion: stableK8sVersion,
|
SourceK8sVersion: stableK8sVersion,
|
||||||
|
|
||||||
TargetInstallerImage: fmt.Sprintf("%s/%s:%s", DefaultSettings.TargetInstallImageRegistry, images.DefaultInstallerImageName, DefaultSettings.CurrentVersion),
|
TargetInstallerImage: fmt.Sprintf(
|
||||||
TargetVersion: DefaultSettings.CurrentVersion,
|
"%s/%s:%s",
|
||||||
TargetK8sVersion: currentK8sVersion,
|
DefaultSettings.TargetInstallImageRegistry,
|
||||||
|
images.DefaultInstallerImageName,
|
||||||
|
DefaultSettings.CurrentVersion,
|
||||||
|
),
|
||||||
|
TargetVersion: DefaultSettings.CurrentVersion,
|
||||||
|
TargetK8sVersion: currentK8sVersion,
|
||||||
|
|
||||||
MasterNodes: 1,
|
MasterNodes: 1,
|
||||||
WorkerNodes: 0,
|
WorkerNodes: 0,
|
||||||
@ -181,9 +201,14 @@ func upgradeStableToCurrentPreserveStage() upgradeSpec {
|
|||||||
SourceVersion: stableRelease,
|
SourceVersion: stableRelease,
|
||||||
SourceK8sVersion: stableK8sVersion,
|
SourceK8sVersion: stableK8sVersion,
|
||||||
|
|
||||||
TargetInstallerImage: fmt.Sprintf("%s/%s:%s", DefaultSettings.TargetInstallImageRegistry, images.DefaultInstallerImageName, DefaultSettings.CurrentVersion),
|
TargetInstallerImage: fmt.Sprintf(
|
||||||
TargetVersion: DefaultSettings.CurrentVersion,
|
"%s/%s:%s",
|
||||||
TargetK8sVersion: currentK8sVersion,
|
DefaultSettings.TargetInstallImageRegistry,
|
||||||
|
images.DefaultInstallerImageName,
|
||||||
|
DefaultSettings.CurrentVersion,
|
||||||
|
),
|
||||||
|
TargetVersion: DefaultSettings.CurrentVersion,
|
||||||
|
TargetK8sVersion: currentK8sVersion,
|
||||||
|
|
||||||
MasterNodes: 1,
|
MasterNodes: 1,
|
||||||
WorkerNodes: 0,
|
WorkerNodes: 0,
|
||||||
@ -209,6 +234,7 @@ type UpgradeSuite struct {
|
|||||||
clusterAccess *access.Adapter
|
clusterAccess *access.Adapter
|
||||||
controlPlaneEndpoint string
|
controlPlaneEndpoint string
|
||||||
|
|
||||||
|
//nolint:containedctx
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
@ -333,55 +359,67 @@ func (suite *UpgradeSuite) setupCluster() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if DefaultSettings.CustomCNIURL != "" {
|
if DefaultSettings.CustomCNIURL != "" {
|
||||||
genOptions = append(genOptions, generate.WithClusterCNIConfig(&v1alpha1.CNIConfig{
|
genOptions = append(
|
||||||
CNIName: constants.CustomCNI,
|
genOptions, generate.WithClusterCNIConfig(
|
||||||
CNIUrls: []string{DefaultSettings.CustomCNIURL},
|
&v1alpha1.CNIConfig{
|
||||||
}))
|
CNIName: constants.CustomCNI,
|
||||||
|
CNIUrls: []string{DefaultSettings.CustomCNIURL},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if suite.spec.WithEncryption {
|
if suite.spec.WithEncryption {
|
||||||
genOptions = append(genOptions, generate.WithSystemDiskEncryption(&v1alpha1.SystemDiskEncryptionConfig{
|
genOptions = append(
|
||||||
StatePartition: &v1alpha1.EncryptionConfig{
|
genOptions, generate.WithSystemDiskEncryption(
|
||||||
EncryptionProvider: encryption.LUKS2,
|
&v1alpha1.SystemDiskEncryptionConfig{
|
||||||
EncryptionKeys: []*v1alpha1.EncryptionKey{
|
StatePartition: &v1alpha1.EncryptionConfig{
|
||||||
{
|
EncryptionProvider: encryption.LUKS2,
|
||||||
KeyNodeID: &v1alpha1.EncryptionKeyNodeID{},
|
EncryptionKeys: []*v1alpha1.EncryptionKey{
|
||||||
KeySlot: 0,
|
{
|
||||||
|
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)
|
versionContract, err := config.ParseContractFromVersion(suite.spec.SourceVersion)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
suite.configBundle, err = bundle.NewConfigBundle(bundle.WithInputOptions(
|
suite.configBundle, err = bundle.NewConfigBundle(
|
||||||
&bundle.InputOptions{
|
bundle.WithInputOptions(
|
||||||
ClusterName: clusterName,
|
&bundle.InputOptions{
|
||||||
Endpoint: suite.controlPlaneEndpoint,
|
ClusterName: clusterName,
|
||||||
KubeVersion: suite.spec.SourceK8sVersion,
|
Endpoint: suite.controlPlaneEndpoint,
|
||||||
GenOptions: append(
|
KubeVersion: suite.spec.SourceK8sVersion,
|
||||||
genOptions,
|
GenOptions: append(
|
||||||
generate.WithEndpointList(masterEndpoints),
|
genOptions,
|
||||||
generate.WithInstallImage(suite.spec.SourceInstallerImage),
|
generate.WithEndpointList(masterEndpoints),
|
||||||
generate.WithDNSDomain("cluster.local"),
|
generate.WithInstallImage(suite.spec.SourceInstallerImage),
|
||||||
generate.WithVersionContract(versionContract),
|
generate.WithDNSDomain("cluster.local"),
|
||||||
),
|
generate.WithVersionContract(versionContract),
|
||||||
}))
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
for i := 0; i < suite.spec.MasterNodes; i++ {
|
for i := 0; i < suite.spec.MasterNodes; i++ {
|
||||||
request.Nodes = append(request.Nodes,
|
request.Nodes = append(
|
||||||
|
request.Nodes,
|
||||||
provision.NodeRequest{
|
provision.NodeRequest{
|
||||||
Name: fmt.Sprintf("master-%d", i+1),
|
Name: fmt.Sprintf("master-%d", i+1),
|
||||||
Type: machine.TypeControlPlane,
|
Type: machine.TypeControlPlane,
|
||||||
@ -394,11 +432,13 @@ func (suite *UpgradeSuite) setupCluster() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Config: suite.configBundle.ControlPlane(),
|
Config: suite.configBundle.ControlPlane(),
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 1; i <= suite.spec.WorkerNodes; i++ {
|
for i := 1; i <= suite.spec.WorkerNodes; i++ {
|
||||||
request.Nodes = append(request.Nodes,
|
request.Nodes = append(
|
||||||
|
request.Nodes,
|
||||||
provision.NodeRequest{
|
provision.NodeRequest{
|
||||||
Name: fmt.Sprintf("worker-%d", i),
|
Name: fmt.Sprintf("worker-%d", i),
|
||||||
Type: machine.TypeWorker,
|
Type: machine.TypeWorker,
|
||||||
@ -411,10 +451,12 @@ func (suite *UpgradeSuite) setupCluster() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Config: suite.configBundle.Worker(),
|
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.WithBootlader(true),
|
||||||
provision.WithUEFI(true),
|
provision.WithUEFI(true),
|
||||||
provision.WithTalosConfig(suite.configBundle.TalosConfig()),
|
provision.WithTalosConfig(suite.configBundle.TalosConfig()),
|
||||||
@ -457,7 +499,14 @@ func (suite *UpgradeSuite) waitForClusterHealth() {
|
|||||||
checkCtx, checkCtxCancel := context.WithTimeout(suite.ctx, 15*time.Minute)
|
checkCtx, checkCtxCancel := context.WithTimeout(suite.ctx, 15*time.Minute)
|
||||||
defer checkCtxCancel()
|
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(
|
err := retry.Constant(
|
||||||
time.Minute,
|
time.Minute,
|
||||||
).Retry(func() error {
|
).Retry(
|
||||||
var e error
|
func() error {
|
||||||
v, e = client.Version(ctx)
|
var e error
|
||||||
|
v, e = client.Version(ctx)
|
||||||
|
|
||||||
return retry.ExpectedError(e)
|
return retry.ExpectedError(e)
|
||||||
})
|
},
|
||||||
|
)
|
||||||
|
|
||||||
suite.Require().NoError(err)
|
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
|
var v *machineapi.VersionResponse
|
||||||
|
|
||||||
v, err = client.Version(nodeCtx)
|
v, err = client.Version(nodeCtx)
|
||||||
@ -526,22 +580,30 @@ func (suite *UpgradeSuite) upgradeNode(client *talosclient.Client, node provisio
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
err = retry.Constant(time.Minute, retry.WithUnits(10*time.Second)).Retry(func() error {
|
err = retry.Constant(time.Minute, retry.WithUnits(10*time.Second)).Retry(
|
||||||
resp, err = client.Upgrade(nodeCtx, suite.spec.TargetInstallerImage, suite.spec.UpgradePreserve, suite.spec.UpgradeStage, false)
|
func() error {
|
||||||
if err != nil {
|
resp, err = client.Upgrade(
|
||||||
if strings.Contains(err.Error(), "leader changed") {
|
nodeCtx,
|
||||||
return retry.ExpectedError(err)
|
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 nil
|
||||||
return retry.ExpectedError(err)
|
},
|
||||||
}
|
)
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
err = base.IgnoreGRPCUnavailable(err)
|
err = base.IgnoreGRPCUnavailable(err)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
@ -554,22 +616,33 @@ func (suite *UpgradeSuite) upgradeNode(client *talosclient.Client, node provisio
|
|||||||
time.Sleep(10 * time.Second)
|
time.Sleep(10 * time.Second)
|
||||||
|
|
||||||
// wait for the version to be equal to target version
|
// wait for the version to be equal to target version
|
||||||
suite.Require().NoError(retry.Constant(10 * time.Minute).Retry(func() error {
|
suite.Require().NoError(
|
||||||
var version string
|
retry.Constant(10 * time.Minute).Retry(
|
||||||
|
func() error {
|
||||||
|
var version string
|
||||||
|
|
||||||
version, err = suite.readVersion(nodeCtx, client)
|
version, err = suite.readVersion(nodeCtx, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// API might be unresponsive during upgrade
|
// API might be unresponsive during upgrade
|
||||||
return retry.ExpectedError(err)
|
return retry.ExpectedError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if version != suite.spec.TargetVersion {
|
if version != suite.spec.TargetVersion {
|
||||||
// upgrade not finished yet
|
// 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 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()
|
suite.waitForClusterHealth()
|
||||||
}
|
}
|
||||||
@ -622,7 +695,13 @@ func (suite *UpgradeSuite) untaint(name string) {
|
|||||||
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, corev1.Node{})
|
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, corev1.Node{})
|
||||||
suite.Require().NoError(err)
|
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)
|
suite.Require().NoError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,7 +749,8 @@ func (suite *UpgradeSuite) SuiteName() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
allSuites = append(allSuites,
|
allSuites = append(
|
||||||
|
allSuites,
|
||||||
&UpgradeSuite{specGen: upgradePreviousToStable, track: 0},
|
&UpgradeSuite{specGen: upgradePreviousToStable, track: 0},
|
||||||
&UpgradeSuite{specGen: upgradeStableToCurrent, track: 1},
|
&UpgradeSuite{specGen: upgradeStableToCurrent, track: 1},
|
||||||
&UpgradeSuite{specGen: upgradeCurrentToCurrent, track: 2},
|
&UpgradeSuite{specGen: upgradeCurrentToCurrent, track: 2},
|
||||||
|
@ -29,7 +29,8 @@ import (
|
|||||||
|
|
||||||
type inspector struct {
|
type inspector struct {
|
||||||
client *containerd.Client
|
client *containerd.Client
|
||||||
nsctx context.Context
|
//nolint:containedctx
|
||||||
|
nsctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
type inspectorOptions struct {
|
type inspectorOptions struct {
|
||||||
@ -97,7 +98,11 @@ func (i *inspector) Images() (map[string]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocyclo,cyclop
|
//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{}
|
cp := &ctrs.Container{}
|
||||||
|
|
||||||
info, err := cntr.Info(i.nsctx)
|
info, err := cntr.Info(i.nsctx)
|
||||||
@ -222,7 +227,11 @@ func (i *inspector) containerInfo(cntr containerd.Container, imageList map[strin
|
|||||||
cp.IsPodSandbox = true
|
cp.IsPodSandbox = true
|
||||||
} else if singleLookup && cns != "" && cname != "" {
|
} else if singleLookup && cns != "" && cname != "" {
|
||||||
// try to find matching infrastructure container and pull sandbox from it
|
// 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)
|
infraContainers, err := i.client.Containers(i.nsctx, query)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -274,7 +283,11 @@ func (i *inspector) Container(id string) (*ctrs.Container, error) {
|
|||||||
pod = pod[:semicolonIdx]
|
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 != "" {
|
if name != "" {
|
||||||
query += fmt.Sprintf(",labels.\"io.kubernetes.container.name\"==%q", name)
|
query += fmt.Sprintf(",labels.\"io.kubernetes.container.name\"==%q", name)
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
|
|
||||||
type inspector struct {
|
type inspector struct {
|
||||||
client *criclient.Client
|
client *criclient.Client
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
}
|
}
|
||||||
|
|
||||||
type inspectorOptions struct {
|
type inspectorOptions struct {
|
||||||
@ -112,15 +112,17 @@ func (i *inspector) Container(id string) (*ctrs.Container, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if name == "" { // request for a pod sandbox
|
if name == "" { // request for a pod sandbox
|
||||||
sandboxes, err := i.client.ListPodSandbox(i.ctx, &runtimeapi.PodSandboxFilter{
|
sandboxes, err := i.client.ListPodSandbox(
|
||||||
State: &runtimeapi.PodSandboxStateValue{
|
i.ctx, &runtimeapi.PodSandboxFilter{
|
||||||
State: runtimeapi.PodSandboxState_SANDBOX_READY,
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -138,13 +140,15 @@ func (i *inspector) Container(id string) (*ctrs.Container, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// request for a container
|
// request for a container
|
||||||
containers, err := i.client.ListContainers(i.ctx, &runtimeapi.ContainerFilter{
|
containers, err := i.client.ListContainers(
|
||||||
LabelSelector: map[string]string{
|
i.ctx, &runtimeapi.ContainerFilter{
|
||||||
"io.kubernetes.pod.name": pod,
|
LabelSelector: map[string]string{
|
||||||
"io.kubernetes.pod.namespace": namespace,
|
"io.kubernetes.pod.name": pod,
|
||||||
"io.kubernetes.container.name": name,
|
"io.kubernetes.pod.namespace": namespace,
|
||||||
|
"io.kubernetes.container.name": name,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -242,11 +246,13 @@ func (i *inspector) buildContainer(container *runtimeapi.Container) (*ctrs.Conta
|
|||||||
//
|
//
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func (i *inspector) Pods() ([]*ctrs.Pod, error) {
|
func (i *inspector) Pods() ([]*ctrs.Pod, error) {
|
||||||
sandboxes, err := i.client.ListPodSandbox(i.ctx, &runtimeapi.PodSandboxFilter{
|
sandboxes, err := i.client.ListPodSandbox(
|
||||||
State: &runtimeapi.PodSandboxStateValue{
|
i.ctx, &runtimeapi.PodSandboxFilter{
|
||||||
State: runtimeapi.PodSandboxState_SANDBOX_READY,
|
State: &runtimeapi.PodSandboxStateValue{
|
||||||
|
State: runtimeapi.PodSandboxState_SANDBOX_READY,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ type CRISuite struct {
|
|||||||
containerdAddress string
|
containerdAddress string
|
||||||
|
|
||||||
client *criclient.Client
|
client *criclient.Client
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
inspector ctrs.Inspector
|
inspector ctrs.Inspector
|
||||||
@ -175,12 +175,15 @@ func (suite *CRISuite) SetupTest() {
|
|||||||
suite.pods = append(suite.pods, podSandboxID)
|
suite.pods = append(suite.pods, podSandboxID)
|
||||||
suite.Require().Len(podSandboxID, 64)
|
suite.Require().Len(podSandboxID, 64)
|
||||||
|
|
||||||
imageRef, err := suite.client.PullImage(suite.ctx, &runtimeapi.ImageSpec{
|
imageRef, err := suite.client.PullImage(
|
||||||
Image: busyboxImage,
|
suite.ctx, &runtimeapi.ImageSpec{
|
||||||
}, podSandboxConfig)
|
Image: busyboxImage,
|
||||||
|
}, podSandboxConfig,
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
ctrID, err := suite.client.CreateContainer(suite.ctx, podSandboxID,
|
ctrID, err := suite.client.CreateContainer(
|
||||||
|
suite.ctx, podSandboxID,
|
||||||
&runtimeapi.ContainerConfig{
|
&runtimeapi.ContainerConfig{
|
||||||
Metadata: &runtimeapi.ContainerMetadata{
|
Metadata: &runtimeapi.ContainerMetadata{
|
||||||
Name: "etcd",
|
Name: "etcd",
|
||||||
@ -197,7 +200,8 @@ func (suite *CRISuite) SetupTest() {
|
|||||||
Image: imageRef,
|
Image: imageRef,
|
||||||
},
|
},
|
||||||
Command: []string{"/bin/sh", "-c", "sleep 3600"},
|
Command: []string{"/bin/sh", "-c", "sleep 3600"},
|
||||||
}, podSandboxConfig)
|
}, podSandboxConfig,
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
suite.Require().Len(ctrID, 64)
|
suite.Require().Len(ctrID, 64)
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ type CRISuite struct {
|
|||||||
containerdAddress string
|
containerdAddress string
|
||||||
|
|
||||||
client *cri.Client
|
client *cri.Client
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,17 +165,22 @@ func (suite *CRISuite) TestRunSandboxContainer() {
|
|||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
suite.Require().Len(podSandboxID, 64)
|
suite.Require().Len(podSandboxID, 64)
|
||||||
|
|
||||||
imageRef, err := suite.client.PullImage(suite.ctx, &runtimeapi.ImageSpec{
|
imageRef, err := suite.client.PullImage(
|
||||||
Image: busyboxImage,
|
suite.ctx, &runtimeapi.ImageSpec{
|
||||||
}, podSandboxConfig)
|
Image: busyboxImage,
|
||||||
|
}, podSandboxConfig,
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
_, err = suite.client.ImageStatus(suite.ctx, &runtimeapi.ImageSpec{
|
_, err = suite.client.ImageStatus(
|
||||||
Image: imageRef,
|
suite.ctx, &runtimeapi.ImageSpec{
|
||||||
})
|
Image: imageRef,
|
||||||
|
},
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
ctrID, err := suite.client.CreateContainer(suite.ctx, podSandboxID,
|
ctrID, err := suite.client.CreateContainer(
|
||||||
|
suite.ctx, podSandboxID,
|
||||||
&runtimeapi.ContainerConfig{
|
&runtimeapi.ContainerConfig{
|
||||||
Metadata: &runtimeapi.ContainerMetadata{
|
Metadata: &runtimeapi.ContainerMetadata{
|
||||||
Name: "etcd",
|
Name: "etcd",
|
||||||
@ -192,7 +197,8 @@ func (suite *CRISuite) TestRunSandboxContainer() {
|
|||||||
Image: imageRef,
|
Image: imageRef,
|
||||||
},
|
},
|
||||||
Command: []string{"/bin/sh", "-c", "sleep 3600"},
|
Command: []string{"/bin/sh", "-c", "sleep 3600"},
|
||||||
}, podSandboxConfig)
|
}, podSandboxConfig,
|
||||||
|
)
|
||||||
suite.Require().NoError(err)
|
suite.Require().NoError(err)
|
||||||
suite.Require().Len(ctrID, 64)
|
suite.Require().Len(ctrID, 64)
|
||||||
|
|
||||||
|
@ -25,12 +25,15 @@ type Connection struct {
|
|||||||
bootstrapEndpoint string
|
bootstrapEndpoint string
|
||||||
nodeClient *client.Client
|
nodeClient *client.Client
|
||||||
bootstrapClient *client.Client
|
bootstrapClient *client.Client
|
||||||
nodeCtx context.Context
|
nodeCtx context.Context //nolint:containedctx
|
||||||
bootstrapCtx context.Context
|
bootstrapCtx context.Context //nolint:containedctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConnection creates new installer connection.
|
// 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{
|
c := &Connection{
|
||||||
nodeEndpoint: endpoint,
|
nodeEndpoint: endpoint,
|
||||||
nodeClient: nodeClient,
|
nodeClient: nodeClient,
|
||||||
@ -48,7 +51,10 @@ func NewConnection(ctx context.Context, nodeClient *client.Client, endpoint stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GenerateConfiguration calls GenerateConfiguration on the target/bootstrap node.
|
// 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 {
|
if c.bootstrapClient != nil {
|
||||||
return c.bootstrapClient.GenerateConfiguration(c.bootstrapCtx, req, callOptions...)
|
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.
|
// 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...)
|
return c.nodeClient.ApplyConfiguration(c.nodeCtx, req, callOptions...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ type Installer struct {
|
|||||||
app *tview.Application
|
app *tview.Application
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
err error
|
err error
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
addedPages map[string]bool
|
addedPages map[string]bool
|
||||||
state *State
|
state *State
|
||||||
@ -204,30 +204,32 @@ func (installer *Installer) configure() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
capture := installer.app.GetInputCapture()
|
capture := installer.app.GetInputCapture()
|
||||||
installer.app.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
installer.app.SetInputCapture(
|
||||||
//nolint:exhaustive
|
func(e *tcell.EventKey) *tcell.EventKey {
|
||||||
switch e.Key() {
|
//nolint:exhaustive
|
||||||
case tcell.KeyCtrlN:
|
switch e.Key() {
|
||||||
setPage(currentPage + 1)
|
case tcell.KeyCtrlN:
|
||||||
case tcell.KeyCtrlB:
|
setPage(currentPage + 1)
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if capture != nil {
|
// page jump by ctrl/alt + N
|
||||||
return capture(e)
|
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)
|
defer installer.app.SetInputCapture(capture)
|
||||||
|
|
||||||
@ -240,9 +242,11 @@ func (installer *Installer) configure() error {
|
|||||||
button.SetInactiveColors(inactiveColor, tcell.ColorIvory)
|
button.SetInactiveColors(inactiveColor, tcell.ColorIvory)
|
||||||
|
|
||||||
func(page int) {
|
func(page int) {
|
||||||
button.SetSelectedFunc(func() {
|
button.SetSelectedFunc(
|
||||||
setPage(page)
|
func() {
|
||||||
})
|
setPage(page)
|
||||||
|
},
|
||||||
|
)
|
||||||
}(index)
|
}(index)
|
||||||
|
|
||||||
menu.AddItem(button, len(name)+4, 1, false)
|
menu.AddItem(button, len(name)+4, 1, false)
|
||||||
@ -267,9 +271,11 @@ func (installer *Installer) configure() error {
|
|||||||
|
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
back := form.AddMenuButton("[::u]B[::-]ack", false)
|
back := form.AddMenuButton("[::u]B[::-]ack", false)
|
||||||
back.SetSelectedFunc(func() {
|
back.SetSelectedFunc(
|
||||||
setPage(index - 1)
|
func() {
|
||||||
})
|
setPage(index - 1)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
addMenuItem(p.name, index)
|
addMenuItem(p.name, index)
|
||||||
@ -278,15 +284,19 @@ func (installer *Installer) configure() error {
|
|||||||
|
|
||||||
if index < len(state.pages)-1 {
|
if index < len(state.pages)-1 {
|
||||||
next := form.AddMenuButton("[::u]N[::-]ext", index == 0)
|
next := form.AddMenuButton("[::u]N[::-]ext", index == 0)
|
||||||
next.SetSelectedFunc(func() {
|
next.SetSelectedFunc(
|
||||||
setPage(index + 1)
|
func() {
|
||||||
})
|
setPage(index + 1)
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
install := form.AddMenuButton("Install", false)
|
install := form.AddMenuButton("Install", false)
|
||||||
install.SetBackgroundColor(tcell.ColorGreen)
|
install.SetBackgroundColor(tcell.ColorGreen)
|
||||||
install.SetSelectedFunc(func() {
|
install.SetSelectedFunc(
|
||||||
close(done)
|
func() {
|
||||||
})
|
close(done)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
installer.addPage(p.name, form, index == 0, menu)
|
installer.addPage(p.name, form, index == 0, menu)
|
||||||
@ -362,9 +372,11 @@ func (installer *Installer) apply(conn *Connection) error {
|
|||||||
|
|
||||||
// TODO: progress bar, logs?
|
// TODO: progress bar, logs?
|
||||||
list.AddItem(s, 1, 1, false)
|
list.AddItem(s, 1, 1, false)
|
||||||
_, err = conn.ApplyConfiguration(&machineapi.ApplyConfigurationRequest{
|
_, err = conn.ApplyConfiguration(
|
||||||
Data: config,
|
&machineapi.ApplyConfigurationRequest{
|
||||||
})
|
Data: config,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
s.Stop(err == nil)
|
s.Stop(err == nil)
|
||||||
|
|
||||||
@ -453,19 +465,21 @@ func (installer *Installer) writeTalosconfig(list *tview.Flex, talosconfig *clie
|
|||||||
func (installer *Installer) awaitKey(keys ...tcell.Key) {
|
func (installer *Installer) awaitKey(keys ...tcell.Key) {
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
|
||||||
installer.app.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
installer.app.SetInputCapture(
|
||||||
for _, key := range keys {
|
func(e *tcell.EventKey) *tcell.EventKey {
|
||||||
if e.Key() == key {
|
for _, key := range keys {
|
||||||
|
if e.Key() == key {
|
||||||
|
close(done)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(keys) == 0 {
|
||||||
close(done)
|
close(done)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if len(keys) == 0 {
|
return e
|
||||||
close(done)
|
},
|
||||||
}
|
)
|
||||||
|
|
||||||
return e
|
|
||||||
})
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
@ -482,10 +496,12 @@ func (installer *Installer) showModal(title, text string, buttons ...string) int
|
|||||||
modal := tview.NewModal().
|
modal := tview.NewModal().
|
||||||
SetText(text).
|
SetText(text).
|
||||||
AddButtons(buttons).
|
AddButtons(buttons).
|
||||||
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
SetDoneFunc(
|
||||||
index = buttonIndex
|
func(buttonIndex int, buttonLabel string) {
|
||||||
close(done)
|
index = buttonIndex
|
||||||
})
|
close(done)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
installer.addPage(title, modal, true, nil)
|
installer.addPage(title, modal, true, nil)
|
||||||
installer.app.SetFocus(modal)
|
installer.app.SetFocus(modal)
|
||||||
@ -524,8 +540,10 @@ func (installer *Installer) addPage(name string, primitive tview.Primitive, swit
|
|||||||
if switchToPage {
|
if switchToPage {
|
||||||
installer.pages.AddAndSwitchToPage(name, frame, true)
|
installer.pages.AddAndSwitchToPage(name, frame, true)
|
||||||
} else {
|
} else {
|
||||||
installer.pages.AddPage(name,
|
installer.pages.AddPage(
|
||||||
frame, true, false)
|
name,
|
||||||
|
frame, true, false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} else if switchToPage {
|
} else if switchToPage {
|
||||||
installer.pages.SwitchToPage(name)
|
installer.pages.SwitchToPage(name)
|
||||||
|
@ -32,7 +32,7 @@ type Stream struct {
|
|||||||
source Source
|
source Source
|
||||||
options *Options
|
options *Options
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context //nolint:containedctx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Source is an interface describing the source of a Stream.
|
// 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)
|
options.Log(" > %q: waiting for node update", node)
|
||||||
|
|
||||||
if err = retry.Constant(3*time.Minute, retry.WithUnits(10*time.Second)).Retry(func() error {
|
if err = retry.Constant(3*time.Minute, retry.WithUnits(10*time.Second)).Retry(
|
||||||
return checkNodeKubeletVersion(ctx, cluster, node, "v"+options.ToVersion)
|
func() error {
|
||||||
}); err != nil {
|
return checkNodeKubeletVersion(ctx, cluster, node, "v"+options.ToVersion)
|
||||||
|
},
|
||||||
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,7 +197,10 @@ func upgradeKubeletOnNode(ctx context.Context, cluster UpgradeProvider, options
|
|||||||
return nil
|
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 {
|
return func(config *v1alpha1config.Config) error {
|
||||||
if config.MachineConfig == nil {
|
if config.MachineConfig == nil {
|
||||||
config.MachineConfig = &v1alpha1config.MachineConfig{}
|
config.MachineConfig = &v1alpha1config.MachineConfig{}
|
||||||
@ -206,15 +211,15 @@ func upgradeKubeletPatcher(options UpgradeOptions, kubeletSpec resource.Resource
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
any *resource.Any
|
anyResource *resource.Any
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
|
|
||||||
if any, ok = kubeletSpec.(*resource.Any); !ok {
|
if anyResource, ok = kubeletSpec.(*resource.Any); !ok {
|
||||||
return fmt.Errorf("unexpected resource type")
|
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) {
|
logUpdate := func(oldImage string) {
|
||||||
parts := strings.Split(oldImage, ":")
|
parts := strings.Split(oldImage, ":")
|
||||||
@ -287,7 +292,13 @@ func checkNodeKubeletVersion(ctx context.Context, cluster UpgradeProvider, nodeT
|
|||||||
nodeFound = true
|
nodeFound = true
|
||||||
|
|
||||||
if node.Status.NodeInfo.KubeletVersion != version {
|
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
|
ready := false
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
type Reader struct {
|
type Reader struct {
|
||||||
source *os.File
|
source *os.File
|
||||||
|
|
||||||
|
//nolint:containedctx
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
ctxCancel context.CancelFunc
|
ctxCancel context.CancelFunc
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
"google.golang.org/grpc/reflection"
|
"google.golang.org/grpc/reflection"
|
||||||
"google.golang.org/grpc/status"
|
"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"
|
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.
|
// 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))
|
recoveryOpt := grpc_recovery.WithRecoveryHandler(recoveryHandler(logger))
|
||||||
opts.UnaryInterceptors = append([]grpc.UnaryServerInterceptor{grpc_recovery.UnaryServerInterceptor(recoveryOpt)}, opts.UnaryInterceptors...)
|
opts.UnaryInterceptors = append(
|
||||||
opts.StreamInterceptors = append([]grpc.StreamServerInterceptor{grpc_recovery.StreamServerInterceptor(recoveryOpt)}, opts.StreamInterceptors...)
|
[]grpc.UnaryServerInterceptor{grpc_recovery.UnaryServerInterceptor(recoveryOpt)},
|
||||||
|
opts.UnaryInterceptors...,
|
||||||
|
)
|
||||||
|
opts.StreamInterceptors = append(
|
||||||
|
[]grpc.StreamServerInterceptor{grpc_recovery.StreamServerInterceptor(recoveryOpt)},
|
||||||
|
opts.StreamInterceptors...,
|
||||||
|
)
|
||||||
|
|
||||||
if logger != nil {
|
if logger != nil {
|
||||||
// Logging is installed as the first middleware (even before recovery middleware) in the chain
|
// 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).
|
// 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.
|
// It also tracks the whole duration of the request, including other middleware overhead.
|
||||||
logMiddleware := grpclog.NewMiddleware(logger)
|
logMiddleware := grpclog.NewMiddleware(logger)
|
||||||
opts.UnaryInterceptors = append([]grpc.UnaryServerInterceptor{logMiddleware.UnaryInterceptor()}, opts.UnaryInterceptors...)
|
opts.UnaryInterceptors = append(
|
||||||
opts.StreamInterceptors = append([]grpc.StreamServerInterceptor{logMiddleware.StreamInterceptor()}, opts.StreamInterceptors...)
|
[]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.UnaryInterceptor(grpc_middleware.ChainUnaryServer(opts.UnaryInterceptors...)),
|
||||||
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(opts.StreamInterceptors...)),
|
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