mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into feature/navigate-back-ui-button
This commit is contained in:
commit
528ca6bf44
5
.github/PULL_REQUEST_TEMPLATE/default.md
vendored
5
.github/PULL_REQUEST_TEMPLATE/default.md
vendored
@ -1,5 +0,0 @@
|
|||||||
Fixes #
|
|
||||||
|
|
||||||
**Description of changes:**
|
|
||||||
|
|
||||||
-
|
|
||||||
16
.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
vendored
Normal file
16
.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<!--
|
||||||
|
All PRs must be labelled with one of the following labels:
|
||||||
|
- enhancement
|
||||||
|
- bug
|
||||||
|
- chore
|
||||||
|
- area/ci
|
||||||
|
- area/tests
|
||||||
|
- area/documentaion
|
||||||
|
- dependencies
|
||||||
|
-->
|
||||||
|
|
||||||
|
Fixes #
|
||||||
|
|
||||||
|
**Description of changes:**
|
||||||
|
|
||||||
|
-
|
||||||
13
.github/PULL_REQUEST_TEMPLATE/release.md
vendored
13
.github/PULL_REQUEST_TEMPLATE/release.md
vendored
@ -1,13 +0,0 @@
|
|||||||
## Changes since v
|
|
||||||
|
|
||||||
## 🚀 Features
|
|
||||||
|
|
||||||
*
|
|
||||||
|
|
||||||
## 🐛 Bug Fixes
|
|
||||||
|
|
||||||
*
|
|
||||||
|
|
||||||
## 🧰 Maintenance
|
|
||||||
|
|
||||||
*
|
|
||||||
1
.github/release-drafter.yml
vendored
1
.github/release-drafter.yml
vendored
@ -14,6 +14,7 @@ categories:
|
|||||||
- 'area/ci'
|
- 'area/ci'
|
||||||
- 'area/tests'
|
- 'area/tests'
|
||||||
- 'dependencies'
|
- 'dependencies'
|
||||||
|
- 'area/documentation'
|
||||||
|
|
||||||
template: |
|
template: |
|
||||||
## Changes since $PREVIOUS_TAG
|
## Changes since $PREVIOUS_TAG
|
||||||
|
|||||||
2
.github/workflows/license-header.yml
vendored
2
.github/workflows/license-header.yml
vendored
@ -14,6 +14,8 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Set up Golang
|
- name: Set up Golang
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: '^1.15.1'
|
||||||
- name: Install addlicense
|
- name: Install addlicense
|
||||||
run: |
|
run: |
|
||||||
export PATH=${PATH}:`go env GOPATH`/bin
|
export PATH=${PATH}:`go env GOPATH`/bin
|
||||||
|
|||||||
13
.github/workflows/require-type-labels.yml
vendored
Normal file
13
.github/workflows/require-type-labels.yml
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
name: Require Release Category Labels
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, labeled, unlabeled, synchronize]
|
||||||
|
jobs:
|
||||||
|
label:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: mheap/github-action-required-labels@v1
|
||||||
|
with:
|
||||||
|
mode: exactly
|
||||||
|
count: 1
|
||||||
|
labels: "enhancement, bug, chore, area/ci, area/tests, dependencies, area/documentation"
|
||||||
@ -19,14 +19,17 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Object.defineProperty(window, "requestIdleCallback", {
|
/**
|
||||||
writable: true,
|
* Mock the global window variable
|
||||||
value: jest.fn().mockImplementation(callback => callback()),
|
*/
|
||||||
});
|
export function mockWindow() {
|
||||||
|
Object.defineProperty(window, "requestIdleCallback", {
|
||||||
|
writable: true,
|
||||||
|
value: jest.fn().mockImplementation(callback => callback()),
|
||||||
|
});
|
||||||
|
|
||||||
Object.defineProperty(window, "cancelIdleCallback", {
|
Object.defineProperty(window, "cancelIdleCallback", {
|
||||||
writable: true,
|
writable: true,
|
||||||
value: jest.fn(),
|
value: jest.fn(),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
export default {};
|
|
||||||
|
|||||||
227
extensions/kube-object-event-status/package-lock.json
generated
227
extensions/kube-object-event-status/package-lock.json
generated
@ -11,7 +11,8 @@
|
|||||||
"@material-ui/core": "*",
|
"@material-ui/core": "*",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/react-select": "*",
|
"@types/react-select": "*",
|
||||||
"conf": "^7.0.1"
|
"conf": "^7.0.1",
|
||||||
|
"typed-emitter": "^1.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": {
|
"@babel/runtime": {
|
||||||
@ -675,6 +676,12 @@
|
|||||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"typed-emitter": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-2h7utWyXgd2R2u2IuL8B4yu1gqMxbgUj2VS/MGVbFhEVQNJKXoQQoS5CBMh+eW31zFeSmDfEQ3qQf4xy5SlPVQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"uri-js": {
|
"uri-js": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
@ -919,9 +926,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"anymatch": {
|
"anymatch": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||||
"integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==",
|
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -972,9 +979,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1026,9 +1033,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"base": {
|
"base": {
|
||||||
@ -1087,9 +1094,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"base64-js": {
|
"base64-js": {
|
||||||
"version": "1.3.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==",
|
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"big.js": {
|
"big.js": {
|
||||||
@ -1099,9 +1106,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "2.1.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -1122,9 +1129,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "5.1.3",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
|
||||||
"integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
|
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
@ -1190,21 +1197,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserify-rsa": {
|
"browserify-rsa": {
|
||||||
"version": "4.0.1",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
|
||||||
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
"integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "^4.1.0",
|
"bn.js": "^5.0.0",
|
||||||
"randombytes": "^2.0.1"
|
"randombytes": "^2.0.1"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"bn.js": {
|
|
||||||
"version": "4.11.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserify-sign": {
|
"browserify-sign": {
|
||||||
@ -1264,9 +1263,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"buffer-from": {
|
"buffer-from": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
|
||||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
|
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"buffer-xor": {
|
"buffer-xor": {
|
||||||
@ -1333,20 +1332,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chokidar": {
|
"chokidar": {
|
||||||
"version": "3.4.3",
|
"version": "3.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
|
||||||
"integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
|
"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"anymatch": "~3.1.1",
|
"anymatch": "~3.1.2",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
"fsevents": "~2.1.2",
|
"fsevents": "~2.3.2",
|
||||||
"glob-parent": "~5.1.0",
|
"glob-parent": "~5.1.2",
|
||||||
"is-binary-path": "~2.1.0",
|
"is-binary-path": "~2.1.0",
|
||||||
"is-glob": "~4.0.1",
|
"is-glob": "~4.0.1",
|
||||||
"normalize-path": "~3.0.0",
|
"normalize-path": "~3.0.0",
|
||||||
"readdirp": "~3.5.0"
|
"readdirp": "~3.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chownr": {
|
"chownr": {
|
||||||
@ -1356,13 +1355,10 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chrome-trace-event": {
|
"chrome-trace-event": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||||
"integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
|
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {
|
|
||||||
"tslib": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"cipher-base": {
|
"cipher-base": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
@ -1507,9 +1503,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1644,9 +1640,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1767,9 +1763,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"version": "3.2.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
"integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==",
|
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"evp_bytestokey": {
|
"evp_bytestokey": {
|
||||||
@ -2011,9 +2007,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
"version": "2.1.3",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -2024,9 +2020,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.6",
|
"version": "7.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
|
||||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs.realpath": "^1.0.0",
|
"fs.realpath": "^1.0.0",
|
||||||
@ -2038,9 +2034,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"glob-parent": {
|
"glob-parent": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -2483,9 +2479,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2819,9 +2815,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"pbkdf2": {
|
"pbkdf2": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
|
||||||
"integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==",
|
"integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"create-hash": "^1.1.2",
|
"create-hash": "^1.1.2",
|
||||||
@ -2897,9 +2893,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2990,9 +2986,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readdirp": {
|
"readdirp": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -3017,9 +3013,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"repeat-element": {
|
"repeat-element": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
|
||||||
"integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
|
"integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"repeat-string": {
|
"repeat-string": {
|
||||||
@ -3305,9 +3301,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map-url": {
|
"source-map-url": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
|
||||||
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
|
"integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"split-string": {
|
"split-string": {
|
||||||
@ -3535,12 +3531,6 @@
|
|||||||
"semver": "^6.0.0"
|
"semver": "^6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"tty-browserify": {
|
"tty-browserify": {
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
||||||
@ -3637,9 +3627,9 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"uri-js": {
|
"uri-js": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
"integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==",
|
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
@ -3705,21 +3695,21 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"watchpack": {
|
"watchpack": {
|
||||||
"version": "1.7.4",
|
"version": "1.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
|
||||||
"integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==",
|
"integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"chokidar": "^3.4.1",
|
"chokidar": "^3.4.1",
|
||||||
"graceful-fs": "^4.1.2",
|
"graceful-fs": "^4.1.2",
|
||||||
"neo-async": "^2.5.0",
|
"neo-async": "^2.5.0",
|
||||||
"watchpack-chokidar2": "^2.0.0"
|
"watchpack-chokidar2": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"watchpack-chokidar2": {
|
"watchpack-chokidar2": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz",
|
||||||
"integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==",
|
"integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -3947,9 +3937,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"webpack": {
|
"webpack": {
|
||||||
"version": "4.44.2",
|
"version": "4.46.0",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz",
|
||||||
"integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==",
|
"integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@webassemblyjs/ast": "1.9.0",
|
"@webassemblyjs/ast": "1.9.0",
|
||||||
@ -3960,7 +3950,7 @@
|
|||||||
"ajv": "^6.10.2",
|
"ajv": "^6.10.2",
|
||||||
"ajv-keywords": "^3.4.1",
|
"ajv-keywords": "^3.4.1",
|
||||||
"chrome-trace-event": "^1.0.2",
|
"chrome-trace-event": "^1.0.2",
|
||||||
"enhanced-resolve": "^4.3.0",
|
"enhanced-resolve": "^4.5.0",
|
||||||
"eslint-scope": "^4.0.3",
|
"eslint-scope": "^4.0.3",
|
||||||
"json-parse-better-errors": "^1.0.2",
|
"json-parse-better-errors": "^1.0.2",
|
||||||
"loader-runner": "^2.4.0",
|
"loader-runner": "^2.4.0",
|
||||||
@ -4006,6 +3996,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"enhanced-resolve": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"memory-fs": "^0.5.0",
|
||||||
|
"tapable": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"memory-fs": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"errno": "^0.1.3",
|
||||||
|
"readable-stream": "^2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"fill-range": {
|
"fill-range": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
|
||||||
@ -4132,9 +4145,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"y18n": {
|
"y18n": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||||
"integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
|
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
|
|||||||
@ -20,6 +20,6 @@
|
|||||||
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
"@k8slens/extensions": "file:../../src/extensions/npm/extensions",
|
||||||
"ts-loader": "^8.0.4",
|
"ts-loader": "^8.0.4",
|
||||||
"typescript": "^4.3.2",
|
"typescript": "^4.3.2",
|
||||||
"webpack": "^4.44.2"
|
"webpack": "^4.46.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
170
extensions/node-menu/package-lock.json
generated
170
extensions/node-menu/package-lock.json
generated
@ -631,7 +631,8 @@
|
|||||||
"@material-ui/core": "*",
|
"@material-ui/core": "*",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/react-select": "*",
|
"@types/react-select": "*",
|
||||||
"conf": "^7.0.1"
|
"conf": "^7.0.1",
|
||||||
|
"typed-emitter": "^1.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": {
|
"@babel/runtime": {
|
||||||
@ -1295,6 +1296,12 @@
|
|||||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"typed-emitter": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-2h7utWyXgd2R2u2IuL8B4yu1gqMxbgUj2VS/MGVbFhEVQNJKXoQQoS5CBMh+eW31zFeSmDfEQ3qQf4xy5SlPVQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"uri-js": {
|
"uri-js": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
@ -1785,9 +1792,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2016,9 +2023,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "2.1.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -2039,9 +2046,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "5.1.3",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
|
||||||
"integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
|
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
@ -2113,21 +2120,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserify-rsa": {
|
"browserify-rsa": {
|
||||||
"version": "4.0.1",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
|
||||||
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
"integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "^4.1.0",
|
"bn.js": "^5.0.0",
|
||||||
"randombytes": "^2.0.1"
|
"randombytes": "^2.0.1"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"bn.js": {
|
|
||||||
"version": "4.11.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserify-sign": {
|
"browserify-sign": {
|
||||||
@ -2308,26 +2307,37 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chokidar": {
|
"chokidar": {
|
||||||
"version": "3.4.3",
|
"version": "3.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
|
||||||
"integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
|
"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"anymatch": "~3.1.1",
|
"anymatch": "~3.1.2",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
"fsevents": "~2.1.2",
|
"fsevents": "~2.3.2",
|
||||||
"glob-parent": "~5.1.0",
|
"glob-parent": "~5.1.2",
|
||||||
"is-binary-path": "~2.1.0",
|
"is-binary-path": "~2.1.0",
|
||||||
"is-glob": "~4.0.1",
|
"is-glob": "~4.0.1",
|
||||||
"normalize-path": "~3.0.0",
|
"normalize-path": "~3.0.0",
|
||||||
"readdirp": "~3.5.0"
|
"readdirp": "~3.6.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"anymatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
"version": "2.1.3",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
@ -2340,13 +2350,10 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chrome-trace-event": {
|
"chrome-trace-event": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||||
"integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
|
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {
|
|
||||||
"tslib": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"ci-info": {
|
"ci-info": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@ -2555,9 +2562,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2790,9 +2797,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2986,9 +2993,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"version": "3.2.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
"integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==",
|
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"evp_bytestokey": {
|
"evp_bytestokey": {
|
||||||
@ -3455,9 +3462,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"glob-parent": {
|
"glob-parent": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -4819,9 +4826,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5362,9 +5369,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"pbkdf2": {
|
"pbkdf2": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
|
||||||
"integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==",
|
"integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"create-hash": "^1.1.2",
|
"create-hash": "^1.1.2",
|
||||||
@ -5489,9 +5496,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5625,9 +5632,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readdirp": {
|
"readdirp": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -6750,12 +6757,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"tty-browserify": {
|
"tty-browserify": {
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
||||||
@ -7287,9 +7288,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"webpack": {
|
"webpack": {
|
||||||
"version": "4.44.2",
|
"version": "4.46.0",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz",
|
||||||
"integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==",
|
"integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@webassemblyjs/ast": "1.9.0",
|
"@webassemblyjs/ast": "1.9.0",
|
||||||
@ -7300,7 +7301,7 @@
|
|||||||
"ajv": "^6.10.2",
|
"ajv": "^6.10.2",
|
||||||
"ajv-keywords": "^3.4.1",
|
"ajv-keywords": "^3.4.1",
|
||||||
"chrome-trace-event": "^1.0.2",
|
"chrome-trace-event": "^1.0.2",
|
||||||
"enhanced-resolve": "^4.3.0",
|
"enhanced-resolve": "^4.5.0",
|
||||||
"eslint-scope": "^4.0.3",
|
"eslint-scope": "^4.0.3",
|
||||||
"json-parse-better-errors": "^1.0.2",
|
"json-parse-better-errors": "^1.0.2",
|
||||||
"loader-runner": "^2.4.0",
|
"loader-runner": "^2.4.0",
|
||||||
@ -7352,6 +7353,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"enhanced-resolve": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"memory-fs": "^0.5.0",
|
||||||
|
"tapable": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"memory-fs": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"errno": "^0.1.3",
|
||||||
|
"readable-stream": "^2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"fill-range": {
|
"fill-range": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
|
||||||
|
|||||||
@ -21,6 +21,6 @@
|
|||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"ts-loader": "^8.0.4",
|
"ts-loader": "^8.0.4",
|
||||||
"typescript": "^4.3.2",
|
"typescript": "^4.3.2",
|
||||||
"webpack": "^4.44.2"
|
"webpack": "^4.46.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
170
extensions/pod-menu/package-lock.json
generated
170
extensions/pod-menu/package-lock.json
generated
@ -631,7 +631,8 @@
|
|||||||
"@material-ui/core": "*",
|
"@material-ui/core": "*",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/react-select": "*",
|
"@types/react-select": "*",
|
||||||
"conf": "^7.0.1"
|
"conf": "^7.0.1",
|
||||||
|
"typed-emitter": "^1.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": {
|
"@babel/runtime": {
|
||||||
@ -1248,6 +1249,12 @@
|
|||||||
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"typed-emitter": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-2h7utWyXgd2R2u2IuL8B4yu1gqMxbgUj2VS/MGVbFhEVQNJKXoQQoS5CBMh+eW31zFeSmDfEQ3qQf4xy5SlPVQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"uri-js": {
|
"uri-js": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
@ -1738,9 +1745,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1969,9 +1976,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"binary-extensions": {
|
"binary-extensions": {
|
||||||
"version": "2.1.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
@ -1992,9 +1999,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "5.1.3",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
|
||||||
"integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==",
|
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
@ -2066,21 +2073,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserify-rsa": {
|
"browserify-rsa": {
|
||||||
"version": "4.0.1",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
|
||||||
"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
|
"integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bn.js": "^4.1.0",
|
"bn.js": "^5.0.0",
|
||||||
"randombytes": "^2.0.1"
|
"randombytes": "^2.0.1"
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"bn.js": {
|
|
||||||
"version": "4.11.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"browserify-sign": {
|
"browserify-sign": {
|
||||||
@ -2261,26 +2260,37 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chokidar": {
|
"chokidar": {
|
||||||
"version": "3.4.3",
|
"version": "3.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
|
||||||
"integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
|
"integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"anymatch": "~3.1.1",
|
"anymatch": "~3.1.2",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
"fsevents": "~2.1.2",
|
"fsevents": "~2.3.2",
|
||||||
"glob-parent": "~5.1.0",
|
"glob-parent": "~5.1.2",
|
||||||
"is-binary-path": "~2.1.0",
|
"is-binary-path": "~2.1.0",
|
||||||
"is-glob": "~4.0.1",
|
"is-glob": "~4.0.1",
|
||||||
"normalize-path": "~3.0.0",
|
"normalize-path": "~3.0.0",
|
||||||
"readdirp": "~3.5.0"
|
"readdirp": "~3.6.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"anymatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"normalize-path": "^3.0.0",
|
||||||
|
"picomatch": "^2.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"fsevents": {
|
"fsevents": {
|
||||||
"version": "2.1.3",
|
"version": "2.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||||
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
|
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true
|
"optional": true
|
||||||
}
|
}
|
||||||
@ -2293,13 +2303,10 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"chrome-trace-event": {
|
"chrome-trace-event": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
|
||||||
"integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==",
|
"integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
|
||||||
"dev": true,
|
"dev": true
|
||||||
"requires": {
|
|
||||||
"tslib": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"ci-info": {
|
"ci-info": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@ -2508,9 +2515,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2743,9 +2750,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2939,9 +2946,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
"version": "3.2.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
"integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==",
|
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"evp_bytestokey": {
|
"evp_bytestokey": {
|
||||||
@ -3408,9 +3415,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"glob-parent": {
|
"glob-parent": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -4772,9 +4779,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5315,9 +5322,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"pbkdf2": {
|
"pbkdf2": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
|
||||||
"integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==",
|
"integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"create-hash": "^1.1.2",
|
"create-hash": "^1.1.2",
|
||||||
@ -5442,9 +5449,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
"version": "4.11.9",
|
"version": "4.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
|
||||||
"integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==",
|
"integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5578,9 +5585,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readdirp": {
|
"readdirp": {
|
||||||
"version": "3.5.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@ -6703,12 +6710,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tslib": {
|
|
||||||
"version": "1.14.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
|
||||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"tty-browserify": {
|
"tty-browserify": {
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
||||||
@ -7240,9 +7241,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"webpack": {
|
"webpack": {
|
||||||
"version": "4.44.2",
|
"version": "4.46.0",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz",
|
||||||
"integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==",
|
"integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@webassemblyjs/ast": "1.9.0",
|
"@webassemblyjs/ast": "1.9.0",
|
||||||
@ -7253,7 +7254,7 @@
|
|||||||
"ajv": "^6.10.2",
|
"ajv": "^6.10.2",
|
||||||
"ajv-keywords": "^3.4.1",
|
"ajv-keywords": "^3.4.1",
|
||||||
"chrome-trace-event": "^1.0.2",
|
"chrome-trace-event": "^1.0.2",
|
||||||
"enhanced-resolve": "^4.3.0",
|
"enhanced-resolve": "^4.5.0",
|
||||||
"eslint-scope": "^4.0.3",
|
"eslint-scope": "^4.0.3",
|
||||||
"json-parse-better-errors": "^1.0.2",
|
"json-parse-better-errors": "^1.0.2",
|
||||||
"loader-runner": "^2.4.0",
|
"loader-runner": "^2.4.0",
|
||||||
@ -7305,6 +7306,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"enhanced-resolve": {
|
||||||
|
"version": "4.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
|
||||||
|
"integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.2",
|
||||||
|
"memory-fs": "^0.5.0",
|
||||||
|
"tapable": "^1.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"memory-fs": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"errno": "^0.1.3",
|
||||||
|
"readable-stream": "^2.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"fill-range": {
|
"fill-range": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
|
||||||
|
|||||||
@ -21,6 +21,6 @@
|
|||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"ts-loader": "^8.0.4",
|
"ts-loader": "^8.0.4",
|
||||||
"typescript": "^4.3.2",
|
"typescript": "^4.3.2",
|
||||||
"webpack": "^4.44.2"
|
"webpack": "^4.46.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,7 +30,7 @@ import * as utils from "../helpers/utils";
|
|||||||
import { listHelmRepositories } from "../helpers/utils";
|
import { listHelmRepositories } from "../helpers/utils";
|
||||||
import { fail } from "assert";
|
import { fail } from "assert";
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(2 * 60 * 1000); // 2 minutes so that we can get better errors from spectron
|
||||||
|
|
||||||
// FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below)
|
// FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below)
|
||||||
describe("Lens integration tests", () => {
|
describe("Lens integration tests", () => {
|
||||||
@ -38,14 +38,10 @@ describe("Lens integration tests", () => {
|
|||||||
|
|
||||||
describe("app start", () => {
|
describe("app start", () => {
|
||||||
utils.beforeAllWrapped(async () => {
|
utils.beforeAllWrapped(async () => {
|
||||||
app = await utils.appStart();
|
app = await utils.setup();
|
||||||
});
|
});
|
||||||
|
|
||||||
utils.afterAllWrapped(async () => {
|
utils.afterAllWrapped(() => utils.tearDown(app));
|
||||||
if (app?.isRunning()) {
|
|
||||||
await utils.tearDown(app);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows "add cluster"', async () => {
|
it('shows "add cluster"', async () => {
|
||||||
await app.electron.ipcRenderer.send("test-menu-item-click", "File", "Add Cluster");
|
await app.electron.ipcRenderer.send("test-menu-item-click", "File", "Add Cluster");
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import * as util from "util";
|
|||||||
|
|
||||||
export const promiseExec = util.promisify(exec);
|
export const promiseExec = util.promisify(exec);
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(2 * 60 * 1000); // 2 minutes so that we can get better errors from spectron
|
||||||
|
|
||||||
// FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below)
|
// FIXME (!): improve / simplify all css-selectors + use [data-test-id="some-id"] (already used in some tests below)
|
||||||
describe("Lens cluster pages", () => {
|
describe("Lens cluster pages", () => {
|
||||||
@ -41,38 +41,36 @@ describe("Lens cluster pages", () => {
|
|||||||
const BACKSPACE = "\uE003";
|
const BACKSPACE = "\uE003";
|
||||||
let app: Application;
|
let app: Application;
|
||||||
const ready = minikubeReady(TEST_NAMESPACE);
|
const ready = minikubeReady(TEST_NAMESPACE);
|
||||||
let clusterAdded = false;
|
|
||||||
|
|
||||||
utils.describeIf(ready)("test common pages", () => {
|
utils.describeIf(ready)("test common pages", () => {
|
||||||
|
let clusterAdded = false;
|
||||||
const addCluster = async () => {
|
const addCluster = async () => {
|
||||||
|
await app.client.waitUntilTextExists("div", "Catalog");
|
||||||
await waitForMinikubeDashboard(app);
|
await waitForMinikubeDashboard(app);
|
||||||
await app.client.click('a[href="/nodes"]');
|
await app.client.click('a[href="/nodes"]');
|
||||||
await app.client.waitUntilTextExists("div.TableCell", "Ready");
|
await app.client.waitUntilTextExists("div.TableCell", "Ready");
|
||||||
};
|
};
|
||||||
|
|
||||||
const appStartAddCluster = async () => {
|
|
||||||
app = await utils.appStart();
|
|
||||||
await addCluster();
|
|
||||||
clusterAdded = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const tearDown = async () => {
|
|
||||||
await utils.tearDown(app);
|
|
||||||
clusterAdded = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
describe("cluster add", () => {
|
describe("cluster add", () => {
|
||||||
utils.beforeAllWrapped(async () => {
|
utils.beforeAllWrapped(async () => {
|
||||||
app = await utils.appStart();
|
app = await utils.setup();
|
||||||
});
|
});
|
||||||
|
|
||||||
utils.afterAllWrapped(tearDown);
|
utils.afterAllWrapped(() => utils.tearDown(app));
|
||||||
|
|
||||||
it("allows to add a cluster", async () => {
|
it("allows to add a cluster", async () => {
|
||||||
await addCluster();
|
await addCluster();
|
||||||
|
clusterAdded = true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const appStartAddCluster = async () => {
|
||||||
|
if (clusterAdded) {
|
||||||
|
app = await utils.setup();
|
||||||
|
await addCluster();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
function getSidebarSelectors(itemId: string) {
|
function getSidebarSelectors(itemId: string) {
|
||||||
const root = `.SidebarItem[data-test-id="${itemId}"]`;
|
const root = `.SidebarItem[data-test-id="${itemId}"]`;
|
||||||
|
|
||||||
@ -84,7 +82,7 @@ describe("Lens cluster pages", () => {
|
|||||||
|
|
||||||
describe("cluster pages", () => {
|
describe("cluster pages", () => {
|
||||||
utils.beforeAllWrapped(appStartAddCluster);
|
utils.beforeAllWrapped(appStartAddCluster);
|
||||||
utils.afterAllWrapped(tearDown);
|
utils.afterAllWrapped(() => utils.tearDown(app));
|
||||||
|
|
||||||
const tests: {
|
const tests: {
|
||||||
drawer?: string
|
drawer?: string
|
||||||
@ -369,7 +367,7 @@ describe("Lens cluster pages", () => {
|
|||||||
|
|
||||||
describe("viewing pod logs", () => {
|
describe("viewing pod logs", () => {
|
||||||
utils.beforeEachWrapped(appStartAddCluster);
|
utils.beforeEachWrapped(appStartAddCluster);
|
||||||
utils.afterEachWrapped(tearDown);
|
utils.afterEachWrapped(() => utils.tearDown(app));
|
||||||
|
|
||||||
it(`shows a log for a pod`, async () => {
|
it(`shows a log for a pod`, async () => {
|
||||||
expect(clusterAdded).toBe(true);
|
expect(clusterAdded).toBe(true);
|
||||||
@ -397,7 +395,6 @@ describe("Lens cluster pages", () => {
|
|||||||
// Open logs tab in dock
|
// Open logs tab in dock
|
||||||
await app.client.click(".list .TableRow:first-child");
|
await app.client.click(".list .TableRow:first-child");
|
||||||
await app.client.waitForVisible(".Drawer");
|
await app.client.waitForVisible(".Drawer");
|
||||||
|
|
||||||
const logsButton = "ul.KubeObjectMenu li.MenuItem i.Icon span[data-icon-name='subject']";
|
const logsButton = "ul.KubeObjectMenu li.MenuItem i.Icon span[data-icon-name='subject']";
|
||||||
|
|
||||||
await app.client.waitForVisible(logsButton);
|
await app.client.waitForVisible(logsButton);
|
||||||
@ -419,7 +416,7 @@ describe("Lens cluster pages", () => {
|
|||||||
|
|
||||||
describe("cluster operations", () => {
|
describe("cluster operations", () => {
|
||||||
utils.beforeEachWrapped(appStartAddCluster);
|
utils.beforeEachWrapped(appStartAddCluster);
|
||||||
utils.afterEachWrapped(tearDown);
|
utils.afterEachWrapped(() => utils.tearDown(app));
|
||||||
|
|
||||||
it("shows default namespace", async () => {
|
it("shows default namespace", async () => {
|
||||||
expect(clusterAdded).toBe(true);
|
expect(clusterAdded).toBe(true);
|
||||||
|
|||||||
@ -22,21 +22,17 @@
|
|||||||
import type { Application } from "spectron";
|
import type { Application } from "spectron";
|
||||||
import * as utils from "../helpers/utils";
|
import * as utils from "../helpers/utils";
|
||||||
|
|
||||||
jest.setTimeout(60000);
|
jest.setTimeout(2 * 60 * 1000); // 2 minutes so that we can get better errors from spectron
|
||||||
|
|
||||||
describe("Lens command palette", () => {
|
describe("Lens command palette", () => {
|
||||||
let app: Application;
|
let app: Application;
|
||||||
|
|
||||||
describe("menu", () => {
|
describe("menu", () => {
|
||||||
utils.beforeAllWrapped(async () => {
|
utils.beforeAllWrapped(async () => {
|
||||||
app = await utils.appStart();
|
app = await utils.setup();
|
||||||
});
|
});
|
||||||
|
|
||||||
utils.afterAllWrapped(async () => {
|
utils.afterAllWrapped(() => utils.tearDown(app));
|
||||||
if (app?.isRunning()) {
|
|
||||||
await utils.tearDown(app);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it("opens command dialog from menu", async () => {
|
it("opens command dialog from menu", async () => {
|
||||||
await app.electron.ipcRenderer.send("test-menu-item-click", "View", "Command Palette...");
|
await app.electron.ipcRenderer.send("test-menu-item-click", "View", "Command Palette...");
|
||||||
|
|||||||
@ -69,24 +69,20 @@ export function describeIf(condition: boolean) {
|
|||||||
return condition ? describe : describe.skip;
|
return condition ? describe : describe.skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setup(): Application {
|
|
||||||
return new Application({
|
|
||||||
path: AppPaths[process.platform], // path to electron app
|
|
||||||
args: [],
|
|
||||||
startTimeout: 30000,
|
|
||||||
waitTimeout: 60000,
|
|
||||||
env: {
|
|
||||||
CICD: "true"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const keys = {
|
export const keys = {
|
||||||
backspace: "\uE003"
|
backspace: "\uE003"
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function appStart() {
|
export async function setup(): Promise<Application> {
|
||||||
const app = setup();
|
const app = new Application({
|
||||||
|
path: AppPaths[process.platform], // path to electron app
|
||||||
|
args: [],
|
||||||
|
startTimeout: 60000,
|
||||||
|
waitTimeout: 10000,
|
||||||
|
env: {
|
||||||
|
CICD: "true"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await app.start();
|
await app.start();
|
||||||
// Wait for splash screen to be closed
|
// Wait for splash screen to be closed
|
||||||
|
|||||||
29
package.json
29
package.json
@ -48,7 +48,7 @@
|
|||||||
"postversion": "git push --set-upstream ${GIT_REMOTE:-origin} release/v$npm_package_version"
|
"postversion": "git push --set-upstream ${GIT_REMOTE:-origin} release/v$npm_package_version"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"bundledKubectlVersion": "1.18.15",
|
"bundledKubectlVersion": "1.21.2",
|
||||||
"bundledHelmVersion": "3.5.4",
|
"bundledHelmVersion": "3.5.4",
|
||||||
"sentryDsn": ""
|
"sentryDsn": ""
|
||||||
},
|
},
|
||||||
@ -185,7 +185,7 @@
|
|||||||
"@hapi/subtext": "^7.0.3",
|
"@hapi/subtext": "^7.0.3",
|
||||||
"@kubernetes/client-node": "^0.14.3",
|
"@kubernetes/client-node": "^0.14.3",
|
||||||
"@sentry/electron": "^2.5.0",
|
"@sentry/electron": "^2.5.0",
|
||||||
"@sentry/integrations": "^6.8.0",
|
"@sentry/integrations": "^6.10.0",
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
"array-move": "^3.0.1",
|
"array-move": "^3.0.1",
|
||||||
"auto-bind": "^4.0.0",
|
"auto-bind": "^4.0.0",
|
||||||
@ -202,6 +202,7 @@
|
|||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"filehound": "^1.17.4",
|
"filehound": "^1.17.4",
|
||||||
"fs-extra": "^9.0.1",
|
"fs-extra": "^9.0.1",
|
||||||
|
"glob-to-regexp": "^0.4.1",
|
||||||
"grapheme-splitter": "^1.0.4",
|
"grapheme-splitter": "^1.0.4",
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
"http-proxy": "^1.18.1",
|
"http-proxy": "^1.18.1",
|
||||||
@ -220,7 +221,8 @@
|
|||||||
"mock-fs": "^4.14.0",
|
"mock-fs": "^4.14.0",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
"moment-timezone": "^0.5.33",
|
"moment-timezone": "^0.5.33",
|
||||||
"node-pty": "^0.9.0",
|
"node-fetch": "^2.6.1",
|
||||||
|
"node-pty": "^0.10.1",
|
||||||
"npm": "^6.14.8",
|
"npm": "^6.14.8",
|
||||||
"openid-client": "^3.15.2",
|
"openid-client": "^3.15.2",
|
||||||
"p-limit": "^3.1.0",
|
"p-limit": "^3.1.0",
|
||||||
@ -237,19 +239,20 @@
|
|||||||
"serializr": "^2.0.3",
|
"serializr": "^2.0.3",
|
||||||
"shell-env": "^3.0.1",
|
"shell-env": "^3.0.1",
|
||||||
"spdy": "^4.0.2",
|
"spdy": "^4.0.2",
|
||||||
"tar": "^6.0.5",
|
"tar": "^6.1.4",
|
||||||
"tcp-port-used": "^1.0.1",
|
"tcp-port-used": "^1.0.1",
|
||||||
"tempy": "^0.5.0",
|
"tempy": "^0.5.0",
|
||||||
"url-parse": "^1.5.1",
|
"url-parse": "^1.5.1",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"win-ca": "^3.2.0",
|
"win-ca": "^3.2.0",
|
||||||
"winston": "^3.2.1",
|
"winston": "^3.3.3",
|
||||||
|
"winston-console-format": "^1.0.8",
|
||||||
"winston-transport-browserconsole": "^1.0.5",
|
"winston-transport-browserconsole": "^1.0.5",
|
||||||
"ws": "^7.4.6"
|
"ws": "^7.4.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@emeraldpay/hashicon-react": "^0.4.0",
|
"@emeraldpay/hashicon-react": "^0.4.0",
|
||||||
"@material-ui/core": "^4.11.4",
|
"@material-ui/core": "^4.12.3",
|
||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
"@material-ui/lab": "^4.0.0-alpha.57",
|
"@material-ui/lab": "^4.0.0-alpha.57",
|
||||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
|
||||||
@ -260,16 +263,17 @@
|
|||||||
"@types/byline": "^4.2.32",
|
"@types/byline": "^4.2.32",
|
||||||
"@types/chart.js": "^2.9.21",
|
"@types/chart.js": "^2.9.21",
|
||||||
"@types/circular-dependency-plugin": "^5.0.1",
|
"@types/circular-dependency-plugin": "^5.0.1",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.2",
|
||||||
"@types/crypto-js": "^3.1.47",
|
"@types/crypto-js": "^3.1.47",
|
||||||
"@types/dompurify": "^2.0.2",
|
"@types/dompurify": "^2.0.2",
|
||||||
"@types/electron-devtools-installer": "^2.2.0",
|
"@types/electron-devtools-installer": "^2.2.0",
|
||||||
"@types/electron-window-state": "^2.0.34",
|
"@types/electron-window-state": "^2.0.34",
|
||||||
"@types/fs-extra": "^9.0.1",
|
"@types/fs-extra": "^9.0.1",
|
||||||
|
"@types/glob-to-regexp": "^0.4.1",
|
||||||
"@types/hapi": "^18.0.6",
|
"@types/hapi": "^18.0.6",
|
||||||
"@types/hoist-non-react-statics": "^3.3.1",
|
"@types/hoist-non-react-statics": "^3.3.1",
|
||||||
"@types/html-webpack-plugin": "^3.2.3",
|
"@types/html-webpack-plugin": "^3.2.3",
|
||||||
"@types/http-proxy": "^1.17.5",
|
"@types/http-proxy": "^1.17.7",
|
||||||
"@types/jest": "^26.0.22",
|
"@types/jest": "^26.0.22",
|
||||||
"@types/js-yaml": "^3.12.4",
|
"@types/js-yaml": "^3.12.4",
|
||||||
"@types/jsdom": "^16.2.4",
|
"@types/jsdom": "^16.2.4",
|
||||||
@ -281,6 +285,7 @@
|
|||||||
"@types/mock-fs": "^4.13.1",
|
"@types/mock-fs": "^4.13.1",
|
||||||
"@types/module-alias": "^2.0.0",
|
"@types/module-alias": "^2.0.0",
|
||||||
"@types/node": "12.20",
|
"@types/node": "12.20",
|
||||||
|
"@types/node-fetch": "^2.5.12",
|
||||||
"@types/npm": "^2.0.31",
|
"@types/npm": "^2.0.31",
|
||||||
"@types/progress-bar-webpack-plugin": "^2.1.2",
|
"@types/progress-bar-webpack-plugin": "^2.1.2",
|
||||||
"@types/proper-lockfile": "^4.1.1",
|
"@types/proper-lockfile": "^4.1.1",
|
||||||
@ -302,6 +307,7 @@
|
|||||||
"@types/tar": "^4.0.5",
|
"@types/tar": "^4.0.5",
|
||||||
"@types/tcp-port-used": "^1.0.0",
|
"@types/tcp-port-used": "^1.0.0",
|
||||||
"@types/tempy": "^0.3.0",
|
"@types/tempy": "^0.3.0",
|
||||||
|
"@types/triple-beam": "^1.3.2",
|
||||||
"@types/url-parse": "^1.4.3",
|
"@types/url-parse": "^1.4.3",
|
||||||
"@types/uuid": "^8.3.0",
|
"@types/uuid": "^8.3.0",
|
||||||
"@types/webdriverio": "^4.13.0",
|
"@types/webdriverio": "^4.13.0",
|
||||||
@ -309,11 +315,11 @@
|
|||||||
"@types/webpack-dev-server": "^3.11.1",
|
"@types/webpack-dev-server": "^3.11.1",
|
||||||
"@types/webpack-env": "^1.15.2",
|
"@types/webpack-env": "^1.15.2",
|
||||||
"@types/webpack-node-externals": "^1.7.1",
|
"@types/webpack-node-externals": "^1.7.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.14.2",
|
"@typescript-eslint/eslint-plugin": "^4.29.0",
|
||||||
"@typescript-eslint/parser": "^4.0.0",
|
"@typescript-eslint/parser": "^4.0.0",
|
||||||
"ace-builds": "^1.4.12",
|
"ace-builds": "^1.4.12",
|
||||||
"ansi_up": "^5.0.0",
|
"ansi_up": "^5.0.0",
|
||||||
"chart.js": "^2.9.3",
|
"chart.js": "^2.9.4",
|
||||||
"circular-dependency-plugin": "^5.2.2",
|
"circular-dependency-plugin": "^5.2.2",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.2",
|
||||||
"concurrently": "^5.2.0",
|
"concurrently": "^5.2.0",
|
||||||
@ -346,9 +352,8 @@
|
|||||||
"node-loader": "^1.0.3",
|
"node-loader": "^1.0.3",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "^4.14.1",
|
||||||
"nodemon": "^2.0.12",
|
"nodemon": "^2.0.12",
|
||||||
"open": "^7.3.1",
|
|
||||||
"patch-package": "^6.2.2",
|
"patch-package": "^6.2.2",
|
||||||
"postcss": "^8.2.14",
|
"postcss": "^8.3.6",
|
||||||
"postcss-loader": "4.0.3",
|
"postcss-loader": "4.0.3",
|
||||||
"postinstall-postinstall": "^2.1.0",
|
"postinstall-postinstall": "^2.1.0",
|
||||||
"progress-bar-webpack-plugin": "^2.1.0",
|
"progress-bar-webpack-plugin": "^2.1.0",
|
||||||
|
|||||||
@ -25,9 +25,11 @@ import yaml from "js-yaml";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import fse from "fs-extra";
|
import fse from "fs-extra";
|
||||||
import { Cluster } from "../../main/cluster";
|
import { Cluster } from "../../main/cluster";
|
||||||
import { ClusterId, ClusterStore, getClusterIdFromHost } from "../cluster-store";
|
import { ClusterStore } from "../cluster-store";
|
||||||
import { Console } from "console";
|
import { Console } from "console";
|
||||||
import { stdout, stderr } from "process";
|
import { stdout, stderr } from "process";
|
||||||
|
import type { ClusterId } from "../cluster-types";
|
||||||
|
import { getCustomKubeConfigPath } from "../utils";
|
||||||
|
|
||||||
console = new Console(stdout, stderr);
|
console = new Console(stdout, stderr);
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ users:
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
function embed(clusterId: ClusterId, contents: any): string {
|
function embed(clusterId: ClusterId, contents: any): string {
|
||||||
const absPath = ClusterStore.getCustomKubeConfigPath(clusterId);
|
const absPath = getCustomKubeConfigPath(clusterId);
|
||||||
|
|
||||||
fse.ensureDirSync(path.dirname(absPath));
|
fse.ensureDirSync(path.dirname(absPath));
|
||||||
fse.writeFileSync(absPath, contents, { encoding: "utf-8", mode: 0o600 });
|
fse.writeFileSync(absPath, contents, { encoding: "utf-8", mode: 0o600 });
|
||||||
@ -550,27 +552,3 @@ describe("pre 3.6.0-beta.1 config with an existing cluster", () => {
|
|||||||
expect(icon.startsWith("data:;base64,")).toBe(true);
|
expect(icon.startsWith("data:;base64,")).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getClusterIdFromHost", () => {
|
|
||||||
const clusterFakeId = "fe540901-0bd6-4f6c-b472-bce1559d7c4a";
|
|
||||||
|
|
||||||
it("should return undefined for non cluster frame hosts", () => {
|
|
||||||
expect(getClusterIdFromHost("localhost:45345")).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return ClusterId for cluster frame hosts", () => {
|
|
||||||
expect(getClusterIdFromHost(`${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return ClusterId for cluster frame hosts with additional subdomains", () => {
|
|
||||||
expect(getClusterIdFromHost(`abc.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.yz.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@ -19,7 +19,9 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { anyObject } from "jest-mock-extended";
|
||||||
import mockFs from "mock-fs";
|
import mockFs from "mock-fs";
|
||||||
|
import logger from "../../main/logger";
|
||||||
import { ClusterStore } from "../cluster-store";
|
import { ClusterStore } from "../cluster-store";
|
||||||
import { HotbarStore } from "../hotbar-store";
|
import { HotbarStore } from "../hotbar-store";
|
||||||
|
|
||||||
@ -187,7 +189,7 @@ describe("HotbarStore", () => {
|
|||||||
hotbarStore.removeFromHotbar("catalog-entity");
|
hotbarStore.removeFromHotbar("catalog-entity");
|
||||||
const items = hotbarStore.getActive().items.filter(Boolean);
|
const items = hotbarStore.getActive().items.filter(Boolean);
|
||||||
|
|
||||||
expect(items.length).toEqual(0);
|
expect(items).toStrictEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does nothing if removing with invalid uid", () => {
|
it("does nothing if removing with invalid uid", () => {
|
||||||
@ -245,6 +247,43 @@ describe("HotbarStore", () => {
|
|||||||
expect(items.slice(0, 4)).toEqual(["catalog-entity", "minikube", "aws", "test"]);
|
expect(items.slice(0, 4)).toEqual(["catalog-entity", "minikube", "aws", "test"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("logs an error if cellIndex is out of bounds", () => {
|
||||||
|
const hotbarStore = HotbarStore.getInstance();
|
||||||
|
|
||||||
|
hotbarStore.add({ name: "hottest", id: "hottest" });
|
||||||
|
hotbarStore.activeHotbarId = "hottest";
|
||||||
|
|
||||||
|
const { error } = logger;
|
||||||
|
const mocked = jest.fn();
|
||||||
|
|
||||||
|
logger.error = mocked;
|
||||||
|
|
||||||
|
hotbarStore.addToHotbar(testCluster, -1);
|
||||||
|
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
|
||||||
|
|
||||||
|
hotbarStore.addToHotbar(testCluster, 12);
|
||||||
|
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
|
||||||
|
|
||||||
|
hotbarStore.addToHotbar(testCluster, 13);
|
||||||
|
expect(mocked).toBeCalledWith("[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range", anyObject());
|
||||||
|
|
||||||
|
logger.error = error;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if getId is invalid or returns not a string", () => {
|
||||||
|
const hotbarStore = HotbarStore.getInstance();
|
||||||
|
|
||||||
|
expect(() => hotbarStore.addToHotbar({} as any)).toThrowError(TypeError);
|
||||||
|
expect(() => hotbarStore.addToHotbar({ getId: () => true } as any)).toThrowError(TypeError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error if getName is invalid or returns not a string", () => {
|
||||||
|
const hotbarStore = HotbarStore.getInstance();
|
||||||
|
|
||||||
|
expect(() => hotbarStore.addToHotbar({ getId: () => "" } as any)).toThrowError(TypeError);
|
||||||
|
expect(() => hotbarStore.addToHotbar({ getId: () => "", getName: () => 4 } as any)).toThrowError(TypeError);
|
||||||
|
});
|
||||||
|
|
||||||
it("does nothing when item moved to same cell", () => {
|
it("does nothing when item moved to same cell", () => {
|
||||||
const hotbarStore = HotbarStore.getInstance();
|
const hotbarStore = HotbarStore.getInstance();
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,8 @@ import { getAppVersion, Singleton, toJS, Disposer } from "./utils";
|
|||||||
import logger from "../main/logger";
|
import logger from "../main/logger";
|
||||||
import { broadcastMessage, ipcMainOn, ipcRendererOn } from "./ipc";
|
import { broadcastMessage, ipcMainOn, ipcRendererOn } from "./ipc";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
|
import { isTestEnv } from "./vars";
|
||||||
|
import { kebabCase } from "lodash";
|
||||||
|
|
||||||
export interface BaseStoreParams<T> extends ConfOptions<T> {
|
export interface BaseStoreParams<T> extends ConfOptions<T> {
|
||||||
syncOptions?: IReactionOptions;
|
syncOptions?: IReactionOptions;
|
||||||
@ -59,12 +61,14 @@ export abstract class BaseStore<T> extends Singleton {
|
|||||||
const res: any = this.fromStore(this.storeConfig.store);
|
const res: any = this.fromStore(this.storeConfig.store);
|
||||||
|
|
||||||
if (res instanceof Promise || (typeof res === "object" && res && typeof res.then === "function")) {
|
if (res instanceof Promise || (typeof res === "object" && res && typeof res.then === "function")) {
|
||||||
console.error(`${this.name} extends BaseStore<T>'s fromStore method returns a Promise or promise-like object. This is an error and must be fixed.`);
|
console.error(`${this.constructor.name} extends BaseStore<T>'s fromStore method returns a Promise or promise-like object. This is an error and must be fixed.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.enableSync();
|
this.enableSync();
|
||||||
|
|
||||||
logger.info(`[STORE]: LOADED from ${this.path}`);
|
if (!isTestEnv) {
|
||||||
|
logger.info(`[${kebabCase(this.constructor.name).toUpperCase()}]: LOADED from ${this.path}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get name() {
|
get name() {
|
||||||
|
|||||||
@ -19,119 +19,26 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import path from "path";
|
import { ipcMain, ipcRenderer, webFrame } from "electron";
|
||||||
import { app, ipcMain, ipcRenderer, remote, webFrame } from "electron";
|
|
||||||
import { action, comparer, computed, makeObservable, observable, reaction } from "mobx";
|
import { action, comparer, computed, makeObservable, observable, reaction } from "mobx";
|
||||||
import { BaseStore } from "./base-store";
|
import { BaseStore } from "./base-store";
|
||||||
import { Cluster, ClusterState } from "../main/cluster";
|
import { Cluster } from "../main/cluster";
|
||||||
import migrations from "../migrations/cluster-store";
|
import migrations from "../migrations/cluster-store";
|
||||||
import * as uuid from "uuid";
|
|
||||||
import logger from "../main/logger";
|
import logger from "../main/logger";
|
||||||
import { appEventBus } from "./event-bus";
|
import { appEventBus } from "./event-bus";
|
||||||
import { ipcMainHandle, ipcMainOn, ipcRendererOn, requestMain } from "./ipc";
|
import { ipcMainHandle, ipcMainOn, ipcRendererOn, requestMain } from "./ipc";
|
||||||
import { disposer, toJS } from "./utils";
|
import { disposer, toJS } from "./utils";
|
||||||
|
import type { ClusterModel, ClusterId, ClusterState } from "./cluster-types";
|
||||||
export interface ClusterIconUpload {
|
|
||||||
clusterId: string;
|
|
||||||
name: string;
|
|
||||||
path: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClusterMetadata {
|
|
||||||
[key: string]: string | number | boolean | object;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ClusterPrometheusMetadata = {
|
|
||||||
success?: boolean;
|
|
||||||
provider?: string;
|
|
||||||
autoDetected?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ClusterStoreModel {
|
export interface ClusterStoreModel {
|
||||||
clusters?: ClusterModel[];
|
clusters?: ClusterModel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ClusterId = string;
|
|
||||||
|
|
||||||
export interface UpdateClusterModel extends Omit<ClusterModel, "id"> {
|
|
||||||
id?: ClusterId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClusterModel {
|
|
||||||
/** Unique id for a cluster */
|
|
||||||
id: ClusterId;
|
|
||||||
|
|
||||||
/** Path to cluster kubeconfig */
|
|
||||||
kubeConfigPath: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Workspace id
|
|
||||||
*
|
|
||||||
* @deprecated
|
|
||||||
*/
|
|
||||||
workspace?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated this is used only for hotbar migrations from 4.2.X
|
|
||||||
*/
|
|
||||||
workspaces?: string[];
|
|
||||||
|
|
||||||
/** User context in kubeconfig */
|
|
||||||
contextName: string;
|
|
||||||
|
|
||||||
/** Preferences */
|
|
||||||
preferences?: ClusterPreferences;
|
|
||||||
|
|
||||||
/** Metadata */
|
|
||||||
metadata?: ClusterMetadata;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Labels for the catalog entity
|
|
||||||
*/
|
|
||||||
labels?: Record<string, string>;
|
|
||||||
|
|
||||||
/** List of accessible namespaces */
|
|
||||||
accessibleNamespaces?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClusterPreferences extends ClusterPrometheusPreferences {
|
|
||||||
terminalCWD?: string;
|
|
||||||
clusterName?: string;
|
|
||||||
iconOrder?: number;
|
|
||||||
icon?: string;
|
|
||||||
httpsProxy?: string;
|
|
||||||
hiddenMetrics?: string[];
|
|
||||||
nodeShellImage?: string;
|
|
||||||
imagePullSecret?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ClusterPrometheusPreferences {
|
|
||||||
prometheus?: {
|
|
||||||
namespace: string;
|
|
||||||
service: string;
|
|
||||||
port: number;
|
|
||||||
prefix: string;
|
|
||||||
};
|
|
||||||
prometheusProvider?: {
|
|
||||||
type: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialStates = "cluster:states";
|
const initialStates = "cluster:states";
|
||||||
|
|
||||||
export const initialNodeShellImage = "docker.io/alpine:3.13";
|
|
||||||
|
|
||||||
export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
||||||
private static StateChannel = "cluster:state";
|
private static StateChannel = "cluster:state";
|
||||||
|
|
||||||
static get storedKubeConfigFolder(): string {
|
|
||||||
return path.resolve((app ?? remote.app).getPath("userData"), "kubeconfigs");
|
|
||||||
}
|
|
||||||
|
|
||||||
static getCustomKubeConfigPath(clusterId: ClusterId = uuid.v4()): string {
|
|
||||||
return path.resolve(ClusterStore.storedKubeConfigFolder, clusterId);
|
|
||||||
}
|
|
||||||
|
|
||||||
clusters = observable.map<ClusterId, Cluster>();
|
clusters = observable.map<ClusterId, Cluster>();
|
||||||
removedClusters = observable.map<ClusterId, Cluster>();
|
removedClusters = observable.map<ClusterId, Cluster>();
|
||||||
|
|
||||||
@ -272,22 +179,3 @@ export class ClusterStore extends BaseStore<ClusterStoreModel> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getClusterIdFromHost(host: string): ClusterId | undefined {
|
|
||||||
// e.g host == "%clusterId.localhost:45345"
|
|
||||||
const subDomains = host.split(":")[0].split(".");
|
|
||||||
|
|
||||||
return subDomains.slice(-2, -1)[0]; // ClusterId or undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getClusterFrameUrl(clusterId: ClusterId) {
|
|
||||||
return `//${clusterId}.${location.host}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getHostedClusterId() {
|
|
||||||
return getClusterIdFromHost(location.host);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getHostedCluster(): Cluster {
|
|
||||||
return ClusterStore.getInstance().getById(getHostedClusterId());
|
|
||||||
}
|
|
||||||
|
|||||||
180
src/common/cluster-types.ts
Normal file
180
src/common/cluster-types.ts
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON serializable metadata type
|
||||||
|
*/
|
||||||
|
export type ClusterMetadata = Record<string, string | number | boolean | object>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metadata for cluster's prometheus settings
|
||||||
|
*/
|
||||||
|
export interface ClusterPrometheusMetadata {
|
||||||
|
success?: boolean;
|
||||||
|
provider?: string;
|
||||||
|
autoDetected?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ClusterId is an opaque string
|
||||||
|
*/
|
||||||
|
export type ClusterId = string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fields that are used for updating a cluster instance
|
||||||
|
*/
|
||||||
|
export type UpdateClusterModel = Omit<ClusterModel, "id">;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model for passing cluster data around, including to disk
|
||||||
|
*/
|
||||||
|
export interface ClusterModel {
|
||||||
|
/** Unique id for a cluster */
|
||||||
|
id: ClusterId;
|
||||||
|
|
||||||
|
/** Path to cluster kubeconfig */
|
||||||
|
kubeConfigPath: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Workspace id
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
workspace?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated this is used only for hotbar migrations from 4.2.X
|
||||||
|
*/
|
||||||
|
workspaces?: string[];
|
||||||
|
|
||||||
|
/** User context in kubeconfig */
|
||||||
|
contextName: string;
|
||||||
|
|
||||||
|
/** Preferences */
|
||||||
|
preferences?: ClusterPreferences;
|
||||||
|
|
||||||
|
/** Metadata */
|
||||||
|
metadata?: ClusterMetadata;
|
||||||
|
|
||||||
|
/** List of accessible namespaces */
|
||||||
|
accessibleNamespaces?: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Labels for the catalog entity
|
||||||
|
*/
|
||||||
|
labels?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The complete set of cluster settings or preferences
|
||||||
|
*/
|
||||||
|
export interface ClusterPreferences extends ClusterPrometheusPreferences {
|
||||||
|
terminalCWD?: string;
|
||||||
|
clusterName?: string;
|
||||||
|
iconOrder?: number;
|
||||||
|
icon?: string;
|
||||||
|
httpsProxy?: string;
|
||||||
|
hiddenMetrics?: string[];
|
||||||
|
nodeShellImage?: string;
|
||||||
|
imagePullSecret?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A cluster's prometheus settings (a subset of cluster settings)
|
||||||
|
*/
|
||||||
|
export interface ClusterPrometheusPreferences {
|
||||||
|
prometheus?: {
|
||||||
|
namespace: string;
|
||||||
|
service: string;
|
||||||
|
port: number;
|
||||||
|
prefix: string;
|
||||||
|
};
|
||||||
|
prometheusProvider?: {
|
||||||
|
type: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The options for the status of connection attempts to a cluster
|
||||||
|
*/
|
||||||
|
export enum ClusterStatus {
|
||||||
|
AccessGranted = 2,
|
||||||
|
AccessDenied = 1,
|
||||||
|
Offline = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The OpenLens known static metadata keys
|
||||||
|
*/
|
||||||
|
export enum ClusterMetadataKey {
|
||||||
|
VERSION = "version",
|
||||||
|
CLUSTER_ID = "id",
|
||||||
|
DISTRIBUTION = "distribution",
|
||||||
|
NODES_COUNT = "nodes",
|
||||||
|
LAST_SEEN = "lastSeen",
|
||||||
|
PROMETHEUS = "prometheus"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A shorthand enum for resource types that have metrics attached to them via OpenLens metrics stack
|
||||||
|
*/
|
||||||
|
export enum ClusterMetricsResourceType {
|
||||||
|
Cluster = "Cluster",
|
||||||
|
Node = "Node",
|
||||||
|
Pod = "Pod",
|
||||||
|
Deployment = "Deployment",
|
||||||
|
StatefulSet = "StatefulSet",
|
||||||
|
Container = "Container",
|
||||||
|
Ingress = "Ingress",
|
||||||
|
VolumeClaim = "VolumeClaim",
|
||||||
|
ReplicaSet = "ReplicaSet",
|
||||||
|
DaemonSet = "DaemonSet",
|
||||||
|
Job = "Job",
|
||||||
|
Namespace = "Namespace",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default node shell image
|
||||||
|
*/
|
||||||
|
export const initialNodeShellImage = "docker.io/alpine:3.13";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The arguments for requesting to refresh a cluster's metadata
|
||||||
|
*/
|
||||||
|
export interface ClusterRefreshOptions {
|
||||||
|
refreshMetadata?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data representing a cluster's state, for passing between main and renderer
|
||||||
|
*/
|
||||||
|
export interface ClusterState {
|
||||||
|
apiUrl: string;
|
||||||
|
online: boolean;
|
||||||
|
disconnected: boolean;
|
||||||
|
accessible: boolean;
|
||||||
|
ready: boolean;
|
||||||
|
failureReason: string;
|
||||||
|
isAdmin: boolean;
|
||||||
|
allowedNamespaces: string[]
|
||||||
|
allowedResources: string[]
|
||||||
|
isGlobalWatchEnabled: boolean;
|
||||||
|
}
|
||||||
@ -22,38 +22,18 @@
|
|||||||
import { action, comparer, observable, makeObservable } from "mobx";
|
import { action, comparer, observable, makeObservable } from "mobx";
|
||||||
import { BaseStore } from "./base-store";
|
import { BaseStore } from "./base-store";
|
||||||
import migrations from "../migrations/hotbar-store";
|
import migrations from "../migrations/hotbar-store";
|
||||||
import * as uuid from "uuid";
|
|
||||||
import isNull from "lodash/isNull";
|
|
||||||
import { toJS } from "./utils";
|
import { toJS } from "./utils";
|
||||||
import { CatalogEntity } from "./catalog";
|
import { CatalogEntity } from "./catalog";
|
||||||
import { catalogEntity } from "../main/catalog-sources/general";
|
import { catalogEntity } from "../main/catalog-sources/general";
|
||||||
|
import logger from "../main/logger";
|
||||||
export interface HotbarItem {
|
import { broadcastMessage, HotbarTooManyItems } from "./ipc";
|
||||||
entity: {
|
import { defaultHotbarCells, getEmptyHotbar, Hotbar, HotbarCreateOptions } from "./hotbar-types";
|
||||||
uid: string;
|
|
||||||
name?: string;
|
|
||||||
source?: string;
|
|
||||||
};
|
|
||||||
params?: {
|
|
||||||
[key: string]: string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Hotbar = Required<HotbarCreateOptions>;
|
|
||||||
|
|
||||||
export interface HotbarCreateOptions {
|
|
||||||
id?: string;
|
|
||||||
name: string;
|
|
||||||
items?: (HotbarItem | null)[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface HotbarStoreModel {
|
export interface HotbarStoreModel {
|
||||||
hotbars: Hotbar[];
|
hotbars: Hotbar[];
|
||||||
activeHotbarId: string;
|
activeHotbarId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultHotbarCells = 12; // Number is chosen to easy hit any item with keyboard
|
|
||||||
|
|
||||||
export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
||||||
@observable hotbars: Hotbar[] = [];
|
@observable hotbars: Hotbar[] = [];
|
||||||
@observable private _activeHotbarId: string;
|
@observable private _activeHotbarId: string;
|
||||||
@ -89,22 +69,22 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
return this.hotbarIndex(this.activeHotbarId);
|
return this.hotbarIndex(this.activeHotbarId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getInitialItems() {
|
|
||||||
return [...Array.from(Array(defaultHotbarCells).fill(null))];
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
protected fromStore(data: Partial<HotbarStoreModel> = {}) {
|
protected fromStore(data: Partial<HotbarStoreModel> = {}) {
|
||||||
if (!data.hotbars || !data.hotbars.length) {
|
if (!data.hotbars || !data.hotbars.length) {
|
||||||
this.hotbars = [{
|
const hotbar = getEmptyHotbar("Default");
|
||||||
id: uuid.v4(),
|
const { metadata: { uid, name, source } } = catalogEntity;
|
||||||
name: "Default",
|
const initialItem = { entity: { uid, name, source } };
|
||||||
items: this.defaultHotbarInitialItems,
|
|
||||||
}];
|
hotbar.items[0] = initialItem;
|
||||||
|
|
||||||
|
this.hotbars = [hotbar];
|
||||||
} else {
|
} else {
|
||||||
this.hotbars = data.hotbars;
|
this.hotbars = data.hotbars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.hotbars.forEach(ensureExactHotbarItemLength);
|
||||||
|
|
||||||
if (data.activeHotbarId) {
|
if (data.activeHotbarId) {
|
||||||
if (this.getById(data.activeHotbarId)) {
|
if (this.getById(data.activeHotbarId)) {
|
||||||
this.activeHotbarId = data.activeHotbarId;
|
this.activeHotbarId = data.activeHotbarId;
|
||||||
@ -116,14 +96,13 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get defaultHotbarInitialItems() {
|
toJSON(): HotbarStoreModel {
|
||||||
const { metadata: { uid, name, source } } = catalogEntity;
|
const model: HotbarStoreModel = {
|
||||||
const initialItem = { entity: { uid, name, source }};
|
hotbars: this.hotbars,
|
||||||
|
activeHotbarId: this.activeHotbarId
|
||||||
|
};
|
||||||
|
|
||||||
return [
|
return toJS(model);
|
||||||
initialItem,
|
|
||||||
...Array.from(Array(defaultHotbarCells - 1).fill(null))
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getActive() {
|
getActive() {
|
||||||
@ -140,16 +119,12 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
add(data: HotbarCreateOptions, { setActive = false } = {}) {
|
add(data: HotbarCreateOptions, { setActive = false } = {}) {
|
||||||
const {
|
const hotbar = getEmptyHotbar(data.name, data.id);
|
||||||
id = uuid.v4(),
|
|
||||||
items = HotbarStore.getInitialItems(),
|
|
||||||
name,
|
|
||||||
} = data;
|
|
||||||
|
|
||||||
this.hotbars.push({ id, name, items });
|
this.hotbars.push(hotbar);
|
||||||
|
|
||||||
if (setActive) {
|
if (setActive) {
|
||||||
this._activeHotbarId = id;
|
this._activeHotbarId = hotbar.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,39 +151,52 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
addToHotbar(item: CatalogEntity, cellIndex = -1) {
|
addToHotbar(item: CatalogEntity, cellIndex?: number) {
|
||||||
const hotbar = this.getActive();
|
const hotbar = this.getActive();
|
||||||
|
const uid = item.metadata?.uid;
|
||||||
|
const name = item.metadata?.name;
|
||||||
|
|
||||||
|
if (typeof uid !== "string") {
|
||||||
|
throw new TypeError("CatalogEntity.metadata.uid must be a string");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof name !== "string") {
|
||||||
|
throw new TypeError("CatalogEntity.metadata.name must be a string");
|
||||||
|
}
|
||||||
|
|
||||||
const newItem = { entity: {
|
const newItem = { entity: {
|
||||||
uid: item.metadata.uid,
|
uid,
|
||||||
name: item.metadata.name,
|
name,
|
||||||
source: item.metadata.source
|
source: item.metadata.source,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
if (hotbar.items.find(i => i?.entity.uid === item.metadata.uid)) {
|
|
||||||
|
if (hotbar.items.find(i => i?.entity.uid === uid)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cellIndex == -1) {
|
if (cellIndex === undefined) {
|
||||||
// Add item to empty cell
|
// Add item to empty cell
|
||||||
const emptyCellIndex = hotbar.items.findIndex(isNull);
|
const emptyCellIndex = hotbar.items.indexOf(null);
|
||||||
|
|
||||||
if (emptyCellIndex != -1) {
|
if (emptyCellIndex != -1) {
|
||||||
hotbar.items[emptyCellIndex] = newItem;
|
hotbar.items[emptyCellIndex] = newItem;
|
||||||
} else {
|
} else {
|
||||||
// Add new item to the end of list
|
broadcastMessage(HotbarTooManyItems);
|
||||||
hotbar.items.push(newItem);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else if (0 <= cellIndex && cellIndex < hotbar.items.length) {
|
||||||
hotbar.items[cellIndex] = newItem;
|
hotbar.items[cellIndex] = newItem;
|
||||||
|
} else {
|
||||||
|
logger.error(`[HOTBAR-STORE]: cannot pin entity to hotbar outside of index range`, { entityId: uid, hotbarId: hotbar.id, cellIndex, });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
removeFromHotbar(uid: string): void {
|
removeFromHotbar(uid: string): void {
|
||||||
const hotbar = this.getActive();
|
const hotbar = this.getActive();
|
||||||
const index = hotbar.items.findIndex((i) => i?.entity.uid === uid);
|
const index = hotbar.items.findIndex(item => item?.entity.uid === uid);
|
||||||
|
|
||||||
if (index == -1) {
|
if (index < 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,13 +210,10 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
*/
|
*/
|
||||||
@action
|
@action
|
||||||
removeAllHotbarItems(uid: string) {
|
removeAllHotbarItems(uid: string) {
|
||||||
const undoItems: [Hotbar, number, HotbarItem][] = [];
|
|
||||||
|
|
||||||
for (const hotbar of this.hotbars) {
|
for (const hotbar of this.hotbars) {
|
||||||
const index = hotbar.items.findIndex((i) => i?.entity.uid === uid);
|
const index = hotbar.items.findIndex((i) => i?.entity.uid === uid);
|
||||||
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
undoItems.push([hotbar, index, hotbar.items[index]]);
|
|
||||||
hotbar.items[index] = null;
|
hotbar.items[index] = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,13 +274,33 @@ export class HotbarStore extends BaseStore<HotbarStoreModel> {
|
|||||||
|
|
||||||
hotbarStore.activeHotbarId = hotbarStore.hotbars[index].id;
|
hotbarStore.activeHotbarId = hotbarStore.hotbars[index].id;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
toJSON(): HotbarStoreModel {
|
/**
|
||||||
const model: HotbarStoreModel = {
|
* This function ensures that there are always exactly `defaultHotbarCells`
|
||||||
hotbars: this.hotbars,
|
* worth of items in the hotbar.
|
||||||
activeHotbarId: this.activeHotbarId
|
* @param hotbar The hotbar to modify
|
||||||
};
|
*/
|
||||||
|
function ensureExactHotbarItemLength(hotbar: Hotbar) {
|
||||||
|
if (hotbar.items.length === defaultHotbarCells) {
|
||||||
|
// if we already have `defaultHotbarCells` then we are good to stop
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return toJS(model);
|
// otherwise, keep adding empty entries until full
|
||||||
|
while (hotbar.items.length < defaultHotbarCells) {
|
||||||
|
hotbar.items.push(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if for some reason the hotbar was overfilled before, remove as many entries
|
||||||
|
// as needed, but prefer empty slots and items at the end first.
|
||||||
|
while (hotbar.items.length > defaultHotbarCells) {
|
||||||
|
const lastNull = hotbar.items.lastIndexOf(null);
|
||||||
|
|
||||||
|
if (lastNull >= 0) {
|
||||||
|
hotbar.items.splice(lastNull, 1);
|
||||||
|
} else {
|
||||||
|
hotbar.items.length = defaultHotbarCells;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
52
src/common/hotbar-types.ts
Normal file
52
src/common/hotbar-types.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as uuid from "uuid";
|
||||||
|
import type { Tuple } from "./utils";
|
||||||
|
|
||||||
|
export interface HotbarItem {
|
||||||
|
entity: {
|
||||||
|
uid: string;
|
||||||
|
name?: string;
|
||||||
|
source?: string;
|
||||||
|
};
|
||||||
|
params?: {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Hotbar = Required<HotbarCreateOptions>;
|
||||||
|
|
||||||
|
export interface HotbarCreateOptions {
|
||||||
|
id?: string;
|
||||||
|
name: string;
|
||||||
|
items?: Tuple<HotbarItem | null, typeof defaultHotbarCells>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultHotbarCells = 12; // Number is chosen to easy hit any item with keyboard
|
||||||
|
|
||||||
|
export function getEmptyHotbar(name: string, id: string = uuid.v4()): Hotbar {
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
items: Array(defaultHotbarCells).fill(null) as Tuple<HotbarItem | null, typeof defaultHotbarCells>,
|
||||||
|
name,
|
||||||
|
};
|
||||||
|
}
|
||||||
22
src/common/ipc/hotbar.ts
Normal file
22
src/common/ipc/hotbar.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const HotbarTooManyItems = "hotbar:too-many-items";
|
||||||
@ -24,3 +24,4 @@ export * from "./invalid-kubeconfig";
|
|||||||
export * from "./update-available.ipc";
|
export * from "./update-available.ipc";
|
||||||
export * from "./cluster.ipc";
|
export * from "./cluster.ipc";
|
||||||
export * from "./type-enforced-ipc";
|
export * from "./type-enforced-ipc";
|
||||||
|
export * from "./hotbar";
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ingressStore } from "../../components/+network-ingresses/ingress.store";
|
import { ingressStore } from "../../../renderer/components/+network-ingresses/ingress.store";
|
||||||
import { apiManager } from "../api-manager";
|
import { apiManager } from "../api-manager";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
@ -20,12 +20,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { KubeJsonApi } from "../kube-json-api";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
|
|
||||||
describe("KubeApi", () => {
|
describe("KubeApi", () => {
|
||||||
|
let request: KubeJsonApi;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
request = new KubeJsonApi({
|
||||||
|
serverAddress: `http://127.0.0.1:9999`,
|
||||||
|
apiBase: "/api-kube"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("uses url from apiBase if apiBase contains the resource", async () => {
|
it("uses url from apiBase if apiBase contains the resource", async () => {
|
||||||
(fetch as any).mockResponse(async (request: any) => {
|
(fetch as any).mockResponse(async (request: any) => {
|
||||||
if (request.url === "/api-kube/apis/networking.k8s.io/v1") {
|
if (request.url === "http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1") {
|
||||||
return {
|
return {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
resources: [{
|
resources: [{
|
||||||
@ -33,7 +43,7 @@ describe("KubeApi", () => {
|
|||||||
}] as any[]
|
}] as any[]
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
} else if (request.url === "/api-kube/apis/extensions/v1beta1") {
|
} else if (request.url === "http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1") {
|
||||||
// Even if the old API contains ingresses, KubeApi should prefer the apiBase url
|
// Even if the old API contains ingresses, KubeApi should prefer the apiBase url
|
||||||
return {
|
return {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@ -54,6 +64,7 @@ describe("KubeApi", () => {
|
|||||||
const apiBase = "/apis/networking.k8s.io/v1/ingresses";
|
const apiBase = "/apis/networking.k8s.io/v1/ingresses";
|
||||||
const fallbackApiBase = "/apis/extensions/v1beta1/ingresses";
|
const fallbackApiBase = "/apis/extensions/v1beta1/ingresses";
|
||||||
const kubeApi = new KubeApi({
|
const kubeApi = new KubeApi({
|
||||||
|
request,
|
||||||
objectConstructor: KubeObject,
|
objectConstructor: KubeObject,
|
||||||
apiBase,
|
apiBase,
|
||||||
fallbackApiBases: [fallbackApiBase],
|
fallbackApiBases: [fallbackApiBase],
|
||||||
@ -67,13 +78,13 @@ describe("KubeApi", () => {
|
|||||||
|
|
||||||
it("uses url from fallbackApiBases if apiBase lacks the resource", async () => {
|
it("uses url from fallbackApiBases if apiBase lacks the resource", async () => {
|
||||||
(fetch as any).mockResponse(async (request: any) => {
|
(fetch as any).mockResponse(async (request: any) => {
|
||||||
if (request.url === "/api-kube/apis/networking.k8s.io/v1") {
|
if (request.url === "http://127.0.0.1:9999/api-kube/apis/networking.k8s.io/v1") {
|
||||||
return {
|
return {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
resources: [] as any[]
|
resources: [] as any[]
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
} else if (request.url === "/api-kube/apis/extensions/v1beta1") {
|
} else if (request.url === "http://127.0.0.1:9999/api-kube/apis/extensions/v1beta1") {
|
||||||
return {
|
return {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
resources: [{
|
resources: [{
|
||||||
@ -93,6 +104,7 @@ describe("KubeApi", () => {
|
|||||||
const apiBase = "apis/networking.k8s.io/v1/ingresses";
|
const apiBase = "apis/networking.k8s.io/v1/ingresses";
|
||||||
const fallbackApiBase = "/apis/extensions/v1beta1/ingresses";
|
const fallbackApiBase = "/apis/extensions/v1beta1/ingresses";
|
||||||
const kubeApi = new KubeApi({
|
const kubeApi = new KubeApi({
|
||||||
|
request,
|
||||||
objectConstructor: KubeObject,
|
objectConstructor: KubeObject,
|
||||||
apiBase,
|
apiBase,
|
||||||
fallbackApiBases: [fallbackApiBase],
|
fallbackApiBases: [fallbackApiBase],
|
||||||
@ -19,12 +19,13 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { KubeObjectStore } from "../kube-object.store";
|
import type { KubeObjectStore } from "./kube-object.store";
|
||||||
|
|
||||||
import { action, observable, makeObservable } from "mobx";
|
import { action, observable, makeObservable } from "mobx";
|
||||||
import { autoBind, iter } from "../utils";
|
import { autoBind, iter } from "../utils";
|
||||||
import { KubeApi, parseKubeApi } from "./kube-api";
|
import type { KubeApi } from "./kube-api";
|
||||||
import type { KubeObject } from "./kube-object";
|
import type { KubeObject } from "./kube-object";
|
||||||
|
import { IKubeObjectRef, parseKubeApi, createKubeApiURL } from "./kube-api-parse";
|
||||||
|
|
||||||
export class ApiManager {
|
export class ApiManager {
|
||||||
private apis = observable.map<string, KubeApi<KubeObject>>();
|
private apis = observable.map<string, KubeApi<KubeObject>>();
|
||||||
@ -48,6 +49,8 @@ export class ApiManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerApi(apiBase: string, api: KubeApi<KubeObject>) {
|
registerApi(apiBase: string, api: KubeApi<KubeObject>) {
|
||||||
|
if (!api.apiBase) return;
|
||||||
|
|
||||||
if (!this.apis.has(apiBase)) {
|
if (!this.apis.has(apiBase)) {
|
||||||
this.stores.forEach((store) => {
|
this.stores.forEach((store) => {
|
||||||
if (store.api === api) {
|
if (store.api === api) {
|
||||||
@ -83,14 +86,53 @@ export class ApiManager {
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
registerStore(store: KubeObjectStore<KubeObject>, apis: KubeApi<KubeObject>[] = [store.api]) {
|
registerStore(store: KubeObjectStore<KubeObject>, apis: KubeApi<KubeObject>[] = [store.api]) {
|
||||||
apis.forEach(api => {
|
apis.filter(Boolean).forEach(api => {
|
||||||
this.stores.set(api.apiBase, store);
|
if (api.apiBase) this.stores.set(api.apiBase, store);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getStore<S extends KubeObjectStore<KubeObject>>(api: string | KubeApi<KubeObject>): S | undefined {
|
getStore<S extends KubeObjectStore<KubeObject>>(api: string | KubeApi<KubeObject>): S | undefined {
|
||||||
return this.stores.get(this.resolveApi(api)?.apiBase) as S;
|
return this.stores.get(this.resolveApi(api)?.apiBase) as S;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string {
|
||||||
|
const {
|
||||||
|
kind, apiVersion, name,
|
||||||
|
namespace = parentObject.getNs()
|
||||||
|
} = ref;
|
||||||
|
|
||||||
|
if (!kind) return "";
|
||||||
|
|
||||||
|
// search in registered apis by 'kind' & 'apiVersion'
|
||||||
|
const api = this.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion);
|
||||||
|
|
||||||
|
if (api) {
|
||||||
|
return api.getUrl({ namespace, name });
|
||||||
|
}
|
||||||
|
|
||||||
|
// lookup api by generated resource link
|
||||||
|
const apiPrefixes = ["/apis", "/api"];
|
||||||
|
const resource = kind.endsWith("s") ? `${kind.toLowerCase()}es` : `${kind.toLowerCase()}s`;
|
||||||
|
|
||||||
|
for (const apiPrefix of apiPrefixes) {
|
||||||
|
const apiLink = createKubeApiURL({ apiPrefix, apiVersion, name, namespace, resource });
|
||||||
|
|
||||||
|
if (this.getApi(apiLink)) {
|
||||||
|
return apiLink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve by kind only (hpa's might use refs to older versions of resources for example)
|
||||||
|
const apiByKind = this.getApi(api => api.kind === kind);
|
||||||
|
|
||||||
|
if (apiByKind) {
|
||||||
|
return apiByKind.getUrl({ name, namespace });
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise generate link with default prefix
|
||||||
|
// resource still might exists in k8s, but api is not registered in the app
|
||||||
|
return createKubeApiURL({ apiVersion, name, namespace, resource });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const apiManager = new ApiManager();
|
export const apiManager = new ApiManager();
|
||||||
28
src/common/k8s-api/cluster-context.ts
Normal file
28
src/common/k8s-api/cluster-context.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Cluster } from "../../main/cluster";
|
||||||
|
|
||||||
|
export interface ClusterContext {
|
||||||
|
cluster?: Cluster;
|
||||||
|
allNamespaces: string[]; // available / allowed namespaces from cluster.ts
|
||||||
|
contextNamespaces: string[]; // selected by user (see: namespace-select.tsx)
|
||||||
|
}
|
||||||
@ -18,6 +18,7 @@
|
|||||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
|
|
||||||
@ -53,6 +54,17 @@ export class ClusterRoleBinding extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const clusterRoleBindingApi = new KubeApi({
|
/**
|
||||||
objectConstructor: ClusterRoleBinding,
|
* Only available within kubernetes cluster pages
|
||||||
});
|
*/
|
||||||
|
let clusterRoleBindingApi: KubeApi<ClusterRoleBinding>;
|
||||||
|
|
||||||
|
if (isClusterPageContext()) {
|
||||||
|
clusterRoleBindingApi = new KubeApi({
|
||||||
|
objectConstructor: ClusterRoleBinding,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
clusterRoleBindingApi
|
||||||
|
};
|
||||||
@ -19,6 +19,7 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
|
|
||||||
@ -41,6 +42,17 @@ export class ClusterRole extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const clusterRoleApi = new KubeApi({
|
/**
|
||||||
objectConstructor: ClusterRole,
|
* Only available within kubernetes cluster pages
|
||||||
});
|
*/
|
||||||
|
let clusterRoleApi: KubeApi<ClusterRole>;
|
||||||
|
|
||||||
|
if (isClusterPageContext()) { // initialize automatically only when within a cluster iframe/context
|
||||||
|
clusterRoleApi = new KubeApi({
|
||||||
|
objectConstructor: ClusterRole,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
clusterRoleApi
|
||||||
|
};
|
||||||
@ -22,6 +22,7 @@
|
|||||||
import { IMetrics, IMetricsReqParams, metricsApi } from "./metrics.api";
|
import { IMetrics, IMetricsReqParams, metricsApi } from "./metrics.api";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class ClusterApi extends KubeApi<Cluster> {
|
export class ClusterApi extends KubeApi<Cluster> {
|
||||||
static kind = "Cluster";
|
static kind = "Cluster";
|
||||||
@ -122,6 +123,17 @@ export class Cluster extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const clusterApi = new ClusterApi({
|
/**
|
||||||
objectConstructor: Cluster,
|
* Only available within kubernetes cluster pages
|
||||||
});
|
*/
|
||||||
|
let clusterApi: ClusterApi;
|
||||||
|
|
||||||
|
if (isClusterPageContext()) { // initialize automatically only when within a cluster iframe/context
|
||||||
|
clusterApi = new ClusterApi({
|
||||||
|
objectConstructor: Cluster,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
clusterApi
|
||||||
|
};
|
||||||
@ -22,7 +22,8 @@
|
|||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { autoBind } from "../../../common/utils";
|
import { autoBind } from "../../utils";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface ConfigMap {
|
export interface ConfigMap {
|
||||||
data: {
|
data: {
|
||||||
@ -47,6 +48,17 @@ export class ConfigMap extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const configMapApi = new KubeApi({
|
/**
|
||||||
objectConstructor: ConfigMap,
|
* Only available within kubernetes cluster pages
|
||||||
});
|
*/
|
||||||
|
let configMapApi: KubeApi<ConfigMap>;
|
||||||
|
|
||||||
|
if (isClusterPageContext()) {
|
||||||
|
configMapApi = new KubeApi({
|
||||||
|
objectConstructor: ConfigMap,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
configMapApi
|
||||||
|
};
|
||||||
@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { crdResourcesURL } from "../../../common/routes";
|
import { crdResourcesURL } from "../../routes";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
type AdditionalPrinterColumnsCommon = {
|
type AdditionalPrinterColumnsCommon = {
|
||||||
name: string;
|
name: string;
|
||||||
@ -174,7 +175,18 @@ export class CustomResourceDefinition extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const crdApi = new KubeApi<CustomResourceDefinition>({
|
/**
|
||||||
objectConstructor: CustomResourceDefinition,
|
* Only available within kubernetes cluster pages
|
||||||
checkPreferredVersion: true,
|
*/
|
||||||
});
|
let crdApi: KubeApi<CustomResourceDefinition>;
|
||||||
|
|
||||||
|
if (isClusterPageContext()) {
|
||||||
|
crdApi = new KubeApi<CustomResourceDefinition>({
|
||||||
|
objectConstructor: CustomResourceDefinition,
|
||||||
|
checkPreferredVersion: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
crdApi
|
||||||
|
};
|
||||||
@ -26,6 +26,7 @@ import { formatDuration } from "../../utils/formatDuration";
|
|||||||
import { autoBind } from "../../utils";
|
import { autoBind } from "../../utils";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class CronJobApi extends KubeApi<CronJob> {
|
export class CronJobApi extends KubeApi<CronJob> {
|
||||||
suspend(params: { namespace: string; name: string }) {
|
suspend(params: { namespace: string; name: string }) {
|
||||||
@ -140,6 +141,17 @@ export class CronJob extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cronJobApi = new CronJobApi({
|
/**
|
||||||
objectConstructor: CronJob,
|
* Only available within kubernetes cluster pages
|
||||||
});
|
*/
|
||||||
|
let cronJobApi: CronJobApi;
|
||||||
|
|
||||||
|
if (isClusterPageContext()) {
|
||||||
|
cronJobApi = new CronJobApi({
|
||||||
|
objectConstructor: CronJob,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
cronJobApi
|
||||||
|
};
|
||||||
@ -26,6 +26,7 @@ import { KubeApi } from "../kube-api";
|
|||||||
import { metricsApi } from "./metrics.api";
|
import { metricsApi } from "./metrics.api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
import type { IPodContainer, IPodMetrics } from "./pods.api";
|
import type { IPodContainer, IPodMetrics } from "./pods.api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class DaemonSet extends WorkloadKubeObject {
|
export class DaemonSet extends WorkloadKubeObject {
|
||||||
static kind = "DaemonSet";
|
static kind = "DaemonSet";
|
||||||
@ -116,6 +117,17 @@ export function getMetricsForDaemonSets(daemonsets: DaemonSet[], namespace: stri
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const daemonSetApi = new DaemonSetApi({
|
/**
|
||||||
objectConstructor: DaemonSet,
|
* Only available within kubernetes cluster pages
|
||||||
});
|
*/
|
||||||
|
let daemonSetApi: DaemonSetApi;
|
||||||
|
|
||||||
|
if (isClusterPageContext()) {
|
||||||
|
daemonSetApi = new DaemonSetApi({
|
||||||
|
objectConstructor: DaemonSet,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
daemonSetApi
|
||||||
|
};
|
||||||
@ -27,6 +27,7 @@ import { KubeApi } from "../kube-api";
|
|||||||
import { metricsApi } from "./metrics.api";
|
import { metricsApi } from "./metrics.api";
|
||||||
import type { IPodMetrics } from "./pods.api";
|
import type { IPodMetrics } from "./pods.api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class DeploymentApi extends KubeApi<Deployment> {
|
export class DeploymentApi extends KubeApi<Deployment> {
|
||||||
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
||||||
@ -232,6 +233,14 @@ export class Deployment extends WorkloadKubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const deploymentApi = new DeploymentApi({
|
let deploymentApi: DeploymentApi;
|
||||||
objectConstructor: Deployment,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
deploymentApi = new DeploymentApi({
|
||||||
|
objectConstructor: Deployment,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
deploymentApi
|
||||||
|
};
|
||||||
@ -24,6 +24,7 @@ import { KubeObject } from "../kube-object";
|
|||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
import { get } from "lodash";
|
import { get } from "lodash";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface IEndpointPort {
|
export interface IEndpointPort {
|
||||||
name?: string;
|
name?: string;
|
||||||
@ -149,6 +150,14 @@ export class Endpoint extends KubeObject {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const endpointApi = new KubeApi({
|
let endpointApi: KubeApi<Endpoint>;
|
||||||
objectConstructor: Endpoint,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
endpointApi = new KubeApi<Endpoint>({
|
||||||
|
objectConstructor: Endpoint,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
endpointApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import moment from "moment";
|
|||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { formatDuration } from "../../utils/formatDuration";
|
import { formatDuration } from "../../utils/formatDuration";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface KubeEvent {
|
export interface KubeEvent {
|
||||||
involvedObject: {
|
involvedObject: {
|
||||||
@ -77,6 +78,14 @@ export class KubeEvent extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const eventApi = new KubeApi({
|
let eventApi: KubeApi<KubeEvent>;
|
||||||
objectConstructor: KubeEvent,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
eventApi = new KubeApi<KubeEvent>({
|
||||||
|
objectConstructor: KubeEvent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
eventApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import { compile } from "path-to-regexp";
|
|||||||
import { apiBase } from "../index";
|
import { apiBase } from "../index";
|
||||||
import { stringify } from "querystring";
|
import { stringify } from "querystring";
|
||||||
import { autoBind } from "../../utils";
|
import { autoBind } from "../../utils";
|
||||||
|
import type { RequestInit } from "node-fetch";
|
||||||
|
|
||||||
export type RepoHelmChartList = Record<string, HelmChart[]>;
|
export type RepoHelmChartList = Record<string, HelmChart[]>;
|
||||||
export type HelmChartList = Record<string, RepoHelmChartList>;
|
export type HelmChartList = Record<string, RepoHelmChartList>;
|
||||||
@ -23,11 +23,11 @@ import jsYaml from "js-yaml";
|
|||||||
import { autoBind, formatDuration } from "../../utils";
|
import { autoBind, formatDuration } from "../../utils";
|
||||||
import capitalize from "lodash/capitalize";
|
import capitalize from "lodash/capitalize";
|
||||||
import { apiBase } from "../index";
|
import { apiBase } from "../index";
|
||||||
import { helmChartStore } from "../../components/+apps-helm-charts/helm-chart.store";
|
import { helmChartStore } from "../../../renderer/components/+apps-helm-charts/helm-chart.store";
|
||||||
import type { ItemObject } from "../../item.store";
|
import type { ItemObject } from "../../item.store";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import type { JsonApiData } from "../json-api";
|
import type { JsonApiData } from "../json-api";
|
||||||
import { buildURLPositional } from "../../../common/utils/buildUrl";
|
import { buildURLPositional } from "../../utils/buildUrl";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
|
||||||
interface IReleasePayload {
|
interface IReleasePayload {
|
||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export enum HpaMetricType {
|
export enum HpaMetricType {
|
||||||
Resource = "Resource",
|
Resource = "Resource",
|
||||||
@ -163,6 +164,14 @@ export class HorizontalPodAutoscaler extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const hpaApi = new KubeApi({
|
let hpaApi: KubeApi<HorizontalPodAutoscaler>;
|
||||||
objectConstructor: HorizontalPodAutoscaler,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
hpaApi = new KubeApi<HorizontalPodAutoscaler>({
|
||||||
|
objectConstructor: HorizontalPodAutoscaler,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
hpaApi
|
||||||
|
};
|
||||||
@ -24,6 +24,7 @@ import { autoBind } from "../../utils";
|
|||||||
import { IMetrics, metricsApi } from "./metrics.api";
|
import { IMetrics, metricsApi } from "./metrics.api";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class IngressApi extends KubeApi<Ingress> {
|
export class IngressApi extends KubeApi<Ingress> {
|
||||||
}
|
}
|
||||||
@ -203,10 +204,17 @@ export class Ingress extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ingressApi = new IngressApi({
|
let ingressApi: IngressApi;
|
||||||
objectConstructor: Ingress,
|
|
||||||
// Add fallback for Kubernetes <1.19
|
if (isClusterPageContext()) {
|
||||||
checkPreferredVersion: true,
|
ingressApi = new IngressApi({
|
||||||
fallbackApiBases: ["/apis/extensions/v1beta1/ingresses"],
|
objectConstructor: Ingress,
|
||||||
logStuff: true
|
// Add fallback for Kubernetes <1.19
|
||||||
} as any);
|
checkPreferredVersion: true,
|
||||||
|
fallbackApiBases: ["/apis/extensions/v1beta1/ingresses"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
ingressApi
|
||||||
|
};
|
||||||
@ -27,6 +27,7 @@ import { metricsApi } from "./metrics.api";
|
|||||||
import type { JsonApiParams } from "../json-api";
|
import type { JsonApiParams } from "../json-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
import type { IPodContainer, IPodMetrics } from "./pods.api";
|
import type { IPodContainer, IPodMetrics } from "./pods.api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class Job extends WorkloadKubeObject {
|
export class Job extends WorkloadKubeObject {
|
||||||
static kind = "Job";
|
static kind = "Job";
|
||||||
@ -148,6 +149,14 @@ export function getMetricsForJobs(jobs: Job[], namespace: string, selector = "")
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const jobApi = new JobApi({
|
let jobApi: JobApi;
|
||||||
objectConstructor: Job,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
jobApi = new JobApi({
|
||||||
|
objectConstructor: Job,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
jobApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object";
|
|||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { autoBind } from "../../utils";
|
import { autoBind } from "../../utils";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export enum LimitType {
|
export enum LimitType {
|
||||||
CONTAINER = "Container",
|
CONTAINER = "Container",
|
||||||
@ -80,6 +81,14 @@ export class LimitRange extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const limitRangeApi = new KubeApi({
|
let limitRangeApi: KubeApi<LimitRange>;
|
||||||
objectConstructor: LimitRange,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
limitRangeApi = new KubeApi<LimitRange>({
|
||||||
|
objectConstructor: LimitRange,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
limitRangeApi
|
||||||
|
};
|
||||||
@ -21,10 +21,11 @@
|
|||||||
|
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { autoBind } from "../../utils";
|
import { autoBind } from "../../../renderer/utils";
|
||||||
import { metricsApi } from "./metrics.api";
|
import { metricsApi } from "./metrics.api";
|
||||||
import type { IPodMetrics } from "./pods.api";
|
import type { IPodMetrics } from "./pods.api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export enum NamespaceStatus {
|
export enum NamespaceStatus {
|
||||||
ACTIVE = "Active",
|
ACTIVE = "Active",
|
||||||
@ -69,6 +70,14 @@ export function getMetricsForNamespace(namespace: string, selector = ""): Promis
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const namespacesApi = new NamespaceApi({
|
let namespacesApi: NamespaceApi;
|
||||||
objectConstructor: Namespace,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
namespacesApi = new NamespaceApi({
|
||||||
|
objectConstructor: Namespace,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
namespacesApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object";
|
|||||||
import { autoBind } from "../../utils";
|
import { autoBind } from "../../utils";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface IPolicyIpBlock {
|
export interface IPolicyIpBlock {
|
||||||
cidr: string;
|
cidr: string;
|
||||||
@ -96,6 +97,14 @@ export class NetworkPolicy extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const networkPolicyApi = new KubeApi({
|
let networkPolicyApi: KubeApi<NetworkPolicy>;
|
||||||
objectConstructor: NetworkPolicy,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
networkPolicyApi = new KubeApi<NetworkPolicy>({
|
||||||
|
objectConstructor: NetworkPolicy,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
networkPolicyApi
|
||||||
|
};
|
||||||
@ -20,10 +20,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { autoBind, cpuUnitsToNumber, unitsToBytes } from "../../utils";
|
import { autoBind, cpuUnitsToNumber, unitsToBytes } from "../../../renderer/utils";
|
||||||
import { IMetrics, metricsApi } from "./metrics.api";
|
import { IMetrics, metricsApi } from "./metrics.api";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class NodesApi extends KubeApi<Node> {
|
export class NodesApi extends KubeApi<Node> {
|
||||||
}
|
}
|
||||||
@ -225,6 +226,14 @@ export class Node extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const nodesApi = new NodesApi({
|
let nodesApi: NodesApi;
|
||||||
objectConstructor: Node,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
nodesApi = new NodesApi({
|
||||||
|
objectConstructor: Node,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
nodesApi
|
||||||
|
};
|
||||||
@ -25,6 +25,7 @@ import { IMetrics, metricsApi } from "./metrics.api";
|
|||||||
import type { Pod } from "./pods.api";
|
import type { Pod } from "./pods.api";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class PersistentVolumeClaimsApi extends KubeApi<PersistentVolumeClaim> {
|
export class PersistentVolumeClaimsApi extends KubeApi<PersistentVolumeClaim> {
|
||||||
}
|
}
|
||||||
@ -116,6 +117,14 @@ export class PersistentVolumeClaim extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const pvcApi = new PersistentVolumeClaimsApi({
|
let pvcApi: PersistentVolumeClaimsApi;
|
||||||
objectConstructor: PersistentVolumeClaim,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
pvcApi = new PersistentVolumeClaimsApi({
|
||||||
|
objectConstructor: PersistentVolumeClaim,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
pvcApi
|
||||||
|
};
|
||||||
@ -20,10 +20,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { unitsToBytes } from "../../utils/convertMemory";
|
import { autoBind, unitsToBytes } from "../../utils";
|
||||||
import { autoBind } from "../../utils";
|
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface PersistentVolume {
|
export interface PersistentVolume {
|
||||||
spec: {
|
spec: {
|
||||||
@ -102,6 +102,14 @@ export class PersistentVolume extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const persistentVolumeApi = new KubeApi({
|
let persistentVolumeApi: KubeApi<PersistentVolume>;
|
||||||
objectConstructor: PersistentVolume,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
persistentVolumeApi = new KubeApi({
|
||||||
|
objectConstructor: PersistentVolume,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
persistentVolumeApi
|
||||||
|
};
|
||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface PodMetrics {
|
export interface PodMetrics {
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
@ -40,6 +41,14 @@ export class PodMetrics extends KubeObject {
|
|||||||
static apiBase = "/apis/metrics.k8s.io/v1beta1/pods";
|
static apiBase = "/apis/metrics.k8s.io/v1beta1/pods";
|
||||||
}
|
}
|
||||||
|
|
||||||
export const podMetricsApi = new KubeApi({
|
let podMetricsApi: KubeApi<PodMetrics>;
|
||||||
objectConstructor: PodMetrics,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
podMetricsApi = new KubeApi<PodMetrics>({
|
||||||
|
objectConstructor: PodMetrics,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
podMetricsApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
|
|||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface PodDisruptionBudget {
|
export interface PodDisruptionBudget {
|
||||||
spec: {
|
spec: {
|
||||||
@ -72,6 +73,14 @@ export class PodDisruptionBudget extends KubeObject {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const pdbApi = new KubeApi({
|
let pdbApi: KubeApi<PodDisruptionBudget>;
|
||||||
objectConstructor: PodDisruptionBudget,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
pdbApi = new KubeApi({
|
||||||
|
objectConstructor: PodDisruptionBudget,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
pdbApi
|
||||||
|
};
|
||||||
@ -24,6 +24,7 @@ import { autoBind } from "../../utils";
|
|||||||
import { IMetrics, metricsApi } from "./metrics.api";
|
import { IMetrics, metricsApi } from "./metrics.api";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class PodsApi extends KubeApi<Pod> {
|
export class PodsApi extends KubeApi<Pod> {
|
||||||
async getLogs(params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise<string> {
|
async getLogs(params: { namespace: string; name: string }, query?: IPodLogsQuery): Promise<string> {
|
||||||
@ -502,6 +503,14 @@ export class Pod extends WorkloadKubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const podsApi = new PodsApi({
|
let podsApi: PodsApi;
|
||||||
objectConstructor: Pod,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
podsApi = new PodsApi({
|
||||||
|
objectConstructor: Pod,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
podsApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
|
|||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface PodSecurityPolicy {
|
export interface PodSecurityPolicy {
|
||||||
spec: {
|
spec: {
|
||||||
@ -117,6 +118,14 @@ export class PodSecurityPolicy extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const pspApi = new KubeApi({
|
let pspApi: KubeApi<PodSecurityPolicy>;
|
||||||
objectConstructor: PodSecurityPolicy,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
pspApi = new KubeApi({
|
||||||
|
objectConstructor: PodSecurityPolicy,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
pspApi
|
||||||
|
};
|
||||||
@ -20,12 +20,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import get from "lodash/get";
|
import get from "lodash/get";
|
||||||
import { autoBind } from "../../utils";
|
import { autoBind } from "../../../renderer/utils";
|
||||||
import { WorkloadKubeObject } from "../workload-kube-object";
|
import { WorkloadKubeObject } from "../workload-kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import { metricsApi } from "./metrics.api";
|
import { metricsApi } from "./metrics.api";
|
||||||
import type { IPodContainer, IPodMetrics, Pod } from "./pods.api";
|
import type { IPodContainer, IPodMetrics, Pod } from "./pods.api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class ReplicaSetApi extends KubeApi<ReplicaSet> {
|
export class ReplicaSetApi extends KubeApi<ReplicaSet> {
|
||||||
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
||||||
@ -123,6 +124,14 @@ export class ReplicaSet extends WorkloadKubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const replicaSetApi = new ReplicaSetApi({
|
let replicaSetApi: ReplicaSetApi;
|
||||||
objectConstructor: ReplicaSet,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
replicaSetApi = new ReplicaSetApi({
|
||||||
|
objectConstructor: ReplicaSet,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
replicaSetApi
|
||||||
|
};
|
||||||
@ -20,35 +20,21 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import jsYaml from "js-yaml";
|
import jsYaml from "js-yaml";
|
||||||
import { KubeObject } from "../kube-object";
|
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
import { apiBase } from "../index";
|
import { apiBase } from "../index";
|
||||||
import { apiManager } from "../api-manager";
|
|
||||||
|
|
||||||
export const resourceApplierApi = {
|
export const resourceApplierApi = {
|
||||||
annotations: [
|
annotations: [
|
||||||
"kubectl.kubernetes.io/last-applied-configuration"
|
"kubectl.kubernetes.io/last-applied-configuration"
|
||||||
],
|
],
|
||||||
|
|
||||||
async update<K extends KubeObject>(resource: object | string): Promise<K | null> {
|
async update(resource: object | string): Promise<KubeJsonApiData | null> {
|
||||||
if (typeof resource === "string") {
|
if (typeof resource === "string") {
|
||||||
resource = jsYaml.safeLoad(resource);
|
resource = jsYaml.safeLoad(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return apiBase
|
const [data = null] = await apiBase.post<KubeJsonApiData[]>("/stack", { data: resource });
|
||||||
.post<KubeJsonApiData[]>("/stack", { data: resource })
|
|
||||||
.then(data => {
|
|
||||||
const items = data.map(obj => {
|
|
||||||
const api = apiManager.getApiByKind(obj.kind, obj.apiVersion);
|
|
||||||
|
|
||||||
if (api) {
|
return data;
|
||||||
return new api.objectConstructor(obj);
|
|
||||||
} else {
|
|
||||||
return new KubeObject(obj);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return items[0] as K ?? null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface IResourceQuotaValues {
|
export interface IResourceQuotaValues {
|
||||||
[quota: string]: string;
|
[quota: string]: string;
|
||||||
@ -80,6 +81,14 @@ export class ResourceQuota extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const resourceQuotaApi = new KubeApi({
|
let resourceQuotaApi: KubeApi<ResourceQuota>;
|
||||||
objectConstructor: ResourceQuota,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
resourceQuotaApi = new KubeApi<ResourceQuota>({
|
||||||
|
objectConstructor: ResourceQuota,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
resourceQuotaApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
|
|||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export type RoleBindingSubjectKind = "Group" | "ServiceAccount" | "User";
|
export type RoleBindingSubjectKind = "Group" | "ServiceAccount" | "User";
|
||||||
|
|
||||||
@ -61,6 +62,14 @@ export class RoleBinding extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const roleBindingApi = new KubeApi({
|
let roleBindingApi: KubeApi<RoleBinding>;
|
||||||
objectConstructor: RoleBinding,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
roleBindingApi = new KubeApi({
|
||||||
|
objectConstructor: RoleBinding,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
roleBindingApi
|
||||||
|
};
|
||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface Role {
|
export interface Role {
|
||||||
rules: {
|
rules: {
|
||||||
@ -41,6 +42,14 @@ export class Role extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const roleApi = new KubeApi({
|
let roleApi: KubeApi<Role>;
|
||||||
objectConstructor: Role,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
roleApi = new KubeApi<Role>({
|
||||||
|
objectConstructor: Role,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export{
|
||||||
|
roleApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import { KubeObject } from "../kube-object";
|
|||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
import { autoBind } from "../../utils";
|
import { autoBind } from "../../utils";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export enum SecretType {
|
export enum SecretType {
|
||||||
Opaque = "Opaque",
|
Opaque = "Opaque",
|
||||||
@ -69,6 +70,14 @@ export class Secret extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const secretsApi = new KubeApi({
|
let secretsApi: KubeApi<Secret>;
|
||||||
objectConstructor: Secret,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
secretsApi = new KubeApi({
|
||||||
|
objectConstructor: Secret,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
secretsApi
|
||||||
|
};
|
||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class SelfSubjectRulesReviewApi extends KubeApi<SelfSubjectRulesReview> {
|
export class SelfSubjectRulesReviewApi extends KubeApi<SelfSubjectRulesReview> {
|
||||||
create({ namespace = "default" }): Promise<SelfSubjectRulesReview> {
|
create({ namespace = "default" }): Promise<SelfSubjectRulesReview> {
|
||||||
@ -86,6 +87,15 @@ export class SelfSubjectRulesReview extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selfSubjectRulesReviewApi = new SelfSubjectRulesReviewApi({
|
let selfSubjectRulesReviewApi: SelfSubjectRulesReviewApi;
|
||||||
objectConstructor: SelfSubjectRulesReview,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
selfSubjectRulesReviewApi = new SelfSubjectRulesReviewApi({
|
||||||
|
objectConstructor: SelfSubjectRulesReview,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
selfSubjectRulesReviewApi
|
||||||
|
};
|
||||||
|
|
||||||
@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
|
|||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface ServiceAccount {
|
export interface ServiceAccount {
|
||||||
secrets?: {
|
secrets?: {
|
||||||
@ -52,6 +53,14 @@ export class ServiceAccount extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const serviceAccountsApi = new KubeApi<ServiceAccount>({
|
let serviceAccountsApi: KubeApi<ServiceAccount>;
|
||||||
objectConstructor: ServiceAccount,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
serviceAccountsApi = new KubeApi<ServiceAccount>({
|
||||||
|
objectConstructor: ServiceAccount,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
serviceAccountsApi
|
||||||
|
};
|
||||||
@ -19,10 +19,11 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { autoBind } from "../../utils";
|
import { autoBind } from "../../../renderer/utils";
|
||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface ServicePort {
|
export interface ServicePort {
|
||||||
name?: string;
|
name?: string;
|
||||||
@ -143,6 +144,14 @@ export class Service extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const serviceApi = new KubeApi({
|
let serviceApi: KubeApi<Service>;
|
||||||
objectConstructor: Service,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
serviceApi = new KubeApi<Service>({
|
||||||
|
objectConstructor: Service,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
serviceApi
|
||||||
|
};
|
||||||
@ -26,6 +26,7 @@ import { KubeApi } from "../kube-api";
|
|||||||
import { metricsApi } from "./metrics.api";
|
import { metricsApi } from "./metrics.api";
|
||||||
import type { IPodContainer, IPodMetrics } from "./pods.api";
|
import type { IPodContainer, IPodMetrics } from "./pods.api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export class StatefulSetApi extends KubeApi<StatefulSet> {
|
export class StatefulSetApi extends KubeApi<StatefulSet> {
|
||||||
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
protected getScaleApiUrl(params: { namespace: string; name: string }) {
|
||||||
@ -149,6 +150,14 @@ export class StatefulSet extends WorkloadKubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const statefulSetApi = new StatefulSetApi({
|
let statefulSetApi: StatefulSetApi;
|
||||||
objectConstructor: StatefulSet,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
statefulSetApi = new StatefulSetApi({
|
||||||
|
objectConstructor: StatefulSet,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
statefulSetApi
|
||||||
|
};
|
||||||
@ -23,6 +23,7 @@ import { autoBind } from "../../utils";
|
|||||||
import { KubeObject } from "../kube-object";
|
import { KubeObject } from "../kube-object";
|
||||||
import { KubeApi } from "../kube-api";
|
import { KubeApi } from "../kube-api";
|
||||||
import type { KubeJsonApiData } from "../kube-json-api";
|
import type { KubeJsonApiData } from "../kube-json-api";
|
||||||
|
import { isClusterPageContext } from "../../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
export interface StorageClass {
|
export interface StorageClass {
|
||||||
provisioner: string; // e.g. "storage.k8s.io/v1"
|
provisioner: string; // e.g. "storage.k8s.io/v1"
|
||||||
@ -62,6 +63,14 @@ export class StorageClass extends KubeObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const storageClassApi = new KubeApi({
|
let storageClassApi: KubeApi<StorageClass>;
|
||||||
objectConstructor: StorageClass,
|
|
||||||
});
|
if (isClusterPageContext()) {
|
||||||
|
storageClassApi = new KubeApi({
|
||||||
|
objectConstructor: StorageClass,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
storageClassApi
|
||||||
|
};
|
||||||
67
src/common/k8s-api/index.ts
Normal file
67
src/common/k8s-api/index.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { JsonApi } from "./json-api";
|
||||||
|
import { KubeJsonApi } from "./kube-json-api";
|
||||||
|
import { apiKubePrefix, apiPrefix, isDebugging, isDevelopment } from "../../common/vars";
|
||||||
|
import { isClusterPageContext } from "../utils/cluster-id-url-parsing";
|
||||||
|
|
||||||
|
let apiBase: JsonApi;
|
||||||
|
let apiKube: KubeJsonApi;
|
||||||
|
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
apiBase = new JsonApi({
|
||||||
|
serverAddress: `http://127.0.0.1:${process.env.LENS_PROXY_PORT}`,
|
||||||
|
apiBase: apiPrefix,
|
||||||
|
debug: isDevelopment || isDebugging,
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
"Host": `localhost:${process.env.LENS_PROXY_PORT}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
apiBase = new JsonApi({
|
||||||
|
serverAddress: `http://127.0.0.1:${window.location.port}`,
|
||||||
|
apiBase: apiPrefix,
|
||||||
|
debug: isDevelopment || isDebugging,
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
"Host": window.location.host
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isClusterPageContext()) {
|
||||||
|
apiKube = new KubeJsonApi({
|
||||||
|
serverAddress: `http://127.0.0.1:${window.location.port}`,
|
||||||
|
apiBase: apiKubePrefix,
|
||||||
|
debug: isDevelopment
|
||||||
|
}, {
|
||||||
|
headers: {
|
||||||
|
"Host": window.location.host
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
apiBase,
|
||||||
|
apiKube
|
||||||
|
};
|
||||||
@ -21,9 +21,11 @@
|
|||||||
|
|
||||||
// Base http-service / json-api class
|
// Base http-service / json-api class
|
||||||
|
|
||||||
|
import { merge } from "lodash";
|
||||||
|
import fetch, { Response, RequestInit } from "node-fetch";
|
||||||
import { stringify } from "querystring";
|
import { stringify } from "querystring";
|
||||||
import { EventEmitter } from "../../common/event-emitter";
|
import { EventEmitter } from "../../common/event-emitter";
|
||||||
import { randomBytes } from "crypto";
|
import logger from "../../common/logger";
|
||||||
|
|
||||||
export interface JsonApiData {
|
export interface JsonApiData {
|
||||||
}
|
}
|
||||||
@ -49,9 +51,9 @@ export interface JsonApiLog {
|
|||||||
|
|
||||||
export interface JsonApiConfig {
|
export interface JsonApiConfig {
|
||||||
apiBase: string;
|
apiBase: string;
|
||||||
|
serverAddress: string;
|
||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
||||||
static reqInitDefault: RequestInit = {
|
static reqInitDefault: RequestInit = {
|
||||||
headers: {
|
headers: {
|
||||||
@ -63,9 +65,9 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
|||||||
debug: false
|
debug: false
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(protected config: JsonApiConfig, protected reqInit?: RequestInit) {
|
constructor(public readonly config: JsonApiConfig, protected reqInit?: RequestInit) {
|
||||||
this.config = Object.assign({}, JsonApi.configDefault, config);
|
this.config = Object.assign({}, JsonApi.configDefault, config);
|
||||||
this.reqInit = Object.assign({}, JsonApi.reqInitDefault, reqInit);
|
this.reqInit = merge({}, JsonApi.reqInitDefault, reqInit);
|
||||||
this.parseResponse = this.parseResponse.bind(this);
|
this.parseResponse = this.parseResponse.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,10 +79,8 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getResponse(path: string, params?: P, init: RequestInit = {}): Promise<Response> {
|
getResponse(path: string, params?: P, init: RequestInit = {}): Promise<Response> {
|
||||||
const reqPath = `${this.config.apiBase}${path}`;
|
let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`;
|
||||||
const subdomain = randomBytes(2).toString("hex");
|
const reqInit: RequestInit = merge({}, this.reqInit, init);
|
||||||
let reqUrl = `http://${subdomain}.${window.location.host}${reqPath}`; // hack around browser connection limits (chromium allows 6 per domain)
|
|
||||||
const reqInit: RequestInit = { ...init };
|
|
||||||
const { query } = params || {} as P;
|
const { query } = params || {} as P;
|
||||||
|
|
||||||
if (!reqInit.method) {
|
if (!reqInit.method) {
|
||||||
@ -95,7 +95,7 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
|||||||
|
|
||||||
this.writeLog({
|
this.writeLog({
|
||||||
method: reqInit.method.toUpperCase(),
|
method: reqInit.method.toUpperCase(),
|
||||||
reqUrl: reqPath,
|
reqUrl,
|
||||||
reqInit,
|
reqInit,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -119,8 +119,8 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected async request<D>(path: string, params?: P, init: RequestInit = {}) {
|
protected async request<D>(path: string, params?: P, init: RequestInit = {}) {
|
||||||
let reqUrl = this.config.apiBase + path;
|
let reqUrl = `${this.config.serverAddress}${this.config.apiBase}${path}`;
|
||||||
const reqInit: RequestInit = { ...this.reqInit, ...init };
|
const reqInit: RequestInit = merge({}, this.reqInit, init);
|
||||||
const { data, query } = params || {} as P;
|
const { data, query } = params || {} as P;
|
||||||
|
|
||||||
if (data && !reqInit.body) {
|
if (data && !reqInit.body) {
|
||||||
@ -192,13 +192,9 @@ export class JsonApi<D = JsonApiData, P extends JsonApiParams = JsonApiParams> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected writeLog(log: JsonApiLog) {
|
protected writeLog(log: JsonApiLog) {
|
||||||
if (!this.config.debug) return;
|
|
||||||
const { method, reqUrl, ...params } = log;
|
const { method, reqUrl, ...params } = log;
|
||||||
let textStyle = "font-weight: bold;";
|
|
||||||
|
|
||||||
if (params.data) textStyle += "background: green; color: white;";
|
logger.info(`[JSON-API] request ${method} ${reqUrl}`, params);
|
||||||
if (params.error) textStyle += "background: red; color: white;";
|
|
||||||
console.log(`%c${method} ${reqUrl}`, textStyle, params);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,10 +21,8 @@
|
|||||||
|
|
||||||
// Parse kube-api path and get api-version, group, etc.
|
// Parse kube-api path and get api-version, group, etc.
|
||||||
|
|
||||||
import type { KubeObject } from "./kube-object";
|
import { splitArray } from "../utils";
|
||||||
import { splitArray } from "../../common/utils";
|
import { isDebugging } from "../vars";
|
||||||
import { apiManager } from "./api-manager";
|
|
||||||
import { isDebugging } from "../../common/vars";
|
|
||||||
import logger from "../../main/logger";
|
import logger from "../../main/logger";
|
||||||
import { inspect } from "util";
|
import { inspect } from "util";
|
||||||
|
|
||||||
@ -68,7 +66,7 @@ export function parseKubeApi(path: string): IKubeApiParsed {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _parseKubeApi(path: string): IKubeApiParsed {
|
function _parseKubeApi(path: string): IKubeApiParsed {
|
||||||
const apiPath = new URL(path, location.origin).pathname;
|
const apiPath = new URL(path, "http://localhost").pathname;
|
||||||
const [, prefix, ...parts] = apiPath.split("/");
|
const [, prefix, ...parts] = apiPath.split("/");
|
||||||
const apiPrefix = `/${prefix}`;
|
const apiPrefix = `/${prefix}`;
|
||||||
const [left, right, namespaced] = splitArray(parts, "namespaces");
|
const [left, right, namespaced] = splitArray(parts, "namespaces");
|
||||||
@ -159,42 +157,3 @@ export function createKubeApiURL(ref: IKubeApiLinkRef): string {
|
|||||||
.filter(v => v)
|
.filter(v => v)
|
||||||
.join("/");
|
.join("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function lookupApiLink(ref: IKubeObjectRef, parentObject: KubeObject): string {
|
|
||||||
const {
|
|
||||||
kind, apiVersion, name,
|
|
||||||
namespace = parentObject.getNs()
|
|
||||||
} = ref;
|
|
||||||
|
|
||||||
if (!kind) return "";
|
|
||||||
|
|
||||||
// search in registered apis by 'kind' & 'apiVersion'
|
|
||||||
const api = apiManager.getApi(api => api.kind === kind && api.apiVersionWithGroup == apiVersion);
|
|
||||||
|
|
||||||
if (api) {
|
|
||||||
return api.getUrl({ namespace, name });
|
|
||||||
}
|
|
||||||
|
|
||||||
// lookup api by generated resource link
|
|
||||||
const apiPrefixes = ["/apis", "/api"];
|
|
||||||
const resource = kind.endsWith("s") ? `${kind.toLowerCase()}es` : `${kind.toLowerCase()}s`;
|
|
||||||
|
|
||||||
for (const apiPrefix of apiPrefixes) {
|
|
||||||
const apiLink = createKubeApiURL({ apiPrefix, apiVersion, name, namespace, resource });
|
|
||||||
|
|
||||||
if (apiManager.getApi(apiLink)) {
|
|
||||||
return apiLink;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve by kind only (hpa's might use refs to older versions of resources for example)
|
|
||||||
const apiByKind = apiManager.getApi(api => api.kind === kind);
|
|
||||||
|
|
||||||
if (apiByKind) {
|
|
||||||
return apiByKind.getUrl({ name, namespace });
|
|
||||||
}
|
|
||||||
|
|
||||||
// otherwise generate link with default prefix
|
|
||||||
// resource still might exists in k8s, but api is not registered in the app
|
|
||||||
return createKubeApiURL({ apiVersion, name, namespace, resource });
|
|
||||||
}
|
|
||||||
@ -23,17 +23,18 @@
|
|||||||
|
|
||||||
import merge from "lodash/merge";
|
import merge from "lodash/merge";
|
||||||
import { stringify } from "querystring";
|
import { stringify } from "querystring";
|
||||||
import { apiKubePrefix, isDevelopment, isTestEnv } from "../../common/vars";
|
import { apiKubePrefix, isDevelopment } from "../../common/vars";
|
||||||
import logger from "../../main/logger";
|
import logger from "../../main/logger";
|
||||||
import { apiManager } from "./api-manager";
|
import { apiManager } from "./api-manager";
|
||||||
import { apiKube } from "./index";
|
import { apiBase, apiKube } from "./index";
|
||||||
import { createKubeApiURL, parseKubeApi } from "./kube-api-parse";
|
import { createKubeApiURL, parseKubeApi } from "./kube-api-parse";
|
||||||
import { KubeObjectConstructor, KubeObject, KubeStatus } from "./kube-object";
|
import { KubeObjectConstructor, KubeObject, KubeStatus } from "./kube-object";
|
||||||
import byline from "byline";
|
import byline from "byline";
|
||||||
import type { IKubeWatchEvent } from "./kube-watch-api";
|
import type { IKubeWatchEvent } from "./kube-watch-api";
|
||||||
import { ReadableWebToNodeStream } from "../utils/readableStream";
|
|
||||||
import { KubeJsonApi, KubeJsonApiData } from "./kube-json-api";
|
import { KubeJsonApi, KubeJsonApiData } from "./kube-json-api";
|
||||||
import { noop } from "../utils";
|
import { noop } from "../utils";
|
||||||
|
import type { RequestInit } from "node-fetch";
|
||||||
|
import AbortController from "abort-controller";
|
||||||
|
|
||||||
export interface IKubeApiOptions<T extends KubeObject> {
|
export interface IKubeApiOptions<T extends KubeObject> {
|
||||||
/**
|
/**
|
||||||
@ -56,11 +57,6 @@ export interface IKubeApiOptions<T extends KubeObject> {
|
|||||||
checkPreferredVersion?: boolean;
|
checkPreferredVersion?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KubeApiListOptions {
|
|
||||||
namespace?: string;
|
|
||||||
reqInit?: RequestInit;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IKubeApiQueryParams {
|
export interface IKubeApiQueryParams {
|
||||||
watch?: boolean | number;
|
watch?: boolean | number;
|
||||||
resourceVersion?: string;
|
resourceVersion?: string;
|
||||||
@ -101,11 +97,12 @@ export interface IKubeApiCluster {
|
|||||||
|
|
||||||
export function forCluster<T extends KubeObject>(cluster: IKubeApiCluster, kubeClass: KubeObjectConstructor<T>): KubeApi<T> {
|
export function forCluster<T extends KubeObject>(cluster: IKubeApiCluster, kubeClass: KubeObjectConstructor<T>): KubeApi<T> {
|
||||||
const request = new KubeJsonApi({
|
const request = new KubeJsonApi({
|
||||||
|
serverAddress: apiBase.config.serverAddress,
|
||||||
apiBase: apiKubePrefix,
|
apiBase: apiKubePrefix,
|
||||||
debug: isDevelopment,
|
debug: isDevelopment,
|
||||||
}, {
|
}, {
|
||||||
headers: {
|
headers: {
|
||||||
"X-Cluster-ID": cluster.metadata.uid
|
"Host": apiBase.config.serverAddress
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -173,7 +170,6 @@ export class KubeApi<T extends KubeObject> {
|
|||||||
this.request = request;
|
this.request = request;
|
||||||
this.objectConstructor = objectConstructor;
|
this.objectConstructor = objectConstructor;
|
||||||
|
|
||||||
this.checkPreferredVersion();
|
|
||||||
this.parseResponse = this.parseResponse.bind(this);
|
this.parseResponse = this.parseResponse.bind(this);
|
||||||
apiManager.registerApi(apiBase, this);
|
apiManager.registerApi(apiBase, this);
|
||||||
}
|
}
|
||||||
@ -206,18 +202,9 @@ export class KubeApi<T extends KubeObject> {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Exception is ignored as we can try the next url
|
// Exception is ignored as we can try the next url
|
||||||
console.error(error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid throwing in tests
|
|
||||||
if (isTestEnv) {
|
|
||||||
return {
|
|
||||||
apiPrefix: this.apiPrefix,
|
|
||||||
apiGroup: this.apiGroup
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`Can't find working API for the Kubernetes resource ${this.apiResource}`);
|
throw new Error(`Can't find working API for the Kubernetes resource ${this.apiResource}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +427,7 @@ export class KubeApi<T extends KubeObject> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const watchUrl = this.getWatchUrl(namespace);
|
const watchUrl = this.getWatchUrl(namespace);
|
||||||
const responsePromise = this.request.getResponse(watchUrl, null, { signal });
|
const responsePromise = this.request.getResponse(watchUrl, null, { signal, timeout: 600_000 });
|
||||||
|
|
||||||
responsePromise
|
responsePromise
|
||||||
.then(response => {
|
.then(response => {
|
||||||
@ -448,10 +435,8 @@ export class KubeApi<T extends KubeObject> {
|
|||||||
return callback(null, response);
|
return callback(null, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
const nodeStream = new ReadableWebToNodeStream(response.body);
|
|
||||||
|
|
||||||
["end", "close", "error"].forEach((eventName) => {
|
["end", "close", "error"].forEach((eventName) => {
|
||||||
nodeStream.on(eventName, () => {
|
response.body.on(eventName, () => {
|
||||||
if (errorReceived) return; // kubernetes errors should be handled in a callback
|
if (errorReceived) return; // kubernetes errors should be handled in a callback
|
||||||
|
|
||||||
clearTimeout(timedRetry);
|
clearTimeout(timedRetry);
|
||||||
@ -461,7 +446,7 @@ export class KubeApi<T extends KubeObject> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
byline(nodeStream).on("data", (line) => {
|
byline(response.body).on("data", (line) => {
|
||||||
try {
|
try {
|
||||||
const event: IKubeWatchEvent<KubeJsonApiData> = JSON.parse(line);
|
const event: IKubeWatchEvent<KubeJsonApiData> = JSON.parse(line);
|
||||||
|
|
||||||
@ -479,7 +464,7 @@ export class KubeApi<T extends KubeObject> {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (error instanceof DOMException) return; // AbortController rejects, we can ignore it
|
if (error?.type === "aborted") return; // AbortController rejects, we can ignore it
|
||||||
|
|
||||||
callback(null, error);
|
callback(null, error);
|
||||||
});
|
});
|
||||||
@ -506,5 +491,3 @@ export class KubeApi<T extends KubeObject> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export * from "./kube-api-parse";
|
|
||||||
@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { JsonApi, JsonApiData, JsonApiError } from "./json-api";
|
import { JsonApi, JsonApiData, JsonApiError } from "./json-api";
|
||||||
|
import type { Response } from "node-fetch";
|
||||||
|
|
||||||
export interface KubeJsonApiListMetadata {
|
export interface KubeJsonApiListMetadata {
|
||||||
resourceVersion: string;
|
resourceVersion: string;
|
||||||
@ -79,3 +80,4 @@ export class KubeJsonApi extends JsonApi<KubeJsonApiData> {
|
|||||||
return super.parseError(error, res);
|
return super.parseError(error, res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,17 +19,19 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { ClusterContext } from "./components/context";
|
import type { ClusterContext } from "./cluster-context";
|
||||||
|
|
||||||
import { action, computed, makeObservable, observable, reaction, when } from "mobx";
|
import { action, computed, makeObservable, observable, reaction, when } from "mobx";
|
||||||
import { autoBind, noop, rejectPromiseBy } from "./utils";
|
import { autoBind, noop, rejectPromiseBy } from "../utils";
|
||||||
import { KubeObject, KubeStatus } from "./api/kube-object";
|
import { KubeObject, KubeStatus } from "./kube-object";
|
||||||
import type { IKubeWatchEvent } from "./api/kube-watch-api";
|
import type { IKubeWatchEvent } from "./kube-watch-api";
|
||||||
import { ItemStore } from "./item.store";
|
import { ItemStore } from "../item.store";
|
||||||
import { apiManager } from "./api/api-manager";
|
import { apiManager } from "./api-manager";
|
||||||
import { ensureObjectSelfLink, IKubeApiQueryParams, KubeApi, parseKubeApi } from "./api/kube-api";
|
import { ensureObjectSelfLink, IKubeApiQueryParams, KubeApi } from "./kube-api";
|
||||||
import type { KubeJsonApiData } from "./api/kube-json-api";
|
import { parseKubeApi } from "./kube-api-parse";
|
||||||
import { Notifications } from "./components/notifications";
|
import type { KubeJsonApiData } from "./kube-json-api";
|
||||||
|
import type { RequestInit } from "node-fetch";
|
||||||
|
import AbortController from "abort-controller";
|
||||||
|
|
||||||
export interface KubeObjectStoreLoadingParams<K extends KubeObject> {
|
export interface KubeObjectStoreLoadingParams<K extends KubeObject> {
|
||||||
namespaces: string[];
|
namespaces: string[];
|
||||||
@ -192,9 +194,6 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
|
|
||||||
return items;
|
return items;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.message) {
|
|
||||||
Notifications.error(error.message);
|
|
||||||
}
|
|
||||||
console.warn("[KubeObjectStore] loadAll failed", this.api.apiBase, error);
|
console.warn("[KubeObjectStore] loadAll failed", this.api.apiBase, error);
|
||||||
this.resetOnError(error);
|
this.resetOnError(error);
|
||||||
this.failedLoading = true;
|
this.failedLoading = true;
|
||||||
@ -279,7 +278,8 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
async update(item: T, data: Partial<T>): Promise<T> {
|
async update(item: T, data: Partial<T>): Promise<T> {
|
||||||
const newItem = await item.update(data);
|
const rawItem = await item.update(data);
|
||||||
|
const newItem = new this.api.objectConstructor(rawItem);
|
||||||
|
|
||||||
ensureObjectSelfLink(this.api, newItem);
|
ensureObjectSelfLink(this.api, newItem);
|
||||||
|
|
||||||
@ -346,7 +346,7 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
|
|||||||
const { signal } = abortController;
|
const { signal } = abortController;
|
||||||
|
|
||||||
const callback = (data: IKubeWatchEvent<T>, error: any) => {
|
const callback = (data: IKubeWatchEvent<T>, error: any) => {
|
||||||
if (!this.isLoaded || error instanceof DOMException) return;
|
if (!this.isLoaded || error?.type === "aborted") return;
|
||||||
|
|
||||||
if (error instanceof Response) {
|
if (error instanceof Response) {
|
||||||
if (error.status === 404 || error.status === 401) {
|
if (error.status === 404 || error.status === 401) {
|
||||||
@ -86,6 +86,16 @@ export class KubeStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface KubeObjectStatus {
|
||||||
|
conditions?: {
|
||||||
|
lastTransitionTime: string;
|
||||||
|
message: string;
|
||||||
|
reason: string;
|
||||||
|
status: string;
|
||||||
|
type?: string;
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
export type KubeMetaField = keyof KubeObjectMetadata;
|
export type KubeMetaField = keyof KubeObjectMetadata;
|
||||||
|
|
||||||
export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
|
export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata, Status = any, Spec = any> implements ItemObject {
|
||||||
@ -277,14 +287,14 @@ export class KubeObject<Metadata extends KubeObjectMetadata = KubeObjectMetadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use unified resource-applier api for updating all k8s objects
|
// use unified resource-applier api for updating all k8s objects
|
||||||
async update<K extends KubeObject>(data: Partial<K>): Promise<K> {
|
async update(data: Partial<this>): Promise<KubeJsonApiData | null> {
|
||||||
for (const field of KubeObject.nonEditableFields) {
|
for (const field of KubeObject.nonEditableFields) {
|
||||||
if (!_.isEqual(_.get(this, field), _.get(data, field))) {
|
if (!_.isEqual(_.get(this, field), _.get(data, field))) {
|
||||||
throw new Error(`Failed to update Kube Object: ${field} has been modified`);
|
throw new Error(`Failed to update Kube Object: ${field} has been modified`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resourceApplierApi.update<K>({
|
return resourceApplierApi.update({
|
||||||
...this.toPlainObject(),
|
...this.toPlainObject(),
|
||||||
...data,
|
...data,
|
||||||
});
|
});
|
||||||
@ -22,15 +22,15 @@
|
|||||||
// Kubernetes watch-api client
|
// Kubernetes watch-api client
|
||||||
// API: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
|
// API: https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_readable_streams
|
||||||
|
|
||||||
import type { KubeObjectStore } from "../kube-object.store";
|
import type { KubeObjectStore } from "./kube-object.store";
|
||||||
import type { ClusterContext } from "../components/context";
|
import type { ClusterContext } from "./cluster-context";
|
||||||
|
|
||||||
import plimit from "p-limit";
|
import plimit from "p-limit";
|
||||||
import { comparer, observable, reaction, makeObservable } from "mobx";
|
import { comparer, observable, reaction, makeObservable } from "mobx";
|
||||||
import { autoBind, Disposer, noop } from "../utils";
|
import { autoBind, Disposer, noop } from "../utils";
|
||||||
import type { KubeApi } from "./kube-api";
|
import type { KubeApi } from "./kube-api";
|
||||||
import type { KubeJsonApiData } from "./kube-json-api";
|
import type { KubeJsonApiData } from "./kube-json-api";
|
||||||
import { isDebugging, isProduction } from "../../common/vars";
|
import { isDebugging, isProduction } from "../vars";
|
||||||
import type { KubeObject } from "./kube-object";
|
import type { KubeObject } from "./kube-object";
|
||||||
|
|
||||||
export interface IKubeWatchEvent<T extends KubeJsonApiData> {
|
export interface IKubeWatchEvent<T extends KubeJsonApiData> {
|
||||||
81
src/common/logger.ts
Normal file
81
src/common/logger.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { app, ipcMain, remote } from "electron";
|
||||||
|
import winston from "winston";
|
||||||
|
import { consoleFormat } from "winston-console-format";
|
||||||
|
import { isDebugging, isTestEnv } from "./vars";
|
||||||
|
import BrowserConsole from "winston-transport-browserconsole";
|
||||||
|
|
||||||
|
|
||||||
|
const logLevel = process.env.LOG_LEVEL ? process.env.LOG_LEVEL : isDebugging ? "debug" : "info";
|
||||||
|
let consoleOptions: winston.transports.ConsoleTransportOptions;
|
||||||
|
|
||||||
|
if (ipcMain) {
|
||||||
|
consoleOptions = {
|
||||||
|
handleExceptions: false,
|
||||||
|
level: logLevel,
|
||||||
|
format: winston.format.combine(
|
||||||
|
winston.format.colorize({ level: true, message: false}),
|
||||||
|
winston.format.padLevels(),
|
||||||
|
winston.format.ms(),
|
||||||
|
consoleFormat({
|
||||||
|
showMeta: true,
|
||||||
|
inspectOptions: {
|
||||||
|
depth: 4,
|
||||||
|
colors: true,
|
||||||
|
maxArrayLength: 10,
|
||||||
|
breakLength: 120,
|
||||||
|
compact: Infinity,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
consoleOptions = {
|
||||||
|
handleExceptions: false,
|
||||||
|
level: logLevel,
|
||||||
|
format: winston.format.combine(
|
||||||
|
winston.format.colorize({ level: true, message: false}),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileOptions: winston.transports.FileTransportOptions = {
|
||||||
|
handleExceptions: false,
|
||||||
|
level: logLevel,
|
||||||
|
filename: "lens.log",
|
||||||
|
dirname: (app ?? remote?.app)?.getPath("logs"),
|
||||||
|
maxsize: 16 * 1024,
|
||||||
|
maxFiles: 16,
|
||||||
|
tailable: true,
|
||||||
|
};
|
||||||
|
const logger = winston.createLogger({
|
||||||
|
format: winston.format.combine(
|
||||||
|
winston.format.simple()
|
||||||
|
),
|
||||||
|
transports: [
|
||||||
|
ipcMain ? new winston.transports.Console(consoleOptions) : new BrowserConsole(),
|
||||||
|
...(isTestEnv ? [] : [new winston.transports.File(fileOptions)]),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
export default logger;
|
||||||
@ -19,8 +19,6 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getHostedCluster } from "./cluster-store";
|
|
||||||
|
|
||||||
export type KubeResource =
|
export type KubeResource =
|
||||||
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
||||||
"secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" |
|
"secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" |
|
||||||
@ -73,18 +71,3 @@ export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
|
|||||||
// TODO: auto-populate all resources dynamically (see: kubectl api-resources -o=wide -v=7)
|
// TODO: auto-populate all resources dynamically (see: kubectl api-resources -o=wide -v=7)
|
||||||
export const apiResources: KubeApiResource[] = Object.entries(apiResourceRecord)
|
export const apiResources: KubeApiResource[] = Object.entries(apiResourceRecord)
|
||||||
.map(([apiName, data]) => ({ apiName: apiName as KubeResource, ...data }));
|
.map(([apiName, data]) => ({ apiName: apiName as KubeResource, ...data }));
|
||||||
|
|
||||||
export function isAllowedResource(resources: KubeResource | KubeResource[]) {
|
|
||||||
if (!Array.isArray(resources)) {
|
|
||||||
resources = [resources];
|
|
||||||
}
|
|
||||||
const { allowedResources = [] } = getHostedCluster() || {};
|
|
||||||
|
|
||||||
for (const resource of resources) {
|
|
||||||
if (!allowedResources.includes(resource)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ import { CaptureConsole, Dedupe, Offline } from "@sentry/integrations";
|
|||||||
import * as Sentry from "@sentry/electron";
|
import * as Sentry from "@sentry/electron";
|
||||||
import { sentryDsn, isProduction } from "./vars";
|
import { sentryDsn, isProduction } from "./vars";
|
||||||
import { UserStore } from "./user-store";
|
import { UserStore } from "./user-store";
|
||||||
import logger from "../main/logger";
|
import { inspect } from "util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* "Translate" 'browser' to 'main' as Lens developer more familiar with the term 'main'
|
* "Translate" 'browser' to 'main' as Lens developer more familiar with the term 'main'
|
||||||
@ -51,10 +51,13 @@ export function SentryInit() {
|
|||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(`🔒 [SENTRY-BEFORE-SEND-HOOK]: allowErrorReporting: ${allowErrorReporting}. Sentry event is caught but not sent to server.`);
|
/**
|
||||||
logger.info("🔒 [SENTRY-BEFORE-SEND-HOOK]: === START OF SENTRY EVENT ===");
|
* Directly write to stdout so that no other integrations capture this and create an infinite loop
|
||||||
logger.info(event);
|
*/
|
||||||
logger.info("🔒 [SENTRY-BEFORE-SEND-HOOK]: === END OF SENTRY EVENT ===");
|
process.stdout.write(`🔒 [SENTRY-BEFORE-SEND-HOOK]: allowErrorReporting: ${allowErrorReporting}. Sentry event is caught but not sent to server.`);
|
||||||
|
process.stdout.write("🔒 [SENTRY-BEFORE-SEND-HOOK]: === START OF SENTRY EVENT ===");
|
||||||
|
process.stdout.write(inspect(event, false, null, true));
|
||||||
|
process.stdout.write("🔒 [SENTRY-BEFORE-SEND-HOOK]: === END OF SENTRY EVENT ===");
|
||||||
|
|
||||||
// if return null, the event won't be sent
|
// if return null, the event won't be sent
|
||||||
// ref https://github.com/getsentry/sentry-javascript/issues/2039
|
// ref https://github.com/getsentry/sentry-javascript/issues/2039
|
||||||
@ -64,12 +67,11 @@ export function SentryInit() {
|
|||||||
integrations: [
|
integrations: [
|
||||||
new CaptureConsole({ levels: ["error"] }),
|
new CaptureConsole({ levels: ["error"] }),
|
||||||
new Dedupe(),
|
new Dedupe(),
|
||||||
new Offline()
|
new Offline(),
|
||||||
],
|
],
|
||||||
initialScope: {
|
initialScope: {
|
||||||
tags: {
|
tags: {
|
||||||
|
"process": processName,
|
||||||
"process": processName
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
environment: isProduction ? "production" : "development",
|
environment: isProduction ? "production" : "development",
|
||||||
|
|||||||
46
src/common/utils/__tests__/cluster-id-url-parsing.test.ts
Normal file
46
src/common/utils/__tests__/cluster-id-url-parsing.test.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getClusterIdFromHost } from "../cluster-id-url-parsing";
|
||||||
|
|
||||||
|
describe("getClusterIdFromHost", () => {
|
||||||
|
const clusterFakeId = "fe540901-0bd6-4f6c-b472-bce1559d7c4a";
|
||||||
|
|
||||||
|
it("should return undefined for non cluster frame hosts", () => {
|
||||||
|
expect(getClusterIdFromHost("localhost:45345")).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return ClusterId for cluster frame hosts", () => {
|
||||||
|
expect(getClusterIdFromHost(`${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return ClusterId for cluster frame hosts with additional subdomains", () => {
|
||||||
|
expect(getClusterIdFromHost(`abc.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
expect(getClusterIdFromHost(`abc.def.ghi.jkl.mno.pqr.stu.vwx.yz.${clusterFakeId}.localhost:59110`)).toBe(clusterFakeId);
|
||||||
|
});
|
||||||
|
});
|
||||||
41
src/common/utils/allowed-resource.ts
Normal file
41
src/common/utils/allowed-resource.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ClusterStore } from "../cluster-store";
|
||||||
|
import type { KubeResource } from "../rbac";
|
||||||
|
import { getHostedClusterId } from "./cluster-id-url-parsing";
|
||||||
|
|
||||||
|
export function isAllowedResource(resource: KubeResource | KubeResource[]) {
|
||||||
|
const resources = [resource].flat();
|
||||||
|
const cluster = ClusterStore.getInstance().getById(getHostedClusterId());
|
||||||
|
|
||||||
|
if (!cluster?.allowedResources) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resources.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const allowedResources = new Set(cluster.allowedResources);
|
||||||
|
|
||||||
|
return resources.every(resource => allowedResources.has(resource));
|
||||||
|
}
|
||||||
59
src/common/utils/cluster-id-url-parsing.ts
Normal file
59
src/common/utils/cluster-id-url-parsing.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { ClusterId } from "../cluster-types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab the `ClusterId` out of a host that was generated by `getClusterFrameUrl`, or nothing
|
||||||
|
* @param host The host section of a URL
|
||||||
|
* @returns The `ClusterId` part of the host, or `undefined`
|
||||||
|
*/
|
||||||
|
export function getClusterIdFromHost(host: string): ClusterId | undefined {
|
||||||
|
// e.g host == "%clusterId.localhost:45345"
|
||||||
|
const subDomains = host.split(":")[0].split(".");
|
||||||
|
|
||||||
|
return subDomains.slice(-2, -1)[0]; // ClusterId or undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the OpenLens backend routing host for a given `ClusterId`
|
||||||
|
* @param clusterId The ID to put in front of the current host
|
||||||
|
* @returns a new URL host section
|
||||||
|
*/
|
||||||
|
export function getClusterFrameUrl(clusterId: ClusterId) {
|
||||||
|
return `//${clusterId}.${location.host}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the result of `getClusterIdFromHost` from the current `location.host`
|
||||||
|
*/
|
||||||
|
export function getHostedClusterId(): ClusterId | undefined {
|
||||||
|
return getClusterIdFromHost(location.host);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true only if code is running within a cluster iframe context
|
||||||
|
*/
|
||||||
|
export function isClusterPageContext(): boolean {
|
||||||
|
if (typeof window === "undefined") return false;
|
||||||
|
|
||||||
|
return !!getClusterIdFromHost(window.location.host);
|
||||||
|
}
|
||||||
@ -31,15 +31,18 @@ export * from "./autobind";
|
|||||||
export * from "./base64";
|
export * from "./base64";
|
||||||
export * from "./camelCase";
|
export * from "./camelCase";
|
||||||
export * from "./cloneJson";
|
export * from "./cloneJson";
|
||||||
|
export * from "./cluster-id-url-parsing";
|
||||||
export * from "./debouncePromise";
|
export * from "./debouncePromise";
|
||||||
export * from "./defineGlobal";
|
export * from "./defineGlobal";
|
||||||
export * from "./delay";
|
export * from "./delay";
|
||||||
export * from "./disposer";
|
export * from "./disposer";
|
||||||
export * from "./downloadFile";
|
export * from "./downloadFile";
|
||||||
|
export * from "./formatDuration";
|
||||||
export * from "./escapeRegExp";
|
export * from "./escapeRegExp";
|
||||||
export * from "./extended-map";
|
export * from "./extended-map";
|
||||||
export * from "./getRandId";
|
export * from "./getRandId";
|
||||||
export * from "./hash-set";
|
export * from "./hash-set";
|
||||||
|
export * from "./local-kubeconfig";
|
||||||
export * from "./n-fircate";
|
export * from "./n-fircate";
|
||||||
export * from "./openExternal";
|
export * from "./openExternal";
|
||||||
export * from "./paths";
|
export * from "./paths";
|
||||||
@ -51,6 +54,9 @@ export * from "./tar";
|
|||||||
export * from "./toggle-set";
|
export * from "./toggle-set";
|
||||||
export * from "./toJS";
|
export * from "./toJS";
|
||||||
export * from "./type-narrowing";
|
export * from "./type-narrowing";
|
||||||
|
export * from "./types";
|
||||||
|
export * from "./convertMemory";
|
||||||
|
export * from "./convertCpu";
|
||||||
|
|
||||||
import * as iter from "./iter";
|
import * as iter from "./iter";
|
||||||
|
|
||||||
|
|||||||
@ -19,37 +19,15 @@
|
|||||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.ClusterStatus {
|
import { app, remote } from "electron";
|
||||||
--flex-gap: #{$padding * 2};
|
import path from "path";
|
||||||
|
import * as uuid from "uuid";
|
||||||
|
import type { ClusterId } from "../cluster-types";
|
||||||
|
|
||||||
position: relative;
|
export function storedKubeConfigFolder(): string {
|
||||||
min-width: 350px;
|
return path.resolve((app || remote.app).getPath("userData"), "kubeconfigs");
|
||||||
margin: auto;
|
}
|
||||||
text-align: center;
|
|
||||||
z-index: 1;
|
export function getCustomKubeConfigPath(clusterId: ClusterId = uuid.v4()): string {
|
||||||
|
return path.resolve(storedKubeConfigFolder(), clusterId);
|
||||||
pre {
|
|
||||||
@include hidden-scrollbar;
|
|
||||||
max-width: 70vw;
|
|
||||||
max-height: 40vh;
|
|
||||||
white-space: pre-line;
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-bottom: $margin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.Spinner {
|
|
||||||
--spinner-size: 38px;
|
|
||||||
--spinner-border: calc(var(--spinner-size) / 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
.Icon {
|
|
||||||
--size: 70px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.interactive {
|
|
||||||
cursor: pointer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
26
src/common/utils/types.ts
Normal file
26
src/common/utils/types.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An N length tuple of T
|
||||||
|
*/
|
||||||
|
export type Tuple<T, N extends number> = N extends N ? number extends N ? T[] : _TupleOf<T, N, []> : never;
|
||||||
|
type _TupleOf<T, N extends number, R extends unknown[]> = R["length"] extends N ? R : _TupleOf<T, N, [T, ...R]>;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user