package
0.0.0-20240905184220-0a5f9d4d9d01
Repository: https://github.com/datadog/chaos-controller.git
Documentation: pkg.go.dev

# README

DDMARK

What is it ?

DDMark is a validation module embedded in the chaos-controller, used to apply validation rules to the Kubernetes Custom Resource Definition of the chaos-controller, Disruptions. It allows for defining rules that put constraints on fields, which will be applied when they're unmarshalled from a file, or read.

Why does it exist ?

DDMark emerged as an idea when using kubebuilder, which uses markers to put constraints on CRD (Custom Resource Definition) fields. Those constraints could later only be applied when parsed by the kubernetes api, which isn't very practical for other uses. It was decided to use the same markers in a customized way to be more flexible and usable.

DDMarkers can be validated through code, which allows us to validate through a CLI and any valid go runner - no need for kubernetes anymore. It also allows us to define custom rules to apply to our structures, and focus the code validation within the chaos-controller to environment-specific validation (does this service exist in this cluster ? Is my cluster in a supported version ?) and not structural config validation (is this field under 100 like we need it to be ?), which would end up being very annoying, cluttered and messy code.

How to use DDMark ?

  1. Setup ddmark fields in your library:
  • Define new rules/read the existing rules within the ddmark/validation/validation.go file (or in this doc)
  • Examples can be found in the ddmark/teststruct.go file
  • Add the desired rules to the appropriate struct fields in the package you wish to add validation to (care for type checking - e.g. Maximum rule can only be applied to int/uint fields). Correct format is // +ddmark:validation:<rulename>=<value>
  • The analyzed library has to contain a self-packaging exported Embed.FS field. This field will then be used by ddmark to import the versioned files into any executable.
  1. Call the validation function from your code:
  • Requirement: code needs to run on a go 1.18+ environment
  • DDMark works through a client interface (which is linked to internal disk resources). Each client instance created with ddmark.NewClient(<embed.FS>) works independently and can be used concurrently. Use client.CleanupLibraries() to remove all files related to a specific client, or ddmark.CleanupAllLibraries() to clean up all the clients' files.
  • Call the ValidateStruct() function with the unmarshalled struct, and the current file/location for debugging purposes (this is a validation tool !). Check cli/chaosli/cmd/validate.go for a functioning example.

Markers Documentation

Field Markers (within structs)

  • Enum:
    • // +ddmark:validation:Enum={<any>,<any>,...}
    • Applies to: <any> field
    • Asserts field value is one of the given values of the Enum list
  • Maximum:
    • // +ddmark:validation:Maximum=<int/uint>
    • Applies to: int/uint field
    • Asserts a value is equal or inferior to a given int
  • Minimum:
    • // +ddmark:validation:Minimum=<int/uint>
    • Applies to: int/uint field
    • Asserts a value is equal or superior to the given int
  • Required:
    • // +ddmark:validation:Required=<bool>
    • Applies to: <any> field
    • Asserts the concerned field isn’t nil (or 0, “”, or other null value)

Type Markers (outside structs)

  • ExclusiveFields:
    • // +ddmark:validation:ExclusiveFields={<fieldName1>,<fieldName2>,...}
    • Applies to: any <struct> type
    • Asserts that <fieldname1> can only be non-nil iff all of the other fields are nil
  • LinkedFieldsValue:
    • without values:
      • // +ddmark:validation:LinkedFieldsValue={<fieldName1>,<fieldName2>,...}
      • Applies to: any <struct> type
      • Asserts the fields in the list are either all nil or all non-nil
    • with values:
      • // +ddmark:validation:LinkedFieldsValue={<fieldName1>=<value>,<fieldName2>,...}
      • Applies to: any <struct> type -- value checks are only for string and int subfields
      • Asserts the fields in the list are either all nil (or are specifically set to the indicated value) or all non-nil (or are specifically not set to the given value)
      • Fields with values and without values can be mixed
  • LinkedFieldsValueWithTrigger
    • without values:
      • // +ddmark:validation:LinkedFieldsValueWithTrigger={<fieldName1>, <fieldName2>,...}
      • Applies to: any <struct> type
      • Asserts the following: if the first field is non-nil, all the following fields have to also be non-nil
    • with values:
      • // +ddmark:validation:LinkedFieldsValueWithTrigger={<fieldName1>=<value>, <fieldName2>,...}
      • Applies to: any <struct> type -- value checks are only for string and int subfields
      • Asserts the following: if the first field is non-nil OR is set to the given <value>, all the following fields have to also be non-nil OR set to their given <value>.
      • Fields with values and without values can be mixed
  • AtLeastOneOf:
    • // +ddmark:validation:AtLeastOneOf={<fieldName1>,<fieldName2>,...}
    • Applies to: any <struct> type
    • Asserts at least one of the fields in the list is non-nil.
      • Note: if all the sub-fields of the <struct> can be/are nil, the parent field will be nil and this marker will be ignored. In this case, please consider using the Required marker on the parent field.

