Skip to content

Commit

Permalink
Introduce a nutanix prism client cache (#415)
Browse files Browse the repository at this point in the history
* Introduce a nutanix prism client cache

The cache stores a prismgoclient.V3 client instance for each NutanixCluster instance.
The cache is shared between nutanixcluster and nutanixmachine controllers.

* Address review comments
  • Loading branch information
thunderboltsid committed May 6, 2024
1 parent f67953b commit 36bea0e
Show file tree
Hide file tree
Showing 24 changed files with 2,184 additions and 931 deletions.
27 changes: 24 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ GOLANGCI_LINT_VER := v1.55.2
GOLANGCI_LINT_BIN := golangci-lint
GOLANGCI_LINT := $(abspath $(TOOLS_BIN_DIR)/$(GOLANGCI_LINT_BIN))

MOCKGEN_VER := v1.6.0
MOCKGEN_BIN := mockgen
MOCKGEN_PKG := github.com/golang/mock/mockgen
MOCKGEN := $(abspath $(TOOLS_BIN_DIR)/$(MOCKGEN_BIN)-$(MOCKGEN_VER))

# CRD_OPTIONS define options to add to the CONTROLLER_GEN
CRD_OPTIONS ?= "crd:crdVersions=v1"

Expand Down Expand Up @@ -342,19 +347,32 @@ prepare-local-clusterctl: manifests kustomize cluster-templates ## Prepare overi
$(KUSTOMIZE) build config/default > ~/.cluster-api/overrides/infrastructure-nutanix/${LOCAL_PROVIDER_VERSION}/infrastructure-components.yaml
cp ./metadata.yaml ~/.cluster-api/overrides/infrastructure-nutanix/${LOCAL_PROVIDER_VERSION}/
cp ./templates/cluster-template*.yaml ~/.cluster-api/overrides/infrastructure-nutanix/${LOCAL_PROVIDER_VERSION}/
cp ./clusterctl.yaml ~/.cluster-api/clusterctl.yaml
env LOCAL_PROVIDER_VERSION=$(LOCAL_PROVIDER_VERSION) \
envsubst -no-unset -no-empty -no-digit < ./clusterctl.yaml > ~/.cluster-api/clusterctl.yaml

.PHONY: mocks
mocks: $(MOCKGEN) ## Generate mocks for the project
$(MOCKGEN) -destination=mocks/ctlclient/client_mock.go -package=mockctlclient sigs.k8s.io/controller-runtime/pkg/client Client
$(MOCKGEN) -destination=mocks/ctlclient/manager_mock.go -package=mockctlclient sigs.k8s.io/controller-runtime/pkg/manager Manager
$(MOCKGEN) -destination=mocks/ctlclient/cache_mock.go -package=mockctlclient sigs.k8s.io/controller-runtime/pkg/cache Cache
$(MOCKGEN) -destination=mocks/k8sclient/cm_informer.go -package=mockk8sclient k8s.io/client-go/informers/core/v1 ConfigMapInformer
$(MOCKGEN) -destination=mocks/k8sclient/secret_informer.go -package=mockk8sclient k8s.io/client-go/informers/core/v1 SecretInformer
$(MOCKGEN) -destination=mocks/k8sclient/secret_lister.go -package=mockk8sclient k8s.io/client-go/listers/core/v1 SecretLister
$(MOCKGEN) -destination=mocks/k8sclient/secret_namespace_lister.go -package=mockk8sclient k8s.io/client-go/listers/core/v1 SecretNamespaceLister

GOTESTPKGS = $(shell go list ./... | grep -v /mocks | grep -v /templates)

.PHONY: unit-test
unit-test: setup-envtest ## Run unit tests.
ifeq ($(EXPORT_RESULT), true)
GO111MODULE=off $(GOGET) -u github.com/jstemmer/go-junit-report
$(eval OUTPUT_OPTIONS = | go-junit-report -set-exit-code > junit-report.xml)
endif
KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --arch=amd64 -p path)" $(GOTEST) ./... $(OUTPUT_OPTIONS)
KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --arch=amd64 -p path)" $(GOTEST) $(GOTESTPKGS) $(OUTPUT_OPTIONS)

