diff --git a/pkg/handlers/httpproxy/matcher.go b/pkg/capi/clustertopology/patches/matchers/match.go similarity index 68% rename from pkg/handlers/httpproxy/matcher.go rename to pkg/capi/clustertopology/patches/matchers/match.go index 54abd2c4e..aa786d0e1 100644 --- a/pkg/handlers/httpproxy/matcher.go +++ b/pkg/capi/clustertopology/patches/matchers/match.go @@ -6,7 +6,7 @@ // See: https://github.com/kubernetes-sigs/cluster-api/blob/46412f0a4ea65d8f02478d2ad09ce12925485f56/internal/controllers/topology/cluster/patches/inline/json_patch_generator.go#L125 // //nolint:lll // Long URLs in comments above. Adding nolint:lll here because it doesn't work in comment lines. See: https://github.com/golangci/golangci-lint/issues/3983 -package httpproxy +package matchers import ( "strconv" @@ -19,65 +19,52 @@ import ( "sigs.k8s.io/cluster-api/exp/runtime/topologymutation" ) -func matchSelector( +func MatchesSelector( selector clusterv1.PatchSelector, obj runtime.Object, holderRef *runtimehooksv1.HolderReference, templateVariables map[string]apiextensionsv1.JSON, ) bool { - if !matchGVK(selector.APIVersion, selector.Kind, obj) { + if !MatchesGVK(selector.APIVersion, selector.Kind, obj) { return false } - if selector.MatchResources.InfrastructureCluster { - if !matchInfrastructure(holderRef) { - return false - } + if selector.MatchResources.InfrastructureCluster && MatchesInfrastructure(holderRef) { + return true } - if selector.MatchResources.ControlPlane { - if !matchControlPlane(holderRef) { - return false - } + if selector.MatchResources.ControlPlane && MatchesControlPlane(holderRef) { + return true } - if selector.MatchResources.MachineDeploymentClass != nil { - if !matchMachineDeploymentClass( + if selector.MatchResources.MachineDeploymentClass != nil && + MatchesMachineDeploymentClass( holderRef, selector.MatchResources.MachineDeploymentClass.Names, templateVariables, ) { - return false - } + return true } - return true + return false } -// Check if the apiVersion and kind are matching. -func matchGVK(apiVersion, kind string, obj runtime.Object) bool { - objAPIVersion, objKind := obj.GetObjectKind().GroupVersionKind().ToAPIVersionAndKind() - // Check if the apiVersion and kind are matching. - if objAPIVersion != apiVersion { - return false - } - if objKind != kind { - return false - } - return true +// MatchesGVK checks if the apiVersion and kind are matching. +func MatchesGVK(apiVersion, kind string, obj runtime.Object) bool { + gvk := obj.GetObjectKind().GroupVersionKind() + + return gvk.GroupVersion().String() == apiVersion && gvk.Kind == kind } -// Check if the request is for an InfrastructureCluster. -func matchInfrastructure(holderRef *runtimehooksv1.HolderReference) bool { - // Cluster.spec.infrastructureRef holds the InfrastructureCluster. - if holderRef.Kind == "Cluster" && holderRef.FieldPath == "spec.infrastructureRef" { - return true - } - return false +// MatchesInfrastructure checks if the request is for an InfrastructureCluster. +// Cluster.spec.infrastructureRef holds the InfrastructureCluster. +func MatchesInfrastructure(holderRef *runtimehooksv1.HolderReference) bool { + return holderRef.Kind == "Cluster" && holderRef.FieldPath == "spec.infrastructureRef" } -// Check if the request is for a ControlPlane or the InfrastructureMachineTemplate of a ControlPlane. -func matchControlPlane(holderRef *runtimehooksv1.HolderReference) bool { +// MatchesControlPlane checks if the request is for a ControlPlane or the InfrastructureMachineTemplate of a +// ControlPlane. +func MatchesControlPlane(holderRef *runtimehooksv1.HolderReference) bool { // Cluster.spec.controlPlaneRef holds the ControlPlane. if holderRef.Kind == "Cluster" && holderRef.FieldPath == "spec.controlPlaneRef" { return true @@ -92,9 +79,9 @@ func matchControlPlane(holderRef *runtimehooksv1.HolderReference) bool { return false } -// Check if the request is for a BootstrapConfigTemplate or an InfrastructureMachineTemplate -// of one of the configured MachineDeploymentClasses. -func matchMachineDeploymentClass( +// MatchesMachineDeploymentClass checks if the request is for a BootstrapConfigTemplate or an +// InfrastructureMachineTemplate of one of the configured MachineDeploymentClasses. +func MatchesMachineDeploymentClass( holderRef *runtimehooksv1.HolderReference, names []string, templateVariables map[string]apiextensionsv1.JSON, @@ -130,5 +117,6 @@ func matchMachineDeploymentClass( } } } + return false } diff --git a/pkg/capi/clustertopology/patches/matchers/match_test.go b/pkg/capi/clustertopology/patches/matchers/match_test.go new file mode 100644 index 000000000..edbb48d62 --- /dev/null +++ b/pkg/capi/clustertopology/patches/matchers/match_test.go @@ -0,0 +1,494 @@ +// Copyright 2023 D2iQ, Inc. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package matchers_test + +import ( + "testing" + + . "github.com/onsi/gomega" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + runtimehooksv1 "sigs.k8s.io/cluster-api/exp/runtime/hooks/api/v1alpha1" + + "github.com/d2iq-labs/capi-runtime-extensions/pkg/capi/clustertopology/patches/matchers" +) + +func TestMatchesSelector(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + obj runtime.Object + templateVariables map[string]apiextensionsv1.JSON + holderRef *runtimehooksv1.HolderReference + selector clusterv1.PatchSelector + match bool + }{{ + name: "Don't match: apiVersion mismatch", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", + "kind": "AzureMachineTemplate", + }, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha4", + Kind: "AzureMachineTemplate", + }, + match: false, + }, { + name: "Don't match: kind mismatch", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", + "kind": "AzureMachineTemplate", + }, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "AzureClusterTemplate", + }, + match: false, + }, { + name: "Match InfrastructureClusterTemplate", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", + "kind": "AzureClusterTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "Cluster", + Name: "my-cluster", + Namespace: "default", + FieldPath: "spec.infrastructureRef", + }, + selector: clusterv1.PatchSelector{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "AzureClusterTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + InfrastructureCluster: true, + }, + }, + match: true, + }, { + name: "Don't match InfrastructureClusterTemplate, .matchResources.infrastructureCluster not set", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", + "kind": "AzureClusterTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "Cluster", + Name: "my-cluster", + Namespace: "default", + FieldPath: "spec.infrastructureRef", + }, + selector: clusterv1.PatchSelector{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "AzureClusterTemplate", + MatchResources: clusterv1.PatchSelectorMatch{}, + }, + match: false, + }, { + name: "Don't match InfrastructureClusterTemplate, .matchResources.infrastructureCluster false", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", + "kind": "AzureClusterTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "Cluster", + Name: "my-cluster", + Namespace: "default", + FieldPath: "spec.infrastructureRef", + }, + selector: clusterv1.PatchSelector{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "AzureClusterTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + InfrastructureCluster: false, + }, + }, + match: false, + }, { + name: "Match ControlPlaneTemplate", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "controlplane.cluster.x-k8s.io/v1beta1", + "kind": "ControlPlaneTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "Cluster", + Name: "my-cluster", + Namespace: "default", + FieldPath: "spec.controlPlaneRef", + }, + selector: clusterv1.PatchSelector{ + APIVersion: "controlplane.cluster.x-k8s.io/v1beta1", + Kind: "ControlPlaneTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + ControlPlane: true, + }, + }, + match: true, + }, { + name: "Don't match ControlPlaneTemplate, .matchResources.controlPlane not set", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "controlplane.cluster.x-k8s.io/v1beta1", + "kind": "ControlPlaneTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "Cluster", + Name: "my-cluster", + Namespace: "default", + FieldPath: "spec.controlPlaneRef", + }, + selector: clusterv1.PatchSelector{ + APIVersion: "controlplane.cluster.x-k8s.io/v1beta1", + Kind: "ControlPlaneTemplate", + MatchResources: clusterv1.PatchSelectorMatch{}, + }, + match: false, + }, { + name: "Don't match ControlPlaneTemplate, .matchResources.controlPlane false", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "controlplane.cluster.x-k8s.io/v1beta1", + "kind": "ControlPlaneTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "Cluster", + Name: "my-cluster", + Namespace: "default", + FieldPath: "spec.controlPlaneRef", + }, + selector: clusterv1.PatchSelector{ + APIVersion: "controlplane.cluster.x-k8s.io/v1beta1", + Kind: "ControlPlaneTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + ControlPlane: false, + }, + }, + match: false, + }, { + name: "Match ControlPlane InfrastructureMachineTemplate", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", + "kind": "AzureMachineTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: "controlplane.cluster.x-k8s.io/v1beta1", + Kind: "KubeadmControlPlane", + Name: "my-controlplane", + Namespace: "default", + FieldPath: "spec.machineTemplate.infrastructureRef", + }, + selector: clusterv1.PatchSelector{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "AzureMachineTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + ControlPlane: true, + }, + }, + match: true, + }, { + name: "Match MD BootstrapTemplate", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1", + "kind": "BootstrapTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.bootstrap.configRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"classA"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1", + Kind: "BootstrapTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{ + Names: []string{"classA"}, + }, + }, + }, + match: true, + }, { + name: "Match all MD BootstrapTemplate", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1", + "kind": "BootstrapTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.bootstrap.configRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"classA"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1", + Kind: "BootstrapTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{ + Names: []string{"*"}, + }, + }, + }, + match: true, + }, { + name: "Glob match MD BootstrapTemplate with -*", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1", + "kind": "BootstrapTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.bootstrap.configRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"class-A"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1", + Kind: "BootstrapTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{ + Names: []string{"class-*"}, + }, + }, + }, + match: true, + }, { + name: "Glob match MD BootstrapTemplate with *-", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1", + "kind": "BootstrapTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.bootstrap.configRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"class-A"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1", + Kind: "BootstrapTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{ + Names: []string{"*-A"}, + }, + }, + }, + match: true, + }, { + name: "Don't match BootstrapTemplate, .matchResources.machineDeploymentClass.names is empty", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1", + "kind": "BootstrapTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.bootstrap.configRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"classA"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1", + Kind: "BootstrapTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{ + Names: []string{}, + }, + }, + }, + match: false, + }, { + name: "Do not match BootstrapTemplate, .matchResources.machineDeploymentClass is set to nil", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1", + "kind": "BootstrapTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.bootstrap.configRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"classA"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1", + Kind: "BootstrapTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + MachineDeploymentClass: nil, + }, + }, + match: false, + }, { + name: "Don't match BootstrapTemplate, .matchResources.machineDeploymentClass not set", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1", + "kind": "BootstrapTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.bootstrap.configRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"classA"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1", + Kind: "BootstrapTemplate", + MatchResources: clusterv1.PatchSelectorMatch{}, + }, + match: false, + }, { + name: "Don't match BootstrapTemplate, .matchResources.machineDeploymentClass does not match", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "bootstrap.cluster.x-k8s.io/v1beta1", + "kind": "BootstrapTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.bootstrap.configRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"classA"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "bootstrap.cluster.x-k8s.io/v1beta1", + Kind: "BootstrapTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{ + Names: []string{"classB"}, + }, + }, + }, + match: false, + }, { + name: "Match MD InfrastructureMachineTemplate", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "infrastructure.cluster.x-k8s.io/v1beta1", + "kind": "AzureMachineTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.template.spec.infrastructureRef", + }, + templateVariables: map[string]apiextensionsv1.JSON{ + "builtin": {Raw: []byte(`{"machineDeployment":{"class":"classA"}}`)}, + }, + selector: clusterv1.PatchSelector{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "AzureMachineTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + MachineDeploymentClass: &clusterv1.PatchSelectorMatchMachineDeploymentClass{ + Names: []string{"classA"}, + }, + }, + }, + match: true, + }, { + name: "Don't match: unknown field path", + obj: &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "controlplane.cluster.x-k8s.io/v1beta1", + "kind": "ControlPlaneTemplate", + }, + }, + holderRef: &runtimehooksv1.HolderReference{ + APIVersion: clusterv1.GroupVersion.String(), + Kind: "Custom", + Name: "my-md-0", + Namespace: "default", + FieldPath: "spec.machineTemplate.unknown.infrastructureRef", + }, + selector: clusterv1.PatchSelector{ + APIVersion: "controlplane.cluster.x-k8s.io/v1beta1", + Kind: "ControlPlaneTemplate", + MatchResources: clusterv1.PatchSelectorMatch{ + ControlPlane: true, + }, + }, + match: false, + }} + for idx := range tests { + tt := tests[idx] + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + g := NewWithT(t) + + g.Expect(matchers.MatchesSelector(tt.selector, tt.obj, tt.holderRef, tt.templateVariables)). + To(Equal(tt.match)) + }) + } +} diff --git a/pkg/capi/variable.go b/pkg/capi/clustertopology/variables/variable.go similarity index 85% rename from pkg/capi/variable.go rename to pkg/capi/clustertopology/variables/variable.go index 4282ae3d7..632f155cf 100644 --- a/pkg/capi/variable.go +++ b/pkg/capi/clustertopology/variables/variable.go @@ -1,7 +1,7 @@ // Copyright 2023 D2iQ, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -package capi +package variables import ( "encoding/json" @@ -10,8 +10,8 @@ import ( "sigs.k8s.io/cluster-api/exp/runtime/topologymutation" ) -// GetVariable finds and parses variable to given type. -func GetVariable[T any]( +// Get finds and parses variable to given type. +func Get[T any]( variables map[string]apiextensionsv1.JSON, name string, ) (value T, found bool, err error) { diff --git a/pkg/capi/variables_test.go b/pkg/capi/clustertopology/variables/variables_test.go similarity index 64% rename from pkg/capi/variables_test.go rename to pkg/capi/clustertopology/variables/variables_test.go index e88777e66..b26a48bea 100644 --- a/pkg/capi/variables_test.go +++ b/pkg/capi/clustertopology/variables/variables_test.go @@ -1,7 +1,7 @@ // Copyright 2023 D2iQ, Inc. All rights reserved. // SPDX-License-Identifier: Apache-2.0 -package capi_test +package variables_test import ( "testing" @@ -9,20 +9,20 @@ import ( . "github.com/onsi/gomega" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "github.com/d2iq-labs/capi-runtime-extensions/pkg/capi" + "github.com/d2iq-labs/capi-runtime-extensions/pkg/capi/clustertopology/variables" ) -func TestGetVariable(t *testing.T) { +func TestGet(t *testing.T) { g := NewWithT(t) type sampleStruct struct { Foo string `json:"foo"` } sampleValue := []byte(`{"foo": "bar"}`) - variables := map[string]apiextensionsv1.JSON{ + vars := map[string]apiextensionsv1.JSON{ "sampleVar": {Raw: sampleValue}, } - parsed, found, err := capi.GetVariable[sampleStruct](variables, "sampleVar") + parsed, found, err := variables.Get[sampleStruct](vars, "sampleVar") g.Expect(err).NotTo(HaveOccurred()) g.Expect(found).To(BeTrue()) g.Expect(parsed).To(Equal(sampleStruct{ @@ -33,8 +33,8 @@ func TestGetVariable(t *testing.T) { func TestGetVariable_NotFound(t *testing.T) { g := NewWithT(t) - variables := map[string]apiextensionsv1.JSON{} - parsed, found, err := capi.GetVariable[string](variables, "not_found") + vars := map[string]apiextensionsv1.JSON{} + parsed, found, err := variables.Get[string](vars, "not_found") g.Expect(err).NotTo(HaveOccurred()) g.Expect(found).To(BeFalse()) g.Expect(parsed).To(BeEmpty()) @@ -43,10 +43,10 @@ func TestGetVariable_NotFound(t *testing.T) { func TestGetVariable_ParseError(t *testing.T) { g := NewWithT(t) - variables := map[string]apiextensionsv1.JSON{ + vars := map[string]apiextensionsv1.JSON{ "intvar": {Raw: []byte("10")}, } - parsed, found, err := capi.GetVariable[string](variables, "intvar") + parsed, found, err := variables.Get[string](vars, "intvar") g.Expect(err).To(HaveOccurred()) g.Expect(found).To(BeFalse()) g.Expect(parsed).To(BeEmpty()) diff --git a/pkg/handlers/httpproxy/inject.go b/pkg/handlers/httpproxy/inject.go index 7a90fb499..6adc255b5 100644 --- a/pkg/handlers/httpproxy/inject.go +++ b/pkg/handlers/httpproxy/inject.go @@ -19,7 +19,8 @@ import ( "sigs.k8s.io/cluster-api/exp/runtime/topologymutation" ctrl "sigs.k8s.io/controller-runtime" - "github.com/d2iq-labs/capi-runtime-extensions/pkg/capi" + "github.com/d2iq-labs/capi-runtime-extensions/pkg/capi/clustertopology/patches/matchers" + "github.com/d2iq-labs/capi-runtime-extensions/pkg/capi/clustertopology/variables" "github.com/d2iq-labs/capi-runtime-extensions/pkg/handlers" ) @@ -66,15 +67,15 @@ func (h *httpProxyPatchHandler) GeneratePatches( func( ctx context.Context, obj runtime.Object, - variables map[string]apiextensionsv1.JSON, + vars map[string]apiextensionsv1.JSON, holderRef runtimehooksv1.HolderReference, ) error { log := ctrl.LoggerFrom(ctx).WithValues( "holderRef", holderRef, ) - httpProxyVariable, found, err := capi.GetVariable[HTTPProxyVariables]( - variables, + httpProxyVariable, found, err := variables.Get[HTTPProxyVariables]( + vars, VariableName, ) if err != nil { @@ -95,7 +96,7 @@ func (h *httpProxyPatchHandler) GeneratePatches( }, } if err := generatePatch( - obj, variables, &holderRef, controlPlaneSelector, log, + obj, vars, &holderRef, controlPlaneSelector, log, func(obj *controlplanev1.KubeadmControlPlaneTemplate) error { log.WithValues("namespacedName", types.NamespacedName{ Name: obj.Name, @@ -122,7 +123,7 @@ func (h *httpProxyPatchHandler) GeneratePatches( }, } if err := generatePatch( - obj, variables, &holderRef, defaultWorkerSelector, log, + obj, vars, &holderRef, defaultWorkerSelector, log, func(obj *bootstrapv1.KubeadmConfigTemplate) error { log.WithValues("namespacedName", types.NamespacedName{ Name: obj.Name, @@ -144,7 +145,7 @@ func (h *httpProxyPatchHandler) GeneratePatches( func generatePatch[T runtime.Object]( obj runtime.Object, - variables map[string]apiextensionsv1.JSON, + vars map[string]apiextensionsv1.JSON, holderRef *runtimehooksv1.HolderReference, patchSelector clusterv1.PatchSelector, log logr.Logger, @@ -159,7 +160,7 @@ func generatePatch[T runtime.Object]( return nil } - if !matchSelector(patchSelector, obj, holderRef, variables) { + if !matchers.MatchesSelector(patchSelector, obj, holderRef, vars) { log.WithValues("selector", patchSelector).Info("not matching selector") return nil }