From 9c63e49e37996ef8caaecf4056e39a419f7c6617 Mon Sep 17 00:00:00 2001 From: Lachezar Tsonov <80523253+ltsonov-cb@users.noreply.github.com> Date: Mon, 30 Aug 2021 10:46:23 +0300 Subject: [PATCH] Add support for Kubernetes 1.22 with backwards compatibility (#49) * Initial adapter for validating webhook * Extended unit tests to validate proper type is used * Changed project structure to support v1 and v1beta1 apiextensions for CRDs * Removed install and uninstall make targets * Restored and fixed install/uninstall targets and merged manifests with the fix for empty object default. Split the CRDs in two folders. Fixed a bug with an optional value that had required children in runtime. * Add some explanation to readmes for defaults and api versions * Remove monitor from operator and its uses * Fix api version in hardening controller as well. Added samples for 2 CRDs for easier debugging. * Fixed an endless reconcile loop due to admission rules being overriden. Added delve config for debugging. * Fixed CR comment * Removed obsolete interface * Changed SetWebhooks() so that we can modify the objects via pointer references and not have to set them every time...this avoids constant reconcile if kubernetes re-orders the items * Fix runtime file generation (from rebase on main) --- Makefile | 45 +- PROJECT | 6 +- README.md | 22 +- api/v1/cbcontainersruntime_types.go | 5 +- .../default_features_status_provider.go | 45 - .../default_features_status_provider_test.go | 111 -- .../monitor/default_health_checker.go | 124 --- cbcontainers/monitor/mocks/generated.go | 5 - ...mock_features_status_provider_generated.go | 64 -- .../mocks/mock_health_checker_generated.go | 112 -- .../mocks/mock_message_reporter_generated.go | 63 -- .../monitor/models/health_report_message.go | 64 -- cbcontainers/monitor/monitor_agent.go | 310 ------ cbcontainers/monitor/monitor_agent_test.go | 314 ------ cbcontainers/monitor/protobuf/monitor.pb.go | 988 ------------------ cbcontainers/monitor/protobuf/monitor.proto | 61 -- cbcontainers/monitor/protobuf/rebuild.sh | 5 - .../reporters/grpc_montior_reporter.go | 152 --- .../cluster/cbcontainerscluster_processor.go | 32 +- .../cbcontainerscluster_processor_test.go | 21 +- .../cluster/default_monitor_creator.go | 64 -- .../processors/cluster/mocks/generated.go | 2 - .../processors/cluster/mocks/mock_monitor.go | 58 - .../cluster/mocks/mock_monitor_creator.go | 51 - .../priority_class_values_setter.go | 2 +- .../state/cluster/objects/priority_class.go | 4 +- .../hardening/adapters/validating_webhook.go | 362 +++++++ .../hardening/hardening_state_applier.go | 2 +- .../hardening/hardening_state_applier_test.go | 58 +- .../hardening/objects/enforcer_webhook.go | 159 ++- ...s.carbonblack.io_cbcontainersclusters.yaml | 128 +-- ...carbonblack.io_cbcontainershardenings.yaml | 501 +++++---- ...s.carbonblack.io_cbcontainersruntimes.yaml | 513 +++++---- ...s.carbonblack.io_cbcontainersclusters.yaml | 88 ++ ...carbonblack.io_cbcontainershardenings.yaml | 255 +++++ ...s.carbonblack.io_cbcontainersruntimes.yaml | 258 +++++ config/crd_v1beta1/kustomization.yaml | 30 + config/crd_v1beta1/kustomizeconfig.yaml | 19 + .../cainjection_in_cbcontainersclusters.yaml | 7 + ...cainjection_in_cbcontainershardenings.yaml | 7 + .../cainjection_in_cbcontainersruntimes.yaml | 7 + .../webhook_in_cbcontainersclusters.yaml | 14 + .../webhook_in_cbcontainershardenings.yaml | 14 + .../webhook_in_cbcontainersruntimes.yaml | 14 + .../crd_apiextensionsv1beta1_patch.yaml | 22 + config/default/kustomization.yaml | 74 +- .../crd_apiextensionsv1_patch.yaml | 22 + config/default_v1beta1/kustomization.yaml | 8 + config/operator/kustomization.yaml | 75 ++ .../manager_auth_proxy_patch.yaml | 0 .../manager_config_patch.yaml | 0 config/rbac/role.yaml | 22 +- config/samples/_v1_cbcontainerscluster.yaml | 11 +- config/samples/_v1_cbcontainershardening.yaml | 7 +- .../cbcontainershardening_controller.go | 6 +- controllers/cbcontainersruntime_controller.go | 1 + docs/developers.md | 55 + main.go | 11 +- 58 files changed, 2113 insertions(+), 3367 deletions(-) delete mode 100644 cbcontainers/monitor/default_features_status_provider.go delete mode 100644 cbcontainers/monitor/default_features_status_provider_test.go delete mode 100644 cbcontainers/monitor/default_health_checker.go delete mode 100644 cbcontainers/monitor/mocks/generated.go delete mode 100644 cbcontainers/monitor/mocks/mock_features_status_provider_generated.go delete mode 100644 cbcontainers/monitor/mocks/mock_health_checker_generated.go delete mode 100644 cbcontainers/monitor/mocks/mock_message_reporter_generated.go delete mode 100644 cbcontainers/monitor/models/health_report_message.go delete mode 100644 cbcontainers/monitor/monitor_agent.go delete mode 100644 cbcontainers/monitor/monitor_agent_test.go delete mode 100644 cbcontainers/monitor/protobuf/monitor.pb.go delete mode 100644 cbcontainers/monitor/protobuf/monitor.proto delete mode 100755 cbcontainers/monitor/protobuf/rebuild.sh delete mode 100644 cbcontainers/monitor/reporters/grpc_montior_reporter.go delete mode 100644 cbcontainers/processors/cluster/default_monitor_creator.go delete mode 100644 cbcontainers/processors/cluster/mocks/mock_monitor.go delete mode 100644 cbcontainers/processors/cluster/mocks/mock_monitor_creator.go rename cbcontainers/state/cluster/{utils => adapters}/priority_class_values_setter.go (99%) create mode 100644 cbcontainers/state/hardening/adapters/validating_webhook.go create mode 100644 config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml create mode 100644 config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml create mode 100644 config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml create mode 100644 config/crd_v1beta1/kustomization.yaml create mode 100644 config/crd_v1beta1/kustomizeconfig.yaml create mode 100644 config/crd_v1beta1/patches/cainjection_in_cbcontainersclusters.yaml create mode 100644 config/crd_v1beta1/patches/cainjection_in_cbcontainershardenings.yaml create mode 100644 config/crd_v1beta1/patches/cainjection_in_cbcontainersruntimes.yaml create mode 100644 config/crd_v1beta1/patches/webhook_in_cbcontainersclusters.yaml create mode 100644 config/crd_v1beta1/patches/webhook_in_cbcontainershardenings.yaml create mode 100644 config/crd_v1beta1/patches/webhook_in_cbcontainersruntimes.yaml create mode 100644 config/default/crd_apiextensionsv1beta1_patch.yaml create mode 100644 config/default_v1beta1/crd_apiextensionsv1_patch.yaml create mode 100644 config/default_v1beta1/kustomization.yaml create mode 100644 config/operator/kustomization.yaml rename config/{default => operator}/manager_auth_proxy_patch.yaml (100%) rename config/{default => operator}/manager_config_patch.yaml (100%) diff --git a/Makefile b/Makefile index 63009858..08a8dda6 100644 --- a/Makefile +++ b/Makefile @@ -16,8 +16,16 @@ BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) IMG ?= controller:latest # Image URL to use all building/pushing image targets OPERATOR_REPLICAS ?= 1 -# Produce CRDs that work back to Kubernetes 1.11 (no version conversion) -CRD_OPTIONS ?= "crd:trivialVersions=true,crdVersions=v1beta1" + +CRD_OPTIONS ?= "crd:crdVersions=v1" +# Produce CRDs that work back to Kubernetes 1.11 (no version conversion) - supported in v1beta1 only +CRD_OPTIONS_V1BETA1 ?= "crd:trivialVersions=true,crdVersions=v1beta1" + +PATH_TO_RELEASE := config/default +PATH_TO_RELEASE := $(if $(findstring v1beta1, $(CRD_VERSION)), $(PATH_TO_RELEASE)_v1beta1, $(PATH_TO_RELEASE)) + +PATH_TO_CRDS := config/crd +PATH_TO_CRDS := $(if $(findstring v1beta1, $(CRD_VERSION)), $(PATH_TO_CRDS)_v1beta1, $(PATH_TO_CRDS)) # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) ifeq (,$(shell go env GOBIN)) @@ -37,6 +45,7 @@ all: build OS = $(shell go env GOOS) ARCH = $(shell go env GOARCH) + # Run tests # Set default shell as bash SHELL := /bin/bash @@ -54,17 +63,24 @@ manager: generate fmt vet run: generate fmt vet manifests go run ./main.go +# Run with Delve for development purposes against the configured Kubernetes cluster in ~/.kube/config +# Delve is a debugger for the Go programming language. More info: https://github.com/go-delve/delve +# Note: use kill -SIGINT $pid to stop delve if it hangs +run-delve: generate fmt vet manifests + go build -gcflags "all=-trimpath=$(shell go env GOPATH) -N -l" -o bin/manager main.go + dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec ./bin/manager + install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. - $(KUSTOMIZE) build config/crd | kubectl apply -f - + $(KUSTOMIZE) build $(PATH_TO_CRDS) | kubectl apply -f - uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. - $(KUSTOMIZE) build config/crd | kubectl delete -f - + $(KUSTOMIZE) build $(PATH_TO_CRDS) | kubectl delete -f - -# Deploy controller in the configured Kubernetes cluster in ~/.kube/config +# Generate and bundle all operator components in a single YAML file create_operator_spec: manifests kustomize rm -f operator.yaml cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} && $(KUSTOMIZE) edit set replicas operator=${OPERATOR_REPLICAS} - - $(KUSTOMIZE) build config/default >> operator.yaml + - $(KUSTOMIZE) build $(PATH_TO_RELEASE) >> operator.yaml git restore config/manager/kustomization.yaml # Deploy controller in the configured Kubernetes cluster in ~/.kube/config @@ -80,16 +96,15 @@ undeploy: create_operator_spec # Generate manifests e.g. CRD, RBAC etc. manifests: controller-gen $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases - -# Generate manifests e.g. CRD, RBAC etc. -manifests_with_defaults: controller-gen - $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases +# This is needed since controller-gen does not support empty object/maps like {} but they are helpful to propagate default values up from nested objects for filename in $$(ls config/crd/bases) ; do \ - XT=config/crd/bases/$$filename ; \ - sed 's/default: <>/default: {}/g' $$XT >> $$XT.temp ; \ - rm -f $$XT ; \ - mv $$XT.temp $$XT ; \ - done + XT=config/crd/bases/$$filename ; \ + sed 's/default: <>/default: {}/g' $$XT >> $$XT.temp ; \ + rm -f $$XT ; \ + mv $$XT.temp $$XT ; \ + done +# The above modification is not needed for v1beta1 as defaults are not supported there at all + $(CONTROLLER_GEN) $(CRD_OPTIONS_V1BETA1) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd_v1beta1/bases # Run go fmt against code fmt: diff --git a/PROJECT b/PROJECT index 8a104804..4bd3930f 100644 --- a/PROJECT +++ b/PROJECT @@ -7,21 +7,21 @@ projectName: cbcontainers repo: github.com/vmware/cbcontainers-operator resources: - api: - crdVersion: v1beta1 + crdVersion: v1 controller: true domain: operator.containers.carbonblack.io kind: CBContainersCluster path: github.com/vmware/cbcontainers-operator/api/v1 version: v1 - api: - crdVersion: v1beta1 + crdVersion: v1 controller: true domain: operator.containers.carbonblack.io kind: CBContainersHardening path: github.com/vmware/cbcontainers-operator/api/v1 version: v1 - api: - crdVersion: v1beta1 + crdVersion: v1 controller: true domain: operator.containers.carbonblack.io kind: CBContainersRuntime diff --git a/README.md b/README.md index 19a7ee97..4a001514 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,10 @@ The Carbon Black Cloud Container Operator utilizes the operator-framework to cre ## Operator Deployment ### Prerequisites -Kubernetes 1.13+ +Kubernetes 1.13+ is supported. + +By default, the operator utilizes CustomResourceDefinitions v1, which requires Kubernetes 1.16+. +Deploying an operator with CustomResourceDefinitions v1beta1 (deprecated in Kubernetes 1.16, removed in Kubernetes 1.22) can be done - see the relevant section below. ### Create the operator image ``` @@ -28,7 +31,7 @@ make docker-build docker-push IMG={IMAGE_NAME} make deploy IMG={IMAGE_NAME} ``` -* View [Developer Guide](docs/developers.md#deploying-the-operator-without-using-an-image) to see how deploy the operator without using an image +* View [Developer Guide](docs/developers.md) to see how deploy the operator without using an image ## Data Plane Deployment @@ -185,3 +188,18 @@ Finding the API-server IP: ```sh kubectl -n default get service kubernetes -o=jsonpath='{..clusterIP}' ``` + +## Utilizing v1beta1 CustomResourceDefinition versions +The operator supports Kubernetes clusters from v1.13+. +The CustomResourceDefinition APIs were in beta stage in those cluster and were later promoted to GA in v1.16. They are no longer served as of v1.22 of Kubernetes. + +To maintain compatibility, this operator offers 2 sets of CustomResoruceDefinitions - one under the `apiextensions/v1beta1` API and one under `apiextensons/v1`. + +By default, all operations in the repository like `deploy` or `install` work with the v1 version of the `apiextensions` API. Utilizing `v1beta1` is supported by passing the `CRD_VERSION=v1beta1` option when running make. +Note that both `apiextensions/v1` and `apiextensions/v1beta1` versions of the CRDs are generated and maintained by `make` - only commands that use the final output work with 1 version at a time. + +For example, this command will deploy the operator resources on the current cluster but utilizing the `apiextensions/v1beta1` API version for them. + +``` +make deploy CRD_VERSION=v1beta1 +``` \ No newline at end of file diff --git a/api/v1/cbcontainersruntime_types.go b/api/v1/cbcontainersruntime_types.go index 18b0e1c8..a1ff3cfb 100644 --- a/api/v1/cbcontainersruntime_types.go +++ b/api/v1/cbcontainersruntime_types.go @@ -68,9 +68,8 @@ type CBContainersRuntimeSensorSpec struct { type CBContainersRuntimeSpec struct { Version string `json:"version,required"` // +kubebuilder:default:="cbcontainers-access-token" - AccessTokenSecretName string `json:"accessTokenSecretName,omitempty"` - // +kubebuilder:default:=<> - ResolverSpec CBContainersRuntimeResolverSpec `json:"resolverSpec,omitempty"` + AccessTokenSecretName string `json:"accessTokenSecretName,omitempty"` + ResolverSpec CBContainersRuntimeResolverSpec `json:"resolverSpec,omitempty"` // +kubebuilder:default:=<> SensorSpec CBContainersRuntimeSensorSpec `json:"sensorSpec,omitempty"` // +kubebuilder:default:=443 diff --git a/cbcontainers/monitor/default_features_status_provider.go b/cbcontainers/monitor/default_features_status_provider.go deleted file mode 100644 index ef6b7299..00000000 --- a/cbcontainers/monitor/default_features_status_provider.go +++ /dev/null @@ -1,45 +0,0 @@ -package monitor - -import ( - "context" - "fmt" - - cbcontainersv1 "github.com/vmware/cbcontainers-operator/api/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type DefaultFeaturesStatusProvider struct { - client client.Client -} - -func NewDefaultFeaturesStatusProvider(client client.Client) *DefaultFeaturesStatusProvider { - return &DefaultFeaturesStatusProvider{ - client: client, - } -} - -func (provider DefaultFeaturesStatusProvider) HardeningEnabled() (bool, error) { - cbContainersHardeningList := &cbcontainersv1.CBContainersHardeningList{} - if err := provider.client.List(context.Background(), cbContainersHardeningList); err != nil { - return false, fmt.Errorf("couldn't find CBContainersHardening k8s object: %v", err) - } - - if cbContainersHardeningList.Items == nil { - return false, fmt.Errorf("couldn't find CBContainersHardening k8s object") - } - - return len(cbContainersHardeningList.Items) > 0, nil -} - -func (provider DefaultFeaturesStatusProvider) RuntimeEnabled() (bool, error) { - cbContainersRuntimeList := &cbcontainersv1.CBContainersRuntimeList{} - if err := provider.client.List(context.Background(), cbContainersRuntimeList); err != nil { - return false, fmt.Errorf("couldn't find CBContainersRuntime k8s object: %v", err) - } - - if cbContainersRuntimeList.Items == nil { - return false, fmt.Errorf("couldn't find CBContainersRuntime k8s object") - } - - return len(cbContainersRuntimeList.Items) > 0, nil -} diff --git a/cbcontainers/monitor/default_features_status_provider_test.go b/cbcontainers/monitor/default_features_status_provider_test.go deleted file mode 100644 index 5c69fa87..00000000 --- a/cbcontainers/monitor/default_features_status_provider_test.go +++ /dev/null @@ -1,111 +0,0 @@ -package monitor_test - -import ( - "context" - "fmt" - "testing" - - "github.com/golang/mock/gomock" - "github.com/stretchr/testify/require" - cbcontainersv1 "github.com/vmware/cbcontainers-operator/api/v1" - "github.com/vmware/cbcontainers-operator/cbcontainers/monitor" - "github.com/vmware/cbcontainers-operator/cbcontainers/test_utils/mocks" -) - -type SetupAndAssertDefaultFeaturesProvider func(*mocks.MockClient, *monitor.DefaultFeaturesStatusProvider) - -func testFeatures(t *testing.T, setupAndAssert SetupAndAssertDefaultFeaturesProvider) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - clientMock := mocks.NewMockClient(ctrl) - setupAndAssert(clientMock, monitor.NewDefaultFeaturesStatusProvider(clientMock)) -} - -func TestHardeningEnabled(t *testing.T) { - t.Run("When Client.List returns error, should return error", func(t *testing.T) { - testFeatures(t, func(client *mocks.MockClient, provider *monitor.DefaultFeaturesStatusProvider) { - client.EXPECT().List(gomock.Any(), &cbcontainersv1.CBContainersHardeningList{}).Return(fmt.Errorf("")) - _, err := provider.HardeningEnabled() - require.Error(t, err) - }) - }) - - t.Run("When Client.List returns no items, should return error", func(t *testing.T) { - testFeatures(t, func(client *mocks.MockClient, provider *monitor.DefaultFeaturesStatusProvider) { - client.EXPECT().List(gomock.Any(), &cbcontainersv1.CBContainersHardeningList{}).Return(nil) - _, err := provider.HardeningEnabled() - require.Error(t, err) - }) - }) - - t.Run("When Client.List returns 0 items, should return false", func(t *testing.T) { - testFeatures(t, func(client *mocks.MockClient, provider *monitor.DefaultFeaturesStatusProvider) { - client.EXPECT().List(gomock.Any(), &cbcontainersv1.CBContainersHardeningList{}). - Do(func(ctx context.Context, list *cbcontainersv1.CBContainersHardeningList, _ ...interface{}) { - list.Items = make([]cbcontainersv1.CBContainersHardening, 0) - }). - Return(nil) - enabled, err := provider.HardeningEnabled() - require.NoError(t, err) - require.False(t, enabled) - }) - }) - - t.Run("When Client.List returns 1 items, should return true", func(t *testing.T) { - testFeatures(t, func(client *mocks.MockClient, provider *monitor.DefaultFeaturesStatusProvider) { - client.EXPECT().List(gomock.Any(), &cbcontainersv1.CBContainersHardeningList{}). - Do(func(ctx context.Context, list *cbcontainersv1.CBContainersHardeningList, _ ...interface{}) { - list.Items = make([]cbcontainersv1.CBContainersHardening, 1) - }). - Return(nil) - enabled, err := provider.HardeningEnabled() - require.NoError(t, err) - require.True(t, enabled) - }) - }) -} - -func TestRuntimeEnabled(t *testing.T) { - t.Run("When Client.List returns error, should return error", func(t *testing.T) { - testFeatures(t, func(client *mocks.MockClient, provider *monitor.DefaultFeaturesStatusProvider) { - client.EXPECT().List(gomock.Any(), &cbcontainersv1.CBContainersRuntimeList{}).Return(fmt.Errorf("")) - _, err := provider.RuntimeEnabled() - require.Error(t, err) - }) - }) - - t.Run("When Client.List returns no items, should return error", func(t *testing.T) { - testFeatures(t, func(client *mocks.MockClient, provider *monitor.DefaultFeaturesStatusProvider) { - client.EXPECT().List(gomock.Any(), &cbcontainersv1.CBContainersRuntimeList{}).Return(nil) - _, err := provider.RuntimeEnabled() - require.Error(t, err) - }) - }) - - t.Run("When Client.List returns 0 items, should return false", func(t *testing.T) { - testFeatures(t, func(client *mocks.MockClient, provider *monitor.DefaultFeaturesStatusProvider) { - client.EXPECT().List(gomock.Any(), &cbcontainersv1.CBContainersRuntimeList{}). - Do(func(ctx context.Context, list *cbcontainersv1.CBContainersRuntimeList, _ ...interface{}) { - list.Items = make([]cbcontainersv1.CBContainersRuntime, 0) - }). - Return(nil) - enabled, err := provider.RuntimeEnabled() - require.NoError(t, err) - require.False(t, enabled) - }) - }) - - t.Run("When Client.List returns 1 items, should return true", func(t *testing.T) { - testFeatures(t, func(client *mocks.MockClient, provider *monitor.DefaultFeaturesStatusProvider) { - client.EXPECT().List(gomock.Any(), &cbcontainersv1.CBContainersRuntimeList{}). - Do(func(ctx context.Context, list *cbcontainersv1.CBContainersRuntimeList, _ ...interface{}) { - list.Items = make([]cbcontainersv1.CBContainersRuntime, 1) - }). - Return(nil) - enabled, err := provider.RuntimeEnabled() - require.NoError(t, err) - require.True(t, enabled) - }) - }) -} diff --git a/cbcontainers/monitor/default_health_checker.go b/cbcontainers/monitor/default_health_checker.go deleted file mode 100644 index 686cf121..00000000 --- a/cbcontainers/monitor/default_health_checker.go +++ /dev/null @@ -1,124 +0,0 @@ -package monitor - -import ( - "context" - "fmt" - admissionsV1 "k8s.io/api/admissionregistration/v1beta1" - appsV1 "k8s.io/api/apps/v1" - coreV1 "k8s.io/api/core/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -type DefaultHealthChecker struct { - client client.Client - namespace string -} - -func NewDefaultHealthChecker(client client.Client, namespace string) *DefaultHealthChecker { - return &DefaultHealthChecker{ - client: client, - namespace: namespace, - } -} - -func (healthChecker *DefaultHealthChecker) listClusterObjects(list client.ObjectList) error { - return healthChecker.list(list, &client.ListOptions{Namespace: ""}) -} - -func (healthChecker *DefaultHealthChecker) listNamespaceObjects(list client.ObjectList) error { - return healthChecker.list(list, &client.ListOptions{Namespace: healthChecker.namespace}) -} - -func (healthChecker *DefaultHealthChecker) list(list client.ObjectList, option client.ListOption) error { - return healthChecker.client.List(context.Background(), list, option) -} - -func (healthChecker *DefaultHealthChecker) GetPods() (map[string]coreV1.Pod, error) { - podsList := &coreV1.PodList{} - if err := healthChecker.listNamespaceObjects(podsList); err != nil { - return nil, err - } - - if podsList.Items == nil { - return nil, fmt.Errorf("got nil for Pods list") - } - - pods := make(map[string]coreV1.Pod) - for _, pod := range podsList.Items { - pods[pod.Name] = pod - } - - return pods, nil -} - -func (healthChecker *DefaultHealthChecker) GetReplicaSets() (map[string]appsV1.ReplicaSet, error) { - replicaSetList := &appsV1.ReplicaSetList{} - if err := healthChecker.listNamespaceObjects(replicaSetList); err != nil { - return nil, err - } - - if replicaSetList.Items == nil { - return nil, fmt.Errorf("got nil for ReplicaSets list") - } - - replicaSets := make(map[string]appsV1.ReplicaSet) - for _, replicaSet := range replicaSetList.Items { - replicaSets[replicaSet.Name] = replicaSet - } - - return replicaSets, nil -} - -func (healthChecker *DefaultHealthChecker) GetDeployments() (map[string]appsV1.Deployment, error) { - deploymentList := &appsV1.DeploymentList{} - if err := healthChecker.listNamespaceObjects(deploymentList); err != nil { - return nil, err - } - - if deploymentList.Items == nil { - return nil, fmt.Errorf("got nil for Deployments list") - } - - deployments := make(map[string]appsV1.Deployment) - for _, deployment := range deploymentList.Items { - deployments[deployment.Name] = deployment - } - - return deployments, nil -} - -func (healthChecker *DefaultHealthChecker) GetDaemonSets() (map[string]appsV1.DaemonSet, error) { - daemonSetList := &appsV1.DaemonSetList{} - if err := healthChecker.listNamespaceObjects(daemonSetList); err != nil { - return nil, err - } - - if daemonSetList.Items == nil { - return nil, fmt.Errorf("got nil for DaemonSets list") - } - - daemonSets := make(map[string]appsV1.DaemonSet) - for _, daemonSet := range daemonSetList.Items { - daemonSets[daemonSet.Name] = daemonSet - } - - return daemonSets, nil -} - -func (healthChecker *DefaultHealthChecker) GetValidatingWebhookConfigurations() (map[string]admissionsV1.ValidatingWebhookConfiguration, error) { - validatingWebhookConfigurationList := &admissionsV1.ValidatingWebhookConfigurationList{} - if err := healthChecker.listClusterObjects(validatingWebhookConfigurationList); err != nil { - return nil, err - } - - if validatingWebhookConfigurationList.Items == nil { - return nil, fmt.Errorf("got nil for ValidatingWebhookConfigurations list") - } - - validatingWebhookConfigurations := make(map[string]admissionsV1.ValidatingWebhookConfiguration) - for _, validatingWebhookConfiguration := range validatingWebhookConfigurationList.Items { - validatingWebhookConfigurations[validatingWebhookConfiguration.Name] = validatingWebhookConfiguration - } - - return validatingWebhookConfigurations, nil -} diff --git a/cbcontainers/monitor/mocks/generated.go b/cbcontainers/monitor/mocks/generated.go deleted file mode 100644 index a02a3418..00000000 --- a/cbcontainers/monitor/mocks/generated.go +++ /dev/null @@ -1,5 +0,0 @@ -package mocks - -//go:generate mockgen -destination mock_features_status_provider_generated.go -package mocks github.com/vmware/cbcontainers-operator/cbcontainers/monitor FeaturesStatusProvider -//go:generate mockgen -destination mock_health_checker_generated.go -package mocks github.com/vmware/cbcontainers-operator/cbcontainers/monitor HealthChecker -//go:generate mockgen -destination mock_message_reporter_generated.go -package mocks github.com/vmware/cbcontainers-operator/cbcontainers/monitor MessageReporter diff --git a/cbcontainers/monitor/mocks/mock_features_status_provider_generated.go b/cbcontainers/monitor/mocks/mock_features_status_provider_generated.go deleted file mode 100644 index 786c9e95..00000000 --- a/cbcontainers/monitor/mocks/mock_features_status_provider_generated.go +++ /dev/null @@ -1,64 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/vmware/cbcontainers-operator/cbcontainers/monitor (interfaces: FeaturesStatusProvider) - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" -) - -// MockFeaturesStatusProvider is a mock of FeaturesStatusProvider interface. -type MockFeaturesStatusProvider struct { - ctrl *gomock.Controller - recorder *MockFeaturesStatusProviderMockRecorder -} - -// MockFeaturesStatusProviderMockRecorder is the mock recorder for MockFeaturesStatusProvider. -type MockFeaturesStatusProviderMockRecorder struct { - mock *MockFeaturesStatusProvider -} - -// NewMockFeaturesStatusProvider creates a new mock instance. -func NewMockFeaturesStatusProvider(ctrl *gomock.Controller) *MockFeaturesStatusProvider { - mock := &MockFeaturesStatusProvider{ctrl: ctrl} - mock.recorder = &MockFeaturesStatusProviderMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockFeaturesStatusProvider) EXPECT() *MockFeaturesStatusProviderMockRecorder { - return m.recorder -} - -// HardeningEnabled mocks base method. -func (m *MockFeaturesStatusProvider) HardeningEnabled() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "HardeningEnabled") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// HardeningEnabled indicates an expected call of HardeningEnabled. -func (mr *MockFeaturesStatusProviderMockRecorder) HardeningEnabled() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HardeningEnabled", reflect.TypeOf((*MockFeaturesStatusProvider)(nil).HardeningEnabled)) -} - -// RuntimeEnabled mocks base method. -func (m *MockFeaturesStatusProvider) RuntimeEnabled() (bool, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RuntimeEnabled") - ret0, _ := ret[0].(bool) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// RuntimeEnabled indicates an expected call of RuntimeEnabled. -func (mr *MockFeaturesStatusProviderMockRecorder) RuntimeEnabled() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RuntimeEnabled", reflect.TypeOf((*MockFeaturesStatusProvider)(nil).RuntimeEnabled)) -} diff --git a/cbcontainers/monitor/mocks/mock_health_checker_generated.go b/cbcontainers/monitor/mocks/mock_health_checker_generated.go deleted file mode 100644 index 35808644..00000000 --- a/cbcontainers/monitor/mocks/mock_health_checker_generated.go +++ /dev/null @@ -1,112 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/vmware/cbcontainers-operator/cbcontainers/monitor (interfaces: HealthChecker) - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - v1beta1 "k8s.io/api/admissionregistration/v1beta1" - v1 "k8s.io/api/apps/v1" - v10 "k8s.io/api/core/v1" -) - -// MockHealthChecker is a mock of HealthChecker interface. -type MockHealthChecker struct { - ctrl *gomock.Controller - recorder *MockHealthCheckerMockRecorder -} - -// MockHealthCheckerMockRecorder is the mock recorder for MockHealthChecker. -type MockHealthCheckerMockRecorder struct { - mock *MockHealthChecker -} - -// NewMockHealthChecker creates a new mock instance. -func NewMockHealthChecker(ctrl *gomock.Controller) *MockHealthChecker { - mock := &MockHealthChecker{ctrl: ctrl} - mock.recorder = &MockHealthCheckerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockHealthChecker) EXPECT() *MockHealthCheckerMockRecorder { - return m.recorder -} - -// GetDaemonSets mocks base method. -func (m *MockHealthChecker) GetDaemonSets() (map[string]v1.DaemonSet, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDaemonSets") - ret0, _ := ret[0].(map[string]v1.DaemonSet) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetDaemonSets indicates an expected call of GetDaemonSets. -func (mr *MockHealthCheckerMockRecorder) GetDaemonSets() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDaemonSets", reflect.TypeOf((*MockHealthChecker)(nil).GetDaemonSets)) -} - -// GetDeployments mocks base method. -func (m *MockHealthChecker) GetDeployments() (map[string]v1.Deployment, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDeployments") - ret0, _ := ret[0].(map[string]v1.Deployment) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetDeployments indicates an expected call of GetDeployments. -func (mr *MockHealthCheckerMockRecorder) GetDeployments() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeployments", reflect.TypeOf((*MockHealthChecker)(nil).GetDeployments)) -} - -// GetPods mocks base method. -func (m *MockHealthChecker) GetPods() (map[string]v10.Pod, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPods") - ret0, _ := ret[0].(map[string]v10.Pod) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPods indicates an expected call of GetPods. -func (mr *MockHealthCheckerMockRecorder) GetPods() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPods", reflect.TypeOf((*MockHealthChecker)(nil).GetPods)) -} - -// GetReplicaSets mocks base method. -func (m *MockHealthChecker) GetReplicaSets() (map[string]v1.ReplicaSet, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetReplicaSets") - ret0, _ := ret[0].(map[string]v1.ReplicaSet) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetReplicaSets indicates an expected call of GetReplicaSets. -func (mr *MockHealthCheckerMockRecorder) GetReplicaSets() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetReplicaSets", reflect.TypeOf((*MockHealthChecker)(nil).GetReplicaSets)) -} - -// GetValidatingWebhookConfigurations mocks base method. -func (m *MockHealthChecker) GetValidatingWebhookConfigurations() (map[string]v1beta1.ValidatingWebhookConfiguration, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetValidatingWebhookConfigurations") - ret0, _ := ret[0].(map[string]v1beta1.ValidatingWebhookConfiguration) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetValidatingWebhookConfigurations indicates an expected call of GetValidatingWebhookConfigurations. -func (mr *MockHealthCheckerMockRecorder) GetValidatingWebhookConfigurations() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetValidatingWebhookConfigurations", reflect.TypeOf((*MockHealthChecker)(nil).GetValidatingWebhookConfigurations)) -} diff --git a/cbcontainers/monitor/mocks/mock_message_reporter_generated.go b/cbcontainers/monitor/mocks/mock_message_reporter_generated.go deleted file mode 100644 index 6350fa1f..00000000 --- a/cbcontainers/monitor/mocks/mock_message_reporter_generated.go +++ /dev/null @@ -1,63 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/vmware/cbcontainers-operator/cbcontainers/monitor (interfaces: MessageReporter) - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - models "github.com/vmware/cbcontainers-operator/cbcontainers/monitor/models" -) - -// MockMessageReporter is a mock of MessageReporter interface. -type MockMessageReporter struct { - ctrl *gomock.Controller - recorder *MockMessageReporterMockRecorder -} - -// MockMessageReporterMockRecorder is the mock recorder for MockMessageReporter. -type MockMessageReporterMockRecorder struct { - mock *MockMessageReporter -} - -// NewMockMessageReporter creates a new mock instance. -func NewMockMessageReporter(ctrl *gomock.Controller) *MockMessageReporter { - mock := &MockMessageReporter{ctrl: ctrl} - mock.recorder = &MockMessageReporterMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockMessageReporter) EXPECT() *MockMessageReporterMockRecorder { - return m.recorder -} - -// Close mocks base method. -func (m *MockMessageReporter) Close() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Close") - ret0, _ := ret[0].(error) - return ret0 -} - -// Close indicates an expected call of Close. -func (mr *MockMessageReporterMockRecorder) Close() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockMessageReporter)(nil).Close)) -} - -// SendMonitorMessage mocks base method. -func (m *MockMessageReporter) SendMonitorMessage(arg0 models.HealthReportMessage) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SendMonitorMessage", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// SendMonitorMessage indicates an expected call of SendMonitorMessage. -func (mr *MockMessageReporterMockRecorder) SendMonitorMessage(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMonitorMessage", reflect.TypeOf((*MockMessageReporter)(nil).SendMonitorMessage), arg0) -} diff --git a/cbcontainers/monitor/models/health_report_message.go b/cbcontainers/monitor/models/health_report_message.go deleted file mode 100644 index de301176..00000000 --- a/cbcontainers/monitor/models/health_report_message.go +++ /dev/null @@ -1,64 +0,0 @@ -package models - -type WorkloadKind string -type WebhookType string - -const ( - WorkloadKindDeployment = WorkloadKind("workload-kind-deployment") - WorkloadKindDaemonSet = WorkloadKind("workload-kind-daemonset") - - WebhookTypeValidating = WebhookType("webhook-type-validating") - WebhookTypeMutating = WebhookType("webhook-type-mutating") -) - -type HealthReportMessage struct { - Account string - Cluster string - Version string - EnabledComponents map[string]bool - Workloads map[string]WorkloadHealthReport - Webhooks map[string]WebhookHealthReport -} - -func NewHealthReportMessage(account, cluster, version string, enabledComponents map[string]bool, workloads map[string]WorkloadHealthReport, webhooks map[string]WebhookHealthReport) HealthReportMessage { - return HealthReportMessage{ - Account: account, - Cluster: cluster, - Version: version, - EnabledComponents: enabledComponents, - Workloads: workloads, - Webhooks: webhooks, - } -} - -type WorkloadHealthReport struct { - Kind WorkloadKind - Status []byte - Labels map[string]string - Spec WorkloadSpecReport - ReplicasReports map[string]WorkloadReplicaHealthReport -} - -type WorkloadSpecReport struct { - Replicas int32 - Containers map[string]ContainerHealthReport -} - -type WorkloadReplicaHealthReport struct { - Node string - Spec WorkloadReplicaSpecReport - Status []byte -} - -type WorkloadReplicaSpecReport struct { - Containers map[string]ContainerHealthReport -} - -type ContainerHealthReport struct { - Image string -} - -type WebhookHealthReport struct { - Type WebhookType - Uid string -} diff --git a/cbcontainers/monitor/monitor_agent.go b/cbcontainers/monitor/monitor_agent.go deleted file mode 100644 index 4b6d83d6..00000000 --- a/cbcontainers/monitor/monitor_agent.go +++ /dev/null @@ -1,310 +0,0 @@ -package monitor - -import ( - "encoding/json" - "fmt" - "github.com/go-logr/logr" - "github.com/vmware/cbcontainers-operator/cbcontainers/monitor/models" - hardeningObjects "github.com/vmware/cbcontainers-operator/cbcontainers/state/hardening/objects" - admissionsV1 "k8s.io/api/admissionregistration/v1beta1" - appsV1 "k8s.io/api/apps/v1" - coreV1 "k8s.io/api/core/v1" - "time" -) - -const ( - HardeningFeature = "guardrails" - RuntimeFeature = "nodeguard" -) - -type FeaturesStatusProvider interface { - HardeningEnabled() (bool, error) - RuntimeEnabled() (bool, error) -} - -type HealthChecker interface { - GetPods() (map[string]coreV1.Pod, error) - GetReplicaSets() (map[string]appsV1.ReplicaSet, error) - GetDeployments() (map[string]appsV1.Deployment, error) - GetDaemonSets() (map[string]appsV1.DaemonSet, error) - GetValidatingWebhookConfigurations() (map[string]admissionsV1.ValidatingWebhookConfiguration, error) -} - -type MessageReporter interface { - SendMonitorMessage(message models.HealthReportMessage) error - Close() error -} - -type MonitorAgent struct { - account string - cluster string - accessToken string - version string - - healthChecker HealthChecker - featuresStatusProvider FeaturesStatusProvider - messageReporter MessageReporter - - // The interval for sending health reports to the backend - interval time.Duration - - // Channel for stopping the agent - stopChan chan struct{} - - log logr.Logger -} - -func NewMonitorAgent(account, cluster, version string, healthChecker HealthChecker, featuresStatus FeaturesStatusProvider, messageReporter MessageReporter, interval time.Duration, log logr.Logger) *MonitorAgent { - return &MonitorAgent{ - account: account, - cluster: cluster, - version: version, - healthChecker: healthChecker, - featuresStatusProvider: featuresStatus, - messageReporter: messageReporter, - interval: interval, - stopChan: make(chan struct{}), - log: log, - } -} - -func (agent *MonitorAgent) Start() { - go agent.run() -} - -func (agent *MonitorAgent) Stop() { - close(agent.stopChan) -} - -func (agent *MonitorAgent) run() { - for { - select { - case <-time.After(agent.interval): - message, err := agent.buildHealthMessage() - if err != nil { - agent.log.Error(err, "error building health message") - continue - } - - if err = agent.messageReporter.SendMonitorMessage(message); err != nil { - agent.log.Error(err, "error reporting message to backend") - continue - } - case <-agent.stopChan: - if err := agent.messageReporter.Close(); err != nil { - agent.log.Error(err, "error closing reporter") - } - return - } - } -} - -func (agent *MonitorAgent) buildHealthMessage() (models.HealthReportMessage, error) { - hardeningEnabled, err := agent.featuresStatusProvider.HardeningEnabled() - if err != nil { - return models.HealthReportMessage{}, err - } - - runtimeEnabled, err := agent.featuresStatusProvider.RuntimeEnabled() - if err != nil { - return models.HealthReportMessage{}, err - } - - workloadsReports, err := agent.createWorkloadsHealthReports() - if err != nil { - return models.HealthReportMessage{}, err - } - - webhooksReports, err := agent.createWebhooksHealthReport() - if err != nil { - return models.HealthReportMessage{}, err - } - - enabledComponents := map[string]bool{ - HardeningFeature: hardeningEnabled, - RuntimeFeature: runtimeEnabled, - } - - return models.NewHealthReportMessage(agent.account, agent.cluster, agent.version, enabledComponents, workloadsReports, webhooksReports), nil -} - -func (agent *MonitorAgent) createWorkloadsHealthReports() (map[string]models.WorkloadHealthReport, error) { - workloadsReports := make(map[string]models.WorkloadHealthReport) - - pods, err := agent.healthChecker.GetPods() - if err != nil { - return nil, err - } - - replicasSets, err := agent.healthChecker.GetReplicaSets() - if err != nil { - return nil, err - } - - deployments, err := agent.healthChecker.GetDeployments() - if err != nil { - return nil, err - } - - daemonSets, err := agent.healthChecker.GetDaemonSets() - if err != nil { - return nil, err - } - - agent.populateWithDeploymentsWorkloads(deployments, workloadsReports) - agent.populateWithDaemonSetsWorkloads(daemonSets, workloadsReports) - agent.updateWorkloadsReplicasWithPodsAndReplicaSets(pods, replicasSets, workloadsReports) - - return workloadsReports, nil -} - -func (agent *MonitorAgent) populateWithDeploymentsWorkloads(deployments map[string]appsV1.Deployment, reports map[string]models.WorkloadHealthReport) { - for _, deployment := range deployments { - workloadMessage, err := agent.buildDeploymentMessage(deployment) - if err != nil { - agent.log.Error(err, "error building Deployment message") - continue - } - - if _, ok := reports[deployment.Name]; ok { - agent.log.Info("duplicated workload name", "service", deployment.Name) - } - - reports[deployment.Name] = workloadMessage - } -} - -func (agent *MonitorAgent) populateWithDaemonSetsWorkloads(daemonSets map[string]appsV1.DaemonSet, services map[string]models.WorkloadHealthReport) { - for _, daemonSet := range daemonSets { - workloadMessage, err := agent.buildDaemonSetMessage(daemonSet) - if err != nil { - agent.log.Error(err, "error building DaemonSet message") - continue - } - - if _, ok := services[daemonSet.Name]; ok { - agent.log.Info("duplicate service name", "service", daemonSet.Name) - } - - services[daemonSet.Name] = workloadMessage - } -} - -func (agent *MonitorAgent) buildDeploymentMessage(deployment appsV1.Deployment) (models.WorkloadHealthReport, error) { - return agent.buildWorkloadMessage(models.WorkloadKindDeployment, deployment.Name, deployment.Spec.Replicas, deployment.Spec.Template.Spec.Containers, deployment.Status, deployment.Labels) -} - -func (agent *MonitorAgent) buildDaemonSetMessage(daemon appsV1.DaemonSet) (models.WorkloadHealthReport, error) { - return agent.buildWorkloadMessage(models.WorkloadKindDaemonSet, daemon.Name, nil, daemon.Spec.Template.Spec.Containers, daemon.Status, daemon.Labels) -} - -func (agent *MonitorAgent) buildReplicaMessage(pod coreV1.Pod) (models.WorkloadReplicaHealthReport, error) { - specContainers := make(map[string]models.ContainerHealthReport) - for _, container := range pod.Spec.Containers { - specContainers[container.Name] = models.ContainerHealthReport{ - Image: container.Image, - } - } - - status, err := json.Marshal(pod.Status) - if err != nil { - return models.WorkloadReplicaHealthReport{}, fmt.Errorf("error marshaling status for pod: %v", pod.Name) - } - - spec := models.WorkloadReplicaSpecReport{ - Containers: specContainers, - } - - return models.WorkloadReplicaHealthReport{ - Node: pod.Spec.NodeName, - Spec: spec, - Status: status, - }, nil -} - -func (agent *MonitorAgent) buildWorkloadMessage(workloadKind models.WorkloadKind, name string, replicas *int32, containers []coreV1.Container, statusObj interface{}, labels map[string]string) (models.WorkloadHealthReport, error) { - containersReports := make(map[string]models.ContainerHealthReport) - for _, container := range containers { - containersReports[container.Name] = models.ContainerHealthReport{Image: container.Image} - } - - status, err := json.Marshal(statusObj) - if err != nil { - return models.WorkloadHealthReport{}, fmt.Errorf("error marshaling status for %v: %v", workloadKind, name) - } - - spec := models.WorkloadSpecReport{ - Containers: containersReports, - } - if replicas != nil { - spec.Replicas = *replicas - } - - return models.WorkloadHealthReport{ - Kind: workloadKind, - Spec: spec, - Status: status, - ReplicasReports: make(map[string]models.WorkloadReplicaHealthReport), - Labels: labels, - }, nil - -} - -func (agent *MonitorAgent) updateWorkloadsReplicasWithPodsAndReplicaSets(pods map[string]coreV1.Pod, replicaSets map[string]appsV1.ReplicaSet, reports map[string]models.WorkloadHealthReport) { - for _, pod := range pods { - if len(pod.OwnerReferences) < 1 { - agent.log.Info("found pod with no parent", "pod", pod.Name) - continue - } - owner := pod.OwnerReferences[0] - ownerName := owner.Name - if owner.Kind == "ReplicaSet" { - if rs, ok := replicaSets[owner.Name]; ok && len(rs.OwnerReferences) > 0 { - ownerName = rs.OwnerReferences[0].Name - } else { - //logger.Info("couldn't determine pod parent", "pod", pod.Name) - continue - } - } - - if workloadMessage, ok := reports[ownerName]; ok { - replicaMsg, err := agent.buildReplicaMessage(pod) - if err != nil { - agent.log.Error(err, "error getting pod data", "pod", pod.Name) - continue - } - - workloadMessage.ReplicasReports[pod.Name] = replicaMsg - } - } -} - -func (agent *MonitorAgent) createWebhooksHealthReport() (map[string]models.WebhookHealthReport, error) { - webhooksReports := make(map[string]models.WebhookHealthReport) - validatingWebhooks, err := agent.healthChecker.GetValidatingWebhookConfigurations() - if err != nil { - return nil, err - } - - agent.populateWithValidatingWebhooks(validatingWebhooks, webhooksReports) - return webhooksReports, nil -} - -func (agent *MonitorAgent) populateWithValidatingWebhooks(webhooks map[string]admissionsV1.ValidatingWebhookConfiguration, reports map[string]models.WebhookHealthReport) { - if webhook, ok := webhooks[hardeningObjects.EnforcerName]; ok { - webhookMessage := agent.buildValidatingWebhookMessage(webhook) - if _, ok := reports[webhook.Name]; ok { - agent.log.Info("duplicated webhook name", "webhook", webhook.Name) - } - reports[webhook.Name] = webhookMessage - } else { - agent.log.Info(fmt.Sprintf("%v validating webhook not found.", hardeningObjects.EnforcerName), "webhook", webhook.Name) - } -} - -func (agent *MonitorAgent) buildValidatingWebhookMessage(webhook admissionsV1.ValidatingWebhookConfiguration) models.WebhookHealthReport { - return models.WebhookHealthReport{ - Type: models.WebhookTypeValidating, - Uid: string(webhook.UID), - } -} diff --git a/cbcontainers/monitor/monitor_agent_test.go b/cbcontainers/monitor/monitor_agent_test.go deleted file mode 100644 index 649d2722..00000000 --- a/cbcontainers/monitor/monitor_agent_test.go +++ /dev/null @@ -1,314 +0,0 @@ -package monitor_test - -import ( - "encoding/json" - "fmt" - logrTesting "github.com/go-logr/logr/testing" - "github.com/golang/mock/gomock" - "github.com/vmware/cbcontainers-operator/cbcontainers/monitor" - "github.com/vmware/cbcontainers-operator/cbcontainers/monitor/mocks" - "github.com/vmware/cbcontainers-operator/cbcontainers/monitor/models" - hardeningObjects "github.com/vmware/cbcontainers-operator/cbcontainers/state/hardening/objects" - "github.com/vmware/cbcontainers-operator/cbcontainers/test_utils" - admissionsV1beta1 "k8s.io/api/admissionregistration/v1beta1" - appsV1 "k8s.io/api/apps/v1" - coreV1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "testing" - "time" -) - -const ( - Account = "account_name" - Cluster = "cluster_name" - Version = "version" - SendInterval = 2 * time.Second -) - -type TestMonitorObjects struct { - healthCheckerMock *mocks.MockHealthChecker - featuresMock *mocks.MockFeaturesStatusProvider - messageReporterMock *mocks.MockMessageReporter -} - -type AgentTestSetupFunc func(*monitor.MonitorAgent, *TestMonitorObjects) (models.HealthReportMessage, error) - -func testMonitorAgent(t *testing.T, setup AgentTestSetupFunc) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - testObjects := &TestMonitorObjects{ - healthCheckerMock: mocks.NewMockHealthChecker(ctrl), - featuresMock: mocks.NewMockFeaturesStatusProvider(ctrl), - messageReporterMock: mocks.NewMockMessageReporter(ctrl), - } - agent := monitor.NewMonitorAgent(Account, Cluster, Version, testObjects.healthCheckerMock, testObjects.featuresMock, testObjects.messageReporterMock, SendInterval, &logrTesting.TestLogger{T: t}) - - expectedHealthReportMessage, err := setup(agent, testObjects) - if err == nil { - testObjects.messageReporterMock.EXPECT().SendMonitorMessage(expectedHealthReportMessage).Return(nil) - } - - testObjects.messageReporterMock.EXPECT().Close().Return(nil) - - agent.Start() - time.Sleep(SendInterval) - agent.Stop() - time.Sleep(SendInterval) -} - -func TestWorkloadsReports(t *testing.T) { - testWorkloadsReports := func(t *testing.T, expectedDeployments map[string]appsV1.Deployment, expectedDaemonSets map[string]appsV1.DaemonSet, expectedReplicaSets map[string]appsV1.ReplicaSet, expectedPods map[string]coreV1.Pod, expectedWorkloadHealthReports map[string]models.WorkloadHealthReport) { - testMonitorAgent(t, func(agent *monitor.MonitorAgent, testObjects *TestMonitorObjects) (models.HealthReportMessage, error) { - testObjects.featuresMock.EXPECT().HardeningEnabled().Return(true, nil) - testObjects.featuresMock.EXPECT().RuntimeEnabled().Return(true, nil) - testObjects.healthCheckerMock.EXPECT().GetPods().Return(expectedPods, nil) - testObjects.healthCheckerMock.EXPECT().GetDaemonSets().Return(expectedDaemonSets, nil) - testObjects.healthCheckerMock.EXPECT().GetDeployments().Return(expectedDeployments, nil) - testObjects.healthCheckerMock.EXPECT().GetReplicaSets().Return(expectedReplicaSets, nil) - testObjects.healthCheckerMock.EXPECT().GetValidatingWebhookConfigurations().Return(map[string]admissionsV1beta1.ValidatingWebhookConfiguration{}, nil) - - return models.NewHealthReportMessage(Account, Cluster, Version, map[string]bool{monitor.HardeningFeature: true, monitor.RuntimeFeature: true}, expectedWorkloadHealthReports, map[string]models.WebhookHealthReport{}), nil - }) - } - - workloadName := test_utils.RandomString() - workloadLabels := test_utils.RandomLabels() - workloadMeta := metav1.ObjectMeta{Name: workloadName, Labels: workloadLabels} - replicaSetName := fmt.Sprintf("%v-%v", workloadName, test_utils.RandomString()) - podName := fmt.Sprintf("%v-%v", replicaSetName, test_utils.RandomString()) - nodeName := test_utils.RandomString() - - replicaCount := int32(2) - readyReplicaCount := int32(1) - deploymentStatus := appsV1.DeploymentStatus{Replicas: replicaCount, ReadyReplicas: readyReplicaCount} - deploymentStatusBytes, _ := json.Marshal(deploymentStatus) - daemonSetStatus := appsV1.DaemonSetStatus{DesiredNumberScheduled: replicaCount, NumberReady: readyReplicaCount} - daemonSetStatusBytes, _ := json.Marshal(daemonSetStatus) - podStatus := coreV1.PodStatus{Message: test_utils.RandomString()} - podStatusBytes, _ := json.Marshal(podStatus) - - firstContainer := test_utils.RandomString() - firstImage := test_utils.RandomString() - secondContainer := test_utils.RandomString() - secondImage := test_utils.RandomString() - podTemplateSpec := coreV1.PodTemplateSpec{ - Spec: coreV1.PodSpec{ - Containers: []coreV1.Container{ - {Name: firstContainer, Image: firstImage}, - {Name: secondContainer, Image: secondImage}, - }, - }, - } - - createDeployments := func() map[string]appsV1.Deployment { - return map[string]appsV1.Deployment{ - workloadName: { - ObjectMeta: workloadMeta, Status: deploymentStatus, - Spec: appsV1.DeploymentSpec{Replicas: &replicaCount, Template: podTemplateSpec}, - }, - } - } - - createDaemonSets := func() map[string]appsV1.DaemonSet { - return map[string]appsV1.DaemonSet{ - workloadName: { - ObjectMeta: workloadMeta, Status: daemonSetStatus, - Spec: appsV1.DaemonSetSpec{Template: podTemplateSpec}, - }, - } - } - - createReplicaSets := func(ownerKind string) map[string]appsV1.ReplicaSet { - return map[string]appsV1.ReplicaSet{ - replicaSetName: { - ObjectMeta: metav1.ObjectMeta{ - Name: replicaSetName, - OwnerReferences: []metav1.OwnerReference{{Kind: ownerKind, Name: workloadName}}}, - }, - } - } - - createPods := func() map[string]coreV1.Pod { - expectedPodSpec := coreV1.PodSpec{ - NodeName: nodeName, - Containers: []coreV1.Container{{Name: secondContainer, Image: secondImage}}, - } - return map[string]coreV1.Pod{ - podName: { - ObjectMeta: metav1.ObjectMeta{ - Name: podName, - OwnerReferences: []metav1.OwnerReference{{Kind: "ReplicaSet", Name: replicaSetName}}, - }, - Status: podStatus, - Spec: expectedPodSpec, - }, - } - } - - createExpectedWorkloadHealthReports := func(kind models.WorkloadKind, replicasReports map[string]models.WorkloadReplicaHealthReport) map[string]models.WorkloadHealthReport { - spec := models.WorkloadSpecReport{ - Containers: map[string]models.ContainerHealthReport{ - firstContainer: {Image: firstImage}, - secondContainer: {Image: secondImage}, - }, - } - var statusBytes []byte - - if kind == models.WorkloadKindDeployment { - spec.Replicas = replicaCount - statusBytes = deploymentStatusBytes - } else if kind == models.WorkloadKindDaemonSet { - spec.Replicas = 0 - statusBytes = daemonSetStatusBytes - } else { - panic("Unsupported workload kind on test") - } - - return map[string]models.WorkloadHealthReport{ - workloadName: { - Kind: kind, - Labels: workloadLabels, - Status: statusBytes, - Spec: spec, - ReplicasReports: replicasReports, - }, - } - } - - createExpectedWorkLoadReplicaReports := func() map[string]models.WorkloadReplicaHealthReport { - return map[string]models.WorkloadReplicaHealthReport{ - podName: { - Node: nodeName, - Status: podStatusBytes, - Spec: models.WorkloadReplicaSpecReport{Containers: map[string]models.ContainerHealthReport{secondContainer: {Image: secondImage}}}, - }, - } - } - - t.Run("When there are no workloads, there should be no workloads reports", func(t *testing.T) { - testWorkloadsReports(t, map[string]appsV1.Deployment{}, map[string]appsV1.DaemonSet{}, map[string]appsV1.ReplicaSet{}, map[string]coreV1.Pod{}, map[string]models.WorkloadHealthReport{}) - }) - - t.Run("When there is a deployment with no replicas, it should be reported with no replicas", func(t *testing.T) { - expectedWorkloadReport := createExpectedWorkloadHealthReports(models.WorkloadKindDeployment, map[string]models.WorkloadReplicaHealthReport{}) - testWorkloadsReports(t, createDeployments(), map[string]appsV1.DaemonSet{}, map[string]appsV1.ReplicaSet{}, map[string]coreV1.Pod{}, expectedWorkloadReport) - }) - - t.Run("When there is a daemonSet with no replicas, it should be reported with no replicas", func(t *testing.T) { - expectedWorkloadReport := createExpectedWorkloadHealthReports(models.WorkloadKindDaemonSet, map[string]models.WorkloadReplicaHealthReport{}) - testWorkloadsReports(t, map[string]appsV1.Deployment{}, createDaemonSets(), map[string]appsV1.ReplicaSet{}, map[string]coreV1.Pod{}, expectedWorkloadReport) - }) - - t.Run("When there is a deployment with replicaset but no pods, it should be reported with no replicas", func(t *testing.T) { - expectedWorkloadReport := createExpectedWorkloadHealthReports(models.WorkloadKindDeployment, map[string]models.WorkloadReplicaHealthReport{}) - testWorkloadsReports(t, createDeployments(), map[string]appsV1.DaemonSet{}, createReplicaSets("Deployment"), map[string]coreV1.Pod{}, expectedWorkloadReport) - }) - - t.Run("When there is a daemonSet with replicaset but no pods, it should be reported with no replicas", func(t *testing.T) { - expectedWorkloadReport := createExpectedWorkloadHealthReports(models.WorkloadKindDaemonSet, map[string]models.WorkloadReplicaHealthReport{}) - testWorkloadsReports(t, map[string]appsV1.Deployment{}, createDaemonSets(), createReplicaSets("DaemonSet"), map[string]coreV1.Pod{}, expectedWorkloadReport) - }) - - t.Run("When there is a deployment with replicas, it should be reported with replicas", func(t *testing.T) { - expectedWorkloadReport := createExpectedWorkloadHealthReports(models.WorkloadKindDeployment, createExpectedWorkLoadReplicaReports()) - testWorkloadsReports(t, createDeployments(), map[string]appsV1.DaemonSet{}, createReplicaSets("Deployment"), createPods(), expectedWorkloadReport) - }) - - t.Run("When there is a daemonSet with replicas, it should be reported with replicas", func(t *testing.T) { - expectedWorkloadReport := createExpectedWorkloadHealthReports(models.WorkloadKindDaemonSet, createExpectedWorkLoadReplicaReports()) - testWorkloadsReports(t, map[string]appsV1.Deployment{}, createDaemonSets(), createReplicaSets("DaemonSet"), createPods(), expectedWorkloadReport) - }) -} - -func TestWebhookReports(t *testing.T) { - testWebhookReports := func(t *testing.T, expectedValidatingWebhooks map[string]admissionsV1beta1.ValidatingWebhookConfiguration, expectedWebhookReports map[string]models.WebhookHealthReport) { - testMonitorAgent(t, func(agent *monitor.MonitorAgent, testObjects *TestMonitorObjects) (models.HealthReportMessage, error) { - testObjects.featuresMock.EXPECT().HardeningEnabled().Return(true, nil) - testObjects.featuresMock.EXPECT().RuntimeEnabled().Return(true, nil) - testObjects.healthCheckerMock.EXPECT().GetPods().Return(map[string]coreV1.Pod{}, nil) - testObjects.healthCheckerMock.EXPECT().GetDaemonSets().Return(map[string]appsV1.DaemonSet{}, nil) - testObjects.healthCheckerMock.EXPECT().GetDeployments().Return(map[string]appsV1.Deployment{}, nil) - testObjects.healthCheckerMock.EXPECT().GetReplicaSets().Return(map[string]appsV1.ReplicaSet{}, nil) - testObjects.healthCheckerMock.EXPECT().GetValidatingWebhookConfigurations().Return(expectedValidatingWebhooks, nil) - - return models.NewHealthReportMessage(Account, Cluster, Version, map[string]bool{monitor.HardeningFeature: true, monitor.RuntimeFeature: true}, map[string]models.WorkloadHealthReport{}, expectedWebhookReports), nil - }) - } - - t.Run("When there are no validating web hooks, there should be no reports", func(t *testing.T) { - testWebhookReports(t, map[string]admissionsV1beta1.ValidatingWebhookConfiguration{}, map[string]models.WebhookHealthReport{}) - }) - - t.Run("When there are validating web hooks but no enforcer web hook, there should be no reports", func(t *testing.T) { - testWebhookReports(t, map[string]admissionsV1beta1.ValidatingWebhookConfiguration{ - test_utils.RandomString(): { - Webhooks: []admissionsV1beta1.ValidatingWebhook{{Name: test_utils.RandomString()}}, - }, - }, map[string]models.WebhookHealthReport{}) - }) - - t.Run("When there are validating web hooks including the enforcer web hook, there should be one report with the enforcer webhook", func(t *testing.T) { - uid := test_utils.RandomString() - testWebhookReports(t, map[string]admissionsV1beta1.ValidatingWebhookConfiguration{ - test_utils.RandomString(): { - Webhooks: []admissionsV1beta1.ValidatingWebhook{{Name: test_utils.RandomString()}}, - }, - hardeningObjects.EnforcerName: { - ObjectMeta: metav1.ObjectMeta{ - Name: hardeningObjects.EnforcerName, - UID: types.UID(uid), - }, - Webhooks: []admissionsV1beta1.ValidatingWebhook{{Name: test_utils.RandomString()}}, - }, - }, map[string]models.WebhookHealthReport{ - hardeningObjects.EnforcerName: { - Type: models.WebhookTypeValidating, - Uid: uid, - }, - }) - }) -} - -func TestEnabledComponents(t *testing.T) { - testEnabledComponents := func(t *testing.T, hardeningEnabled, runtimeEnabled bool) { - testMonitorAgent(t, func(agent *monitor.MonitorAgent, testObjects *TestMonitorObjects) (models.HealthReportMessage, error) { - testObjects.featuresMock.EXPECT().HardeningEnabled().Return(hardeningEnabled, nil) - testObjects.featuresMock.EXPECT().RuntimeEnabled().Return(runtimeEnabled, nil) - testObjects.healthCheckerMock.EXPECT().GetPods().Return(map[string]coreV1.Pod{}, nil) - testObjects.healthCheckerMock.EXPECT().GetDaemonSets().Return(map[string]appsV1.DaemonSet{}, nil) - testObjects.healthCheckerMock.EXPECT().GetDeployments().Return(map[string]appsV1.Deployment{}, nil) - testObjects.healthCheckerMock.EXPECT().GetReplicaSets().Return(map[string]appsV1.ReplicaSet{}, nil) - testObjects.healthCheckerMock.EXPECT().GetValidatingWebhookConfigurations().Return(map[string]admissionsV1beta1.ValidatingWebhookConfiguration{}, nil) - - return models.NewHealthReportMessage(Account, Cluster, Version, map[string]bool{monitor.HardeningFeature: hardeningEnabled, monitor.RuntimeFeature: runtimeEnabled}, map[string]models.WorkloadHealthReport{}, map[string]models.WebhookHealthReport{}), nil - }) - } - - t.Run("When can't get hardening enabled status, log error", func(t *testing.T) { - testMonitorAgent(t, func(agent *monitor.MonitorAgent, testObjects *TestMonitorObjects) (models.HealthReportMessage, error) { - err := fmt.Errorf("mock-error-for-getting-hardening") - testObjects.featuresMock.EXPECT().HardeningEnabled().Return(false, err) - return models.HealthReportMessage{}, err - }) - }) - - t.Run("When can't get runtime enabled status, log error", func(t *testing.T) { - testMonitorAgent(t, func(agent *monitor.MonitorAgent, testObjects *TestMonitorObjects) (models.HealthReportMessage, error) { - err := fmt.Errorf("mock-error-for-getting-runtime") - testObjects.featuresMock.EXPECT().HardeningEnabled().Return(true, nil) - testObjects.featuresMock.EXPECT().RuntimeEnabled().Return(false, err) - return models.HealthReportMessage{}, err - }) - }) - - possibleFlags := []bool{true, false} - for _, hardeningEnabled := range possibleFlags { - for _, runtimeEnabled := range possibleFlags { - t.Run(fmt.Sprintf("When Hardening is set to %v and Runtime is set to %v, message should be built properly", hardeningEnabled, runtimeEnabled), func(t *testing.T) { - testEnabledComponents(t, hardeningEnabled, runtimeEnabled) - }) - } - } -} diff --git a/cbcontainers/monitor/protobuf/monitor.pb.go b/cbcontainers/monitor/protobuf/monitor.pb.go deleted file mode 100644 index 918ff1ac..00000000 --- a/cbcontainers/monitor/protobuf/monitor.pb.go +++ /dev/null @@ -1,988 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0-devel -// protoc v3.13.0 -// source: monitor.proto - -package monitor - -import ( - context "context" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -type ServiceHealthReport_Kind int32 - -const ( - ServiceHealthReport_DEPLOYMENT ServiceHealthReport_Kind = 0 - ServiceHealthReport_DAEMONSET ServiceHealthReport_Kind = 1 -) - -// Enum value maps for ServiceHealthReport_Kind. -var ( - ServiceHealthReport_Kind_name = map[int32]string{ - 0: "DEPLOYMENT", - 1: "DAEMONSET", - } - ServiceHealthReport_Kind_value = map[string]int32{ - "DEPLOYMENT": 0, - "DAEMONSET": 1, - } -) - -func (x ServiceHealthReport_Kind) Enum() *ServiceHealthReport_Kind { - p := new(ServiceHealthReport_Kind) - *p = x - return p -} - -func (x ServiceHealthReport_Kind) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ServiceHealthReport_Kind) Descriptor() protoreflect.EnumDescriptor { - return file_monitor_proto_enumTypes[0].Descriptor() -} - -func (ServiceHealthReport_Kind) Type() protoreflect.EnumType { - return &file_monitor_proto_enumTypes[0] -} - -func (x ServiceHealthReport_Kind) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ServiceHealthReport_Kind.Descriptor instead. -func (ServiceHealthReport_Kind) EnumDescriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{4, 0} -} - -type WebhookHealthReport_WebhookType int32 - -const ( - WebhookHealthReport_VALIDATING WebhookHealthReport_WebhookType = 0 - WebhookHealthReport_MUTATING WebhookHealthReport_WebhookType = 1 -) - -// Enum value maps for WebhookHealthReport_WebhookType. -var ( - WebhookHealthReport_WebhookType_name = map[int32]string{ - 0: "VALIDATING", - 1: "MUTATING", - } - WebhookHealthReport_WebhookType_value = map[string]int32{ - "VALIDATING": 0, - "MUTATING": 1, - } -) - -func (x WebhookHealthReport_WebhookType) Enum() *WebhookHealthReport_WebhookType { - p := new(WebhookHealthReport_WebhookType) - *p = x - return p -} - -func (x WebhookHealthReport_WebhookType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (WebhookHealthReport_WebhookType) Descriptor() protoreflect.EnumDescriptor { - return file_monitor_proto_enumTypes[1].Descriptor() -} - -func (WebhookHealthReport_WebhookType) Type() protoreflect.EnumType { - return &file_monitor_proto_enumTypes[1] -} - -func (x WebhookHealthReport_WebhookType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use WebhookHealthReport_WebhookType.Descriptor instead. -func (WebhookHealthReport_WebhookType) EnumDescriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{5, 0} -} - -type ContainerSpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Image string `protobuf:"bytes,1,opt,name=image,proto3" json:"image,omitempty"` -} - -func (x *ContainerSpec) Reset() { - *x = ContainerSpec{} - if protoimpl.UnsafeEnabled { - mi := &file_monitor_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ContainerSpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ContainerSpec) ProtoMessage() {} - -func (x *ContainerSpec) ProtoReflect() protoreflect.Message { - mi := &file_monitor_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ContainerSpec.ProtoReflect.Descriptor instead. -func (*ContainerSpec) Descriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{0} -} - -func (x *ContainerSpec) GetImage() string { - if x != nil { - return x.Image - } - return "" -} - -type ReplicaSpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Containers map[string]*ContainerSpec `protobuf:"bytes,1,rep,name=containers,proto3" json:"containers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ReplicaSpec) Reset() { - *x = ReplicaSpec{} - if protoimpl.UnsafeEnabled { - mi := &file_monitor_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReplicaSpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReplicaSpec) ProtoMessage() {} - -func (x *ReplicaSpec) ProtoReflect() protoreflect.Message { - mi := &file_monitor_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReplicaSpec.ProtoReflect.Descriptor instead. -func (*ReplicaSpec) Descriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{1} -} - -func (x *ReplicaSpec) GetContainers() map[string]*ContainerSpec { - if x != nil { - return x.Containers - } - return nil -} - -type ReplicaHealth struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Node string `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` - Spec *ReplicaSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` - Status []byte `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` -} - -func (x *ReplicaHealth) Reset() { - *x = ReplicaHealth{} - if protoimpl.UnsafeEnabled { - mi := &file_monitor_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ReplicaHealth) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ReplicaHealth) ProtoMessage() {} - -func (x *ReplicaHealth) ProtoReflect() protoreflect.Message { - mi := &file_monitor_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ReplicaHealth.ProtoReflect.Descriptor instead. -func (*ReplicaHealth) Descriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{2} -} - -func (x *ReplicaHealth) GetNode() string { - if x != nil { - return x.Node - } - return "" -} - -func (x *ReplicaHealth) GetSpec() *ReplicaSpec { - if x != nil { - return x.Spec - } - return nil -} - -func (x *ReplicaHealth) GetStatus() []byte { - if x != nil { - return x.Status - } - return nil -} - -type ServiceSpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Replicas int32 `protobuf:"varint,1,opt,name=replicas,proto3" json:"replicas,omitempty"` - Containers map[string]*ContainerSpec `protobuf:"bytes,2,rep,name=containers,proto3" json:"containers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ServiceSpec) Reset() { - *x = ServiceSpec{} - if protoimpl.UnsafeEnabled { - mi := &file_monitor_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ServiceSpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServiceSpec) ProtoMessage() {} - -func (x *ServiceSpec) ProtoReflect() protoreflect.Message { - mi := &file_monitor_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServiceSpec.ProtoReflect.Descriptor instead. -func (*ServiceSpec) Descriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{3} -} - -func (x *ServiceSpec) GetReplicas() int32 { - if x != nil { - return x.Replicas - } - return 0 -} - -func (x *ServiceSpec) GetContainers() map[string]*ContainerSpec { - if x != nil { - return x.Containers - } - return nil -} - -type ServiceHealthReport struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Kind ServiceHealthReport_Kind `protobuf:"varint,1,opt,name=kind,proto3,enum=monitor.ServiceHealthReport_Kind" json:"kind,omitempty"` - Spec *ServiceSpec `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` - Status []byte `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` - Replicas map[string]*ReplicaHealth `protobuf:"bytes,4,rep,name=replicas,proto3" json:"replicas,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *ServiceHealthReport) Reset() { - *x = ServiceHealthReport{} - if protoimpl.UnsafeEnabled { - mi := &file_monitor_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ServiceHealthReport) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ServiceHealthReport) ProtoMessage() {} - -func (x *ServiceHealthReport) ProtoReflect() protoreflect.Message { - mi := &file_monitor_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ServiceHealthReport.ProtoReflect.Descriptor instead. -func (*ServiceHealthReport) Descriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{4} -} - -func (x *ServiceHealthReport) GetKind() ServiceHealthReport_Kind { - if x != nil { - return x.Kind - } - return ServiceHealthReport_DEPLOYMENT -} - -func (x *ServiceHealthReport) GetSpec() *ServiceSpec { - if x != nil { - return x.Spec - } - return nil -} - -func (x *ServiceHealthReport) GetStatus() []byte { - if x != nil { - return x.Status - } - return nil -} - -func (x *ServiceHealthReport) GetReplicas() map[string]*ReplicaHealth { - if x != nil { - return x.Replicas - } - return nil -} - -func (x *ServiceHealthReport) GetLabels() map[string]string { - if x != nil { - return x.Labels - } - return nil -} - -type WebhookHealthReport struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - WebhookType WebhookHealthReport_WebhookType `protobuf:"varint,1,opt,name=webhookType,proto3,enum=monitor.WebhookHealthReport_WebhookType" json:"webhookType,omitempty"` - Uid string `protobuf:"bytes,2,opt,name=uid,proto3" json:"uid,omitempty"` -} - -func (x *WebhookHealthReport) Reset() { - *x = WebhookHealthReport{} - if protoimpl.UnsafeEnabled { - mi := &file_monitor_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WebhookHealthReport) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WebhookHealthReport) ProtoMessage() {} - -func (x *WebhookHealthReport) ProtoReflect() protoreflect.Message { - mi := &file_monitor_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WebhookHealthReport.ProtoReflect.Descriptor instead. -func (*WebhookHealthReport) Descriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{5} -} - -func (x *WebhookHealthReport) GetWebhookType() WebhookHealthReport_WebhookType { - if x != nil { - return x.WebhookType - } - return WebhookHealthReport_VALIDATING -} - -func (x *WebhookHealthReport) GetUid() string { - if x != nil { - return x.Uid - } - return "" -} - -type HealthReport struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Account string `protobuf:"bytes,1,opt,name=account,proto3" json:"account,omitempty"` - Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"` - Webhooks map[string]*WebhookHealthReport `protobuf:"bytes,3,rep,name=webhooks,proto3" json:"webhooks,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - Services map[string]*ServiceHealthReport `protobuf:"bytes,4,rep,name=services,proto3" json:"services,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - EnabledComponents map[string]bool `protobuf:"bytes,5,rep,name=enabledComponents,proto3" json:"enabledComponents,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"` - Version string `protobuf:"bytes,6,opt,name=version,proto3" json:"version,omitempty"` -} - -func (x *HealthReport) Reset() { - *x = HealthReport{} - if protoimpl.UnsafeEnabled { - mi := &file_monitor_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthReport) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthReport) ProtoMessage() {} - -func (x *HealthReport) ProtoReflect() protoreflect.Message { - mi := &file_monitor_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthReport.ProtoReflect.Descriptor instead. -func (*HealthReport) Descriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{6} -} - -func (x *HealthReport) GetAccount() string { - if x != nil { - return x.Account - } - return "" -} - -func (x *HealthReport) GetDomain() string { - if x != nil { - return x.Domain - } - return "" -} - -func (x *HealthReport) GetWebhooks() map[string]*WebhookHealthReport { - if x != nil { - return x.Webhooks - } - return nil -} - -func (x *HealthReport) GetServices() map[string]*ServiceHealthReport { - if x != nil { - return x.Services - } - return nil -} - -func (x *HealthReport) GetEnabledComponents() map[string]bool { - if x != nil { - return x.EnabledComponents - } - return nil -} - -func (x *HealthReport) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -type HealthReportReply struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Ack bool `protobuf:"varint,1,opt,name=ack,proto3" json:"ack,omitempty"` -} - -func (x *HealthReportReply) Reset() { - *x = HealthReportReply{} - if protoimpl.UnsafeEnabled { - mi := &file_monitor_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *HealthReportReply) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HealthReportReply) ProtoMessage() {} - -func (x *HealthReportReply) ProtoReflect() protoreflect.Message { - mi := &file_monitor_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use HealthReportReply.ProtoReflect.Descriptor instead. -func (*HealthReportReply) Descriptor() ([]byte, []int) { - return file_monitor_proto_rawDescGZIP(), []int{7} -} - -func (x *HealthReportReply) GetAck() bool { - if x != nil { - return x.Ack - } - return false -} - -var File_monitor_proto protoreflect.FileDescriptor - -var file_monitor_proto_rawDesc = []byte{ - 0x0a, 0x0d, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x07, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x22, 0x25, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x70, 0x65, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6d, 0x61, - 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, - 0xaa, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x53, 0x70, 0x65, 0x63, 0x12, - 0x44, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x73, 0x1a, 0x55, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x70, 0x65, - 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x65, 0x0a, 0x0d, - 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x6f, 0x64, - 0x65, 0x12, 0x28, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, - 0x61, 0x53, 0x70, 0x65, 0x63, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x22, 0xc6, 0x01, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, - 0x70, 0x65, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, - 0x44, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x61, - 0x69, 0x6e, 0x65, 0x72, 0x73, 0x1a, 0x55, 0x0a, 0x0f, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x53, 0x70, 0x65, - 0x63, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xcf, 0x03, 0x0a, - 0x13, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x12, 0x35, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x4b, 0x69, 0x6e, 0x64, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x73, - 0x70, 0x65, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x53, 0x70, 0x65, 0x63, 0x52, - 0x04, 0x73, 0x70, 0x65, 0x63, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x46, 0x0a, - 0x08, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2a, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x52, 0x65, - 0x70, 0x6c, 0x69, 0x63, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x72, 0x65, 0x70, - 0x6c, 0x69, 0x63, 0x61, 0x73, 0x12, 0x40, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, - 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x1a, 0x53, 0x0a, 0x0d, 0x52, 0x65, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x39, 0x0a, 0x0b, - 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x25, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, - 0x0e, 0x0a, 0x0a, 0x44, 0x45, 0x50, 0x4c, 0x4f, 0x59, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, - 0x0d, 0x0a, 0x09, 0x44, 0x41, 0x45, 0x4d, 0x4f, 0x4e, 0x53, 0x45, 0x54, 0x10, 0x01, 0x22, 0xa0, - 0x01, 0x0a, 0x13, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x4a, 0x0a, 0x0b, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, - 0x6b, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x6d, 0x6f, - 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, - 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x75, 0x69, 0x64, 0x22, 0x2b, 0x0a, 0x0b, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4e, - 0x47, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x4d, 0x55, 0x54, 0x41, 0x54, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x22, 0xb4, 0x04, 0x0a, 0x0c, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x08, 0x77, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, - 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x57, 0x65, - 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x77, 0x65, 0x62, - 0x68, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x3f, 0x0a, 0x08, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, - 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2c, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x59, 0x0a, 0x0d, - 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x59, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x32, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x1a, 0x44, 0x0a, 0x16, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x43, 0x6f, 0x6d, - 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x25, 0x0a, 0x11, 0x48, 0x65, 0x61, 0x6c, - 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x61, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x61, 0x63, 0x6b, 0x32, - 0x54, 0x0a, 0x07, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x12, 0x49, 0x0a, 0x12, 0x48, 0x61, - 0x6e, 0x64, 0x6c, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x12, 0x15, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x1a, 0x1a, 0x2e, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, - 0x72, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x3b, 0x6d, 0x6f, 0x6e, 0x69, 0x74, - 0x6f, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_monitor_proto_rawDescOnce sync.Once - file_monitor_proto_rawDescData = file_monitor_proto_rawDesc -) - -func file_monitor_proto_rawDescGZIP() []byte { - file_monitor_proto_rawDescOnce.Do(func() { - file_monitor_proto_rawDescData = protoimpl.X.CompressGZIP(file_monitor_proto_rawDescData) - }) - return file_monitor_proto_rawDescData -} - -var file_monitor_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_monitor_proto_msgTypes = make([]protoimpl.MessageInfo, 15) -var file_monitor_proto_goTypes = []interface{}{ - (ServiceHealthReport_Kind)(0), // 0: monitor.ServiceHealthReport.Kind - (WebhookHealthReport_WebhookType)(0), // 1: monitor.WebhookHealthReport.WebhookType - (*ContainerSpec)(nil), // 2: monitor.ContainerSpec - (*ReplicaSpec)(nil), // 3: monitor.ReplicaSpec - (*ReplicaHealth)(nil), // 4: monitor.ReplicaHealth - (*ServiceSpec)(nil), // 5: monitor.ServiceSpec - (*ServiceHealthReport)(nil), // 6: monitor.ServiceHealthReport - (*WebhookHealthReport)(nil), // 7: monitor.WebhookHealthReport - (*HealthReport)(nil), // 8: monitor.HealthReport - (*HealthReportReply)(nil), // 9: monitor.HealthReportReply - nil, // 10: monitor.ReplicaSpec.ContainersEntry - nil, // 11: monitor.ServiceSpec.ContainersEntry - nil, // 12: monitor.ServiceHealthReport.ReplicasEntry - nil, // 13: monitor.ServiceHealthReport.LabelsEntry - nil, // 14: monitor.HealthReport.WebhooksEntry - nil, // 15: monitor.HealthReport.ServicesEntry - nil, // 16: monitor.HealthReport.EnabledComponentsEntry -} -var file_monitor_proto_depIdxs = []int32{ - 10, // 0: monitor.ReplicaSpec.containers:type_name -> monitor.ReplicaSpec.ContainersEntry - 3, // 1: monitor.ReplicaHealth.spec:type_name -> monitor.ReplicaSpec - 11, // 2: monitor.ServiceSpec.containers:type_name -> monitor.ServiceSpec.ContainersEntry - 0, // 3: monitor.ServiceHealthReport.kind:type_name -> monitor.ServiceHealthReport.Kind - 5, // 4: monitor.ServiceHealthReport.spec:type_name -> monitor.ServiceSpec - 12, // 5: monitor.ServiceHealthReport.replicas:type_name -> monitor.ServiceHealthReport.ReplicasEntry - 13, // 6: monitor.ServiceHealthReport.labels:type_name -> monitor.ServiceHealthReport.LabelsEntry - 1, // 7: monitor.WebhookHealthReport.webhookType:type_name -> monitor.WebhookHealthReport.WebhookType - 14, // 8: monitor.HealthReport.webhooks:type_name -> monitor.HealthReport.WebhooksEntry - 15, // 9: monitor.HealthReport.services:type_name -> monitor.HealthReport.ServicesEntry - 16, // 10: monitor.HealthReport.enabledComponents:type_name -> monitor.HealthReport.EnabledComponentsEntry - 2, // 11: monitor.ReplicaSpec.ContainersEntry.value:type_name -> monitor.ContainerSpec - 2, // 12: monitor.ServiceSpec.ContainersEntry.value:type_name -> monitor.ContainerSpec - 4, // 13: monitor.ServiceHealthReport.ReplicasEntry.value:type_name -> monitor.ReplicaHealth - 7, // 14: monitor.HealthReport.WebhooksEntry.value:type_name -> monitor.WebhookHealthReport - 6, // 15: monitor.HealthReport.ServicesEntry.value:type_name -> monitor.ServiceHealthReport - 8, // 16: monitor.Monitor.HandleHealthReport:input_type -> monitor.HealthReport - 9, // 17: monitor.Monitor.HandleHealthReport:output_type -> monitor.HealthReportReply - 17, // [17:18] is the sub-list for method output_type - 16, // [16:17] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name -} - -func init() { file_monitor_proto_init() } -func file_monitor_proto_init() { - if File_monitor_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_monitor_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ContainerSpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_monitor_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReplicaSpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_monitor_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ReplicaHealth); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_monitor_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceSpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_monitor_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ServiceHealthReport); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_monitor_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WebhookHealthReport); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_monitor_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthReport); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_monitor_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*HealthReportReply); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_monitor_proto_rawDesc, - NumEnums: 2, - NumMessages: 15, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_monitor_proto_goTypes, - DependencyIndexes: file_monitor_proto_depIdxs, - EnumInfos: file_monitor_proto_enumTypes, - MessageInfos: file_monitor_proto_msgTypes, - }.Build() - File_monitor_proto = out.File - file_monitor_proto_rawDesc = nil - file_monitor_proto_goTypes = nil - file_monitor_proto_depIdxs = nil -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConnInterface - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 - -// MonitorClient is the client API for Monitor service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type MonitorClient interface { - HandleHealthReport(ctx context.Context, in *HealthReport, opts ...grpc.CallOption) (*HealthReportReply, error) -} - -type monitorClient struct { - cc grpc.ClientConnInterface -} - -func NewMonitorClient(cc grpc.ClientConnInterface) MonitorClient { - return &monitorClient{cc} -} - -func (c *monitorClient) HandleHealthReport(ctx context.Context, in *HealthReport, opts ...grpc.CallOption) (*HealthReportReply, error) { - out := new(HealthReportReply) - err := c.cc.Invoke(ctx, "/monitor.Monitor/HandleHealthReport", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// MonitorServer is the server API for Monitor service. -type MonitorServer interface { - HandleHealthReport(context.Context, *HealthReport) (*HealthReportReply, error) -} - -// UnimplementedMonitorServer can be embedded to have forward compatible implementations. -type UnimplementedMonitorServer struct { -} - -func (*UnimplementedMonitorServer) HandleHealthReport(context.Context, *HealthReport) (*HealthReportReply, error) { - return nil, status.Errorf(codes.Unimplemented, "method HandleHealthReport not implemented") -} - -func RegisterMonitorServer(s *grpc.Server, srv MonitorServer) { - s.RegisterService(&_Monitor_serviceDesc, srv) -} - -func _Monitor_HandleHealthReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(HealthReport) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MonitorServer).HandleHealthReport(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/monitor.Monitor/HandleHealthReport", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MonitorServer).HandleHealthReport(ctx, req.(*HealthReport)) - } - return interceptor(ctx, in, info, handler) -} - -var _Monitor_serviceDesc = grpc.ServiceDesc{ - ServiceName: "monitor.Monitor", - HandlerType: (*MonitorServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "HandleHealthReport", - Handler: _Monitor_HandleHealthReport_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "monitor.proto", -} diff --git a/cbcontainers/monitor/protobuf/monitor.proto b/cbcontainers/monitor/protobuf/monitor.proto deleted file mode 100644 index 62abac91..00000000 --- a/cbcontainers/monitor/protobuf/monitor.proto +++ /dev/null @@ -1,61 +0,0 @@ -syntax = "proto3"; - -option go_package = ".;monitor"; -package monitor; - -service Monitor { - rpc HandleHealthReport (HealthReport) returns (HealthReportReply) {} -} - -message ContainerSpec { - string image = 1; -} - -message ReplicaSpec { - map containers = 1; -} - -message ReplicaHealth { - string node = 1; - ReplicaSpec spec = 2; - bytes status = 3; -} - -message ServiceSpec { - int32 replicas = 1; - map containers = 2; -} - -message ServiceHealthReport { - enum Kind { - DEPLOYMENT = 0; - DAEMONSET = 1; - } - Kind kind = 1; - ServiceSpec spec = 2; - bytes status = 3; - map replicas = 4; - map labels = 5; -} - -message WebhookHealthReport { - enum WebhookType { - VALIDATING = 0; - MUTATING = 1; - } - WebhookType webhookType = 1; - string uid = 2; -} - -message HealthReport { - string account = 1; - string domain = 2; - map webhooks = 3; - map services = 4; - map enabledComponents = 5; - string version = 6; -} - -message HealthReportReply { - bool ack = 1; -} \ No newline at end of file diff --git a/cbcontainers/monitor/protobuf/rebuild.sh b/cbcontainers/monitor/protobuf/rebuild.sh deleted file mode 100755 index efc3912a..00000000 --- a/cbcontainers/monitor/protobuf/rebuild.sh +++ /dev/null @@ -1,5 +0,0 @@ -# Please install protobuf C executable from https://github.com/google/protobuf/releases/tag/v3.5.1 for your platform -# Also - install the go pugin : go get -u github.com/golang/protobuf/protoc-gen-go -# export PATH=$PATH;~/go/bin - -protoc --go_out=plugins=grpc:. *.proto \ No newline at end of file diff --git a/cbcontainers/monitor/reporters/grpc_montior_reporter.go b/cbcontainers/monitor/reporters/grpc_montior_reporter.go deleted file mode 100644 index 47719f03..00000000 --- a/cbcontainers/monitor/reporters/grpc_montior_reporter.go +++ /dev/null @@ -1,152 +0,0 @@ -package reporters - -import ( - "context" - "crypto/tls" - "crypto/x509" - "fmt" - grpcCommunication "github.com/vmware/cbcontainers-operator/cbcontainers/communication/grpc" - monitorModels "github.com/vmware/cbcontainers-operator/cbcontainers/monitor/models" - pb "github.com/vmware/cbcontainers-operator/cbcontainers/monitor/protobuf" - "google.golang.org/grpc" - "time" -) - -type GrpcMonitorReporter struct { - connection *grpc.ClientConn -} - -func NewGrpcMonitorReporter(host string, port int, certPool *x509.CertPool, cert *tls.Certificate) (*GrpcMonitorReporter, error) { - connection, err := grpcCommunication.GetGrpcConnection(host, port, certPool, cert) - if err != nil { - return nil, err - } - - return &GrpcMonitorReporter{ - connection: connection, - }, nil -} - -func (reporter *GrpcMonitorReporter) Close() error { - return reporter.connection.Close() -} - -func (reporter *GrpcMonitorReporter) SendMonitorMessage(message monitorModels.HealthReportMessage) error { - grpcMessage, err := reporter.convertMessageToGrpcMessage(message) - if err != nil { - return err - } - - client := pb.NewMonitorClient(reporter.connection) - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - _, err = client.HandleHealthReport(ctx, grpcMessage, grpc.WaitForReady(true)) - return err -} - -func (reporter *GrpcMonitorReporter) convertMessageToGrpcMessage(message monitorModels.HealthReportMessage) (*pb.HealthReport, error) { - servicesSpec, err := reporter.convertWorkloadsReportsToGrpcMessage(message.Workloads) - if err != nil { - return nil, err - } - - webhooksSpec, err := reporter.convertWebhooksReportsToGrpcMessage(message.Webhooks) - if err != nil { - return nil, err - } - - return &pb.HealthReport{ - Account: message.Account, - Domain: message.Cluster, - Version: message.Version, - EnabledComponents: message.EnabledComponents, - Services: servicesSpec, - Webhooks: webhooksSpec, - }, nil -} - -func (reporter *GrpcMonitorReporter) convertWorkloadsReportsToGrpcMessage(workloadsReports map[string]monitorModels.WorkloadHealthReport) (map[string]*pb.ServiceHealthReport, error) { - reports := make(map[string]*pb.ServiceHealthReport) - for workloadName, workloadReport := range workloadsReports { - grpcKind, err := reporter.convertWorkloadKindToGrpcKind(workloadReport.Kind) - if err != nil { - return nil, err - } - - reports[workloadName] = &pb.ServiceHealthReport{ - Kind: grpcKind, - Status: workloadReport.Status, - Labels: workloadReport.Labels, - Spec: &pb.ServiceSpec{ - Replicas: workloadReport.Spec.Replicas, - Containers: reporter.convertContainersReportsToGrpcMessage(workloadReport.Spec.Containers), - }, - Replicas: reporter.convertWorkloadReplicasReportsToGrpcMessage(workloadReport.ReplicasReports), - } - } - - return reports, nil -} - -func (reporter *GrpcMonitorReporter) convertContainersReportsToGrpcMessage(containersReports map[string]monitorModels.ContainerHealthReport) map[string]*pb.ContainerSpec { - grpcContainersMessage := make(map[string]*pb.ContainerSpec) - for containerName, containerReport := range containersReports { - grpcContainersMessage[containerName] = &pb.ContainerSpec{Image: containerReport.Image} - } - - return grpcContainersMessage -} - -func (reporter *GrpcMonitorReporter) convertWorkloadKindToGrpcKind(kind monitorModels.WorkloadKind) (pb.ServiceHealthReport_Kind, error) { - switch kind { - case monitorModels.WorkloadKindDeployment: - return pb.ServiceHealthReport_DEPLOYMENT, nil - case monitorModels.WorkloadKindDaemonSet: - return pb.ServiceHealthReport_DAEMONSET, nil - } - - return 0, fmt.Errorf("failed to convert workload kind %v", kind) -} - -func (reporter *GrpcMonitorReporter) convertWebhooksReportsToGrpcMessage(webhooksReports map[string]monitorModels.WebhookHealthReport) (map[string]*pb.WebhookHealthReport, error) { - webhooksGrpcMessage := make(map[string]*pb.WebhookHealthReport) - for webhookName, webhookReport := range webhooksReports { - grpcType, err := reporter.convertWebhookTypeToGrpcType(webhookReport.Type) - if err != nil { - return nil, err - } - - webhooksGrpcMessage[webhookName] = &pb.WebhookHealthReport{ - WebhookType: grpcType, - Uid: webhookReport.Uid, - } - } - - return webhooksGrpcMessage, nil -} - -func (reporter *GrpcMonitorReporter) convertWebhookTypeToGrpcType(webhookType monitorModels.WebhookType) (pb.WebhookHealthReport_WebhookType, error) { - switch webhookType { - case monitorModels.WebhookTypeValidating: - return pb.WebhookHealthReport_VALIDATING, nil - case monitorModels.WebhookTypeMutating: - return pb.WebhookHealthReport_MUTATING, nil - } - - return 0, fmt.Errorf("failed to convert webhook type %v", webhookType) -} - -func (reporter *GrpcMonitorReporter) convertWorkloadReplicasReportsToGrpcMessage(workloadReplicasReports map[string]monitorModels.WorkloadReplicaHealthReport) map[string]*pb.ReplicaHealth { - grpcReplicasMessage := make(map[string]*pb.ReplicaHealth) - for replicaName, replicaReport := range workloadReplicasReports { - grpcReplicasMessage[replicaName] = &pb.ReplicaHealth{ - Node: replicaReport.Node, - Status: replicaReport.Status, - Spec: &pb.ReplicaSpec{ - Containers: reporter.convertContainersReportsToGrpcMessage(replicaReport.Spec.Containers), - }, - } - } - - return grpcReplicasMessage -} diff --git a/cbcontainers/processors/cluster/cbcontainerscluster_processor.go b/cbcontainers/processors/cluster/cbcontainerscluster_processor.go index 3562047e..bfa18e71 100644 --- a/cbcontainers/processors/cluster/cbcontainerscluster_processor.go +++ b/cbcontainers/processors/cluster/cbcontainerscluster_processor.go @@ -20,20 +20,8 @@ type GatewayCreator interface { CreateGateway(cbContainersCluster *cbcontainersv1.CBContainersCluster, accessToken string) Gateway } -type MonitorCreator interface { - CreateMonitor(cbContainersCluster *cbcontainersv1.CBContainersCluster, gateway Gateway) (Monitor, error) -} - -type Monitor interface { - Start() - Stop() -} - type CBContainerClusterProcessor struct { gatewayCreator GatewayCreator - monitorCreator MonitorCreator - - monitor Monitor lastRegistrySecretValues *models.RegistrySecretValues @@ -42,11 +30,9 @@ type CBContainerClusterProcessor struct { log logr.Logger } -func NewCBContainerClusterProcessor(log logr.Logger, clusterRegistrarCreator GatewayCreator, monitorCreator MonitorCreator) *CBContainerClusterProcessor { +func NewCBContainerClusterProcessor(log logr.Logger, clusterRegistrarCreator GatewayCreator) *CBContainerClusterProcessor { return &CBContainerClusterProcessor{ gatewayCreator: clusterRegistrarCreator, - monitorCreator: monitorCreator, - monitor: nil, lastProcessedObject: nil, log: log, } @@ -61,8 +47,7 @@ func (processor *CBContainerClusterProcessor) Process(cbContainersCluster *cbcon } func (processor *CBContainerClusterProcessor) isInitialized(cbContainersCluster *cbcontainersv1.CBContainersCluster) bool { - return processor.monitor != nil && - processor.lastRegistrySecretValues != nil && + return processor.lastRegistrySecretValues != nil && processor.lastProcessedObject != nil && reflect.DeepEqual(processor.lastProcessedObject, cbContainersCluster) } @@ -74,10 +59,6 @@ func (processor *CBContainerClusterProcessor) initializeIfNeeded(cbContainersClu processor.log.Info("Initializing CBContainerClusterProcessor components") gateway := processor.gatewayCreator.CreateGateway(cbContainersCluster, accessToken) - monitor, err := processor.monitorCreator.CreateMonitor(cbContainersCluster, gateway) - if err != nil { - return err - } processor.log.Info("Calling get registry secret") registrySecretValues, err := gateway.GetRegistrySecret() @@ -92,14 +73,5 @@ func (processor *CBContainerClusterProcessor) initializeIfNeeded(cbContainersClu processor.lastRegistrySecretValues = registrySecretValues processor.lastProcessedObject = cbContainersCluster - - if processor.monitor != nil { - processor.log.Info("Stopping old monitor") - processor.monitor.Stop() - } - processor.monitor = monitor - processor.log.Info("Starting new monitor") - processor.monitor.Start() - return nil } diff --git a/cbcontainers/processors/cluster/cbcontainerscluster_processor_test.go b/cbcontainers/processors/cluster/cbcontainerscluster_processor_test.go index f938ef1a..fc2106d1 100644 --- a/cbcontainers/processors/cluster/cbcontainerscluster_processor_test.go +++ b/cbcontainers/processors/cluster/cbcontainerscluster_processor_test.go @@ -16,8 +16,6 @@ import ( type ClusterProcessorTestMocks struct { gatewayMock *mocks.MockGateway gatewayCreatorMock *mocks.MockGatewayCreator - monitorMock *mocks.MockMonitor - monitorCreatorMock *mocks.MockMonitorCreator } type SetupAndAssertClusterProcessorTest func(*ClusterProcessorTestMocks, *cluster.CBContainerClusterProcessor) @@ -33,22 +31,18 @@ func testClusterProcessor(t *testing.T, setupAndAssert SetupAndAssertClusterProc mocksObjects := &ClusterProcessorTestMocks{ gatewayMock: mocks.NewMockGateway(ctrl), gatewayCreatorMock: mocks.NewMockGatewayCreator(ctrl), - monitorMock: mocks.NewMockMonitor(ctrl), - monitorCreatorMock: mocks.NewMockMonitorCreator(ctrl), } - processor := cluster.NewCBContainerClusterProcessor(&logrTesting.TestLogger{T: t}, mocksObjects.gatewayCreatorMock, mocksObjects.monitorCreatorMock) + processor := cluster.NewCBContainerClusterProcessor(&logrTesting.TestLogger{T: t}, mocksObjects.gatewayCreatorMock) setupAndAssert(mocksObjects, processor) } func setupValidMocksCalls(testMocks *ClusterProcessorTestMocks, times int) { testMocks.gatewayCreatorMock.EXPECT().CreateGateway(gomock.Any(), AccessToken).Return(testMocks.gatewayMock).Times(times) - testMocks.monitorCreatorMock.EXPECT().CreateMonitor(gomock.Any(), testMocks.gatewayMock).Return(testMocks.monitorMock, nil).Times(times) testMocks.gatewayMock.EXPECT().GetRegistrySecret().DoAndReturn(func() (*models.RegistrySecretValues, error) { return &models.RegistrySecretValues{Data: map[string][]byte{test_utils.RandomString(): {}}}, nil }).Times(times) testMocks.gatewayMock.EXPECT().RegisterCluster().Return(nil).Times(times) - testMocks.monitorMock.EXPECT().Start().Times(times) } func TestProcessorIsNotRecreatingComponentsForSameCR(t *testing.T) { @@ -71,7 +65,6 @@ func TestProcessorIsReCreatingComponentsForDifferentCR(t *testing.T) { clusterCR1 := &cbcontainersv1.CBContainersCluster{Spec: cbcontainersv1.CBContainersClusterSpec{Account: test_utils.RandomString(), ClusterName: test_utils.RandomString()}} clusterCR2 := &cbcontainersv1.CBContainersCluster{Spec: cbcontainersv1.CBContainersClusterSpec{Account: test_utils.RandomString(), ClusterName: test_utils.RandomString()}} setupValidMocksCalls(testMocks, 2) - testMocks.monitorMock.EXPECT().Stop().Times(1) values1, err1 := processor.Process(clusterCR1, AccessToken) values2, err2 := processor.Process(clusterCR2, AccessToken) @@ -84,21 +77,10 @@ func TestProcessorIsReCreatingComponentsForDifferentCR(t *testing.T) { }) } -func TestProcessorReturnsErrorWhenCanNotCreateMonitor(t *testing.T) { - testClusterProcessor(t, func(testMocks *ClusterProcessorTestMocks, processor *cluster.CBContainerClusterProcessor) { - clusterCR := &cbcontainersv1.CBContainersCluster{Spec: cbcontainersv1.CBContainersClusterSpec{Account: test_utils.RandomString(), ClusterName: test_utils.RandomString()}} - testMocks.gatewayCreatorMock.EXPECT().CreateGateway(gomock.Any(), gomock.Any()).Return(testMocks.gatewayMock) - testMocks.monitorCreatorMock.EXPECT().CreateMonitor(gomock.Any(), gomock.Any()).Return(testMocks.monitorMock, fmt.Errorf("")) - _, err := processor.Process(clusterCR, AccessToken) - require.Error(t, err) - }) -} - func TestProcessorReturnsErrorWhenCanNotGetRegisterySecret(t *testing.T) { testClusterProcessor(t, func(testMocks *ClusterProcessorTestMocks, processor *cluster.CBContainerClusterProcessor) { clusterCR := &cbcontainersv1.CBContainersCluster{Spec: cbcontainersv1.CBContainersClusterSpec{Account: test_utils.RandomString(), ClusterName: test_utils.RandomString()}} testMocks.gatewayCreatorMock.EXPECT().CreateGateway(gomock.Any(), gomock.Any()).Return(testMocks.gatewayMock) - testMocks.monitorCreatorMock.EXPECT().CreateMonitor(gomock.Any(), gomock.Any()).Return(testMocks.monitorMock, nil) testMocks.gatewayMock.EXPECT().GetRegistrySecret().Return(nil, fmt.Errorf("")) _, err := processor.Process(clusterCR, AccessToken) require.Error(t, err) @@ -109,7 +91,6 @@ func TestProcessorReturnsErrorWhenCanNotRegisterCluster(t *testing.T) { testClusterProcessor(t, func(testMocks *ClusterProcessorTestMocks, processor *cluster.CBContainerClusterProcessor) { clusterCR := &cbcontainersv1.CBContainersCluster{Spec: cbcontainersv1.CBContainersClusterSpec{Account: test_utils.RandomString(), ClusterName: test_utils.RandomString()}} testMocks.gatewayCreatorMock.EXPECT().CreateGateway(gomock.Any(), gomock.Any()).Return(testMocks.gatewayMock) - testMocks.monitorCreatorMock.EXPECT().CreateMonitor(gomock.Any(), gomock.Any()).Return(testMocks.monitorMock, nil) testMocks.gatewayMock.EXPECT().GetRegistrySecret().Return(&models.RegistrySecretValues{}, nil) testMocks.gatewayMock.EXPECT().RegisterCluster().Return(fmt.Errorf("")) _, err := processor.Process(clusterCR, AccessToken) diff --git a/cbcontainers/processors/cluster/default_monitor_creator.go b/cbcontainers/processors/cluster/default_monitor_creator.go deleted file mode 100644 index 3f6a5022..00000000 --- a/cbcontainers/processors/cluster/default_monitor_creator.go +++ /dev/null @@ -1,64 +0,0 @@ -package cluster - -import ( - "crypto/rand" - "crypto/rsa" - "github.com/go-logr/logr" - cbcontainersv1 "github.com/vmware/cbcontainers-operator/api/v1" - "github.com/vmware/cbcontainers-operator/cbcontainers/monitor" - "github.com/vmware/cbcontainers-operator/cbcontainers/monitor/reporters" - "time" -) - -const ( - MonitorInterval = 20 * time.Second -) - -type DefaultMonitorCreator struct { - healthChecker monitor.HealthChecker - featuresStatusProvider monitor.FeaturesStatusProvider - privateKey *rsa.PrivateKey - - log logr.Logger -} - -func NewDefaultMonitorCreator(healthChecker monitor.HealthChecker, featuresStatusProvider monitor.FeaturesStatusProvider, log logr.Logger) (*DefaultMonitorCreator, error) { - privateKey, err := makePrivateKey() - if err != nil { - return nil, err - } - - return &DefaultMonitorCreator{ - healthChecker: healthChecker, - featuresStatusProvider: featuresStatusProvider, - privateKey: privateKey, - log: log, - }, nil -} - -func makePrivateKey() (*rsa.PrivateKey, error) { - reader := rand.Reader - privateKey, err := rsa.GenerateKey(reader, 4096) - if err != nil { - return nil, err - } - - return privateKey, nil -} - -func (creator *DefaultMonitorCreator) CreateMonitor(cbContainersCluster *cbcontainersv1.CBContainersCluster, gateway Gateway) (Monitor, error) { - spec := cbContainersCluster.Spec - eventsSpec := cbContainersCluster.Spec.EventsGatewaySpec - - certPool, cert, err := gateway.GetCertificates("monitor-agent", creator.privateKey) - if err != nil { - return nil, err - } - - reporter, err := reporters.NewGrpcMonitorReporter(eventsSpec.Host, eventsSpec.Port, certPool, cert) - if err != nil { - return nil, err - } - - return monitor.NewMonitorAgent(spec.Account, spec.ClusterName, "", creator.healthChecker, creator.featuresStatusProvider, reporter, MonitorInterval, creator.log), nil -} diff --git a/cbcontainers/processors/cluster/mocks/generated.go b/cbcontainers/processors/cluster/mocks/generated.go index e711724a..4804eee2 100644 --- a/cbcontainers/processors/cluster/mocks/generated.go +++ b/cbcontainers/processors/cluster/mocks/generated.go @@ -2,5 +2,3 @@ package mocks //go:generate mockgen -destination mock_gateway.go -package mocks github.com/vmware/cbcontainers-operator/cbcontainers/processors/cluster Gateway //go:generate mockgen -destination mock_gateway_creator.go -package mocks github.com/vmware/cbcontainers-operator/cbcontainers/processors/cluster GatewayCreator -//go:generate mockgen -destination mock_monitor.go -package mocks github.com/vmware/cbcontainers-operator/cbcontainers/processors/cluster Monitor -//go:generate mockgen -destination mock_monitor_creator.go -package mocks github.com/vmware/cbcontainers-operator/cbcontainers/processors/cluster MonitorCreator diff --git a/cbcontainers/processors/cluster/mocks/mock_monitor.go b/cbcontainers/processors/cluster/mocks/mock_monitor.go deleted file mode 100644 index 2c9b1ccc..00000000 --- a/cbcontainers/processors/cluster/mocks/mock_monitor.go +++ /dev/null @@ -1,58 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/vmware/cbcontainers-operator/cbcontainers/processors/cluster (interfaces: Monitor) - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" -) - -// MockMonitor is a mock of Monitor interface. -type MockMonitor struct { - ctrl *gomock.Controller - recorder *MockMonitorMockRecorder -} - -// MockMonitorMockRecorder is the mock recorder for MockMonitor. -type MockMonitorMockRecorder struct { - mock *MockMonitor -} - -// NewMockMonitor creates a new mock instance. -func NewMockMonitor(ctrl *gomock.Controller) *MockMonitor { - mock := &MockMonitor{ctrl: ctrl} - mock.recorder = &MockMonitorMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockMonitor) EXPECT() *MockMonitorMockRecorder { - return m.recorder -} - -// Start mocks base method. -func (m *MockMonitor) Start() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Start") -} - -// Start indicates an expected call of Start. -func (mr *MockMonitorMockRecorder) Start() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Start", reflect.TypeOf((*MockMonitor)(nil).Start)) -} - -// Stop mocks base method. -func (m *MockMonitor) Stop() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Stop") -} - -// Stop indicates an expected call of Stop. -func (mr *MockMonitorMockRecorder) Stop() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stop", reflect.TypeOf((*MockMonitor)(nil).Stop)) -} diff --git a/cbcontainers/processors/cluster/mocks/mock_monitor_creator.go b/cbcontainers/processors/cluster/mocks/mock_monitor_creator.go deleted file mode 100644 index 0f1cdbe0..00000000 --- a/cbcontainers/processors/cluster/mocks/mock_monitor_creator.go +++ /dev/null @@ -1,51 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/vmware/cbcontainers-operator/cbcontainers/processors/cluster (interfaces: MonitorCreator) - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - v1 "github.com/vmware/cbcontainers-operator/api/v1" - cluster "github.com/vmware/cbcontainers-operator/cbcontainers/processors/cluster" -) - -// MockMonitorCreator is a mock of MonitorCreator interface. -type MockMonitorCreator struct { - ctrl *gomock.Controller - recorder *MockMonitorCreatorMockRecorder -} - -// MockMonitorCreatorMockRecorder is the mock recorder for MockMonitorCreator. -type MockMonitorCreatorMockRecorder struct { - mock *MockMonitorCreator -} - -// NewMockMonitorCreator creates a new mock instance. -func NewMockMonitorCreator(ctrl *gomock.Controller) *MockMonitorCreator { - mock := &MockMonitorCreator{ctrl: ctrl} - mock.recorder = &MockMonitorCreatorMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockMonitorCreator) EXPECT() *MockMonitorCreatorMockRecorder { - return m.recorder -} - -// CreateMonitor mocks base method. -func (m *MockMonitorCreator) CreateMonitor(arg0 *v1.CBContainersCluster, arg1 cluster.Gateway) (cluster.Monitor, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateMonitor", arg0, arg1) - ret0, _ := ret[0].(cluster.Monitor) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateMonitor indicates an expected call of CreateMonitor. -func (mr *MockMonitorCreatorMockRecorder) CreateMonitor(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMonitor", reflect.TypeOf((*MockMonitorCreator)(nil).CreateMonitor), arg0, arg1) -} diff --git a/cbcontainers/state/cluster/utils/priority_class_values_setter.go b/cbcontainers/state/cluster/adapters/priority_class_values_setter.go similarity index 99% rename from cbcontainers/state/cluster/utils/priority_class_values_setter.go rename to cbcontainers/state/cluster/adapters/priority_class_values_setter.go index 51cf54af..af6f1e21 100644 --- a/cbcontainers/state/cluster/utils/priority_class_values_setter.go +++ b/cbcontainers/state/cluster/adapters/priority_class_values_setter.go @@ -1,4 +1,4 @@ -package utils +package adapters import ( schedulingV1 "k8s.io/api/scheduling/v1" diff --git a/cbcontainers/state/cluster/objects/priority_class.go b/cbcontainers/state/cluster/objects/priority_class.go index 8cefefd3..e90f4f98 100644 --- a/cbcontainers/state/cluster/objects/priority_class.go +++ b/cbcontainers/state/cluster/objects/priority_class.go @@ -3,7 +3,7 @@ package objects import ( "fmt" cbcontainersv1 "github.com/vmware/cbcontainers-operator/api/v1" - clusterStateUtils "github.com/vmware/cbcontainers-operator/cbcontainers/state/cluster/utils" + clusterStateAdapters "github.com/vmware/cbcontainers-operator/cbcontainers/state/cluster/adapters" commonState "github.com/vmware/cbcontainers-operator/cbcontainers/state/common" schedulingV1 "k8s.io/api/scheduling/v1" schedulingV1alpha1 "k8s.io/api/scheduling/v1alpha1" @@ -43,7 +43,7 @@ func (obj *PriorityClassK8sObject) ClusterChildNamespacedName(_ *cbcontainersv1. } func (obj *PriorityClassK8sObject) MutateClusterChildK8sObject(k8sObject client.Object, _ *cbcontainersv1.CBContainersCluster) error { - priorityClassSetter, ok := clusterStateUtils.GetPriorityClassSetter(k8sObject) + priorityClassSetter, ok := clusterStateAdapters.GetPriorityClassSetter(k8sObject) if !ok { return fmt.Errorf("expected PriorityClass setter K8s object") } diff --git a/cbcontainers/state/hardening/adapters/validating_webhook.go b/cbcontainers/state/hardening/adapters/validating_webhook.go new file mode 100644 index 00000000..34d916f7 --- /dev/null +++ b/cbcontainers/state/hardening/adapters/validating_webhook.go @@ -0,0 +1,362 @@ +package adapters + +import ( + "fmt" + admissionsV1 "k8s.io/api/admissionregistration/v1" + admissionsV1Beta1 "k8s.io/api/admissionregistration/v1beta1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type ValidatingWebhookConfigurationAdapter interface { + // SetLabels will update the validating webhook configuration's labels + SetLabels(labels map[string]string) + // GetWebhooks will return the webhooks attached to this configuration instance wrapped in an adapter. + // The returned adapters wrap pointers to the original values so any modifications are propagated on the objects + // For adding/removing webhooks to the list, use SetWebhooks + GetWebhooks() []ValidatingWebhookAdapter + // SetWebhooks will replace the configuration's webhooks with the provided list + // + // This method creates copied values of the provided webhooks so any pointers to the passed values will _not_ modify them directly + // This method returns adapters for the inner webhooks after replacement to support this use-case + // Calling SetXXX() to the returned adapters _will_ reflect the changes into the configuration's webhooks + // + // If any of the provided webhooks do not match the version of the adapter, an error is returned + // E.g. passing a list of {v1, v1beta1, v1} wrapped webhooks to a v1 ValidatingWebhookAdapter will produce an error + SetWebhooks([]ValidatingWebhookAdapter) ([]ValidatingWebhookAdapter, error) +} + +type ValidatingWebhookAdapter interface { + GetName() string + SetName(name string) + SetAdmissionReviewVersions(versions []string) + SetFailurePolicy(policy string) + SetSideEffects(sideEffectsClass string) + SetMatchPolicy(policy string) + GetNamespaceSelector() *metav1.LabelSelector + SetNamespaceSelector(selector *metav1.LabelSelector) + SetTimeoutSeconds(timeoutSeconds int32) + SetCABundle(bundle []byte) + SetServiceNamespace(namespace string) + SetServiceName(name string) + SetServicePath(path *string) + GetAdmissionRules() []AdmissionRuleAdapter + SetAdmissionRules([]AdmissionRuleAdapter) +} + +// These are the same between v1 and v1beta1 - if they diverge; the adapters should handle internal conversion. +const ( + FailurePolicyFail = string(admissionsV1.Fail) + FailurePolicyIgnore = string(admissionsV1.Ignore) + + OperationAll = string(admissionsV1.OperationAll) + OperationCreate = string(admissionsV1.Create) + OperationUpdate = string(admissionsV1.Update) + OperationDelete = string(admissionsV1.Delete) + OperationConnect = string(admissionsV1.Connect) + + MatchPolicyExact = string(admissionsV1.Exact) + MatchPolicyEquivalent = string(admissionsV1.Equivalent) + + SideEffectsClassNone = string(admissionsV1.SideEffectClassNone) + SideEffectClassNoneOnDryRun = string(admissionsV1.SideEffectClassNoneOnDryRun) +) + +// EmptyValidatingWebhookConfigForVersion returns an empty ValidatingWebhookConfiguration instance that is suitable for the provided k8s version +func EmptyValidatingWebhookConfigForVersion(k8sVersion string) client.Object { + if k8sVersion < "v1.16" { + return &admissionsV1Beta1.ValidatingWebhookConfiguration{} + } + + return &admissionsV1.ValidatingWebhookConfiguration{} +} + +// EmptyValidatingWebhookAdapterForVersion creates an empty ValidatingWebhook instance for the given k8s version and returns an adapter that wraps it +func EmptyValidatingWebhookAdapterForVersion(k8sVersion string) ValidatingWebhookAdapter { + if k8sVersion < "v1.16" { + return (*validatingWebhookV1Beta1)(&admissionsV1Beta1.ValidatingWebhook{}) + } else { + return (*validatingWebhookV1)(&admissionsV1.ValidatingWebhook{}) + } +} + +func TryGetValidatingWebhookConfigurationAdapter(k8sObject client.Object) (ValidatingWebhookConfigurationAdapter, bool) { + switch value := k8sObject.(type) { + case *admissionsV1.ValidatingWebhookConfiguration: + return (*validatingWebhookConfigurationV1)(value), true + case *admissionsV1Beta1.ValidatingWebhookConfiguration: + return (*validatingWebhookConfigurationV1Beta1)(value), true + } + + return nil, false +} + +// AdmissionRuleAdapter is a simple struct that mimics the admission.Rule struct +type AdmissionRuleAdapter struct { + Operations []string + APIGroups []string + APIVersions []string + Resources []string + Scope *string +} + +type validatingWebhookConfigurationV1 admissionsV1.ValidatingWebhookConfiguration + +func (webhookConfig *validatingWebhookConfigurationV1) GetWebhooks() []ValidatingWebhookAdapter { + result := make([]ValidatingWebhookAdapter, 0, len(webhookConfig.Webhooks)) + for i := range webhookConfig.Webhooks { + var webhookAdapter ValidatingWebhookAdapter = (*validatingWebhookV1)(&webhookConfig.Webhooks[i]) + result = append(result, webhookAdapter) + } + return result +} + +func (webhookConfig *validatingWebhookConfigurationV1) SetWebhooks(webhooks []ValidatingWebhookAdapter) ([]ValidatingWebhookAdapter, error) { + convertedWebhooks := make([]admissionsV1.ValidatingWebhook, 0, len(webhooks)) + for _, webhookAdapter := range webhooks { + convertedToV1Adapter, ok := webhookAdapter.(*validatingWebhookV1) + if !ok { + return nil, fmt.Errorf("this is an adapter for v1 but got a non-v1 webhook: %v", webhookAdapter) + } + var validatingWebhook = admissionsV1.ValidatingWebhook(*convertedToV1Adapter) + convertedWebhooks = append(convertedWebhooks, validatingWebhook) + } + webhookConfig.Webhooks = convertedWebhooks + // Return adapters for the new webhooks to enable direct modifications via the adapter methods + return webhookConfig.GetWebhooks(), nil +} + +func (webhookConfig *validatingWebhookConfigurationV1) SetLabels(labels map[string]string) { + webhookConfig.Labels = labels +} + +type validatingWebhookConfigurationV1Beta1 admissionsV1Beta1.ValidatingWebhookConfiguration + +func (webhookConfig *validatingWebhookConfigurationV1Beta1) GetWebhooks() []ValidatingWebhookAdapter { + result := make([]ValidatingWebhookAdapter, 0, len(webhookConfig.Webhooks)) + for i := range webhookConfig.Webhooks { + var webhookAdapter ValidatingWebhookAdapter = (*validatingWebhookV1Beta1)(&webhookConfig.Webhooks[i]) + result = append(result, webhookAdapter) + } + return result +} + +func (webhookConfig *validatingWebhookConfigurationV1Beta1) SetWebhooks(webhooks []ValidatingWebhookAdapter) ([]ValidatingWebhookAdapter, error) { + convertedWebhooks := make([]admissionsV1Beta1.ValidatingWebhook, 0, len(webhooks)) + for _, webhookAdapter := range webhooks { + convertedToV1Adapter, ok := webhookAdapter.(*validatingWebhookV1Beta1) + if !ok { + return nil, fmt.Errorf("this is an adapter for v1beta1 but got a non-v1beta1 webhook: %v", webhookAdapter) + } + var validatingWebhook = admissionsV1Beta1.ValidatingWebhook(*convertedToV1Adapter) + convertedWebhooks = append(convertedWebhooks, validatingWebhook) + } + webhookConfig.Webhooks = convertedWebhooks + // Return adapters for the new webhooks to enable direct modifications via the adapter methods + return webhookConfig.GetWebhooks(), nil +} + +func (webhookConfig *validatingWebhookConfigurationV1Beta1) SetLabels(labels map[string]string) { + webhookConfig.Labels = labels +} + +type validatingWebhookV1 admissionsV1.ValidatingWebhook + +func (w *validatingWebhookV1) SetCABundle(bundle []byte) { + w.ClientConfig.CABundle = bundle +} + +func (w *validatingWebhookV1) SetServiceNamespace(namespace string) { + w.InitializeServiceReference() + w.ClientConfig.Service.Namespace = namespace +} + +func (w *validatingWebhookV1) SetServiceName(name string) { + w.InitializeServiceReference() + w.ClientConfig.Service.Name = name +} + +func (w *validatingWebhookV1) SetServicePath(path *string) { + w.InitializeServiceReference() + w.ClientConfig.Service.Path = path +} + +func (w *validatingWebhookV1) GetName() string { return w.Name } + +func (w *validatingWebhookV1) SetName(name string) { w.Name = name } + +func (w *validatingWebhookV1) SetAdmissionReviewVersions(versions []string) { + w.AdmissionReviewVersions = versions +} + +func (w *validatingWebhookV1) SetFailurePolicy(policy string) { + temp := admissionsV1.FailurePolicyType(policy) + w.FailurePolicy = &temp +} + +func (w *validatingWebhookV1) SetMatchPolicy(policy string) { + temp := admissionsV1.MatchPolicyType(policy) + w.MatchPolicy = &temp +} + +func (w *validatingWebhookV1) SetSideEffects(sideEffectsClass string) { + temp := admissionsV1.SideEffectClass(sideEffectsClass) + w.SideEffects = &temp +} + +func (w *validatingWebhookV1) GetNamespaceSelector() *metav1.LabelSelector { + return w.NamespaceSelector +} + +func (w *validatingWebhookV1) SetNamespaceSelector(selector *metav1.LabelSelector) { + w.NamespaceSelector = selector +} + +func (w *validatingWebhookV1) SetTimeoutSeconds(timeoutSeconds int32) { + w.TimeoutSeconds = &timeoutSeconds +} + +func (w *validatingWebhookV1) GetAdmissionRules() []AdmissionRuleAdapter { + result := make([]AdmissionRuleAdapter, 0, len(w.Rules)) + for i := range w.Rules { + var ruleAdapter = AdmissionRuleAdapter{ + Operations: make([]string, 0, len(w.Rules[i].Operations)), + APIGroups: w.Rules[i].APIGroups, + APIVersions: w.Rules[i].APIVersions, + Resources: w.Rules[i].Resources, + Scope: (*string)(w.Rules[i].Scope), + } + for _, op := range w.Rules[i].Operations { + ruleAdapter.Operations = append(ruleAdapter.Operations, string(op)) + } + result = append(result, ruleAdapter) + } + return result +} + +func (w *validatingWebhookV1) SetAdmissionRules(rules []AdmissionRuleAdapter) { + newRules := make([]admissionsV1.RuleWithOperations, 0, len(rules)) + for _, r := range rules { + stringOperations := make([]admissionsV1.OperationType, 0, len(r.Operations)) + for _, op := range r.Operations { + stringOperations = append(stringOperations, admissionsV1.OperationType(op)) + } + newRules = append(newRules, admissionsV1.RuleWithOperations{ + Operations: stringOperations, + Rule: admissionsV1.Rule{ + APIGroups: r.APIGroups, + APIVersions: r.APIVersions, + Resources: r.Resources, + Scope: (*admissionsV1.ScopeType)(r.Scope), + }, + }) + } + w.Rules = newRules +} + +func (w *validatingWebhookV1) InitializeServiceReference() { + if w.ClientConfig.Service == nil { + w.ClientConfig.Service = &admissionsV1.ServiceReference{} + } +} + +type validatingWebhookV1Beta1 admissionsV1Beta1.ValidatingWebhook + +func (w *validatingWebhookV1Beta1) GetName() string { return w.Name } + +func (w *validatingWebhookV1Beta1) SetName(name string) { + w.Name = name +} + +func (w *validatingWebhookV1Beta1) SetAdmissionReviewVersions(versions []string) { + w.AdmissionReviewVersions = versions +} + +func (w *validatingWebhookV1Beta1) SetFailurePolicy(policy string) { + temp := admissionsV1Beta1.FailurePolicyType(policy) + w.FailurePolicy = &temp +} + +func (w *validatingWebhookV1Beta1) SetMatchPolicy(policy string) { + temp := admissionsV1Beta1.MatchPolicyType(policy) + w.MatchPolicy = &temp +} + +func (w *validatingWebhookV1Beta1) SetSideEffects(sideEffectsClass string) { + temp := admissionsV1Beta1.SideEffectClass(sideEffectsClass) + w.SideEffects = &temp +} + +func (w *validatingWebhookV1Beta1) GetNamespaceSelector() *metav1.LabelSelector { + return w.NamespaceSelector +} + +func (w *validatingWebhookV1Beta1) SetNamespaceSelector(selector *metav1.LabelSelector) { + w.NamespaceSelector = selector +} + +func (w *validatingWebhookV1Beta1) SetTimeoutSeconds(timeoutSeconds int32) { + w.TimeoutSeconds = &timeoutSeconds +} + +func (w *validatingWebhookV1Beta1) SetCABundle(bundle []byte) { + w.ClientConfig.CABundle = bundle +} + +func (w *validatingWebhookV1Beta1) SetServiceNamespace(namespace string) { + w.InitializeServiceReference() + w.ClientConfig.Service.Namespace = namespace +} + +func (w *validatingWebhookV1Beta1) SetServiceName(name string) { + w.InitializeServiceReference() + w.ClientConfig.Service.Name = name +} + +func (w *validatingWebhookV1Beta1) SetServicePath(path *string) { + w.InitializeServiceReference() + w.ClientConfig.Service.Path = path +} + +func (w *validatingWebhookV1Beta1) GetAdmissionRules() []AdmissionRuleAdapter { + result := make([]AdmissionRuleAdapter, 0, len(w.Rules)) + for i := range w.Rules { + var ruleAdapter = AdmissionRuleAdapter{ + Operations: make([]string, 0, len(w.Rules[i].Operations)), + APIGroups: w.Rules[i].APIGroups, + APIVersions: w.Rules[i].APIVersions, + Resources: w.Rules[i].Resources, + Scope: (*string)(w.Rules[i].Scope), + } + for _, op := range w.Rules[i].Operations { + ruleAdapter.Operations = append(ruleAdapter.Operations, string(op)) + } + result = append(result, ruleAdapter) + } + return result +} + +func (w *validatingWebhookV1Beta1) SetAdmissionRules(rules []AdmissionRuleAdapter) { + newRules := make([]admissionsV1Beta1.RuleWithOperations, 0, len(rules)) + for _, r := range rules { + stringOperations := make([]admissionsV1Beta1.OperationType, 0, len(r.Operations)) + for _, op := range r.Operations { + stringOperations = append(stringOperations, admissionsV1Beta1.OperationType(op)) + } + newRules = append(newRules, admissionsV1Beta1.RuleWithOperations{ + Operations: stringOperations, + Rule: admissionsV1Beta1.Rule{ + APIGroups: r.APIGroups, + APIVersions: r.APIVersions, + Resources: r.Resources, + Scope: (*admissionsV1Beta1.ScopeType)(r.Scope), + }, + }) + } + w.Rules = newRules +} +func (w *validatingWebhookV1Beta1) InitializeServiceReference() { + if w.ClientConfig.Service == nil { + w.ClientConfig.Service = &admissionsV1Beta1.ServiceReference{} + } +} diff --git a/cbcontainers/state/hardening/hardening_state_applier.go b/cbcontainers/state/hardening/hardening_state_applier.go index 73a1a4c9..7b63be9e 100644 --- a/cbcontainers/state/hardening/hardening_state_applier.go +++ b/cbcontainers/state/hardening/hardening_state_applier.go @@ -64,7 +64,7 @@ func (c *HardeningStateApplier) applyEnforcer(ctx context.Context, cbContainersH if err != nil { return false, err } - c.log.Info("Applied enfocer tls secret", "Mutated", mutatedSecret) + c.log.Info("Applied enforcer tls secret", "Mutated", mutatedSecret) tlsSecret, ok := secretK8sObject.(*coreV1.Secret) if !ok { diff --git a/cbcontainers/state/hardening/hardening_state_applier_test.go b/cbcontainers/state/hardening/hardening_state_applier_test.go index 4d80cd5a..4c9dced8 100644 --- a/cbcontainers/state/hardening/hardening_state_applier_test.go +++ b/cbcontainers/state/hardening/hardening_state_applier_test.go @@ -16,7 +16,8 @@ import ( "github.com/vmware/cbcontainers-operator/cbcontainers/state/hardening/objects" "github.com/vmware/cbcontainers-operator/cbcontainers/test_utils" testUtilsMocks "github.com/vmware/cbcontainers-operator/cbcontainers/test_utils/mocks" - admissionsV1 "k8s.io/api/admissionregistration/v1beta1" + admissionsV1 "k8s.io/api/admissionregistration/v1" + admissionsV1Beta1 "k8s.io/api/admissionregistration/v1beta1" appsV1 "k8s.io/api/apps/v1" coreV1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -121,6 +122,7 @@ func getAppliedAndDeletedObjects(t *testing.T, k8sVersion string, appliedK8sObje k8sObject := childObject.EmptyK8sObject() objType := reflect.TypeOf(k8sObject) objectDetails := K8sObjectDetails{Namespace: namespacedName.Namespace, Name: namespacedName.Name, ObjectType: objType} + appliedObjects = append(appliedObjects, objectDetails) for _, changeAppliedK8sObjects := range appliedK8sObjectsChangers { @@ -174,17 +176,55 @@ func TestEnforcerDeploymentIsApplied(t *testing.T) { } func TestEnforcerWebhookIsApplied(t *testing.T) { - appliedObjects, deletedObjects := getAndAssertAppliedAndDeletedObjects(t, "") - require.Contains(t, appliedObjects, EnforcerWebhookDetails) - require.NotContains(t, deletedObjects, EnforcerWebhookDetails) + assertValidatingWebhookIsApplied := func(t *testing.T, appliedObjects, deletedObjects []K8sObjectDetails, webhookObject K8sObjectDetails) { + require.Contains(t, appliedObjects, webhookObject) + require.NotContains(t, deletedObjects, webhookObject) + } + + t.Run("With empty K8S version, should use `v1` by default", func(t *testing.T) { + appliedObjects, deletedObjects := getAndAssertAppliedAndDeletedObjects(t, "") + assertValidatingWebhookIsApplied(t, appliedObjects, deletedObjects, EnforcerWebhookDetails) + }) + + t.Run("With K8S version 1.15 or lower, should use `v1beta1` version of webhook", func(t *testing.T) { + appliedObjects, deletedObjects := getAndAssertAppliedAndDeletedObjects(t, "v1.15") + legacyWebhookDetails := EnforcerWebhookDetails + legacyWebhookDetails.ObjectType = reflect.TypeOf(&admissionsV1Beta1.ValidatingWebhookConfiguration{}) + assertValidatingWebhookIsApplied(t, appliedObjects, deletedObjects, legacyWebhookDetails) + }) + + t.Run("With K8S version 1.16 or higher, should use `v1` version of webhook", func(t *testing.T) { + appliedObjects, deletedObjects := getAndAssertAppliedAndDeletedObjects(t, "v1.16") + assertValidatingWebhookIsApplied(t, appliedObjects, deletedObjects, EnforcerWebhookDetails) + }) } func TestEnforcerWebhookIsDeleted(t *testing.T) { - appliedObjects, deletedObjects, err := getAppliedAndDeletedObjects(t, "", MutateDeploymentToBeWithNoReadyReplica) - require.NoError(t, err) - require.Len(t, appliedObjects, NumberOfExpectedAppliedObjects-1) - require.NotContains(t, appliedObjects, EnforcerWebhookDetails) - require.Contains(t, deletedObjects, EnforcerWebhookDetails) + assertValidatingWebhookIsDeleted := func(t *testing.T, appliedObjects, deletedObjects []K8sObjectDetails, webhookObject K8sObjectDetails) { + require.Len(t, appliedObjects, NumberOfExpectedAppliedObjects-1) + require.NotContains(t, appliedObjects, webhookObject) + require.Contains(t, deletedObjects, webhookObject) + } + + t.Run("With empty K8S version, should use `v1` by default", func(t *testing.T) { + appliedObjects, deletedObjects, err := getAppliedAndDeletedObjects(t, "") + require.NoError(t, err) + assertValidatingWebhookIsDeleted(t, appliedObjects, deletedObjects, EnforcerWebhookDetails) + }) + + t.Run("With K8S version 1.15 or lower, should use `v1beta1` version of webhook", func(t *testing.T) { + appliedObjects, deletedObjects, err := getAppliedAndDeletedObjects(t, "v1.15") + require.NoError(t, err) + legacyWebhookDetails := EnforcerWebhookDetails + legacyWebhookDetails.ObjectType = reflect.TypeOf(&admissionsV1Beta1.ValidatingWebhookConfiguration{}) + assertValidatingWebhookIsDeleted(t, appliedObjects, deletedObjects, legacyWebhookDetails) + }) + + t.Run("With K8S version 1.16 or higher, should use `v1` version of webhook", func(t *testing.T) { + appliedObjects, deletedObjects, err := getAppliedAndDeletedObjects(t, "v1.16") + require.NoError(t, err) + assertValidatingWebhookIsDeleted(t, appliedObjects, deletedObjects, EnforcerWebhookDetails) + }) } func TestStateReporterDeploymentIsApplied(t *testing.T) { diff --git a/cbcontainers/state/hardening/objects/enforcer_webhook.go b/cbcontainers/state/hardening/objects/enforcer_webhook.go index 1fa910f4..12c8ff4b 100644 --- a/cbcontainers/state/hardening/objects/enforcer_webhook.go +++ b/cbcontainers/state/hardening/objects/enforcer_webhook.go @@ -5,8 +5,8 @@ import ( cbcontainersv1 "github.com/vmware/cbcontainers-operator/api/v1" "github.com/vmware/cbcontainers-operator/cbcontainers/models" commonState "github.com/vmware/cbcontainers-operator/cbcontainers/state/common" + "github.com/vmware/cbcontainers-operator/cbcontainers/state/hardening/adapters" "github.com/vmware/cbcontainers-operator/cbcontainers/utils" - admissionsV1 "k8s.io/api/admissionregistration/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "reflect" @@ -19,11 +19,13 @@ const ( ) var ( - WebhookFailurePolicy = admissionsV1.Ignore + WebhookFailurePolicy = adapters.FailurePolicyIgnore WebhookPath = "/validate" + // This value's default changes across versions so we want to ensure consistency by setting it explicitly + WebhookMatchPolicy = adapters.MatchPolicyEquivalent - ResourcesWebhookSideEffect = admissionsV1.SideEffectClassNoneOnDryRun - NamespacesWebhookSideEffect = admissionsV1.SideEffectClassNone + ResourcesWebhookSideEffect = adapters.SideEffectClassNoneOnDryRun + NamespacesWebhookSideEffect = adapters.SideEffectsClassNone ) type EnforcerWebhookK8sObject struct { @@ -42,7 +44,7 @@ func (obj *EnforcerWebhookK8sObject) UpdateTlsSecretValues(tlsSecretValues model } func (obj *EnforcerWebhookK8sObject) EmptyK8sObject() client.Object { - return &admissionsV1.ValidatingWebhookConfiguration{} + return adapters.EmptyValidatingWebhookConfigForVersion(obj.kubeletVersion) } func (obj *EnforcerWebhookK8sObject) HardeningChildNamespacedName(_ *cbcontainersv1.CBContainersHardening) types.NamespacedName { @@ -50,9 +52,9 @@ func (obj *EnforcerWebhookK8sObject) HardeningChildNamespacedName(_ *cbcontainer } func (obj *EnforcerWebhookK8sObject) MutateHardeningChildK8sObject(k8sObject client.Object, cbContainersHardening *cbcontainersv1.CBContainersHardening) error { - webhookConfiguration, ok := k8sObject.(*admissionsV1.ValidatingWebhookConfiguration) + webhookConfiguration, ok := adapters.TryGetValidatingWebhookConfigurationAdapter(k8sObject) if !ok { - return fmt.Errorf("expected Service K8s object") + return fmt.Errorf("expected a valid instance of ValidatingWebhookConfiguration") } if obj.tlsSecretValues == nil { @@ -61,65 +63,71 @@ func (obj *EnforcerWebhookK8sObject) MutateHardeningChildK8sObject(k8sObject cli enforcerSpec := cbContainersHardening.Spec.EnforcerSpec - webhookConfiguration.Labels = enforcerSpec.Labels - obj.mutateWebhooks(webhookConfiguration, cbContainersHardening) - - return nil + webhookConfiguration.SetLabels(enforcerSpec.Labels) + return obj.mutateWebhooks(webhookConfiguration, cbContainersHardening) } -func (obj *EnforcerWebhookK8sObject) mutateWebhooks(webhookConfiguration *admissionsV1.ValidatingWebhookConfiguration, cbContainersHardening *cbcontainersv1.CBContainersHardening) { - var resourcesWebhookObj *admissionsV1.ValidatingWebhook - var namespacesWebhookObj *admissionsV1.ValidatingWebhook - initializeWebhooks := false +func (obj *EnforcerWebhookK8sObject) mutateWebhooks(webhookConfiguration adapters.ValidatingWebhookConfigurationAdapter, cbContainersHardening *cbcontainersv1.CBContainersHardening) error { + var resourcesWebhookObj adapters.ValidatingWebhookAdapter + var namespacesWebhookObj adapters.ValidatingWebhookAdapter - if webhookConfiguration.Webhooks == nil || len(webhookConfiguration.Webhooks) != 2 { + initializeWebhooks := false + webhooks := webhookConfiguration.GetWebhooks() + if webhooks == nil || len(webhooks) != 2 { initializeWebhooks = true } else { - resourcesWebhook, resourcesWebhookFound := obj.findWebhookByName(webhookConfiguration.Webhooks, ResourcesWebhookName) + resourcesWebhook, resourcesWebhookFound := obj.findWebhookByName(webhooks, ResourcesWebhookName) resourcesWebhookObj = resourcesWebhook - namespacesWebhook, namespacesWebhookFound := obj.findWebhookByName(webhookConfiguration.Webhooks, NamespacesWebhookName) + namespacesWebhook, namespacesWebhookFound := obj.findWebhookByName(webhooks, NamespacesWebhookName) namespacesWebhookObj = namespacesWebhook initializeWebhooks = !resourcesWebhookFound || !namespacesWebhookFound } if initializeWebhooks { - webhookConfiguration.Webhooks = make([]admissionsV1.ValidatingWebhook, 2) - resourcesWebhookObj = &webhookConfiguration.Webhooks[0] - namespacesWebhookObj = &webhookConfiguration.Webhooks[1] + webhooks := []adapters.ValidatingWebhookAdapter{ + adapters.EmptyValidatingWebhookAdapterForVersion(obj.kubeletVersion), + adapters.EmptyValidatingWebhookAdapterForVersion(obj.kubeletVersion), + } + updatedWebhooks, err := webhookConfiguration.SetWebhooks(webhooks) + if err != nil { + return err + } + + resourcesWebhookObj = updatedWebhooks[0] + namespacesWebhookObj = updatedWebhooks[1] } obj.mutateResourcesWebhook(resourcesWebhookObj, cbContainersHardening.Spec.EnforcerSpec.WebhookTimeoutSeconds) obj.mutateNamespacesWebhook(namespacesWebhookObj, cbContainersHardening.Spec.EnforcerSpec.WebhookTimeoutSeconds) + return nil } -func (obj *EnforcerWebhookK8sObject) findWebhookByName(webhooks []admissionsV1.ValidatingWebhook, name string) (*admissionsV1.ValidatingWebhook, bool) { +func (obj *EnforcerWebhookK8sObject) findWebhookByName(webhooks []adapters.ValidatingWebhookAdapter, name string) (adapters.ValidatingWebhookAdapter, bool) { for idx, webhook := range webhooks { - if webhook.Name == name { - return &webhooks[idx], true + if webhook.GetName() == name { + return webhooks[idx], true } } return nil, false } -func (obj *EnforcerWebhookK8sObject) mutateResourcesWebhook(resourcesWebhook *admissionsV1.ValidatingWebhook, timeoutSeconds int32) { - resourcesWebhook.Name = ResourcesWebhookName - //resourcesWebhook.AdmissionReviewVersions = []string{"v1beta1"} - resourcesWebhook.FailurePolicy = &WebhookFailurePolicy - //resourcesWebhook.MatchPolicy = &WebhookMatchPolicyType - resourcesWebhook.SideEffects = &ResourcesWebhookSideEffect - resourcesWebhook.NamespaceSelector = obj.getResourcesNamespaceSelector(resourcesWebhook.NamespaceSelector) +func (obj *EnforcerWebhookK8sObject) mutateResourcesWebhook(resourcesWebhook adapters.ValidatingWebhookAdapter, timeoutSeconds int32) { + resourcesWebhook.SetName(ResourcesWebhookName) + resourcesWebhook.SetAdmissionReviewVersions([]string{"v1beta1"}) + resourcesWebhook.SetFailurePolicy(WebhookFailurePolicy) + resourcesWebhook.SetSideEffects(ResourcesWebhookSideEffect) + resourcesWebhook.SetMatchPolicy(WebhookMatchPolicy) + namespaceSelector := obj.getResourcesNamespaceSelector(resourcesWebhook.GetNamespaceSelector()) + resourcesWebhook.SetNamespaceSelector(namespaceSelector) obj.mutateResourcesWebhooksRules(resourcesWebhook) if obj.kubeletVersion == "" || obj.kubeletVersion >= "v1.14" { - resourcesWebhook.TimeoutSeconds = &timeoutSeconds + resourcesWebhook.SetTimeoutSeconds(timeoutSeconds) } - resourcesWebhook.ClientConfig.CABundle = obj.tlsSecretValues.CaCert - if resourcesWebhook.ClientConfig.Service == nil { - resourcesWebhook.ClientConfig.Service = &admissionsV1.ServiceReference{} - } - resourcesWebhook.ClientConfig.Service.Namespace = commonState.DataPlaneNamespaceName - resourcesWebhook.ClientConfig.Service.Name = EnforcerName - resourcesWebhook.ClientConfig.Service.Path = &WebhookPath + resourcesWebhook.SetCABundle(obj.tlsSecretValues.CaCert) + resourcesWebhook.SetServiceName(EnforcerName) + resourcesWebhook.SetServiceNamespace(commonState.DataPlaneNamespaceName) + resourcesWebhook.SetServicePath(&WebhookPath) } func (obj *EnforcerWebhookK8sObject) getResourcesNamespaceSelector(selector *metav1.LabelSelector) *metav1.LabelSelector { @@ -162,19 +170,21 @@ func (obj *EnforcerWebhookK8sObject) getResourcesNamespaceSelector(selector *met } -func (obj *EnforcerWebhookK8sObject) mutateResourcesWebhooksRules(webhook *admissionsV1.ValidatingWebhook) { - if webhook.Rules == nil || len(webhook.Rules) != 1 { - webhook.Rules = make([]admissionsV1.RuleWithOperations, 1) +func (obj *EnforcerWebhookK8sObject) mutateResourcesWebhooksRules(webhook adapters.ValidatingWebhookAdapter) { + rules := webhook.GetAdmissionRules() + if rules == nil || len(rules) != 1 { + rules = make([]adapters.AdmissionRuleAdapter, 1) } - webhook.Rules[0].Operations = []admissionsV1.OperationType{admissionsV1.OperationAll} - webhook.Rules[0].Rule.APIGroups = []string{"*"} - webhook.Rules[0].Rule.APIVersions = []string{"*"} + rules[0].Operations = []string{adapters.OperationAll} + rules[0].APIVersions = []string{"*"} + rules[0].APIGroups = []string{"*"} expectedResourcesList := obj.getResourcesList() - if !utils.StringsSlicesHaveSameItems(webhook.Rules[0].Rule.Resources, expectedResourcesList) { - webhook.Rules[0].Rule.Resources = expectedResourcesList + if !utils.StringsSlicesHaveSameItems(rules[0].Resources, expectedResourcesList) { + rules[0].Resources = expectedResourcesList } + webhook.SetAdmissionRules(rules) } func (obj *EnforcerWebhookK8sObject) getResourcesList() []string { @@ -201,46 +211,35 @@ func (obj *EnforcerWebhookK8sObject) getResourcesList() []string { } } -func (obj *EnforcerWebhookK8sObject) mutateNamespacesWebhook(namespacesWebhook *admissionsV1.ValidatingWebhook, timeoutSeconds int32) { - namespacesWebhook.Name = NamespacesWebhookName - //namespacesWebhook.AdmissionReviewVersions = []string{"v1beta1"} - namespacesWebhook.FailurePolicy = &WebhookFailurePolicy - //namespacesWebhook.MatchPolicy = &WebhookMatchPolicyType - namespacesWebhook.SideEffects = &NamespacesWebhookSideEffect - namespacesWebhook.NamespaceSelector = &metav1.LabelSelector{} - obj.mutateNamespacesWebhooksRules(namespacesWebhook) +func (obj *EnforcerWebhookK8sObject) mutateNamespacesWebhook(namespacesWebhook adapters.ValidatingWebhookAdapter, timeoutSeconds int32) { + namespacesWebhook.SetName(NamespacesWebhookName) + namespacesWebhook.SetAdmissionReviewVersions([]string{"v1beta1"}) + namespacesWebhook.SetFailurePolicy(WebhookFailurePolicy) + namespacesWebhook.SetMatchPolicy(WebhookMatchPolicy) + namespacesWebhook.SetSideEffects(NamespacesWebhookSideEffect) + namespacesWebhook.SetNamespaceSelector(&metav1.LabelSelector{}) if obj.kubeletVersion == "" || obj.kubeletVersion >= "v1.14" { - namespacesWebhook.TimeoutSeconds = &timeoutSeconds + namespacesWebhook.SetTimeoutSeconds(timeoutSeconds) } - namespacesWebhook.ClientConfig.CABundle = obj.tlsSecretValues.CaCert - if namespacesWebhook.ClientConfig.Service == nil { - namespacesWebhook.ClientConfig.Service = &admissionsV1.ServiceReference{} - } - namespacesWebhook.ClientConfig.Service.Namespace = commonState.DataPlaneNamespaceName - namespacesWebhook.ClientConfig.Service.Name = EnforcerName - namespacesWebhook.ClientConfig.Service.Path = &WebhookPath -} + namespacesWebhook.SetCABundle(obj.tlsSecretValues.CaCert) + namespacesWebhook.SetServiceNamespace(commonState.DataPlaneNamespaceName) + namespacesWebhook.SetServiceName(EnforcerName) + namespacesWebhook.SetServicePath(&WebhookPath) -func (obj *EnforcerWebhookK8sObject) mutateNamespacesWebhooksRules(webhook *admissionsV1.ValidatingWebhook) { - if webhook.Rules == nil || len(webhook.Rules) != 1 { - webhook.Rules = make([]admissionsV1.RuleWithOperations, 1) - } + obj.mutateNamespacesWebhooksRules(namespacesWebhook) - expectedOperations := []admissionsV1.OperationType{admissionsV1.Create, admissionsV1.Update, admissionsV1.Connect} - if !utils.StringsSlicesHaveSameItems(obj.operationsToStrings(webhook.Rules[0].Operations), obj.operationsToStrings(expectedOperations)) { - webhook.Rules[0].Operations = expectedOperations - } - webhook.Rules[0].Rule.APIGroups = []string{"*"} - webhook.Rules[0].Rule.APIVersions = []string{"*"} - webhook.Rules[0].Rule.Resources = []string{"namespaces"} } -func (obj *EnforcerWebhookK8sObject) operationsToStrings(operations []admissionsV1.OperationType) []string { - operationsStrings := make([]string, 0, len(operations)) - for _, operation := range operations { - operationsStrings = append(operationsStrings, string(operation)) +func (obj *EnforcerWebhookK8sObject) mutateNamespacesWebhooksRules(webhook adapters.ValidatingWebhookAdapter) { + rules := webhook.GetAdmissionRules() + if rules == nil || len(rules) != 1 { + rules = make([]adapters.AdmissionRuleAdapter, 1) } - return operationsStrings + rules[0].Operations = []string{adapters.OperationCreate, adapters.OperationUpdate, adapters.OperationConnect} + rules[0].APIVersions = []string{"*"} + rules[0].APIGroups = []string{"*"} + rules[0].Resources = []string{"namespaces"} + webhook.SetAdmissionRules(rules) } diff --git a/config/crd/bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml b/config/crd/bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml index d92d2217..d16f296c 100644 --- a/config/crd/bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml +++ b/config/crd/bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml @@ -1,6 +1,6 @@ --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: @@ -15,71 +15,75 @@ spec: plural: cbcontainersclusters singular: cbcontainerscluster scope: Cluster - subresources: - status: {} - validation: - openAPIV3Schema: - description: CBContainersCluster is the Schema for the cbcontainersclusters - API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: CBContainersClusterSpec defines the desired state of CBContainersCluster - properties: - account: - type: string - apiGatewaySpec: - properties: - accessTokenSecretName: - type: string - adapter: - type: string - host: - type: string - port: - type: integer - scheme: - type: string - required: - - host - type: object - clusterName: - type: string - eventsGatewaySpec: - properties: - host: - type: string - port: - type: integer - required: - - host - type: object - required: - - account - - apiGatewaySpec - - clusterName - - eventsGatewaySpec - type: object - status: - description: CBContainersClusterStatus defines the observed state of CBContainersCluster - type: object - type: object - version: v1 versions: - name: v1 + schema: + openAPIV3Schema: + description: CBContainersCluster is the Schema for the cbcontainersclusters + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CBContainersClusterSpec defines the desired state of CBContainersCluster + properties: + account: + type: string + apiGatewaySpec: + properties: + accessTokenSecretName: + default: cbcontainers-access-token + type: string + adapter: + default: containers + type: string + host: + type: string + port: + default: 443 + type: integer + scheme: + default: https + type: string + required: + - host + type: object + clusterName: + type: string + eventsGatewaySpec: + properties: + host: + type: string + port: + default: 443 + type: integer + required: + - host + type: object + required: + - account + - apiGatewaySpec + - clusterName + - eventsGatewaySpec + type: object + status: + description: CBContainersClusterStatus defines the observed state of CBContainersCluster + type: object + type: object served: true storage: true + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/config/crd/bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml b/config/crd/bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml index 239507f3..0a969499 100644 --- a/config/crd/bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml +++ b/config/crd/bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml @@ -1,6 +1,6 @@ --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: @@ -15,238 +15,295 @@ spec: plural: cbcontainershardenings singular: cbcontainershardening scope: Cluster - subresources: - status: {} - validation: - openAPIV3Schema: - description: CBContainersHardening is the Schema for the cbcontainershardenings - API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - properties: - accessTokenSecretName: - type: string - enforcerSpec: - properties: - deploymentAnnotations: - additionalProperties: - type: string - type: object - env: - additionalProperties: - type: string - type: object - image: - properties: - pullPolicy: - description: PullPolicy describes a policy for if/when to pull - a container image - type: string - repository: - type: string - tag: + versions: + - name: v1 + schema: + openAPIV3Schema: + description: CBContainersHardening is the Schema for the cbcontainershardenings + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + accessTokenSecretName: + default: cbcontainers-access-token + type: string + enforcerSpec: + default: {} + properties: + deploymentAnnotations: + additionalProperties: type: string - type: object - labels: - additionalProperties: - type: string - type: object - podTemplateAnnotations: - additionalProperties: - type: string - type: object - probes: - properties: - failureThreshold: - format: int32 - type: integer - initialDelaySeconds: - format: int32 - type: integer - livenessPath: + default: {} + type: object + env: + additionalProperties: type: string - periodSeconds: - format: int32 - type: integer - port: - type: integer - readinessPath: + default: {} + type: object + image: + default: + repository: cbartifactory/guardrails-enforcer + properties: + pullPolicy: + default: Always + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: type: string - scheme: - description: URIScheme identifies the scheme used for connection - to a host for Get actions + default: {} + type: object + podTemplateAnnotations: + additionalProperties: type: string - successThreshold: - format: int32 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - prometheus: - properties: - enabled: - type: boolean - port: - type: integer - type: object - replicasCount: - format: int32 - type: integer - resources: - description: ResourceRequirements describes the compute resource - requirements. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - webhookTimeoutSeconds: - format: int32 - type: integer - type: object - eventsGatewaySpec: - properties: - host: - type: string - port: - type: integer - required: - - host - type: object - stateReporterSpec: - properties: - deploymentAnnotations: - additionalProperties: + default: {} + type: object + probes: + default: {} + properties: + failureThreshold: + default: 3 + format: int32 + type: integer + initialDelaySeconds: + default: 3 + format: int32 + type: integer + livenessPath: + default: /alive + type: string + periodSeconds: + default: 30 + format: int32 + type: integer + port: + default: 8181 + type: integer + readinessPath: + default: /ready + type: string + scheme: + default: HTTP + description: URIScheme identifies the scheme used for connection + to a host for Get actions + type: string + successThreshold: + default: 1 + format: int32 + type: integer + timeoutSeconds: + default: 1 + format: int32 + type: integer + type: object + prometheus: + default: {} + properties: + enabled: + default: false + type: boolean + port: + default: 7071 + type: integer + type: object + replicasCount: + default: 1 + format: int32 + type: integer + resources: + default: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 30m + memory: 64Mi + description: ResourceRequirements describes the compute resource + requirements. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + webhookTimeoutSeconds: + default: 5 + format: int32 + type: integer + type: object + eventsGatewaySpec: + properties: + host: type: string - type: object - env: - additionalProperties: - type: string - type: object - image: - properties: - pullPolicy: - description: PullPolicy describes a policy for if/when to pull - a container image - type: string - repository: + port: + default: 443 + type: integer + required: + - host + type: object + stateReporterSpec: + default: {} + properties: + deploymentAnnotations: + additionalProperties: type: string - tag: + default: {} + type: object + env: + additionalProperties: type: string - type: object - labels: - additionalProperties: - type: string - type: object - podTemplateAnnotations: - additionalProperties: - type: string - type: object - probes: - properties: - failureThreshold: - format: int32 - type: integer - initialDelaySeconds: - format: int32 - type: integer - livenessPath: + default: {} + type: object + image: + default: + repository: cbartifactory/guardrails-state-reporter + properties: + pullPolicy: + default: Always + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: type: string - periodSeconds: - format: int32 - type: integer - port: - type: integer - readinessPath: + default: {} + type: object + podTemplateAnnotations: + additionalProperties: type: string - scheme: - description: URIScheme identifies the scheme used for connection - to a host for Get actions - type: string - successThreshold: - format: int32 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - resources: - description: ResourceRequirements describes the compute resource - requirements. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - type: object - version: - type: string - required: - - eventsGatewaySpec - - version - type: object - status: - description: CBContainersHardeningStatus defines the observed state of CBContainersHardening - type: object - required: - - spec - type: object - version: v1 - versions: - - name: v1 + default: {} + type: object + probes: + default: {} + properties: + failureThreshold: + default: 3 + format: int32 + type: integer + initialDelaySeconds: + default: 3 + format: int32 + type: integer + livenessPath: + default: /alive + type: string + periodSeconds: + default: 30 + format: int32 + type: integer + port: + default: 8181 + type: integer + readinessPath: + default: /ready + type: string + scheme: + default: HTTP + description: URIScheme identifies the scheme used for connection + to a host for Get actions + type: string + successThreshold: + default: 1 + format: int32 + type: integer + timeoutSeconds: + default: 1 + format: int32 + type: integer + type: object + resources: + default: + limits: + cpu: 200m + memory: 256Mi + requests: + cpu: 30m + memory: 64Mi + description: ResourceRequirements describes the compute resource + requirements. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + type: object + version: + type: string + required: + - eventsGatewaySpec + - version + type: object + status: + description: CBContainersHardeningStatus defines the observed state of + CBContainersHardening + type: object + required: + - spec + type: object served: true storage: true + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/config/crd/bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml b/config/crd/bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml index b1ff64d7..bbdd5bd3 100644 --- a/config/crd/bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml +++ b/config/crd/bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml @@ -1,6 +1,6 @@ --- -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: @@ -15,241 +15,302 @@ spec: plural: cbcontainersruntimes singular: cbcontainersruntime scope: Cluster - subresources: - status: {} - validation: - openAPIV3Schema: - description: CBContainersRuntime is the Schema for the cbcontainersruntimes - API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: CBContainersRuntimeSpec defines the desired state of CBContainersRuntime - properties: - accessTokenSecretName: - type: string - internalGrpcPort: - format: int32 - type: integer - resolverSpec: - properties: - deploymentAnnotations: - additionalProperties: - type: string - type: object - env: - additionalProperties: - type: string - type: object - eventsGatewaySpec: - properties: - host: - type: string - port: - type: integer - required: - - host - type: object - image: - properties: - pullPolicy: - description: PullPolicy describes a policy for if/when to pull - a container image - type: string - repository: - type: string - tag: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - podTemplateAnnotations: - additionalProperties: - type: string - type: object - probes: - properties: - failureThreshold: - format: int32 - type: integer - initialDelaySeconds: - format: int32 - type: integer - livenessPath: + versions: + - name: v1 + schema: + openAPIV3Schema: + description: CBContainersRuntime is the Schema for the cbcontainersruntimes + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CBContainersRuntimeSpec defines the desired state of CBContainersRuntime + properties: + accessTokenSecretName: + default: cbcontainers-access-token + type: string + internalGrpcPort: + default: 443 + format: int32 + type: integer + resolverSpec: + properties: + deploymentAnnotations: + additionalProperties: type: string - periodSeconds: - format: int32 - type: integer - port: - type: integer - readinessPath: + default: {} + type: object + env: + additionalProperties: type: string - scheme: - description: URIScheme identifies the scheme used for connection - to a host for Get actions + default: {} + type: object + eventsGatewaySpec: + properties: + host: + type: string + port: + default: 443 + type: integer + required: + - host + type: object + image: + default: + repository: cbartifactory/runtime-kubernetes-resolver + properties: + pullPolicy: + default: Always + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: type: string - successThreshold: - format: int32 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - prometheus: - properties: - enabled: - type: boolean - port: - type: integer - type: object - replicasCount: - format: int32 - type: integer - resources: - description: ResourceRequirements describes the compute resource - requirements. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - required: - - eventsGatewaySpec - type: object - sensorSpec: - properties: - daemonSetAnnotations: - additionalProperties: - type: string - type: object - env: - additionalProperties: - type: string - type: object - image: - properties: - pullPolicy: - description: PullPolicy describes a policy for if/when to pull - a container image + default: {} + type: object + podTemplateAnnotations: + additionalProperties: type: string - repository: + default: + prometheus.io/port: "7071" + prometheus.io/scrape: "false" + type: object + probes: + default: {} + properties: + failureThreshold: + default: 3 + format: int32 + type: integer + initialDelaySeconds: + default: 3 + format: int32 + type: integer + livenessPath: + default: /alive + type: string + periodSeconds: + default: 30 + format: int32 + type: integer + port: + default: 8181 + type: integer + readinessPath: + default: /ready + type: string + scheme: + default: HTTP + description: URIScheme identifies the scheme used for connection + to a host for Get actions + type: string + successThreshold: + default: 1 + format: int32 + type: integer + timeoutSeconds: + default: 1 + format: int32 + type: integer + type: object + prometheus: + default: {} + properties: + enabled: + default: false + type: boolean + port: + default: 7071 + type: integer + type: object + replicasCount: + default: 1 + format: int32 + type: integer + resources: + default: + limits: + cpu: 900m + memory: 1024Mi + requests: + cpu: 200m + memory: 64Mi + description: ResourceRequirements describes the compute resource + requirements. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + required: + - eventsGatewaySpec + type: object + sensorSpec: + default: {} + properties: + daemonSetAnnotations: + additionalProperties: type: string - tag: + default: {} + type: object + env: + additionalProperties: type: string - type: object - labels: - additionalProperties: - type: string - type: object - podTemplateAnnotations: - additionalProperties: - type: string - type: object - probes: - properties: - failureThreshold: - format: int32 - type: integer - initialDelaySeconds: - format: int32 - type: integer - livenessPath: + default: {} + type: object + image: + default: + repository: cbartifactory/runtime-kubernetes-sensor + properties: + pullPolicy: + default: Always + description: PullPolicy describes a policy for if/when to + pull a container image + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: type: string - periodSeconds: - format: int32 - type: integer - readinessPath: + default: {} + type: object + podTemplateAnnotations: + additionalProperties: type: string - successThreshold: - format: int32 - type: integer - timeoutSeconds: - format: int32 - type: integer - type: object - prometheus: - properties: - enabled: - type: boolean - port: - type: integer - type: object - resources: - description: ResourceRequirements describes the compute resource - requirements. - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Limits describes the maximum amount of compute - resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute - resources required. If Requests is omitted for a container, - it defaults to Limits if that is explicitly specified, otherwise - to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - type: object - verbosity_level: - type: integer - type: object - version: - type: string - required: - - version - type: object - status: - description: CBContainersRuntimeStatus defines the observed state of CBContainersRuntime - type: object - type: object - version: v1 - versions: - - name: v1 + default: + prometheus.io/port: "7071" + prometheus.io/scrape: "false" + type: object + probes: + default: {} + properties: + failureThreshold: + default: 3 + format: int32 + type: integer + initialDelaySeconds: + default: 3 + format: int32 + type: integer + livenessPath: + default: /tmp/alive + type: string + periodSeconds: + default: 30 + format: int32 + type: integer + readinessPath: + default: /tmp/ready + type: string + successThreshold: + default: 1 + format: int32 + type: integer + timeoutSeconds: + default: 1 + format: int32 + type: integer + type: object + prometheus: + default: {} + properties: + enabled: + default: false + type: boolean + port: + default: 7071 + type: integer + type: object + resources: + default: + limits: + cpu: 500m + memory: 1024Mi + requests: + cpu: 30m + memory: 64Mi + description: ResourceRequirements describes the compute resource + requirements. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + verbosity_level: + default: 2 + type: integer + type: object + version: + type: string + required: + - version + type: object + status: + description: CBContainersRuntimeStatus defines the observed state of CBContainersRuntime + type: object + type: object served: true storage: true + subresources: + status: {} status: acceptedNames: kind: "" diff --git a/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml b/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml new file mode 100644 index 00000000..d92d2217 --- /dev/null +++ b/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml @@ -0,0 +1,88 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: cbcontainersclusters.operator.containers.carbonblack.io +spec: + group: operator.containers.carbonblack.io + names: + kind: CBContainersCluster + listKind: CBContainersClusterList + plural: cbcontainersclusters + singular: cbcontainerscluster + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: CBContainersCluster is the Schema for the cbcontainersclusters + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CBContainersClusterSpec defines the desired state of CBContainersCluster + properties: + account: + type: string + apiGatewaySpec: + properties: + accessTokenSecretName: + type: string + adapter: + type: string + host: + type: string + port: + type: integer + scheme: + type: string + required: + - host + type: object + clusterName: + type: string + eventsGatewaySpec: + properties: + host: + type: string + port: + type: integer + required: + - host + type: object + required: + - account + - apiGatewaySpec + - clusterName + - eventsGatewaySpec + type: object + status: + description: CBContainersClusterStatus defines the observed state of CBContainersCluster + type: object + type: object + version: v1 + versions: + - name: v1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml b/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml new file mode 100644 index 00000000..239507f3 --- /dev/null +++ b/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml @@ -0,0 +1,255 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: cbcontainershardenings.operator.containers.carbonblack.io +spec: + group: operator.containers.carbonblack.io + names: + kind: CBContainersHardening + listKind: CBContainersHardeningList + plural: cbcontainershardenings + singular: cbcontainershardening + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: CBContainersHardening is the Schema for the cbcontainershardenings + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + accessTokenSecretName: + type: string + enforcerSpec: + properties: + deploymentAnnotations: + additionalProperties: + type: string + type: object + env: + additionalProperties: + type: string + type: object + image: + properties: + pullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + podTemplateAnnotations: + additionalProperties: + type: string + type: object + probes: + properties: + failureThreshold: + format: int32 + type: integer + initialDelaySeconds: + format: int32 + type: integer + livenessPath: + type: string + periodSeconds: + format: int32 + type: integer + port: + type: integer + readinessPath: + type: string + scheme: + description: URIScheme identifies the scheme used for connection + to a host for Get actions + type: string + successThreshold: + format: int32 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + prometheus: + properties: + enabled: + type: boolean + port: + type: integer + type: object + replicasCount: + format: int32 + type: integer + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + webhookTimeoutSeconds: + format: int32 + type: integer + type: object + eventsGatewaySpec: + properties: + host: + type: string + port: + type: integer + required: + - host + type: object + stateReporterSpec: + properties: + deploymentAnnotations: + additionalProperties: + type: string + type: object + env: + additionalProperties: + type: string + type: object + image: + properties: + pullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + podTemplateAnnotations: + additionalProperties: + type: string + type: object + probes: + properties: + failureThreshold: + format: int32 + type: integer + initialDelaySeconds: + format: int32 + type: integer + livenessPath: + type: string + periodSeconds: + format: int32 + type: integer + port: + type: integer + readinessPath: + type: string + scheme: + description: URIScheme identifies the scheme used for connection + to a host for Get actions + type: string + successThreshold: + format: int32 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + type: object + version: + type: string + required: + - eventsGatewaySpec + - version + type: object + status: + description: CBContainersHardeningStatus defines the observed state of CBContainersHardening + type: object + required: + - spec + type: object + version: v1 + versions: + - name: v1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml b/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml new file mode 100644 index 00000000..b1ff64d7 --- /dev/null +++ b/config/crd_v1beta1/bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml @@ -0,0 +1,258 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: cbcontainersruntimes.operator.containers.carbonblack.io +spec: + group: operator.containers.carbonblack.io + names: + kind: CBContainersRuntime + listKind: CBContainersRuntimeList + plural: cbcontainersruntimes + singular: cbcontainersruntime + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + description: CBContainersRuntime is the Schema for the cbcontainersruntimes + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CBContainersRuntimeSpec defines the desired state of CBContainersRuntime + properties: + accessTokenSecretName: + type: string + internalGrpcPort: + format: int32 + type: integer + resolverSpec: + properties: + deploymentAnnotations: + additionalProperties: + type: string + type: object + env: + additionalProperties: + type: string + type: object + eventsGatewaySpec: + properties: + host: + type: string + port: + type: integer + required: + - host + type: object + image: + properties: + pullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + podTemplateAnnotations: + additionalProperties: + type: string + type: object + probes: + properties: + failureThreshold: + format: int32 + type: integer + initialDelaySeconds: + format: int32 + type: integer + livenessPath: + type: string + periodSeconds: + format: int32 + type: integer + port: + type: integer + readinessPath: + type: string + scheme: + description: URIScheme identifies the scheme used for connection + to a host for Get actions + type: string + successThreshold: + format: int32 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + prometheus: + properties: + enabled: + type: boolean + port: + type: integer + type: object + replicasCount: + format: int32 + type: integer + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + required: + - eventsGatewaySpec + type: object + sensorSpec: + properties: + daemonSetAnnotations: + additionalProperties: + type: string + type: object + env: + additionalProperties: + type: string + type: object + image: + properties: + pullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + repository: + type: string + tag: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + podTemplateAnnotations: + additionalProperties: + type: string + type: object + probes: + properties: + failureThreshold: + format: int32 + type: integer + initialDelaySeconds: + format: int32 + type: integer + livenessPath: + type: string + periodSeconds: + format: int32 + type: integer + readinessPath: + type: string + successThreshold: + format: int32 + type: integer + timeoutSeconds: + format: int32 + type: integer + type: object + prometheus: + properties: + enabled: + type: boolean + port: + type: integer + type: object + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + type: object + verbosity_level: + type: integer + type: object + version: + type: string + required: + - version + type: object + status: + description: CBContainersRuntimeStatus defines the observed state of CBContainersRuntime + type: object + type: object + version: v1 + versions: + - name: v1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd_v1beta1/kustomization.yaml b/config/crd_v1beta1/kustomization.yaml new file mode 100644 index 00000000..a0d1a863 --- /dev/null +++ b/config/crd_v1beta1/kustomization.yaml @@ -0,0 +1,30 @@ +# IMPORTANT - this file is made for backwards compatibility with K8S 1.15 and below. +# It should be kept in-sync with the /config/crd version when applicable. + +# This kustomization.yaml is not intended to be run by itself, +# since it depends on service name and namespace that are out of this kustomize package. +# It should be run by config/default_v1beta1c +resources: +- bases/operator.containers.carbonblack.io_cbcontainersclusters.yaml +- bases/operator.containers.carbonblack.io_cbcontainershardenings.yaml +- bases/operator.containers.carbonblack.io_cbcontainersruntimes.yaml +# +kubebuilder:scaffold:crdkustomizeresource + +patchesStrategicMerge: +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. +# patches here are for enabling the conversion webhook for each CRD +#- patches/webhook_in_cbcontainersclusters.yaml +#- patches/webhook_in_cbcontainershardenings.yaml +#- patches/webhook_in_cbcontainersruntimes.yaml +# +kubebuilder:scaffold:crdkustomizewebhookpatch + +# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. +# patches here are for enabling the CA injection for each CRD +#- patches/cainjection_in_cbcontainersclusters.yaml +#- patches/cainjection_in_cbcontainershardenings.yaml +#- patches/cainjection_in_cbcontainersruntimes.yaml +# +kubebuilder:scaffold:crdkustomizecainjectionpatch + +# the following config is for teaching kustomize how to do kustomization for CRDs. +configurations: +- kustomizeconfig.yaml diff --git a/config/crd_v1beta1/kustomizeconfig.yaml b/config/crd_v1beta1/kustomizeconfig.yaml new file mode 100644 index 00000000..651b34fd --- /dev/null +++ b/config/crd_v1beta1/kustomizeconfig.yaml @@ -0,0 +1,19 @@ +# This file is for teaching kustomize how to substitute name and namespace reference in CRD +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + version: v1beta1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/name + +namespace: +- kind: CustomResourceDefinition + version: v1beta1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/namespace + create: false + +varReference: +- path: metadata/annotations diff --git a/config/crd_v1beta1/patches/cainjection_in_cbcontainersclusters.yaml b/config/crd_v1beta1/patches/cainjection_in_cbcontainersclusters.yaml new file mode 100644 index 00000000..05d25c32 --- /dev/null +++ b/config/crd_v1beta1/patches/cainjection_in_cbcontainersclusters.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: cbcontainersclusters.operator.containers.carbonblack.io diff --git a/config/crd_v1beta1/patches/cainjection_in_cbcontainershardenings.yaml b/config/crd_v1beta1/patches/cainjection_in_cbcontainershardenings.yaml new file mode 100644 index 00000000..8200cc8b --- /dev/null +++ b/config/crd_v1beta1/patches/cainjection_in_cbcontainershardenings.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: cbcontainershardenings.operator.containers.carbonblack.io diff --git a/config/crd_v1beta1/patches/cainjection_in_cbcontainersruntimes.yaml b/config/crd_v1beta1/patches/cainjection_in_cbcontainersruntimes.yaml new file mode 100644 index 00000000..077cf902 --- /dev/null +++ b/config/crd_v1beta1/patches/cainjection_in_cbcontainersruntimes.yaml @@ -0,0 +1,7 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: cbcontainersruntimes.operator.containers.carbonblack.io diff --git a/config/crd_v1beta1/patches/webhook_in_cbcontainersclusters.yaml b/config/crd_v1beta1/patches/webhook_in_cbcontainersclusters.yaml new file mode 100644 index 00000000..4ff66533 --- /dev/null +++ b/config/crd_v1beta1/patches/webhook_in_cbcontainersclusters.yaml @@ -0,0 +1,14 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cbcontainersclusters.operator.containers.carbonblack.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert diff --git a/config/crd_v1beta1/patches/webhook_in_cbcontainershardenings.yaml b/config/crd_v1beta1/patches/webhook_in_cbcontainershardenings.yaml new file mode 100644 index 00000000..eaf85924 --- /dev/null +++ b/config/crd_v1beta1/patches/webhook_in_cbcontainershardenings.yaml @@ -0,0 +1,14 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cbcontainershardenings.operator.containers.carbonblack.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert diff --git a/config/crd_v1beta1/patches/webhook_in_cbcontainersruntimes.yaml b/config/crd_v1beta1/patches/webhook_in_cbcontainersruntimes.yaml new file mode 100644 index 00000000..12f0a4b3 --- /dev/null +++ b/config/crd_v1beta1/patches/webhook_in_cbcontainersruntimes.yaml @@ -0,0 +1,14 @@ +# The following patch enables a conversion webhook for the CRD +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cbcontainersruntimes.operator.containers.carbonblack.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + namespace: system + name: webhook-service + path: /convert diff --git a/config/default/crd_apiextensionsv1beta1_patch.yaml b/config/default/crd_apiextensionsv1beta1_patch.yaml new file mode 100644 index 00000000..f2a4eb46 --- /dev/null +++ b/config/default/crd_apiextensionsv1beta1_patch.yaml @@ -0,0 +1,22 @@ +# Removes the v1beta1 apiextensions version of the CRDs as the default is v1 now +--- + +$patch: delete +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cbcontainersclusters.operator.containers.carbonblack.io +--- + +$patch: delete +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cbcontainershardenings.operator.containers.carbonblack.io +--- + +$patch: delete +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: cbcontainersruntimes.operator.containers.carbonblack.io \ No newline at end of file diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 1eb39b9f..199860ef 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -1,74 +1,8 @@ -# Adds namespace to all resources. -namespace: cbcontainers-dataplane - -# Value of this field is prepended to the -# names of all resources, e.g. a deployment named -# "wordpress" becomes "alices-wordpress". -# Note that it should also match with the prefix (text before '-') of the namespace -# field above. -namePrefix: cbcontainers- - -# Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue +# This file is only used to support apiextensions/v1 and apiextensions/v1beta1 CRD versions +# For any functional modifications, use ../operator/kustomization.yaml instead bases: -- ../crd -- ../rbac -- ../manager -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- ../webhook -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. -#- ../certmanager -# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. -#- ../prometheus + - ../operator patchesStrategicMerge: -# Protect the /metrics endpoint by putting it behind auth. -# If you want your operator to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. -- manager_auth_proxy_patch.yaml - -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -#- manager_config_patch.yaml - -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- manager_webhook_patch.yaml - -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -#- webhookcainjection_patch.yaml - -# the following config is for teaching kustomize how to do var substitution -vars: -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -#- name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -#- name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -#- name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service + - crd_apiextensionsv1beta1_patch.yaml \ No newline at end of file diff --git a/config/default_v1beta1/crd_apiextensionsv1_patch.yaml b/config/default_v1beta1/crd_apiextensionsv1_patch.yaml new file mode 100644 index 00000000..b7a69baf --- /dev/null +++ b/config/default_v1beta1/crd_apiextensionsv1_patch.yaml @@ -0,0 +1,22 @@ +# Legacy support for v1beta1 by removing the CRDs that use the newer v1 version +--- + +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: cbcontainersclusters.operator.containers.carbonblack.io +--- + +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: cbcontainershardenings.operator.containers.carbonblack.io +--- + +$patch: delete +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: cbcontainersruntimes.operator.containers.carbonblack.io \ No newline at end of file diff --git a/config/default_v1beta1/kustomization.yaml b/config/default_v1beta1/kustomization.yaml new file mode 100644 index 00000000..23d56da2 --- /dev/null +++ b/config/default_v1beta1/kustomization.yaml @@ -0,0 +1,8 @@ +# This file is only used to support apiextensions/v1 and apiextensions/v1beta1 CRD versions +# For any functional modifications, use ../operator/kustomization.yaml instead + +bases: + - ../operator + +patchesStrategicMerge: + - crd_apiextensionsv1_patch.yaml \ No newline at end of file diff --git a/config/operator/kustomization.yaml b/config/operator/kustomization.yaml new file mode 100644 index 00000000..6b56c092 --- /dev/null +++ b/config/operator/kustomization.yaml @@ -0,0 +1,75 @@ +# Adds namespace to all resources. +namespace: cbcontainers-dataplane + +# Value of this field is prepended to the +# names of all resources, e.g. a deployment named +# "wordpress" becomes "alices-wordpress". +# Note that it should also match with the prefix (text before '-') of the namespace +# field above. +namePrefix: cbcontainers- + +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +bases: +- ../crd +- ../crd_v1beta1 +- ../rbac +- ../manager +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +#- ../webhook +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. +#- ../certmanager +# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. +#- ../prometheus + +patchesStrategicMerge: +# Protect the /metrics endpoint by putting it behind auth. +# If you want your operator to expose the /metrics +# endpoint w/o any authn/z, please comment the following line. +- manager_auth_proxy_patch.yaml + +# Mount the controller config file for loading manager configurations +# through a ComponentConfig type +#- manager_config_patch.yaml + +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +#- manager_webhook_patch.yaml + +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. +# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. +# 'CERTMANAGER' needs to be enabled to use ca injection +#- webhookcainjection_patch.yaml + +# the following config is for teaching kustomize how to do var substitution +vars: +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +#- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +# fieldref: +# fieldpath: metadata.namespace +#- name: CERTIFICATE_NAME +# objref: +# kind: Certificate +# group: cert-manager.io +# version: v1 +# name: serving-cert # this name should match the one in certificate.yaml +#- name: SERVICE_NAMESPACE # namespace of the service +# objref: +# kind: Service +# version: v1 +# name: webhook-service +# fieldref: +# fieldpath: metadata.namespace +#- name: SERVICE_NAME +# objref: +# kind: Service +# version: v1 +# name: webhook-service diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/operator/manager_auth_proxy_patch.yaml similarity index 100% rename from config/default/manager_auth_proxy_patch.yaml rename to config/operator/manager_auth_proxy_patch.yaml diff --git a/config/default/manager_config_patch.yaml b/config/operator/manager_config_patch.yaml similarity index 100% rename from config/default/manager_config_patch.yaml rename to config/operator/manager_config_patch.yaml diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index c4fa5225..e08cf657 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -6,6 +6,17 @@ metadata: creationTimestamp: null name: manager-role rules: +- apiGroups: + - "" + - discovery.k8s.io + resources: + - endpoints + - endpointslices + - services + verbs: + - get + - list + - watch - apiGroups: - admissionregistration.k8s.io resources: @@ -84,17 +95,6 @@ rules: - patch - update - watch -- apiGroups: - - discovery.k8s.io - - "" - resources: - - services - - endpoints - - endpointslices - verbs: - - get - - list - - watch - apiGroups: - operator.containers.carbonblack.io resources: diff --git a/config/samples/_v1_cbcontainerscluster.yaml b/config/samples/_v1_cbcontainerscluster.yaml index 2597369a..d4b5e08e 100644 --- a/config/samples/_v1_cbcontainerscluster.yaml +++ b/config/samples/_v1_cbcontainerscluster.yaml @@ -1,7 +1,12 @@ apiVersion: operator.containers.carbonblack.io/v1 kind: CBContainersCluster metadata: - name: cbcontainerscluster-sample + name: cbcontainers-cluster spec: - # Add fields here - foo: bar + account: + clusterName: test:cluster + apiGatewaySpec: + host: + adapter: + eventsGatewaySpec: + host: \ No newline at end of file diff --git a/config/samples/_v1_cbcontainershardening.yaml b/config/samples/_v1_cbcontainershardening.yaml index 737590f9..97fe9332 100644 --- a/config/samples/_v1_cbcontainershardening.yaml +++ b/config/samples/_v1_cbcontainershardening.yaml @@ -1,7 +1,8 @@ apiVersion: operator.containers.carbonblack.io/v1 kind: CBContainersHardening metadata: - name: cbcontainershardening-sample + name: cbcontainers-hardening spec: - # Add fields here - foo: bar + version: + eventsGatewaySpec: + host: diff --git a/controllers/cbcontainershardening_controller.go b/controllers/cbcontainershardening_controller.go index 4f98d947..25d5dbc8 100644 --- a/controllers/cbcontainershardening_controller.go +++ b/controllers/cbcontainershardening_controller.go @@ -22,7 +22,7 @@ import ( cbcontainersv1 "github.com/vmware/cbcontainers-operator/api/v1" applymentOptions "github.com/vmware/cbcontainers-operator/cbcontainers/state/applyment/options" - admissionsV1 "k8s.io/api/admissionregistration/v1beta1" + "github.com/vmware/cbcontainers-operator/cbcontainers/state/hardening/adapters" appsV1 "k8s.io/api/apps/v1" coreV1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -42,6 +42,7 @@ type CBContainersHardeningReconciler struct { Log logr.Logger Scheme *runtime.Scheme HardeningStateApplier HardeningStateApplier + K8sVersion string } func (r *CBContainersHardeningReconciler) getContainersHardeningObject(ctx context.Context) (*cbcontainersv1.CBContainersHardening, error) { @@ -175,11 +176,12 @@ func (r *CBContainersHardeningReconciler) setDefaults(cbContainersHardening *cbc // SetupWithManager sets up the controller with the Manager. func (r *CBContainersHardeningReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). For(&cbcontainersv1.CBContainersHardening{}). Owns(&coreV1.Secret{}). Owns(&appsV1.Deployment{}). Owns(&coreV1.Service{}). - Owns(&admissionsV1.ValidatingWebhookConfiguration{}). + Owns(adapters.EmptyValidatingWebhookConfigForVersion(r.K8sVersion)). Complete(r) } diff --git a/controllers/cbcontainersruntime_controller.go b/controllers/cbcontainersruntime_controller.go index 4ad70c66..4a56f5b6 100644 --- a/controllers/cbcontainersruntime_controller.go +++ b/controllers/cbcontainersruntime_controller.go @@ -65,6 +65,7 @@ func (r *CBContainersRuntimeReconciler) getContainersRuntimeObject(ctx context.C // +kubebuilder:rbac:groups=operator.containers.carbonblack.io,resources=cbcontainersruntimes/status,verbs=get;update;patch // +kubebuilder:rbac:groups=operator.containers.carbonblack.io,resources=cbcontainersruntimes/finalizers,verbs=update // +kubebuilder:rbac:groups={apps,core},resources={deployments,services,daemonsets},verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups={discovery.k8s.io,""},resources={services,endpoints,endpointslices},verbs=get;list;watch func (r *CBContainersRuntimeReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { r.Log.Info("\n\n") diff --git a/docs/developers.md b/docs/developers.md index 340f2400..0f8b2763 100644 --- a/docs/developers.md +++ b/docs/developers.md @@ -38,3 +38,58 @@ The default value is `containers` Under `cbcontainers/state/hardening/objects` for `enforcer_deployment.go` or `state_reporter_deployment.go` You can change the values on the top of the file to suite your needs. + +### Using defaults +One of the new features in `apiextensions/v1` version of CustomResourceDefinitions is defaults in the OpenAPISchema. These are supported by kubebuilder via tags - e.g. `kubebuilder:default=something` +For backwards compatibility reasons, all defaults should also be implemented and set in the controllers to ensure they work on clusters v1.15 and below. + +One issue with defaults is that kubebuilder does not support empty object as default value - see +[related issue](https://github.com/kubernetes-sigs/controller-tools/issues/550). The issue is about maps but the same code causes problems with objects. + +What this means is that the following spec will _not_ apply the default for foo unless the user specifies bar. + +```yaml +spec: + properties: + bar: + properties: + foo: + default: 10 + type: integer +``` +So applying this YAML will lead to empty object for `bar` being saved: +```yaml +spec: {} +``` + +Instead, applying +```yaml +spec: { bar: {} } +``` +would work as expected and save the following object: +```yaml +spec: { bar: { foo: 10 }} +``` + +This would work as expected when adding an empty object default to the example as below: +```yaml +spec: + properties: + bar: + default: {} + properties: + foo: + default: 10 + type: integer +``` +Unfortunately kubebuilder cannot produce that output today. +Therefore, a special `make` target works around this by replacing all instance of `<>` with `{}` so using `kubebuilder:default=<>` will produce the correct output. + +Defaulting is not supported by `v1beta1` versions of CRDs so warnings are expected when generating those since kubebuilder. + +## Debugging locally + +To debug locally, run `make run-delve` which will build and start a delve debugger in headless mode. +Then use your editor to start a remote session and connect to the delve instance. + +For goland, the built-in `go remote` configuration works fine. \ No newline at end of file diff --git a/main.go b/main.go index f7ded393..2a1585cd 100644 --- a/main.go +++ b/main.go @@ -22,8 +22,6 @@ import ( "fmt" "os" - "github.com/vmware/cbcontainers-operator/cbcontainers/monitor" - commonState "github.com/vmware/cbcontainers-operator/cbcontainers/state/common" coreV1 "k8s.io/api/core/v1" clusterProcessors "github.com/vmware/cbcontainers-operator/cbcontainers/processors/cluster" @@ -100,18 +98,12 @@ func main() { k8sVersion := nodesList.Items[0].Status.NodeInfo.KubeletVersion setupLog.Info(fmt.Sprintf("K8s version is: %v", k8sVersion)) - defaultMonitorCreator, err := clusterProcessors.NewDefaultMonitorCreator(monitor.NewDefaultHealthChecker(mgr.GetClient(), commonState.DataPlaneNamespaceName), monitor.NewDefaultFeaturesStatusProvider(mgr.GetClient()), ctrl.Log.WithName("monitor")) - if err != nil { - setupLog.Error(err, "unable to create default monitor creator") - os.Exit(1) - } - cbContainersClusterLogger := ctrl.Log.WithName("controllers").WithName("CBContainersCluster") if err = (&controllers.CBContainersClusterReconciler{ Client: mgr.GetClient(), Log: cbContainersClusterLogger, Scheme: mgr.GetScheme(), - ClusterProcessor: clusterProcessors.NewCBContainerClusterProcessor(cbContainersClusterLogger, clusterProcessors.NewDefaultGatewayCreator(), defaultMonitorCreator), + ClusterProcessor: clusterProcessors.NewCBContainerClusterProcessor(cbContainersClusterLogger, clusterProcessors.NewDefaultGatewayCreator()), ClusterStateApplier: clusterState.NewClusterStateApplier(cbContainersClusterLogger, k8sVersion, clusterState.NewDefaultClusterChildK8sObjectApplier()), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "CBContainersCluster") @@ -123,6 +115,7 @@ func main() { Client: mgr.GetClient(), Log: cbContainersHardeningLogger, Scheme: mgr.GetScheme(), + K8sVersion: k8sVersion, HardeningStateApplier: hardeningState.NewHardeningStateApplier(cbContainersHardeningLogger, k8sVersion, certificatesUtils.NewCertificateCreator(), hardeningState.NewDefaultHardeningChildK8sObjectApplier()), }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "CBContainersHardening")