From 0813e9a11a3687e234091b94a285c65fe0f548a5 Mon Sep 17 00:00:00 2001 From: Sam Mayer Date: Thu, 12 Sep 2024 14:02:48 -0500 Subject: [PATCH] chore: support optional fields in ownerReferences (#1104) ## Description This PR adds support for optional fields defined in [ownerReferences](https://kubernetes.io/docs/reference/kubernetes-api/common-definitions/object-meta/#System). It also changes the test block to use a parameterized test. End to End Test: N/A ## Related Issue Fixes #1060 ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Other (security config, docs update, etc) ## Checklist before merging - [x] Unit, [Journey](https://github.com/defenseunicorns/pepr/tree/main/journey), [E2E Tests](https://github.com/defenseunicorns/pepr-excellent-examples), [docs](https://github.com/defenseunicorns/pepr/tree/main/docs), [adr](https://github.com/defenseunicorns/pepr/tree/main/adr) added or updated as needed - [x] [Contributor Guide Steps](https://docs.pepr.dev/main/contribute/#submitting-a-pull-request) followed --------- Co-authored-by: Case Wylie --- docs/030_user-guide/015_sdk.md | 4 ++- src/sdk/sdk.test.ts | 59 ++++++++++++++++++++++++++-------- src/sdk/sdk.ts | 21 ++++++++---- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/docs/030_user-guide/015_sdk.md b/docs/030_user-guide/015_sdk.md index 8ede89529..aa8937204 100644 --- a/docs/030_user-guide/015_sdk.md +++ b/docs/030_user-guide/015_sdk.md @@ -47,9 +47,11 @@ let result = containers(peprValidationRequest, "ephemeralContainers") ## `getOwnerRefFrom` -Returns the owner reference for a Kubernetes resource. Accepts the following parameters: +Returns the owner reference for a Kubernetes resource as an array. Accepts the following parameters: - **@param kubernetesResource: GenericKind** The Kubernetes resource to get the owner reference for +- **@param blockOwnerDeletion: boolean** If true, AND if the owner has the "foregroundDeletion" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. +- **@param controller: boolean** If true, this reference points to the managing controller. **Usage:** diff --git a/src/sdk/sdk.test.ts b/src/sdk/sdk.test.ts index f8ca65ee5..18e39ede8 100644 --- a/src/sdk/sdk.test.ts +++ b/src/sdk/sdk.test.ts @@ -11,6 +11,7 @@ import { beforeEach, describe, it, jest } from "@jest/globals"; import { GenericKind } from "kubernetes-fluent-client"; import { K8s, kind } from "kubernetes-fluent-client"; import { Mock } from "jest-mock"; +import { V1OwnerReference } from "@kubernetes/client-node"; jest.mock("kubernetes-fluent-client", () => ({ K8s: jest.fn(), @@ -163,23 +164,55 @@ describe("writeEvent", () => { }); describe("getOwnerRefFrom", () => { - it("should return the owner reference for the CRD", () => { - const cr = { + const customResource = { + apiVersion: "v1", + kind: "Package", + metadata: { name: "test", namespace: "default", uid: "1" }, + }; + + const ownerRef = [ + { apiVersion: "v1", kind: "Package", - metadata: { name: "test", namespace: "default", uid: "1" }, - }; - const ownerRef = getOwnerRefFrom(cr as GenericKind); - expect(ownerRef).toEqual([ - { - apiVersion: "v1", - kind: "Package", - name: "test", - uid: "1", - }, - ]); + name: "test", + uid: "1", + }, + ]; + + const ownerRefWithController = ownerRef.map(item => ({ + ...item, + controller: true, + })); + const ownerRefWithBlockOwnerDeletion = ownerRef.map(item => ({ + ...item, + blockOwnerDeletion: false, + })); + const ownerRefWithAllFields = ownerRef.map(item => ({ + ...item, + blockOwnerDeletion: true, + controller: false, + })); + + test.each([ + [true, false, ownerRefWithAllFields], + [false, undefined, ownerRefWithBlockOwnerDeletion], + [undefined, true, ownerRefWithController], + [undefined, undefined, ownerRef], + ])( + "should return owner reference for the CRD for combinations of V1OwnerReference fields - Optionals: blockOwnerDeletion (%s), controller (%s)", + (blockOwnerDeletion, controller, expected) => { + const result = getOwnerRefFrom(customResource, blockOwnerDeletion, controller); + expect(result).toStrictEqual(expected); + }, + ); + + it("should support all defined fields in the V1OwnerReference type", () => { + const V1OwnerReferenceFieldCount = Object.getOwnPropertyNames(V1OwnerReference).length; + const result = getOwnerRefFrom(customResource, false, true); + expect(Object.keys(result[0]).length).toEqual(V1OwnerReferenceFieldCount); }); }); + describe("sanitizeResourceName Fuzzing Tests", () => { test("should handle any random string input", () => { fc.assert( diff --git a/src/sdk/sdk.ts b/src/sdk/sdk.ts index 99620eb20..921eb7483 100644 --- a/src/sdk/sdk.ts +++ b/src/sdk/sdk.ts @@ -79,18 +79,27 @@ export async function writeEvent( /** * Get the owner reference for a custom resource - * @param cr the custom resource to get the owner reference for - * @returns the owner reference for the custom resource + * @param customResource the custom resource to get the owner reference for + * @param blockOwnerDeletion if true, AND if the owner has the "foregroundDeletion" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed. + * @param controller if true, this reference points to the managing controller. + * @returns the owner reference array for the custom resource */ -export function getOwnerRefFrom(cr: GenericKind): V1OwnerReference[] { - const { name, uid } = cr.metadata!; +export function getOwnerRefFrom( + customResource: GenericKind, + blockOwnerDeletion?: boolean, + controller?: boolean, +): V1OwnerReference[] { + const { apiVersion, kind, metadata } = customResource; + const { name, uid } = metadata!; return [ { - apiVersion: cr.apiVersion!, - kind: cr.kind!, + apiVersion: apiVersion!, + kind: kind!, uid: uid!, name: name!, + ...(blockOwnerDeletion !== undefined && { blockOwnerDeletion }), + ...(controller !== undefined && { controller }), }, ]; }