github.com/operator-framework/operator-lifecycle-manager@v0.30.0/doc/contributors/design-proposals/operator-validation-library.md (about) 1 # Operator Validation Library 2 3 ### Problem Statement 4 5 This project aims to create a validation library within OLM for operators managed by OLM. Such operators are manageable by creating a manifest bundle composed of [ClusterServiceVersions](https://github.com/operator-framework/operator-lifecycle-manager/blob/master/doc/design/building-your-csv.md), [CustomResourceDefinitions](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/), and [Package Manifest](https://github.com/operator-framework/operator-lifecycle-manager#discovery-catalogs-and-automated-upgrades) yamls. The steps to creating these files are error-prone and validation of this bundle happens in scattered places that are not always up to date with the latest changes to the manifest's definition. 6 7 For example, operator-sdk's [csv-gen](https://github.com/operator-framework/operator-sdk/blob/master/doc/user/olm-catalog/generating-a-csv.md) tool uses static verification logic based on OLM's CSV type to validate the generated file. There is also [scorecard](https://github.com/operator-framework/operator-sdk/blob/master/doc/test-framework/scorecard.md) that uses runtime checks to validate the bundle. [operator-courier](https://github.com/operator-framework/operator-courier) uses static verification logic before pushing the bundles to an app-registry. Finally, the [operator-registry](https://github.com/operator-framework/operator-registry) and [olm-operator](https://github.com/operator-framework/operator-lifecycle-manager/tree/master/pkg/controller/operators/olm) both contain logic for static and runtime validation of CSVs. 8 9 Each of these validates only a piece of the bundle and most are not in sync with changes to the CSV type. This means operator owners use different tools to validate their bundle - each providing partial or inconsistent validation - which dampens the user experience. The operator framework needs to agree on a single source of truth for a valid OLM-managed operator. 10 11 Our plan is to bring the already defined validators scattered across various code bases (along with potentially new validators) into a single location/package with validation logic that adapts to changes made to OLM. 12 13 ### Stakeholders 14 15 Our main stakeholders of this library are: 16 17 - OLM/operator-registry: refactoring some code to call a single validation library may help with improving user experience. 18 - Operator-sdk: calling this library for the csv-gen tool instead of creating custom functions. 19 - Operator-courier (or similar tool): community-operators or upstream operator owners who are not using the sdk to build their operator need a validation tool. 20 - OSD SRE: validating bundles before pushing them down their deployment pipeline to minimize resource expenditure. 21 22 ### Development Strategy 23 24 As a preliminary step, this library is interested in static verification of operator bundles. Static verification is crucial to help improve the development process of operators. It is time efficient and can be used in a variety of contexts: from IDE linter extensions to CI pipelines with limited resources to command line utilities. All consistent by calling the same APIs from this library. 25 26 In the future, we aim to extend this library to contain runtime tests and apis to be called by runtime tools on cluster. 27 28 ### Requirements 29 30 - Methods of this library should adapt to any changes in OLM's type. There should be minimal to no changes required when there is a change in OLM's type and/or version. Or if this is not possible, methods of the library need to be part of the build/test pipeline of OLM. 31 - Better error reporting by informing the user of all errors found instead of exiting after the first occurrence. We should define custom error types easily digestible by users of these APIs. 32 - APIs should expose verification methods for individual yaml files as well as for the bundle as a whole. 33 - This library should expose a validator interface for users to define their own custom validators (ex: operatorhub.io specific validators) while obeying the same overarching structure. 34 35 ### Progress so far 36 37 [https://github.com/dweepgogia/new-manifest-verification](https://github.com/dweepgogia/new-manifest-verification) 38 39 We have started with the validation of Cluster Service Version yaml files. Currently, this library checks for the following against OLM's CSV type: 40 41 - Data type mismatch. 42 - Mandatory/optional field/struct/value missing (reports errors and warnings for mandatory and optional fields, respectively). Currently, this uses the json annotation `omitempty` to determine whether the field is optional. 43 44 There is also a Command Line Tool that serves as an example of how a user can interact with the library. Details on using the CLI tool can be found in the `README` of the repo above. 45 46 ### Outcomes 47 48 - A universally accepted definition of operator validation tests. 49 - Improved developer experience brought about through the reduction of the number of tools required to build, test, and distribute an operator. 50 - Stronger alignment across operator-framework teams. 51 52 ### Open Questions 53 54 - How do we deal with different versions of the CSV type? 55 56 Ideas: 57 - Include a version of the library alongside the CSV type definition so that it is versioned in the same way the CSV is versioned. 58 - To be compatible across different versions of OLM's types and changing requirements/fields within the same version, this library can use the version defined in csv yaml and enforces the field requirements accordingly for validating the manifest. 59 60 # Fake README 61 62 ## Installing 63 64 ### Command Line Tool 65 66 You can interact with this library with a command line tool. 67 68 You can install the `operator-verify` tool from source using: 69 70 ``` 71 $ go install 72 ``` 73 74 ```bash 75 $ echo $PATH 76 ``` 77 78 If you do not have your workspace's `bin` subdirectory in your `$PATH`, 79 80 ```bash 81 $ export PATH=$PATH:$(go env GOPATH)/bin 82 ``` 83 84 This adds your workspace's bin subdirectory to your PATH. As a result, you can use the `operator-verify` tool anywhere on your system. Otherwise, you would have to `cd` to your workspace's `bin` directory to run the executable. Verify that we can find `operator-verify` in our new `PATH`: 85 86 ```bash 87 $ which operator-verify 88 ``` 89 90 This should return something like: 91 92 ``` 93 ~/go/bin/operator-verify 94 ``` 95 96 To verify that the library installed correctly, use it to validate the ClusterServiceVersion yaml, 97 98 ``` 99 $ operator-verify csv /path/to/filename.yaml 100 ``` 101 102 ## Usage 103 104 The command line tool's `help` flag gives the following output: 105 106 ```text 107 operator-verify is a command line tool for the Operator Manifest Verification Library. This library provides functions to validate the operator manifest bundles against Operator-Lifecycle-Manager's clusterServiceVersion type, customResourceDefinitions, and package yamls. Currently, this application supports static validation of both individual operator files and the manifest bundle. 108 109 Usage: 110 operator-verify [flags] 111 operator-verify [command] 112 113 Available Commands: 114 help Help about any command 115 csv Validate CSV against OLM's type 116 crd Validate manifest CRDs 117 package Validate package yaml 118 manifest Validate operator manifest bundle 119 120 Flags: 121 -h, --help help for operator-verify 122 -i, --ignore ignore warnings in log 123 124 Use "operator-verify [command] --help" for more information about a command. 125 ``` 126 127 128 ### Commands 129 **For individual files**: 130 131 ``` 132 $ operator-verify csv /path/to/csv.yaml 133 ``` 134 135 Validates the given CSV yaml file against OLM type and reports errors and warnings as described in the `List of Errors` section below. 136 137 Similarly, 138 139 ``` 140 $ operator-verify crd /path/to/crd.yaml 141 ``` 142 143 and 144 145 ``` 146 $ operator-verify package /path/to/package.yaml 147 ``` 148 149 validates CRD and package yaml, respectively. The `crd` command can accept and validate both a single yaml file and a bunch of CRDs at once and report a separate log for each. 150 151 **For manifest bundle**: 152 153 ``` 154 $ operator-verify manifest /path/to/bundle 155 ``` 156 157 Here `path/to/bundle` is a directory structure as per the [operator manifest format](https://github.com/operator-framework/operator-registry#manifest-format). This command reports errors and/or warnings for each file in the bundle. 158 159 Using the `help` flag with `manifest` command we get, 160 161 ```text 162 Validates the manifest bundle as a whole, in addition to validating individual operator files. `manifest` reports errors/warnings for each file in the bundle. It works both with a directory structure (as per operator manifest format) and an operator image. `manifest` can also validate only the CSVs or CRDs present in a bundle. See flags for more information. 163 164 Usage: 165 operator-verify verify [flags] 166 167 Flags: 168 -h, --help help for verify 169 -r, --remote remote manifest (requires operator image) 170 --csv-only validate only bundle CSVs 171 --crd-only validate only bundle CRDs 172 ``` 173 174 ### Flags 175 176 To ignore warnings in the log, we have `-i` flag available, 177 178 ``` 179 $ operator-verify -i csv /path/to/csv.yaml 180 ``` 181 182 This flag works similarly for other commands available in `operator-verify` tool. To validate a remote manifest, we an use the operator image with `-r` flag, 183 184 ``` 185 $ operator-verify manifest -r <link to operator image> 186 ``` 187 188 For validating only the CSVs or CRDs in the manifest, we have `--csv-only` and `--crd-only` flags under the `manifest` command. 189 190 ``` 191 $ operator-verify manifest --csv-only or --crd-only /path/to/bundle 192 ``` 193 194 We can also use these flags on remote manifest by combining the respective flags. 195 196 ## Examples 197 198 ``` 199 $ operator-verify csv csv.yaml 200 ``` 201 202 Output of the `csv` command against a valid sample csv yaml with some missing optional fields/struct: 203 204 ``` 205 Warning: Optional Field Missing (ObjectMeta.GenerateName) 206 Warning: Optional Field Missing (ObjectMeta.SelfLink) 207 Warning: Optional Field Missing (ObjectMeta.UID) 208 Warning: Optional Field Missing (ObjectMeta.ResourceVersion) 209 Warning: Optional Field Missing (ObjectMeta.Generation) 210 Warning: Optional Struct Missing (ObjectMeta.CreationTimestamp) 211 Warning: Optional Field Missing (ObjectMeta.DeletionTimestamp) 212 Warning: Optional Field Missing (ObjectMeta.DeletionGracePeriodSeconds) 213 Warning: Optional Field Missing (ObjectMeta.Labels) 214 Warning: Optional Field Missing (ObjectMeta.OwnerReferences) 215 Warning: Optional Field Missing (ObjectMeta.Initializers) 216 Warning: Optional Field Missing (ObjectMeta.Finalizers) 217 Warning: Optional Field Missing (ObjectMeta.ClusterName) 218 Warning: Optional Field Missing (Spec.CustomResourceDefinitions.Required) 219 Warning: Optional Struct Missing (Spec.APIServiceDefinitions) 220 Warning: Optional Field Missing (Spec.NativeAPIs) 221 Warning: Optional Field Missing (Spec.MinKubeVersion) 222 Warning: Optional Field Missing (Spec.Provider.URL) 223 Warning: Optional Field Missing (Spec.Replaces) 224 Warning: Optional Field Missing (Spec.Annotations) 225 csv.yaml is verified. 226 ``` 227 228 Omitting `Spec.InstallStrategy.StrategyName`, one of the mandatory fields, yields 229 230 ``` 231 Error: Mandatory Field Missing (Spec.InstallStrategy.StrategyName) 232 Populate all the mandatory fields missing from csv.yaml file. 233 ``` 234 235 in addition to the warnings shown above. 236 237 To ignore the warnings, we have `-i` flag available. 238 239 ``` 240 $ operator-verify -i csv csv.yaml 241 ``` 242 243 `crd` and `package` commands work in a similar way as the `csv`. The `manifest` command returns a log similar to the one shown above for `csv` for each file in the manifest bundle. For validating just the CSVs or CRDs in the manifest, we can use the flags mentioned above. 244 245 ```text 246 Note: We can have various other APIs for validating only the CSVs or CRDs. For instance, 247 248 - `csv`/`crd` command accepts both an individual file or a directory containing a group of respective files. 249 250 Usage: $operator-verify crd /path/to/directory 251 252 - Using a flag for indicating a directory structure. 253 254 Usage: $operator-verify crd -d /path/to/directory 255 ``` 256 257 # Library 258 259 ## Getting Started 260 261 The Operator Manifest Verfication library provides APIs for validating both individual yaml files and the manifest bundle as a whole. For **individual yaml files**, it checks for: 262 263 * Data type mismatch 264 * Missing mandatory and optional fields 265 * Incompatible configurations 266 * Logical errors (e.g. business logic) 267 268 against OLM's type. 269 270 For **manifest bundle**, in addition to verifying the individual operator files, this library checks for: 271 272 * CRDs mentioned in the CSV 273 * Incompatible CSV configurations when upgrading to a newer version of CSV 274 275 It accepts both nested and flattened directory structures containing manifest yamls. The directory structure is expected to adhere to [manifest format](https://github.com/operator-framework/operator-registry#manifest-format). See `usage` for more information. 276 277 ### List of Errors 278 279 * Unmarshalling errors like 280 * Data type mismatch 281 * Incorrect indentation 282 * Inconsistent yaml file structure that can't be converted to JSON for unmarshalling 283 * Warning for any missing optional field 284 * Error for any missing mandatory field 285 * Error for missing CRDs which are mentioned in the CSV 286 287 Errors and warnings returned by the API are of type `missingTypeError` and can be used to extract more information. `missingTypeError` is struct type and its implementation in the library is as follows, 288 289 ```go 290 type missingTypeError struct { 291 err string 292 typeName string 293 path string 294 isMandatory bool 295 } 296 ``` 297 298 For each error/warning, we can check if it's a field or a struct (`typeName`), path of that field in the nested yaml file (`path`), and if the field is mandatory or not (`isMandatory`).