Skip to content

Commit 5b19313

Browse files
authored
chore: remove undeeded metadata when applying k8s objects (#9267)
### What does this PR do? * Removes undeeded metadata objects which are not applicable / not needed when applying a patch. This includes resourceVersion, UID, selfLink and creationTimestamp. These are automatically created when applying a resource if undefined / blank. * This change is needed as Kubernetes javascript client added serialization / checks with regards to creationTimestamps as well as other metadata objects from PR: kubernetes-client/javascript#1695 ### Screenshot / video of UI <!-- If this PR is changing UI, please include screenshots or screencasts showing the difference --> ### What issues does this PR fix or reference? <!-- Include any related issues from Podman Desktop repository (or from another issue tracker). --> Closes #9260 Closes #9262 ### How to test this PR? <!-- Please explain steps to verify the functionality, do not forget to provide unit/component tests --> - [X] Tests are covering the bug fix or the new feature 1. Edit any k8s yaml 2. Press apply 3. Success 4. Edit again 5. Press apply 6. Success Signed-off-by: Charlie Drage <[email protected]>
1 parent 645fc5b commit 5b19313

File tree

2 files changed

+111
-0
lines changed

2 files changed

+111
-0
lines changed

packages/main/src/plugin/kubernetes/kubernetes-client.spec.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2407,3 +2407,103 @@ test('Should throw an error if unable to restart controlled pod', async () => {
24072407

24082408
await expect(client.restartPod('test-pod')).rejects.toThrow('unable to restart controlled pod');
24092409
});
2410+
2411+
test('test sync resources was called', async () => {
2412+
const client = createTestClient('default');
2413+
const context = 'test-context';
2414+
const namespace = 'default';
2415+
const manifests: KubernetesObject[] = [
2416+
{
2417+
apiVersion: 'v1',
2418+
kind: 'Pod',
2419+
metadata: {
2420+
name: 'test-pod',
2421+
},
2422+
},
2423+
];
2424+
2425+
const mockedPatch = vi.fn();
2426+
2427+
makeApiClientMock.mockReturnValue({
2428+
read: vi.fn(),
2429+
create: vi.fn(),
2430+
patch: mockedPatch,
2431+
});
2432+
2433+
// Call the syncResources method with 'create' action
2434+
await client.syncResources(context, manifests, 'apply', namespace);
2435+
2436+
// Expect patch method to have been called
2437+
expect(mockedPatch).toHaveBeenCalled();
2438+
2439+
// We expect it to have been called with the same object, but with a few "extra" fiels such as last-applied-configuration
2440+
expect(mockedPatch).toHaveBeenCalledWith(
2441+
{
2442+
apiVersion: 'v1',
2443+
kind: 'Pod',
2444+
metadata: {
2445+
annotations: {
2446+
// eslint-disable-next-line no-useless-escape
2447+
'kubectl.kubernetes.io/last-applied-configuration': `{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"test-pod\",\"annotations\":{}}}`,
2448+
},
2449+
name: 'test-pod',
2450+
namespace: 'default',
2451+
},
2452+
},
2453+
undefined,
2454+
undefined,
2455+
'podman-desktop',
2456+
);
2457+
});
2458+
2459+
test('test sync resources was called with no resourceVersion, uid, selfLink, or creationTimestamp being passed through', async () => {
2460+
const client = createTestClient('default');
2461+
const context = 'test-context';
2462+
const namespace = 'default';
2463+
const manifests: KubernetesObject[] = [
2464+
{
2465+
apiVersion: 'v1',
2466+
kind: 'Pod',
2467+
metadata: {
2468+
name: 'test-pod',
2469+
resourceVersion: '123',
2470+
uid: 'uid123',
2471+
selfLink: '/api/v1/namespaces/default/pods/test-pod',
2472+
creationTimestamp: new Date(42),
2473+
},
2474+
},
2475+
];
2476+
2477+
const mockedPatch = vi.fn();
2478+
2479+
makeApiClientMock.mockReturnValue({
2480+
read: vi.fn(),
2481+
create: vi.fn(),
2482+
patch: mockedPatch,
2483+
});
2484+
2485+
// Call the syncResources method with 'create' action
2486+
await client.syncResources(context, manifests, 'apply', namespace);
2487+
2488+
// Expect patch method to have been called
2489+
expect(mockedPatch).toHaveBeenCalled();
2490+
2491+
// Expect it to be called with NO resourceVersion, uid, selfLink, or creationTimestamp in the metadata, however, it is okay to have it in 'last-applied-configuration'
2492+
expect(mockedPatch).toHaveBeenCalledWith(
2493+
{
2494+
apiVersion: 'v1',
2495+
kind: 'Pod',
2496+
metadata: {
2497+
annotations: {
2498+
// eslint-disable-next-line no-useless-escape
2499+
'kubectl.kubernetes.io/last-applied-configuration': `{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"name\":\"test-pod\",\"resourceVersion\":\"123\",\"uid\":\"uid123\",\"selfLink\":\"/api/v1/namespaces/default/pods/test-pod\",\"creationTimestamp\":\"1970-01-01T00:00:00.042Z\",\"annotations\":{}}}`,
2500+
},
2501+
name: 'test-pod',
2502+
namespace: 'default',
2503+
},
2504+
},
2505+
undefined,
2506+
undefined,
2507+
'podman-desktop',
2508+
);
2509+
});

packages/main/src/plugin/kubernetes/kubernetes-client.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1315,6 +1315,17 @@ export class KubernetesClient {
13151315
//
13161316
// See: https://github.com/kubernetes/kubernetes/issues/97423
13171317
if (action === 'apply') {
1318+
// When patching a resource, we do not need certain metadata fields to be present such as resourceVersion, uid, selfLink, and creationTimestamp
1319+
// these cause conflicts when patching a resource since client.patch will serialize these fields and the server will reject the request
1320+
// this change is due to changes on how client.patch / client.create works with the latest serialization changes in:
1321+
// https://github.com/kubernetes-client/javascript/pull/1695 with regards to date.
1322+
// we also remove resourceVersion so we may apply multiple edits to the same resource without having to entirely retrieve and reload the YAML
1323+
// from the server before applying.
1324+
delete spec.metadata?.resourceVersion;
1325+
delete spec.metadata?.uid;
1326+
delete spec.metadata?.selfLink;
1327+
delete spec.metadata?.creationTimestamp;
1328+
13181329
const response = await client.patch(
13191330
spec,
13201331
undefined /* pretty */,

0 commit comments

Comments
 (0)