# Functions

CleanupAllLibraries deletes the common ddmark lib folder ($GOPATH/src/ddmarktemp/*) Will remove the disk dependencies for all ddmark clients.
GetErrorList returns a list of errors as a string.
NewClient create an new instance of DDMark.
NewClientMock creates a new instance of ClientMock.
NewDDValidationMarkerMock creates a new instance of DDValidationMarkerMock.
No description provided by the author

# Variables

AllDefinitions contains all marker definitions for this package.
EmbeddedDDMarkAPI includes the teststruct so it can be statically exported for ddmark testing go:embed validation_teststruct.go.

# Structs

+ddmark:validation:AtLeastOneOf={StrField,IntField} +ddmark:validation:AtLeastOneOf={PStrField,PIntField,AIntField}.
ClientMock is an autogenerated mock type for the Client type.
ClientMock_CleanupLibraries_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CleanupLibraries'.
No description provided by the author
ClientMock_ValidateStruct_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValidateStruct'.
ClientMock_ValidateStructMultierror_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValidateStructMultierror'.
DDValidationMarkerMock is an autogenerated mock type for the DDValidationMarker type.
DDValidationMarkerMock_ApplyRule_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyRule'.
No description provided by the author
DDValidationMarkerMock_TypeCheckError_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TypeCheckError'.
DDValidationMarkerMock_ValueCheckError_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValueCheckError'.
No description provided by the author
+ddmark:validation:ExclusiveFields={PIntField,PStrField} +ddmark:validation:ExclusiveFields={PIntField,BField,CField} +ddmark:validation:ExclusiveFields={IntField,StrField}.
+ddmark:validation:LinkedFieldsValue={StrField=aaa,IntField} +ddmark:validation:LinkedFieldsValue={PStrField,PIntField,AIntField}.
+ddmark:validation:LinkedFieldsValueWithTrigger={StrField=aaa,IntField=2} +ddmark:validation:LinkedFieldsValueWithTrigger={PStrField=bbb,PIntField=12,AIntField}.
No description provided by the author
No description provided by the author
No description provided by the author

# Interfaces

Client interface to manage validation of struct fields Client is the expected way to use DDMark.
DDValidationMarker is the interface for Validation Markers, which apply rules to a given structure's field.

# Type aliases

AtLeastOneOf can be applied to structs, and asserts at least one of the following fields is non-'nil'.
Enum can be applied to any interface field and provides a restricted amount of possible values for that field.
ExclusiveFields can be applied to structs, and asserts that the first field can only be non-'nil' iff all of the other fields are 'nil'.
LinkedFieldsValue can be applied to structs, and asserts the fields in the list are either all 'nil' or all non-'nil'.
LinkedFieldsValueWithTrigger can be applied to structs, and asserts the following: - if first field exists (or has the indicated value), all the following fields need to exist (or have the indicated value) - fields in question can be int or strings.
Maximum can applied to an int field and provides a (non-strict) maximum value for that field.
Minimum can applied to an int field and provides a (non-strict) minimum value for that field.
Required can be applied to any field, and asserts this field will return an error if not provided.