Skip to content

Commit

Permalink
add defaulting to nats-cr in nats-manger (#61)
Browse files Browse the repository at this point in the history
* unify consts

* change enable to enabled

* add defaulting for cluster.size

* add marshaled nats to error message for failed text

* simplify test

* reformat test

* add nats matchers

* adjust samples

* adjust samples

* adding defaults and matchers

* add matchers and tests

* create a matcher

* add logs for debug

* add log for resources

* stringify logs

* move log to the actual

* refine debug messages

* stringify in debugs

* return nil

* Add default spec as test utils

* Make FileStorageSize a pointer

this will break overrride tests that need to be fixed later.

* Revert "Make FileStorageSize a pointer"

This reverts commit f040777.

* Test against unstructured

* fixed test

* test against mem storage defaulting

* test against resource

* clean up the code.

* add doc

* refine doc

* go mod tidy

* Update api/v1alpha1/nats_types.go

Co-authored-by: Muhammad Faizan <mfaizanse@users.noreply.github.com>

* Improve docs with proper english

* remove redundant +optional decorators

* fix typos

* add more tests

* bump the manifests

* add test case

* fix typo

---------

Co-authored-by: Muhammad Faizan <m.faizan@sap.com>
Co-authored-by: Muhammad Faizan <mfaizanse@users.noreply.github.com>
  • Loading branch information
3 people authored Jun 15, 2023
1 parent 4f32347 commit 26450f4
Show file tree
Hide file tree
Showing 20 changed files with 455 additions and 100 deletions.
73 changes: 49 additions & 24 deletions api/v1alpha1/nats_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

// +kubebuilder:validation:Optional // This sets 'required' as the default behaviour.
//
//nolint:lll //this is annotation
package v1alpha1

import (
Expand All @@ -38,28 +41,45 @@ const (
ConditionReasonProcessing ConditionReason = "Processing"
ConditionReasonDeploying ConditionReason = "Deploying"
ConditionReasonDeployed ConditionReason = "Deployed"
ConditionReasonProcessingError = ConditionReason("FailedProcessing")
ConditionReasonForbidden = ConditionReason("Forbidden")
ConditionReasonProcessingError ConditionReason = "FailedProcessing"
ConditionReasonForbidden ConditionReason = "Forbidden"
ConditionReasonStatefulSetAvailable ConditionReason = "Available"
ConditionReasonStatefulSetPending ConditionReason = "Pending"
ConditionReasonSyncFailError ConditionReason = "FailedToSyncResources"
ConditionReasonManifestError ConditionReason = "InvalidManifests"
ConditionReasonDeletionError ConditionReason = "DeletionError"
)

// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
/*
NATS uses kubebuilder decorators for validation and defaulting instead of webhooks. You can find an overview to this
topic at https://book.kubebuilder.io/reference/markers/crd-validation.html.
//nolint:lll //this is annotation
Default values are defined at multiple levels to ensure that values are set independently of what level of NATS is
defined or gets deleted. For example, spec.cluster.size will get set to a default value whether spec.cluster.size,
spec.cluster or spec gets deleted.
Validation uses the Common Expression Language (CEL, https://github.com/google/cel-spec). You can find an introduction
to this topic at https://kubernetes.io/docs/reference/using-api/cel/.
Testing of validation and defaulting is done via envtest in
nats-manager/internal/controller/nats/integrationtests/validation/integration_test.go.
For testing of defaulting, it is recommended to send an Unstructured object
(https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured#Unstructured) to the API-Server. If
non-nil-able properties like ResourceRequirements (https://pkg.go.dev/k8s.io/api/core/v1#ResourceRequirements) are
undefined they will be interpreted as "" and result in 0 instead of being replaced by the default value.
*/

// NATS is the Schema for the NATS API.
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="State",type="string",JSONPath=".status.state",description="State of NATS deployment"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Age of the resource"

// NATS is the Schema for the nats API.
type NATS struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

// +kubebuilder:default:={jetStream:{fileStorage:{storageClassName:"default", size:"1Gi"},memStorage:{size:"20Mi",enabled:false}}, cluster:{size:3},logging:{trace:false,debug:false}, resources:{limits:{cpu:"20m",memory:"64Mi"}, requests:{cpu:"5m",memory:"16Mi"}}}
Spec NATSSpec `json:"spec,omitempty"`
Status NATSStatus `json:"status,omitempty"`
}
Expand All @@ -73,74 +93,79 @@ type NATSStatus struct {
// NATSSpec defines the desired state of NATS.
type NATSSpec struct {
// Cluster defines configurations that are specific to NATS clusters.
Cluster `json:"cluster"`
// +kubebuilder:default:={size:3}
Cluster `json:"cluster,omitempty"`

// JetStream defines configurations that are specific to NATS JetStream.
// +optional
// +kubebuilder:default:={fileStorage:{storageClassName:"default", size:"1Gi"},memStorage:{size:"20Mi",enabled:false}}
JetStream `json:"jetStream,omitempty"`

// JetStream defines configurations that are specific to NATS logging in NATS.
// +optional
// +kubebuilder:default:={trace:false,debug:false}
Logging `json:"logging,omitempty"`

// Resources defines resources for NATS.
// +optional
// +kubebuilder:default:={limits:{cpu:"20m",memory:"64Mi"}, requests:{cpu:"5m",memory:"16Mi"}}
Resources corev1.ResourceRequirements `json:"resources,omitempty"`

// Annotations allows to add annotations to NATS.
// +optional
Annotations map[string]string `json:"annotations,omitempty"`

// Labels allows to add Labels to NATS.
// +optional
Labels map[string]string `json:"labels,omitempty"`
}

// Cluster defines configurations that are specific to NATS clusters.
type Cluster struct {
// Size of a NATS cluster, i.e. number of NATS nodes.
// +optional
// +kubebuilder:default:=3
// +kubebuilder:validation:Minimum:=1
// +kubebuilder:validation:XValidation:rule="self%2!=0", message="size only accepts odd numbers"
Size int `json:"size"`
// +kubebuilder:validation:XValidation:rule="(self%2) != 0", message="size only accepts odd numbers"
Size int `json:"size,omitempty"`
}

// JetStream defines configurations that are specific to NATS JetStream.
type JetStream struct {
// MemStorage defines configurations to memory storage in NATS JetStream.
// +optional
// +kubebuilder:default:={size:"20Mi",enabled:false}
MemStorage `json:"memStorage,omitempty"`

// FileStorage defines configurations to file storage in NATS JetStream.
// +optional
// +kubebuilder:default:={storageClassName:"default",size:"1Gi"}
FileStorage `json:"fileStorage,omitempty"`
}

// MemStorage defines configurations to memory storage in NATS JetStream.
type MemStorage struct {
// Enable allows the enablement of memory storage.
Enable bool `json:"enable"`
// Enabled allows the enablement of memory storage.
// +kubebuilder:default:=false
Enabled bool `json:"enabled,omitempty"`

// Size defines the mem.
Size resource.Quantity `json:"size"`
// +kubebuilder:default:="20Mi"
Size resource.Quantity `json:"size,omitempty"`
}

// FileStorage defines configurations to file storage in NATS JetStream.
type FileStorage struct {
// StorageClassName defines the file storage class name.
StorageClassName string `json:"storageClassName"`
// +kubebuilder:default:="default"
StorageClassName string `json:"storageClassName,omitempty"`

// Size defines the file storage size.
Size resource.Quantity `json:"size"`
// +kubebuilder:default:="1Gi"
Size resource.Quantity `json:"size,omitempty"`
}

// Logging defines logging options.
type Logging struct {
// Debug allows debug logging.
Debug bool `json:"debug"`
// +kubebuilder:default:=false
Debug bool `json:"debug,omitempty"`

// Trace allows trace logging.
Trace bool `json:"trace"`
// +kubebuilder:default:=false
Trace bool `json:"trace,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ import (
"flag"
"os"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/kyma-project/nats-manager/pkg/env"
"github.com/kyma-project/nats-manager/pkg/k8s"
"github.com/kyma-project/nats-manager/pkg/k8s/chart"
"github.com/kyma-project/nats-manager/pkg/manager"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"

// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
Expand All @@ -40,9 +40,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/healthz"
k8szap "sigs.k8s.io/controller-runtime/pkg/log/zap"

apiclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"

natsv1alpha1 "github.com/kyma-project/nats-manager/api/v1alpha1"
natscontroller "github.com/kyma-project/nats-manager/internal/controller/nats"
apiclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
)

const defaultMetricsPort = 9443
Expand Down Expand Up @@ -161,7 +162,7 @@ func main() { //nolint:funlen // main function needs to initialize many object
setupLog.Error(err, "unable to create controller", "controller", "NATS")
os.Exit(1)
}
//+kubebuilder:scaffold:builder
// +kubebuilder:scaffold:builder

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
Expand Down
71 changes: 56 additions & 15 deletions config/crd/bases/operator.kyma-project.io_nats.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ spec:
name: v1alpha1
schema:
openAPIV3Schema:
description: NATS is the Schema for the nats API.
description: NATS is the Schema for the NATS API.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
Expand All @@ -42,6 +42,26 @@ spec:
metadata:
type: object
spec:
default:
cluster:
size: 3
jetStream:
fileStorage:
size: 1Gi
storageClassName: default
memStorage:
enabled: false
size: 20Mi
logging:
debug: false
trace: false
resources:
limits:
cpu: 20m
memory: 64Mi
requests:
cpu: 5m
memory: 16Mi
description: NATSSpec defines the desired state of NATS.
properties:
annotations:
Expand All @@ -50,57 +70,71 @@ spec:
description: Annotations allows to add annotations to NATS.
type: object
cluster:
default:
size: 3
description: Cluster defines configurations that are specific to NATS
clusters.
properties:
size:
default: 3
description: Size of a NATS cluster, i.e. number of NATS nodes.
minimum: 1
type: integer
x-kubernetes-validations:
- message: size only accepts odd numbers
rule: self%2!=0
rule: (self%2) != 0
type: object
jetStream:
default:
fileStorage:
size: 1Gi
storageClassName: default
memStorage:
enabled: false
size: 20Mi
description: JetStream defines configurations that are specific to
NATS JetStream.
properties:
fileStorage:
default:
size: 1Gi
storageClassName: default
description: FileStorage defines configurations to file storage
in NATS JetStream.
properties:
size:
anyOf:
- type: integer
- type: string
default: 1Gi
description: Size defines the file storage size.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
storageClassName:
default: default
description: StorageClassName defines the file storage class
name.
type: string
required:
- size
- storageClassName
type: object
memStorage:
default:
enabled: false
size: 20Mi
description: MemStorage defines configurations to memory storage
in NATS JetStream.
properties:
enable:
description: Enable allows the enablement of memory storage.
enabled:
default: false
description: Enabled allows the enablement of memory storage.
type: boolean
size:
anyOf:
- type: integer
- type: string
default: 20Mi
description: Size defines the mem.
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
required:
- enable
- size
type: object
type: object
labels:
Expand All @@ -109,20 +143,29 @@ spec:
description: Labels allows to add Labels to NATS.
type: object
logging:
default:
debug: false
trace: false
description: JetStream defines configurations that are specific to
NATS logging in NATS.
properties:
debug:
default: false
description: Debug allows debug logging.
type: boolean
trace:
default: false
description: Trace allows trace logging.
type: boolean
required:
- debug
- trace
type: object
resources:
default:
limits:
cpu: 20m
memory: 64Mi
requests:
cpu: 5m
memory: 16Mi
description: Resources defines resources for NATS.
properties:
claims:
Expand Down Expand Up @@ -170,8 +213,6 @@ spec:
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
type: object
type: object
required:
- cluster
type: object
status:
description: NATSStatus defines the observed state of NATS.
Expand Down
2 changes: 1 addition & 1 deletion config/samples/kyma-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ spec:
size: "1Gi"
storageClassName: "default"
memStorage:
enable: false
enabled: false
size: "20Mi"
logging:
debug: false
Expand Down
5 changes: 5 additions & 0 deletions config/samples/minimal.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apiVersion: operator.kyma-project.io/v1alpha1
kind: NATS
metadata:
name: eventing-nats
namespace: kyma-system
2 changes: 1 addition & 1 deletion config/samples/nats-full-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ spec:
size: "2Gi"
storageClassName: "gce-sc-hdd"
memStorage:
enable: true
enabled: true
size: "256Mi"
logging:
debug: true
Expand Down
Loading

0 comments on commit 26450f4

Please sign in to comment.