mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Resolve PR comments, fix load issue
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
c73876170e
commit
63eca3f426
@ -286,7 +286,13 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
||||
|
||||
ensureObjectSelfLink(this.api, newItem);
|
||||
|
||||
return this.items[index] = newItem;
|
||||
if (index < 0) {
|
||||
this.items.push(newItem);
|
||||
} else {
|
||||
this.items[index] = newItem;
|
||||
}
|
||||
|
||||
return newItem;
|
||||
}
|
||||
|
||||
async patch(item: T, patch: Patch): Promise<T> {
|
||||
|
||||
@ -192,7 +192,7 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
|
||||
}
|
||||
|
||||
/**
|
||||
* These must be RFC6902 complient paths
|
||||
* These must be RFC6902 compliant paths
|
||||
*/
|
||||
private static readonly nonEditiablePathPrefixes = [
|
||||
"/metadata/managedFields",
|
||||
@ -209,6 +209,10 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
|
||||
]);
|
||||
|
||||
constructor(data: KubeJsonApiData) {
|
||||
if (typeof data !== "object") {
|
||||
throw new TypeError(`Cannot create a KubeObject from ${typeof data}`);
|
||||
}
|
||||
|
||||
Object.assign(this, data);
|
||||
autoBind(this);
|
||||
}
|
||||
@ -311,8 +315,9 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
|
||||
/**
|
||||
* Perform a full update (or more specifically a replace)
|
||||
*
|
||||
* Note: this is brittle if `data` is not a object spread with the current
|
||||
* fields as the `resourceVersion` maybe out of date. This is a common race condition.
|
||||
* Note: this is brittle if `data` is not actually partial (but instead whole).
|
||||
* As fields such as `resourceVersion` will probably out of date. This is a
|
||||
* common race condition.
|
||||
*/
|
||||
async update(data: Partial<this>): Promise<KubeJsonApiData | null> {
|
||||
// use unified resource-applier api for updating all k8s objects
|
||||
|
||||
@ -62,7 +62,7 @@ export class ResourceApplier {
|
||||
args.push(
|
||||
"--type", "json",
|
||||
"--patch", JSON.stringify(patch),
|
||||
"-o", "yaml"
|
||||
"-o", "json"
|
||||
);
|
||||
|
||||
try {
|
||||
@ -93,18 +93,17 @@ export class ResourceApplier {
|
||||
"-f", fileName,
|
||||
];
|
||||
|
||||
await fs.writeFile(fileName, content);
|
||||
|
||||
logger.debug(`shooting manifests with with ${kubectlPath}`, { args });
|
||||
logger.debug(`shooting manifests with ${kubectlPath}`, { args });
|
||||
|
||||
const execEnv = { ...process.env };
|
||||
const httpsProxy = this.cluster.preferences?.httpsProxy;
|
||||
|
||||
if (httpsProxy) {
|
||||
execEnv["HTTPS_PROXY"] = httpsProxy;
|
||||
execEnv.HTTPS_PROXY = httpsProxy;
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.writeFile(fileName, content);
|
||||
const { stdout } = await promiseExecFile(kubectlPath, args);
|
||||
|
||||
return stdout;
|
||||
|
||||
@ -40,7 +40,7 @@ export class ResourceApplierApiRoute {
|
||||
const { response, cluster, payload } = request;
|
||||
|
||||
try {
|
||||
const resource = await new ResourceApplier(cluster).patch(payload.name, payload.kind, payload.ns, payload.patch);
|
||||
const resource = await new ResourceApplier(cluster).patch(payload.name, payload.kind, payload.patch, payload.ns);
|
||||
|
||||
respondJson(response, resource, 200);
|
||||
} catch (error) {
|
||||
|
||||
@ -21,14 +21,37 @@
|
||||
|
||||
import type http from "http";
|
||||
|
||||
export function respondJson(res: http.ServerResponse, content: any, status = 200) {
|
||||
respond(res, JSON.stringify(content), "application/json", status);
|
||||
/**
|
||||
* Respond to a HTTP request with a body of JSON data
|
||||
* @param res The HTTP response to write data to
|
||||
* @param content The data or its JSON stringified version of it
|
||||
* @param status [200] The status code to respond with
|
||||
*/
|
||||
export function respondJson(res: http.ServerResponse, content: Object | string, status = 200) {
|
||||
const normalizedContent = typeof content === "object"
|
||||
? JSON.stringify(content)
|
||||
: content;
|
||||
|
||||
respond(res, normalizedContent, "application/json", status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to a HTTP request with a body of plain text data
|
||||
* @param res The HTTP response to write data to
|
||||
* @param content The string data to respond with
|
||||
* @param status [200] The status code to respond with
|
||||
*/
|
||||
export function respondText(res: http.ServerResponse, content: string, status = 200) {
|
||||
respond(res, content, "text/plain", status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond to a HTTP request with a body of plain text data
|
||||
* @param res The HTTP response to write data to
|
||||
* @param content The string data to respond with
|
||||
* @param contentType The HTTP Content-Type header value
|
||||
* @param status [200] The status code to respond with
|
||||
*/
|
||||
export function respond(res: http.ServerResponse, content: string, contentType: string, status = 200) {
|
||||
res.setHeader("Content-Type", contentType);
|
||||
res.statusCode = status;
|
||||
|
||||
@ -72,6 +72,8 @@ export class ConfigMapDetails extends React.Component<Props> {
|
||||
<>ConfigMap <b>{configMap.getName()}</b> successfully updated.</>
|
||||
</p>
|
||||
);
|
||||
} catch (error) {
|
||||
Notifications.error(`Failed to save config map: ${error}`);
|
||||
} finally {
|
||||
this.isSaving = false;
|
||||
}
|
||||
|
||||
@ -34,9 +34,9 @@ import type { DockTab } from "./dock.store";
|
||||
import { EditorPanel } from "./editor-panel";
|
||||
import { InfoPanel } from "./info-panel";
|
||||
import * as resourceApplierApi from "../../../common/k8s-api/endpoints/resource-applier.api";
|
||||
import type { JsonApiErrorParsed } from "../../../common/k8s-api/json-api";
|
||||
import { Notifications } from "../notifications";
|
||||
import { monacoModelsManager } from "./monaco-model-manager";
|
||||
import logger from "../../../common/logger";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@ -95,7 +95,7 @@ export class CreateResource extends React.Component<Props> {
|
||||
});
|
||||
};
|
||||
|
||||
create = async () => {
|
||||
create = async (): Promise<undefined> => {
|
||||
if (this.error || !this.data.trim()) {
|
||||
// do not save when field is empty or there is an error
|
||||
return null;
|
||||
@ -103,31 +103,31 @@ export class CreateResource extends React.Component<Props> {
|
||||
|
||||
// skip empty documents if "---" pasted at the beginning or end
|
||||
const resources = jsYaml.safeLoadAll(this.data).filter(Boolean);
|
||||
const createdResources: string[] = [];
|
||||
const errors: string[] = [];
|
||||
|
||||
await Promise.all(
|
||||
resources.map(data => {
|
||||
return resourceApplierApi.update(data)
|
||||
.then(item => createdResources.push(item.metadata.name))
|
||||
.catch((err: JsonApiErrorParsed) => errors.push(err.toString()));
|
||||
})
|
||||
);
|
||||
|
||||
if (errors.length) {
|
||||
errors.forEach(error => Notifications.error(error));
|
||||
if (!createdResources.length) throw errors[0];
|
||||
if (resources.length === 0) {
|
||||
return void logger.info("Nothing to create");
|
||||
}
|
||||
const successMessage = (
|
||||
<p>
|
||||
{createdResources.length === 1 ? "Resource" : "Resources"}{" "}
|
||||
<b>{createdResources.join(", ")}</b> successfully created
|
||||
</p>
|
||||
);
|
||||
|
||||
Notifications.ok(successMessage);
|
||||
const createdResources: string[] = [];
|
||||
|
||||
return successMessage;
|
||||
for (const result of await Promise.allSettled(resources.map(resourceApplierApi.update))) {
|
||||
if (result.status === "fulfilled") {
|
||||
createdResources.push(result.value.metadata.name);
|
||||
} else {
|
||||
Notifications.error(result.reason.toString());
|
||||
}
|
||||
}
|
||||
|
||||
if (createdResources.length > 0) {
|
||||
Notifications.ok((
|
||||
<p>
|
||||
{createdResources.length === 1 ? "Resource" : "Resources"}{" "}
|
||||
<b>{createdResources.join(", ")}</b> successfully created
|
||||
</p>
|
||||
));
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
|
||||
renderControls(){
|
||||
|
||||
@ -98,9 +98,11 @@ export class EditResource extends React.Component<Props> {
|
||||
return null;
|
||||
}
|
||||
const store = editResourceStore.getStore(this.tabId);
|
||||
const currentEdit = yaml.safeLoad(this.draft);
|
||||
const currentVersion = yaml.safeLoad(this.draft);
|
||||
const firstVersion = yaml.safeLoad(editResourceStore.getData(this.tabId).firstDraft ?? this.draft);
|
||||
const patches = createPatch(firstVersion, currentEdit);
|
||||
const patches = createPatch(firstVersion, currentVersion);
|
||||
|
||||
console.log({ currentVersion, firstVersion, patches });
|
||||
const updatedResource = await store.patch(this.resource, patches);
|
||||
|
||||
return (
|
||||
@ -127,9 +129,9 @@ export class EditResource extends React.Component<Props> {
|
||||
submittingMessage="Applying.."
|
||||
controls={(
|
||||
<div className="resource-info flex gaps align-center">
|
||||
<span>Kind:</span> <Badge label={resource.kind}/>
|
||||
<span>Kind:</span><Badge label={resource.kind}/>
|
||||
<span>Name:</span><Badge label={resource.getName()}/>
|
||||
<span>Namespace:</span> <Badge label={resource.getNs() || "global"}/>
|
||||
<span>Namespace:</span><Badge label={resource.getNs() || "global"}/>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
|
||||
@ -91,10 +91,7 @@ export class EditorPanel extends React.Component<Props> {
|
||||
|
||||
onChange = (value: string) => {
|
||||
this.validate(value);
|
||||
|
||||
if (this.props.onChange) {
|
||||
this.props.onChange(value, this.yamlError);
|
||||
}
|
||||
this.props.onChange?.(value, this.yamlError);
|
||||
};
|
||||
|
||||
render() {
|
||||
|
||||
@ -44,15 +44,11 @@ export class KubeObjectMenu<T extends KubeObject> extends React.Component<KubeOb
|
||||
}
|
||||
|
||||
get isEditable() {
|
||||
const { editable } = this.props;
|
||||
|
||||
return editable !== undefined ? editable : !!(this.store && this.store.update);
|
||||
return this.props.editable ?? Boolean(this.store?.patch);
|
||||
}
|
||||
|
||||
get isRemovable() {
|
||||
const { removable } = this.props;
|
||||
|
||||
return removable !== undefined ? removable : !!(this.store && this.store.remove);
|
||||
return this.props.removable ?? Boolean(this.store?.remove);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
|
||||
46
yarn.lock
46
yarn.lock
@ -4622,7 +4622,7 @@ debug@^3.0.0, debug@^3.1.1, debug@^3.2.6:
|
||||
dependencies:
|
||||
ms "^2.1.1"
|
||||
|
||||
debuglog@*, debuglog@^1.0.1:
|
||||
debuglog@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz"
|
||||
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
|
||||
@ -6315,7 +6315,7 @@ fs-extra@^9.0.0, fs-extra@^9.0.1:
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
fs-minipass@^1.2.7:
|
||||
fs-minipass@^1.2.5, fs-minipass@^1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz"
|
||||
integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
|
||||
@ -7287,7 +7287,7 @@ import-local@^3.0.2:
|
||||
pkg-dir "^4.2.0"
|
||||
resolve-cwd "^3.0.0"
|
||||
|
||||
imurmurhash@*, imurmurhash@^0.1.4:
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz"
|
||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||
@ -9075,11 +9075,6 @@ lodash-es@^4.17.20:
|
||||
resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz"
|
||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||
|
||||
lodash._baseindexof@*:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
|
||||
integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=
|
||||
|
||||
lodash._baseuniq@~4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.npmjs.org/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz"
|
||||
@ -9088,33 +9083,11 @@ lodash._baseuniq@~4.6.0:
|
||||
lodash._createset "~4.0.0"
|
||||
lodash._root "~3.0.0"
|
||||
|
||||
lodash._bindcallback@*:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
|
||||
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=
|
||||
|
||||
lodash._cacheindexof@*:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
|
||||
integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=
|
||||
|
||||
lodash._createcache@*:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
|
||||
integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
|
||||
dependencies:
|
||||
lodash._getnative "^3.0.0"
|
||||
|
||||
lodash._createset@~4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmjs.org/lodash._createset/-/lodash._createset-4.0.3.tgz"
|
||||
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=
|
||||
|
||||
lodash._getnative@*, lodash._getnative@^3.0.0:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
|
||||
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=
|
||||
|
||||
lodash._root@~3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz"
|
||||
@ -9140,11 +9113,6 @@ lodash.isequal@^4.5.0:
|
||||
resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz"
|
||||
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
|
||||
|
||||
lodash.restparam@*:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
|
||||
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=
|
||||
|
||||
lodash.sortby@^4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||
@ -9564,7 +9532,7 @@ minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5:
|
||||
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0:
|
||||
minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz"
|
||||
integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
|
||||
@ -9579,7 +9547,7 @@ minipass@^3.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
minizlib@^1.3.3:
|
||||
minizlib@^1.2.1, minizlib@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz"
|
||||
integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
|
||||
@ -9628,7 +9596,7 @@ mkdirp@1.x, mkdirp@^1.0.3, mkdirp@~1.0.4:
|
||||
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.0:
|
||||
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.0:
|
||||
version "0.5.5"
|
||||
resolved "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz"
|
||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
||||
@ -14818,7 +14786,7 @@ yallist@^2.1.2:
|
||||
resolved "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz"
|
||||
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
|
||||
|
||||
yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1:
|
||||
yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3, yallist@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz"
|
||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||
|
||||
Loading…
Reference in New Issue
Block a user