diff --git a/.changeset/pretty-donkeys-wash.md b/.changeset/pretty-donkeys-wash.md new file mode 100644 index 000000000..c3875416b --- /dev/null +++ b/.changeset/pretty-donkeys-wash.md @@ -0,0 +1,5 @@ +--- +"@monokle/validation": minor +--- + +Add ValidatingAdmissionPolicy references diff --git a/packages/validation/src/references/mappers/mappers.ts b/packages/validation/src/references/mappers/mappers.ts index d9ff96f8d..d44e605e0 100644 --- a/packages/validation/src/references/mappers/mappers.ts +++ b/packages/validation/src/references/mappers/mappers.ts @@ -12,6 +12,7 @@ import {endpointSliceMappers} from './endpointSlice.js'; import {Resource} from '../../common/types.js'; import {isDefined} from '../../utils/isDefined.js'; import {ownerReferenceMapper} from './ownerReference.js'; +import {validatingAdmissionPolicyBindingMappers} from './validatingAdmissionPolicyBinding'; export type SiblingMatcher = ( source: Resource, @@ -82,6 +83,7 @@ export const OUTGOING_MAPPERS_BY_KIND: Partial, + resourcesByKind: Record, + parser: ResourceParser +) { + const paramName = policyBinding.content?.spec?.paramRef?.name; + const {paramKind} = determineParamKind(policyBinding, resourceMap); + const paramNamespace = policyBinding.content?.spec?.paramRef?.namespace; + + if (!policyBinding.refs || !paramName || !paramKind) { + return; + } + + const relatedParams = resourcesByKind[paramKind].find(o => { + const matchingName = paramName === o.name; + const matchingNamespace = paramNamespace ? paramNamespace === o.namespace : true; + return matchingName && matchingNamespace; + }); + + if (!relatedParams) { + return; + } + + // Add reference to Binding object + policyBinding.refs.push({ + type: ResourceRefType.Outgoing, + name: paramName, + target: { + type: 'resource', + resourceId: relatedParams.id, + resourceKind: relatedParams.kind, + }, + position: getPosition(parser, policyBinding, ['spec', 'paramRef', 'name']), + }); + + // Add reference to Params object + if (!relatedParams.refs) { + relatedParams.refs = []; + } + + const hasRef = relatedParams.refs.some( + ref => + ref.type === ResourceRefType.Incoming && + ref.name === paramName && + ref.target && + ref.target.type === 'resource' && + ref.target.resourceId === policyBinding.id + ); + if (hasRef) { + return; + } + + relatedParams.refs.push({ + type: ResourceRefType.Incoming, + name: paramName, + target: { + type: 'resource', + resourceId: policyBinding.id, + resourceKind: policyBinding.kind, + }, + position: getPosition(parser, relatedParams, ['metadata', 'name']), + }); +} + +function determineParamKind( + policyBinding: Resource, + resourceMap: Record +): {paramKind: string | undefined; paramApiVersion: string | undefined} { + if (!policyBinding.refs) { + return {paramKind: undefined, paramApiVersion: undefined}; + } + + const relatedPolicy = policyBinding.refs + .map(ref => (ref.target?.type === 'resource' ? ref.target.resourceId : undefined)) + .filter(isDefined) + .map(relatedId => resourceMap[relatedId]) + .find(object => object?.kind === 'ValidatingAdmissionPolicy'); + + return { + paramKind: relatedPolicy?.content?.spec?.paramKind?.kind, + paramApiVersion: relatedPolicy?.content?.spec?.paramKind?.apiVersion, + }; +} + +function getPosition(parser: ResourceParser, object: Resource, path: YamlPath) { + const parsedObject = parser.parse(object); + const node = parsedObject.parsedDoc.getIn(path, true); + + if (!isNode(node)) { + return {line: 0, column: 0, length: 0}; + } + + if (node && parsedObject.lineCounter && node.range) { + const linePos = parsedObject.lineCounter.linePos(node.range[0]); + return { + line: linePos.line, + column: linePos.col, + length: node.range[1] - node.range[0], + }; + } + + return {line: 0, column: 0, length: 0}; +} diff --git a/packages/validation/src/utils/knownResourceKinds.ts b/packages/validation/src/utils/knownResourceKinds.ts index 5a894895c..cf55e023b 100644 --- a/packages/validation/src/utils/knownResourceKinds.ts +++ b/packages/validation/src/utils/knownResourceKinds.ts @@ -33,4 +33,6 @@ export const KNOWN_RESOURCE_KINDS = [ 'StatefulSet', 'StorageClass', 'VolumeAttachment', + 'ValidatingAdmissionPolicy', + 'ValidatingAdmissionPolicyBinding', ] as const;