Skip to content

Commit

Permalink
fix: separate handlers for control-plane and workers
Browse files Browse the repository at this point in the history
  • Loading branch information
dkoshkin committed Oct 4, 2023
1 parent a57eb29 commit 497c612
Show file tree
Hide file tree
Showing 11 changed files with 328 additions and 123 deletions.
8 changes: 8 additions & 0 deletions common/pkg/capi/clustertopology/handlers/mutation/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ import (
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers"
)

type MutateFunc func(
ctx context.Context,
obj runtime.Object,
vars map[string]apiextensionsv1.JSON,
holderRef runtimehooksv1.HolderReference,
clusterKey client.ObjectKey,
) error

type MetaMutator interface {
Mutate(
ctx context.Context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func InfrastructureWorkerMachineTemplates(

// InfrastructureControlPlaneMachines selector matches against infrastructure control-plane machines.
// Passing in the API version (not the API group) is required because different providers could support different API
// versions. This also allows for a oatch to select multiple infrastructure versions for the same provider.
// versions. This also allows for a patch to select multiple infrastructure versions for the same provider.
func InfrastructureControlPlaneMachines(
capiInfrastructureAPIVersion, kind string,
) clusterv1.PatchSelector {
Expand Down
157 changes: 157 additions & 0 deletions pkg/handlers/docker/mutation/customimage/inject_control_plane.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// Copyright 2023 D2iQ, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package customimage

import (
"context"
_ "embed"
"fmt"
"strings"

apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/d2iq-labs/capi-runtime-extensions/api/v1alpha1"
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/apis"
commonhandlers "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers"
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers/mutation"
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches"
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches/selectors"
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/variables"
capdv1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1"
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers"
dockerclusterconfig "github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/docker/clusterconfig"
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/clusterconfig"
)

const (
// HandlerNamePatch is the name of the inject handler.
HandlerNamePatch = "DockerCustomImagePatch"

defaultKinDImageRepository = "ghcr.io/mesosphere/kind-node"
)

type customImageControlPlanePatchHandler struct {
variableName string
variableFieldPath []string
}

var (
_ commonhandlers.Named = &customImageControlPlanePatchHandler{}
_ mutation.GeneratePatches = &customImageControlPlanePatchHandler{}
_ mutation.MetaMutator = &customImageControlPlanePatchHandler{}
)

func NewControlPlanePatch() *customImageControlPlanePatchHandler {
return newCustomImageControlPlanePatchHandler(VariableName)
}

func NewControlPlaneMetaPatch() *customImageControlPlanePatchHandler {
return newCustomImageControlPlanePatchHandler(
clusterconfig.MetaVariableName,
clusterconfig.MetaControlPlaneConfigName,
dockerclusterconfig.DockerVariableName,
VariableName,
)
}

func newCustomImageControlPlanePatchHandler(
variableName string,
variableFieldPath ...string,
) *customImageControlPlanePatchHandler {
return &customImageControlPlanePatchHandler{
variableName: variableName,
variableFieldPath: variableFieldPath,
}
}

func (h *customImageControlPlanePatchHandler) Name() string {
return HandlerNamePatch
}

func (h *customImageControlPlanePatchHandler) Mutate(
ctx context.Context,
obj runtime.Object,
vars map[string]apiextensionsv1.JSON,
holderRef runtimehooksv1.HolderReference,
_ client.ObjectKey,
) error {
log := ctrl.LoggerFrom(ctx).WithValues(
"holderRef", holderRef,
)

customImageVar, found, err := variables.Get[v1alpha1.OCIImage](
vars,
h.variableName,
h.variableFieldPath...,
)
if err != nil {
return err
}
if !found {
log.V(5).
Info("Docker customImage variable not defined for control-plane, using default KinD node image")
}

log = log.WithValues(
"variableName",
h.variableName,
"variableFieldPath",
h.variableFieldPath,
"variableValue",
customImageVar,
)

return patches.Generate(
obj,
vars,
&holderRef,
selectors.InfrastructureControlPlaneMachines("v1beta1", "DockerMachineTemplate"),
log,
func(obj *capdv1.DockerMachineTemplate) error {
variablePath := []string{"builtin", "controlPlane", "version"}

if customImageVar == "" {
kubernetesVersion, found, err := variables.Get[string](
vars,
variablePath[0],
variablePath[1:]...)
if err != nil {
return err
}
if !found {
return fmt.Errorf(
"missing required variable: %s",
strings.Join(variablePath, "."),
)
}

customImageVar = v1alpha1.OCIImage(
defaultKinDImageRepository + ":" + kubernetesVersion,
)
}

log.WithValues(
"patchedObjectKind", obj.GetObjectKind().GroupVersionKind().String(),
"patchedObjectName", client.ObjectKeyFromObject(obj),
"customImage", customImageVar,
).Info("setting customImage in control plane DockerMachineTemplate spec")

obj.Spec.Template.Spec.CustomImage = string(customImageVar)

return nil
},
)
}

func (h *customImageControlPlanePatchHandler) GeneratePatches(
ctx context.Context,
req *runtimehooksv1.GeneratePatchesRequest,
resp *runtimehooksv1.GeneratePatchesResponse,
) {
handlers.GeneratePatches(ctx, req, resp, apis.CAPDDecoder(), h.Mutate)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2023 D2iQ, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package customimage

import (
"testing"

"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/handlers/mutation"
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/docker/mutation/customimage/tests"
)

func TestControlPlaneGeneratePatches(t *testing.T) {
t.Parallel()

tests.TestControlPlaneGeneratePatches(
t,
func() mutation.GeneratePatches { return NewControlPlanePatch() },
VariableName,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1"
"sigs.k8s.io/cluster-api/exp/runtime/topologymutation"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

Expand All @@ -24,65 +23,60 @@ import (
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/patches/selectors"
"github.com/d2iq-labs/capi-runtime-extensions/common/pkg/capi/clustertopology/variables"
capdv1 "github.com/d2iq-labs/capi-runtime-extensions/common/pkg/external/sigs.k8s.io/cluster-api/test/infrastructure/docker/api/v1beta1"
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers"
dockerclusterconfig "github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/docker/clusterconfig"
dockerworkerconfig "github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/docker/workerconfig"
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/clusterconfig"
"github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers/generic/workerconfig"
)

const (
// HandlerNamePatch is the name of the inject handler.
HandlerNamePatch = "DockerCustomImagePatch"

defaultKinDImageRepository = "ghcr.io/mesosphere/kind-node"
)

type customImagePatchHandler struct {
type customImageWorkerPatchHandler struct {
variableName string
variableFieldPath []string
}

var (
_ commonhandlers.Named = &customImagePatchHandler{}
_ mutation.GeneratePatches = &customImagePatchHandler{}
_ mutation.MetaMutator = &customImagePatchHandler{}
_ commonhandlers.Named = &customImageWorkerPatchHandler{}
_ mutation.GeneratePatches = &customImageWorkerPatchHandler{}
_ mutation.MetaMutator = &customImageWorkerPatchHandler{}
)

func NewPatch() *customImagePatchHandler {
return newCustomImagePatchHandler(VariableName)
func NewWorkerPatch() *customImageWorkerPatchHandler {
return newcustomImageWorkerPatchHandler(VariableName)
}

func NewMetaPatch() *customImagePatchHandler {
return newCustomImagePatchHandler(
func NewWorkerInClusterConfigMetaPatch() *customImageControlPlanePatchHandler {
return newCustomImageControlPlanePatchHandler(
clusterconfig.MetaVariableName,
clusterconfig.MetaWorkerConfigName,
dockerclusterconfig.DockerVariableName,
VariableName,
)
}

func NewMetaWorkerPatch() *customImagePatchHandler {
return newCustomImagePatchHandler(
func NewMetaWorkerPatch() *customImageWorkerPatchHandler {
return newcustomImageWorkerPatchHandler(
workerconfig.MetaVariableName,
dockerworkerconfig.DockerVariableName,
VariableName,
)
}

func newCustomImagePatchHandler(
func newcustomImageWorkerPatchHandler(
variableName string,
variableFieldPath ...string,
) *customImagePatchHandler {
return &customImagePatchHandler{
) *customImageWorkerPatchHandler {
return &customImageWorkerPatchHandler{
variableName: variableName,
variableFieldPath: variableFieldPath,
}
}

func (h *customImagePatchHandler) Name() string {
func (h *customImageWorkerPatchHandler) Name() string {
return HandlerNamePatch
}

func (h *customImagePatchHandler) Mutate(
func (h *customImageWorkerPatchHandler) Mutate(
ctx context.Context,
obj runtime.Object,
vars map[string]apiextensionsv1.JSON,
Expand All @@ -102,7 +96,8 @@ func (h *customImagePatchHandler) Mutate(
return err
}
if !found {
log.V(5).Info("Docker customImage variable not defined, using default KinD node image")
log.V(5).
Info("Docker customImage variable not defined for workers, using default KinD node image")
}

log = log.WithValues(
Expand All @@ -114,7 +109,7 @@ func (h *customImagePatchHandler) Mutate(
customImageVar,
)

err = patches.Generate(
return patches.Generate(
obj,
vars,
&holderRef,
Expand Down Expand Up @@ -154,74 +149,12 @@ func (h *customImagePatchHandler) Mutate(
return nil
},
)

if err != nil {
return err
}

if h.variableName == workerconfig.MetaVariableName {
return nil
}

return patches.Generate(
obj,
vars,
&holderRef,
selectors.InfrastructureControlPlaneMachines("v1beta1", "DockerMachineTemplate"),
log,
func(obj *capdv1.DockerMachineTemplate) error {
variablePath := []string{"builtin", "controlPlane", "version"}

if customImageVar == "" {
kubernetesVersion, found, err := variables.Get[string](
vars,
variablePath[0],
variablePath[1:]...)
if err != nil {
return err
}
if !found {
return fmt.Errorf(
"missing required variable: %s",
strings.Join(variablePath, "."),
)
}

customImageVar = v1alpha1.OCIImage(
defaultKinDImageRepository + ":" + kubernetesVersion,
)
}

log.WithValues(
"patchedObjectKind", obj.GetObjectKind().GroupVersionKind().String(),
"patchedObjectName", client.ObjectKeyFromObject(obj),
"customImage", customImageVar,
).Info("setting customImage in control plane DockerMachineTemplate spec")

obj.Spec.Template.Spec.CustomImage = string(customImageVar)

return nil
},
)
}

func (h *customImagePatchHandler) GeneratePatches(
func (h *customImageWorkerPatchHandler) GeneratePatches(
ctx context.Context,
req *runtimehooksv1.GeneratePatchesRequest,
resp *runtimehooksv1.GeneratePatchesResponse,
) {
topologymutation.WalkTemplates(
ctx,
apis.CAPDDecoder(),
req,
resp,
func(
ctx context.Context,
obj runtime.Object,
vars map[string]apiextensionsv1.JSON,
holderRef runtimehooksv1.HolderReference,
) error {
return h.Mutate(ctx, obj, vars, holderRef, client.ObjectKey{})
},
)
handlers.GeneratePatches(ctx, req, resp, apis.CAPDDecoder(), h.Mutate)
}
Loading

0 comments on commit 497c612

Please sign in to comment.