-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #534 from kubeshop/razvantopliceanu/feat/test-crd
feat: crd x-kubernetes-validation
- Loading branch information
Showing
9 changed files
with
306 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@monokle/validation": patch | ||
--- | ||
|
||
Added crds x-kubernetes-validation validate of custom resources |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
packages/validation/src/__tests__/resources/admissionPolicy/CRDValidatorResources.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import {Resource} from '../../../common/types.js'; | ||
|
||
export const CRD: Resource = { | ||
fileId: 'd4fc87d28c6bd', | ||
filePath: 'crd.yaml', | ||
fileOffset: 0, | ||
text: 'apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n name: mycustomresources.example.com\nspec:\n group: example.com\n names:\n kind: MyCustomResource\n plural: mycustomresources\n singular: mycustomresource\n shortNames:\n - mcr\n scope: Namespaced\n versions:\n - name: v1\n schema:\n openAPIV3Schema:\n type: object\n properties:\n spec:\n type: object\n x-kubernetes-validation:\n - rule: "self.replicas <= self.maxReplicas"\n message: "replicas must be less than or equal to maxReplicas"\n properties:\n replicas:\n type: integer\n maxReplicas:\n type: integer\n required:\n - replicas\n - maxReplicas\n', | ||
apiVersion: 'apiextensions.k8s.io/v1', | ||
kind: 'CustomResourceDefinition', | ||
content: { | ||
apiVersion: 'apiextensions.k8s.io/v1', | ||
kind: 'CustomResourceDefinition', | ||
metadata: { | ||
name: 'mycustomresources.example.com', | ||
}, | ||
spec: { | ||
group: 'example.com', | ||
names: { | ||
kind: 'MyCustomResource', | ||
plural: 'mycustomresources', | ||
singular: 'mycustomresource', | ||
shortNames: ['mcr'], | ||
}, | ||
scope: 'Namespaced', | ||
versions: [ | ||
{ | ||
name: 'v1', | ||
schema: { | ||
openAPIV3Schema: { | ||
type: 'object', | ||
properties: { | ||
spec: { | ||
type: 'object', | ||
'x-kubernetes-validation': [ | ||
{ | ||
rule: 'self.replicas <= self.maxReplicas', | ||
message: 'replicas must be less than or equal to maxReplicas', | ||
}, | ||
], | ||
properties: { | ||
replicas: { | ||
type: 'integer', | ||
}, | ||
maxReplicas: { | ||
type: 'integer', | ||
}, | ||
}, | ||
required: ['replicas', 'maxReplicas'], | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
id: 'd4fc87d28c6bd-0', | ||
name: 'mycustomresources.example.com', | ||
}; | ||
|
||
export const CRD_2: Resource = { | ||
fileId: 'd4fc87d28c6bd', | ||
filePath: 'crd.yaml', | ||
fileOffset: 0, | ||
text: 'apiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n name: mycustomresources.example.com\nspec:\n group: example.com\n names:\n kind: MyCustomResource\n plural: mycustomresources\n singular: mycustomresource\n shortNames:\n - mcr\n scope: Namespaced\n versions:\n - name: v1\n schema:\n openAPIV3Schema:\n type: object\n properties:\n spec:\n type: object\n x-kubernetes-validation:\n - rule: "self.replicas <= self.maxReplicas"\n message: "replicas must be less than or equal to maxReplicas"\n properties:\n replicas:\n type: integer\n maxReplicas:\n type: integer\n required:\n - replicas\n - maxReplicas\n', | ||
apiVersion: 'apiextensions.k8s.io/v1', | ||
kind: 'CustomResourceDefinition', | ||
content: { | ||
apiVersion: 'apiextensions.k8s.io/v1', | ||
kind: 'CustomResourceDefinition', | ||
metadata: { | ||
name: 'mycustomresources.example.com', | ||
}, | ||
spec: { | ||
group: 'example.com', | ||
names: { | ||
kind: 'MyCustomResource', | ||
plural: 'mycustomresources', | ||
singular: 'mycustomresource', | ||
shortNames: ['mcr'], | ||
}, | ||
scope: 'Namespaced', | ||
versions: [ | ||
{ | ||
name: 'v1', | ||
schema: { | ||
openAPIV3Schema: { | ||
type: 'object', | ||
'x-kubernetes-validation': [ | ||
{ | ||
rule: 'self.spec.replicas <= self.status.maxReplicas', | ||
message: 'replicas must be less than or equal to maxReplicas', | ||
}, | ||
], | ||
properties: { | ||
spec: { | ||
type: 'object', | ||
properties: { | ||
replicas: { | ||
type: 'integer', | ||
}, | ||
}, | ||
required: ['replicas'], | ||
}, | ||
status: { | ||
type: 'object', | ||
properties: { | ||
maxReplicas: { | ||
type: 'integer', | ||
}, | ||
}, | ||
required: ['maxReplicas'], | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
id: 'd4fc87d28c6bd-0', | ||
name: 'mycustomresources.example.com', | ||
}; | ||
|
||
export const CUSTOM_RESOURCE: Resource = { | ||
fileId: '13cf92c8d3181f', | ||
filePath: 'custom-resource.yaml', | ||
fileOffset: 0, | ||
text: 'apiVersion: example.com/v1\nkind: MyCustomResource\nmetadata:\n name: my-new-cron-object\nspec:\n replicas: 20\n maxReplicas: 10\n', | ||
apiVersion: 'example.com/v1', | ||
kind: 'MyCustomResource', | ||
content: { | ||
apiVersion: 'example.com/v1', | ||
kind: 'MyCustomResource', | ||
metadata: { | ||
name: 'my-new-cron-object', | ||
}, | ||
spec: { | ||
replicas: 20, | ||
maxReplicas: 10, | ||
}, | ||
}, | ||
id: '13cf92c8d3181f-0', | ||
name: 'my-new-cron-object', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
42 changes: 42 additions & 0 deletions
42
packages/validation/src/validators/admission-policy/utils.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import {CustomSchema, Resource} from '../../common/types.js'; | ||
import {Expression} from './types.js'; | ||
|
||
export function getCRDExpressions(schema: CustomSchema, crd: Resource): Record<string, Expression[]> { | ||
const expressions: Record<string, Expression[]> = {}; | ||
|
||
const versions = crd.content?.spec?.versions; | ||
|
||
if (!versions?.length) return expressions; | ||
|
||
const [, apiName] = schema.apiVersion.split('/'); | ||
|
||
const version = versions.find((v: any) => v.name === apiName); | ||
|
||
if (!version) return expressions; | ||
|
||
const rootRules = version.schema?.openAPIV3Schema?.['x-kubernetes-validation']; | ||
|
||
if (rootRules?.length) { | ||
expressions['<root>'] = []; | ||
|
||
for (const rule of rootRules) { | ||
expressions['<root>'].push({expression: rule.rule, message: rule.message ?? ''}); | ||
} | ||
} | ||
|
||
const properties = version.schema?.openAPIV3Schema?.properties as Record<string, any>; | ||
|
||
if (!properties) return expressions; | ||
|
||
for (const [key, values] of Object.entries(properties)) { | ||
if (values['x-kubernetes-validation']?.length) { | ||
expressions[key] = []; | ||
|
||
for (const rule of values['x-kubernetes-validation']) { | ||
expressions[key].push({expression: rule.rule, message: rule.message ?? ''}); | ||
} | ||
} | ||
} | ||
|
||
return expressions; | ||
} |
Oops, something went wrong.