.PHONY: coverage
coverage: setup-envtest ## Run the tests of the project and export the coverage
KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --arch=amd64 -p path)" $(GOTEST) -cover -covermode=count -coverprofile=profile.cov ./...
KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --arch=amd64 -p path)" $(GOTEST) -cover -covermode=count -coverprofile=profile.cov $(GOTESTPKGS)
$(GOTOOL) cover -func profile.cov
ifeq ($(EXPORT_RESULT), true)
GO111MODULE=off $(GOGET) -u github.com/AlekSi/gocov-xml
Expand Down Expand Up @@ -513,6 +531,9 @@ $(KO): # Build ko from tools folder.
$(KUSTOMIZE): # Build kustomize from tools folder.
GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(KUSTOMIZE_PKG) $(KUSTOMIZE_BIN) $(KUSTOMIZE_VER)

$(MOCKGEN): # Build mockgen from tools folder.
GOBIN=$(TOOLS_BIN_DIR) $(GO_INSTALL) $(MOCKGEN_PKG) $(MOCKGEN_BIN) $(MOCKGEN_VER)

.PHONY: $(KO_BIN)
$(KO_BIN): $(KO) ## Build a local copy of ko

Expand Down
11 changes: 11 additions & 0 deletions api/v1beta1/nutanixcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@ limitations under the License.
package v1beta1

import (
"cmp"
"fmt"

credentialTypes "github.com/nutanix-cloud-native/prism-go-client/environment/credentials"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
capiv1 "sigs.k8s.io/cluster-api/api/v1beta1"
"sigs.k8s.io/cluster-api/errors"
)

const (
// NutanixClusterKind represents the Kind of NutanixCluster
NutanixClusterKind = "NutanixCluster"

// NutanixClusterFinalizer allows NutanixClusterReconciler to clean up AHV
// resources associated with NutanixCluster before removing it from the
// API Server.
Expand Down Expand Up @@ -118,6 +123,12 @@ func (ncl *NutanixCluster) GetPrismCentralCredentialRef() (*credentialTypes.Nuta
return prismCentralInfo.CredentialRef, nil
}

// GetNamespacedName returns the namespaced name of the NutanixCluster.
func (ncl *NutanixCluster) GetNamespacedName() string {
namespace := cmp.Or(ncl.Namespace, corev1.NamespaceDefault)
return fmt.Sprintf("%s/%s", namespace, ncl.Name)
}

// +kubebuilder:object:root=true

// NutanixClusterList contains a list of NutanixCluster
Expand Down
36 changes: 36 additions & 0 deletions api/v1beta1/nutanixcluster_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,39 @@ func TestGetCredentialRefForCluster(t *testing.T) {
})
}
}

func TestGetNamespacedName(t *testing.T) {
t.Parallel()
tests := []struct {
name string
nutanixCluster *NutanixCluster
expectedFullName string
}{
{
name: "namespace and name are set",
nutanixCluster: &NutanixCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "test-namespace",
},
},
expectedFullName: "test-namespace/test",
},
{
name: "namespace is not set, should use default",
nutanixCluster: &NutanixCluster{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
},
expectedFullName: "default/test",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
fullName := tt.nutanixCluster.GetNamespacedName()
assert.Equal(t, tt.expectedFullName, fullName)
})
}
}
3 changes: 3 additions & 0 deletions api/v1beta1/nutanixmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import (
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.

const (
// NutanixMachineKind represents the Kind of NutanixMachine
NutanixMachineKind = "NutanixMachine"

// NutanixMachineFinalizer allows NutanixMachineReconciler to clean up AHV
// resources associated with NutanixMachine before removing it from the
// API Server.
Expand Down
Loading

0 comments on commit 36bea0e

Please sign in to comment.