1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Parse jsonPath expressions (#1793)

* Fix jsonPath calls by removing \ characters and using $..[] notation

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>

* Parse jsonPath properly

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>

* Cleanup

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>

* More cleanup

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>

* Improve parsing

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>

* Finetuning

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>

* Stringify children only if value is object or array

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>

* Test other escaped characters do not cause issues

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>
This commit is contained in:
Lauri Nevala 2020-12-21 22:16:57 +02:00 committed by GitHub
parent c8a93414b2
commit e8f36e97a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 92 additions and 6 deletions

View File

@ -13,6 +13,7 @@ import { crdStore } from "./crd.store";
import { KubeObjectMeta } from "../kube-object/kube-object-meta";
import { Input } from "../input";
import { AdditionalPrinterColumnsV1, CustomResourceDefinition } from "../../api/endpoints/crd.api";
import { parseJsonPath } from "../../utils/jsonPath";
interface Props extends KubeObjectDetailsProps<CustomResourceDefinition> {
}
@ -46,7 +47,7 @@ export class CrdResourceDetails extends React.Component<Props> {
renderAdditionalColumns(crd: CustomResourceDefinition, columns: AdditionalPrinterColumnsV1[]) {
return columns.map(({ name, jsonPath: jp }) => (
<DrawerItem key={name} name={name} renderBoolean>
{convertSpecValue(jsonPath.value(crd, jp.slice(1)))}
{convertSpecValue(jsonPath.value(crd, parseJsonPath(jp.slice(1))))}
</DrawerItem>
));
}

View File

@ -12,6 +12,7 @@ import { autorun, computed } from "mobx";
import { crdStore } from "./crd.store";
import { TableSortCallback } from "../table";
import { apiManager } from "../../api/api-manager";
import { parseJsonPath } from "../../utils/jsonPath";
interface Props extends RouteComponentProps<ICRDRouteParams> {
}
@ -61,7 +62,7 @@ export class CrdResources extends React.Component<Props> {
};
extraColumns.forEach(column => {
sortingCallbacks[column.name] = (item: KubeObject) => jsonPath.value(item, column.jsonPath.slice(1));
sortingCallbacks[column.name] = (item: KubeObject) => jsonPath.value(item, parseJsonPath(column.jsonPath.slice(1)));
});
return (
@ -91,10 +92,18 @@ export class CrdResources extends React.Component<Props> {
renderTableContents={(crdInstance: KubeObject) => [
crdInstance.getName(),
isNamespaced && crdInstance.getNs(),
...extraColumns.map(column => ({
renderBoolean: true,
children: JSON.stringify(jsonPath.value(crdInstance, column.jsonPath.slice(1))),
})),
...extraColumns.map((column) => {
let value = jsonPath.value(crdInstance, parseJsonPath(column.jsonPath.slice(1)));
if (Array.isArray(value) || typeof value === "object") {
value = JSON.stringify(value);
}
return {
renderBoolean: true,
children: value,
};
}),
crdInstance.getAge(),
]}
/>

View File

@ -0,0 +1,41 @@
import { parseJsonPath } from "../jsonPath";
describe("parseJsonPath", () => {
test("should convert \\. to use indexed notation", () => {
const res = parseJsonPath(".metadata.labels.kubesphere\\.io/alias-name");
expect(res).toBe(".metadata.labels['kubesphere.io/alias-name']");
});
test("should convert keys with escpaped charatecrs to use indexed notation", () => {
const res = parseJsonPath(".metadata.labels.kubesphere\\\"io/alias-name");
expect(res).toBe(".metadata.labels['kubesphere\"io/alias-name']");
});
test("should convert '-' to use indexed notation", () => {
const res = parseJsonPath(".metadata.labels.alias-name");
expect(res).toBe(".metadata.labels['alias-name']");
});
test("should handle scenario when both \\. and indexed notation are present", () => {
const rest = parseJsonPath(".metadata.labels\\.serving['some.other.item']");
expect(rest).toBe(".metadata['labels.serving']['some.other.item']");
});
test("should not touch given jsonPath if no invalid characters present", () => {
const res = parseJsonPath(".status.conditions[?(@.type=='Ready')].status");
expect(res).toBe(".status.conditions[?(@.type=='Ready')].status");
});
test("strips '\\' away from the result", () => {
const res = parseJsonPath(".metadata.labels['serving\\.knative\\.dev/configuration']");
expect(res).toBe(".metadata.labels['serving.knative.dev/configuration']");
});
});

View File

@ -0,0 +1,35 @@
// Helper to convert strings used for jsonPath where \. or - is present to use indexed notation,
// for example: .metadata.labels.kubesphere\.io/alias-name -> .metadata.labels['kubesphere\.io/alias-name']
export function parseJsonPath(jsonPath: string) {
let pathExpression = jsonPath;
if (jsonPath.match(/[\\-]/g)) { // search for '\' and '-'
const [first, ...rest] = jsonPath.split(/(?<=\w)\./); // split jsonPath by '.' (\. cases are ignored)
pathExpression = `${convertToIndexNotation(first, true)}${rest.map(value => convertToIndexNotation(value)).join("")}`;
}
// strip '\' characters from the result
return pathExpression.replace(/\\/g, "");
}
function convertToIndexNotation(key: string, firstItem = false) {
if (key.match(/[\\-]/g)) { // check if found '\' and '-' in key
if (key.includes("[")) { // handle cases where key contains [...]
const keyToConvert = key.match(/^.*(?=\[)/g); // get the text from the key before '['
if (keyToConvert && keyToConvert[0].match(/[\\-]/g)) { // check if that part contains illegal characters
return key.replace(keyToConvert[0], `['${keyToConvert[0]}']`); // surround key with '[' and ']'
} else {
return `.${key}`; // otherwise return as is with leading '.'
}
}
return `['${key}']`;
} else { // no illegal chracters found, do not touch
const prefix = firstItem ? "" : ".";
return `${prefix}${key}`;
}
}