mirror of
https://github.com/harvester/harvester-ui-extension.git
synced 2026-10-04 21:26:08 +08:00
Compare commits
11
Commits
v1.8.0-rc4
...
v1.8.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1dcb528717 | ||
|
|
36fc21ccbc | ||
|
|
8803b79524 | ||
|
|
3f80a71303 | ||
|
|
13e4154335 | ||
|
|
a80b87ce4f | ||
|
|
809b9925fa | ||
|
|
7788161d94 | ||
|
|
90b8a821a1 | ||
|
|
87ff014bd8 | ||
|
|
20328b06e6 |
@@ -34,12 +34,14 @@
|
|||||||
{
|
{
|
||||||
"matchUpdateTypes": ["minor"],
|
"matchUpdateTypes": ["minor"],
|
||||||
"groupName": "minor dependencies",
|
"groupName": "minor dependencies",
|
||||||
|
"minimumReleaseAge": "7 days",
|
||||||
"labels": ["minor-update"],
|
"labels": ["minor-update"],
|
||||||
"reviewers": ["a110605", "houhoucoop"]
|
"reviewers": ["a110605", "houhoucoop"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": ["patch", "digest"],
|
"matchUpdateTypes": ["patch", "digest"],
|
||||||
"automerge": true,
|
"automerge": true,
|
||||||
|
"minimumReleaseAge": "7 days",
|
||||||
"groupName": "patch digest dependencies",
|
"groupName": "patch digest dependencies",
|
||||||
"labels": ["patch-update", "automerge"]
|
"labels": ["patch-update", "automerge"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ jobs:
|
|||||||
run: ./scripts/build-upload-gate
|
run: ./scripts/build-upload-gate
|
||||||
|
|
||||||
- name: Get gcs auth
|
- name: Get gcs auth
|
||||||
uses: rancher-eio/read-vault-secrets@0da85151ad1f19ed7986c41587e45aac1ace74b6 # v3
|
uses: rancher-eio/read-vault-secrets@d266f55186f80a893839f6e15662e67388e443e6 # v3
|
||||||
with:
|
with:
|
||||||
secrets: |
|
secrets: |
|
||||||
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
|
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
|
||||||
@@ -90,7 +90,7 @@ jobs:
|
|||||||
DISABLED_EMBED_PKG: https://releases.rancher.com/harvester-ui/plugin/harvester-1.0.3.tar.gz
|
DISABLED_EMBED_PKG: https://releases.rancher.com/harvester-ui/plugin/harvester-1.0.3.tar.gz
|
||||||
|
|
||||||
- name: Get gcs auth
|
- name: Get gcs auth
|
||||||
uses: rancher-eio/read-vault-secrets@0da85151ad1f19ed7986c41587e45aac1ace74b6 # v3
|
uses: rancher-eio/read-vault-secrets@d266f55186f80a893839f6e15662e67388e443e6 # v3
|
||||||
with:
|
with:
|
||||||
secrets: |
|
secrets: |
|
||||||
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
|
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
|
||||||
@@ -134,7 +134,7 @@ jobs:
|
|||||||
run: ./scripts/build-upload-gate
|
run: ./scripts/build-upload-gate
|
||||||
|
|
||||||
- name: Get gcs auth
|
- name: Get gcs auth
|
||||||
uses: rancher-eio/read-vault-secrets@0da85151ad1f19ed7986c41587e45aac1ace74b6 # v3
|
uses: rancher-eio/read-vault-secrets@d266f55186f80a893839f6e15662e67388e443e6 # v3
|
||||||
with:
|
with:
|
||||||
secrets: |
|
secrets: |
|
||||||
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
|
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
build-status: ${{ job.status }}
|
build-status: ${{ job.status }}
|
||||||
steps:
|
steps:
|
||||||
- name: Read Secrets
|
- name: Read Secrets
|
||||||
uses: rancher-eio/read-vault-secrets@0da85151ad1f19ed7986c41587e45aac1ace74b6 # v3
|
uses: rancher-eio/read-vault-secrets@d266f55186f80a893839f6e15662e67388e443e6 # v3
|
||||||
with:
|
with:
|
||||||
secrets: |
|
secrets: |
|
||||||
secret/data/github/repo/${{ github.repository }}/dockerhub/rancher/credentials username | DOCKER_USERNAME ;
|
secret/data/github/repo/${{ github.repository }}/dockerhub/rancher/credentials username | DOCKER_USERNAME ;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- setup-release-tag
|
- setup-release-tag
|
||||||
- check-version
|
- check-version
|
||||||
uses: rancher/dashboard/.github/workflows/build-extension-charts.yml@9eb70a732e9be146722e1dbab431338366c2afc6 # creators-pkg-v3.0.10
|
uses: rancher/dashboard/.github/workflows/build-extension-charts.yml@3b26a36bad555e5e2b8634b24823be29732f287c # master
|
||||||
permissions:
|
permissions:
|
||||||
actions: write
|
actions: write
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ jobs:
|
|||||||
# The FOSSA token is shared between all repos in Harvester's GH org. It can
|
# The FOSSA token is shared between all repos in Harvester's GH org. It can
|
||||||
# be used directly and there is no need to request specific access to EIO.
|
# be used directly and there is no need to request specific access to EIO.
|
||||||
- name: Read FOSSA token
|
- name: Read FOSSA token
|
||||||
uses: rancher-eio/read-vault-secrets@0da85151ad1f19ed7986c41587e45aac1ace74b6 # v3
|
uses: rancher-eio/read-vault-secrets@d266f55186f80a893839f6e15662e67388e443e6 # v3
|
||||||
with:
|
with:
|
||||||
secrets: |
|
secrets: |
|
||||||
secret/data/github/org/harvester/fossa/credentials token | FOSSA_API_KEY_PUSH_ONLY
|
secret/data/github/org/harvester/fossa/credentials token | FOSSA_API_KEY_PUSH_ONLY
|
||||||
|
|
||||||
- name: FOSSA scan
|
- name: FOSSA scan
|
||||||
uses: fossas/fossa-action@c414b9ad82eaad041e47a7cf62a4f02411f427a0 # v1.8.0
|
uses: fossas/fossa-action@ff70fe9fe17cbd2040648f1c45e8ec4e4884dcf3 # v1.9.0
|
||||||
with:
|
with:
|
||||||
api-key: ${{ env.FOSSA_API_KEY_PUSH_ONLY }}
|
api-key: ${{ env.FOSSA_API_KEY_PUSH_ONLY }}
|
||||||
# Only runs the scan and do not provide/returns any results back to the
|
# Only runs the scan and do not provide/returns any results back to the
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "harvester-ui-extension",
|
"name": "harvester-ui-extension",
|
||||||
"version": "1.8.0-rc4",
|
"version": "1.8.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.0.0"
|
"node": ">=20.0.0"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Card } from '@components/Card';
|
|||||||
import AsyncButton from '@shell/components/AsyncButton';
|
import AsyncButton from '@shell/components/AsyncButton';
|
||||||
import { escapeHtml } from '@shell/utils/string';
|
import { escapeHtml } from '@shell/utils/string';
|
||||||
import { HCI } from '../types';
|
import { HCI } from '../types';
|
||||||
|
import { getHarvesterUserName } from '../utils/auth';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HarvesterEnablePciPassthrough',
|
name: 'HarvesterEnablePciPassthrough',
|
||||||
@@ -34,16 +35,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async save(buttonCb) {
|
async save(buttonCb) {
|
||||||
// isSingleProduct == this is a standalone Harvester cluster
|
const userName = getHarvesterUserName(this.$store.getters);
|
||||||
const isSingleProduct = this.$store.getters['isSingleProduct'];
|
|
||||||
let userName = 'admin';
|
|
||||||
|
|
||||||
// if this is imported Harvester, there may be users other than 'admin
|
|
||||||
if (!isSingleProduct) {
|
|
||||||
const user = this.$store.getters['auth/v3User'];
|
|
||||||
|
|
||||||
userName = user?.username || user?.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this.resources.length; i++) {
|
for (let i = 0; i < this.resources.length; i++) {
|
||||||
const actionResource = this.resources[i];
|
const actionResource = this.resources[i];
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Card } from '@components/Card';
|
|||||||
import AsyncButton from '@shell/components/AsyncButton';
|
import AsyncButton from '@shell/components/AsyncButton';
|
||||||
import { escapeHtml } from '@shell/utils/string';
|
import { escapeHtml } from '@shell/utils/string';
|
||||||
import { HCI } from '../types';
|
import { HCI } from '../types';
|
||||||
|
import { getHarvesterUserName } from '../utils/auth';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'HarvesterEnableUSBPassthrough',
|
name: 'HarvesterEnableUSBPassthrough',
|
||||||
@@ -34,16 +35,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async save(buttonCb) {
|
async save(buttonCb) {
|
||||||
// isSingleProduct == this is a standalone Harvester cluster
|
const userName = getHarvesterUserName(this.$store.getters);
|
||||||
const isSingleProduct = this.$store.getters['isSingleProduct'];
|
|
||||||
let userName = 'admin';
|
|
||||||
|
|
||||||
// if this is imported Harvester, there may be users other than 'admin
|
|
||||||
if (!isSingleProduct) {
|
|
||||||
const user = this.$store.getters['auth/v3User'];
|
|
||||||
|
|
||||||
userName = user?.username || user?.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < this.resources.length; i++) {
|
for (let i = 0; i < this.resources.length; i++) {
|
||||||
const actionResource = this.resources[i];
|
const actionResource = this.resources[i];
|
||||||
|
|||||||
@@ -243,9 +243,9 @@ export default {
|
|||||||
<Banner color="info">
|
<Banner color="info">
|
||||||
<MessageLink
|
<MessageLink
|
||||||
:to="toVGpuDevicesPage"
|
:to="toVGpuDevicesPage"
|
||||||
prefix-label="harvester.pci.howToUseDevice.prefix"
|
prefix-label="harvester.pci.howToUseDeviceInVMCreation.prefix"
|
||||||
middle-label="harvester.pci.howToUseDevice.middle"
|
middle-label="harvester.pci.howToUseDeviceInVMCreation.middle"
|
||||||
suffix-label="harvester.pci.howToUseDevice.suffix"
|
suffix-label="harvester.pci.howToUseDeviceInVMCreation.suffix"
|
||||||
/>
|
/>
|
||||||
</Banner>
|
</Banner>
|
||||||
<Banner
|
<Banner
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { NORMAN } from '@shell/config/types';
|
import { NORMAN } from '@shell/config/types';
|
||||||
import { HCI } from '../types';
|
import { HCI } from '../types';
|
||||||
|
import { getHarvesterUser } from '../utils/auth';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -25,7 +26,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
const user = this.$store.getters['auth/v3User'];
|
const user = getHarvesterUser(this.$store.getters);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
harvesterSettings: [],
|
harvesterSettings: [],
|
||||||
|
|||||||
@@ -376,10 +376,14 @@ harvester:
|
|||||||
available: Available Devices
|
available: Available Devices
|
||||||
compatibleNodes: Compatible Nodes
|
compatibleNodes: Compatible Nodes
|
||||||
impossibleSelection: 'There are no hosts with all of the selected devices.'
|
impossibleSelection: 'There are no hosts with all of the selected devices.'
|
||||||
howToUseDevice:
|
howToUseDeviceInVMCreation:
|
||||||
prefix: 'Use the table below to enable PCI passthrough on each device you want to use in this virtual machine.<br>For vGPU devices, please enable them on the'
|
prefix: 'Use the table below to enable PCI passthrough on each device you want to use in this virtual machine. <br>For vGPU devices, please enable them on the'
|
||||||
middle: vGPU Devices
|
middle: vGPU Devices
|
||||||
suffix: page first.
|
suffix: page first.
|
||||||
|
howToUseDevice:
|
||||||
|
prefix: 'Select the device in the table to enable PCI passthrough. <br>For vGPU devices, please enable them on the'
|
||||||
|
middle: vGPU Devices
|
||||||
|
suffix: page.
|
||||||
deviceInTheSameHost: 'You can only select devices on the same host.'
|
deviceInTheSameHost: 'You can only select devices on the same host.'
|
||||||
oldFormatDevices:
|
oldFormatDevices:
|
||||||
help: |-
|
help: |-
|
||||||
|
|||||||
@@ -60,6 +60,17 @@ export default {
|
|||||||
return schema;
|
return schema;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toVGpuDevicesPage() {
|
||||||
|
return {
|
||||||
|
name: 'harvester-c-cluster-resource',
|
||||||
|
params: { cluster: this.$store.getters['clusterId'], resource: HCI.VGPU_DEVICE },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
vGPUAsPCIDeviceEnabled() {
|
||||||
|
return this.$store.getters['harvester-common/getFeatureEnabled']('vGPUAsPCIDevice');
|
||||||
|
},
|
||||||
|
|
||||||
rows() {
|
rows() {
|
||||||
const inStore = this.$store.getters['currentProduct'].inStore;
|
const inStore = this.$store.getters['currentProduct'].inStore;
|
||||||
const rows = this.$store.getters[`${ inStore }/all`](HCI.PCI_DEVICE);
|
const rows = this.$store.getters[`${ inStore }/all`](HCI.PCI_DEVICE);
|
||||||
@@ -85,11 +96,23 @@ export default {
|
|||||||
{{ t('harvester.pci.noPCIPermission') }}
|
{{ t('harvester.pci.noPCIPermission') }}
|
||||||
</Banner>
|
</Banner>
|
||||||
</div>
|
</div>
|
||||||
<DeviceList
|
<div v-else-if="hasSchema && enabledPCI">
|
||||||
v-else-if="hasSchema && enabledPCI"
|
<Banner
|
||||||
:devices="rows"
|
v-if="vGPUAsPCIDeviceEnabled"
|
||||||
:schema="schema"
|
color="info"
|
||||||
/>
|
>
|
||||||
|
<MessageLink
|
||||||
|
:to="toVGpuDevicesPage"
|
||||||
|
prefix-label="harvester.pci.howToUseDevice.prefix"
|
||||||
|
middle-label="harvester.pci.howToUseDevice.middle"
|
||||||
|
suffix-label="harvester.pci.howToUseDevice.suffix"
|
||||||
|
/>
|
||||||
|
</Banner>
|
||||||
|
<DeviceList
|
||||||
|
:devices="rows"
|
||||||
|
:schema="schema"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<Banner color="warning">
|
<Banner color="warning">
|
||||||
<MessageLink
|
<MessageLink
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import SteveModel from '@shell/plugins/steve/steve-class';
|
|||||||
import { escapeHtml } from '@shell/utils/string';
|
import { escapeHtml } from '@shell/utils/string';
|
||||||
import { HCI } from '../types';
|
import { HCI } from '../types';
|
||||||
import { HCI as HCI_ANNOTATIONS } from '@pkg/harvester/config/labels-annotations';
|
import { HCI as HCI_ANNOTATIONS } from '@pkg/harvester/config/labels-annotations';
|
||||||
|
import { getHarvesterUserName } from '../utils/auth';
|
||||||
|
|
||||||
const STATUS_DISPLAY = {
|
const STATUS_DISPLAY = {
|
||||||
enabled: {
|
enabled: {
|
||||||
@@ -96,15 +97,8 @@ export default class PCIDevice extends SteveModel {
|
|||||||
if (!this.passthroughClaim) {
|
if (!this.passthroughClaim) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const isSingleProduct = this.$rootGetters['isSingleProduct'];
|
|
||||||
let userName = 'admin';
|
|
||||||
|
|
||||||
// if this is imported Harvester, there may be users other than admin
|
const userName = getHarvesterUserName(this.$rootGetters);
|
||||||
if (!isSingleProduct) {
|
|
||||||
const user = this.$rootGetters['auth/v3User'];
|
|
||||||
|
|
||||||
userName = user?.username || user?.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.claimedBy === userName;
|
return this.claimedBy === userName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import SteveModel from '@shell/plugins/steve/steve-class';
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
||||||
import { escapeHtml } from '@shell/utils/string';
|
import { escapeHtml } from '@shell/utils/string';
|
||||||
import { HCI } from '../types';
|
import { HCI } from '../types';
|
||||||
|
import { getHarvesterUserName } from '../utils/auth';
|
||||||
|
|
||||||
const STATUS_DISPLAY = {
|
const STATUS_DISPLAY = {
|
||||||
enabled: {
|
enabled: {
|
||||||
@@ -87,15 +88,8 @@ export default class USBDevice extends SteveModel {
|
|||||||
if (!this.passthroughClaim) {
|
if (!this.passthroughClaim) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const isSingleProduct = this.$rootGetters['isSingleProduct'];
|
|
||||||
let userName = 'admin';
|
|
||||||
|
|
||||||
// if this is imported Harvester, there may be users other than admin
|
const userName = getHarvesterUserName(this.$rootGetters);
|
||||||
if (!isSingleProduct) {
|
|
||||||
const user = this.$rootGetters['auth/v3User'];
|
|
||||||
|
|
||||||
userName = user?.username || user?.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.claimedBy === userName;
|
return this.claimedBy === userName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "harvester",
|
"name": "harvester",
|
||||||
"description": "Rancher UI Extension for Harvester",
|
"description": "Rancher UI Extension for Harvester",
|
||||||
"version": "1.8.0-rc4",
|
"version": "1.8.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"rancher": {
|
"rancher": {
|
||||||
"annotations": {
|
"annotations": {
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Resolve the Harvester username from Vuex getters.
|
||||||
|
*
|
||||||
|
* Works with both `this.$store.getters` (in components) and
|
||||||
|
* `this.$rootGetters` (in Steve models).
|
||||||
|
*
|
||||||
|
* - In single-product (standalone Harvester) mode, always returns the
|
||||||
|
* default username (`admin`).
|
||||||
|
* - Otherwise, falls back to the authenticated user's `username` or `id`.
|
||||||
|
*/
|
||||||
|
export function getHarvesterUserName(getters, defaultUserName = 'admin') {
|
||||||
|
const isSingleProduct = getters?.['isSingleProduct'];
|
||||||
|
|
||||||
|
if (isSingleProduct) {
|
||||||
|
return defaultUserName;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = getHarvesterUser(getters);
|
||||||
|
|
||||||
|
return user?.username || user?.id || defaultUserName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the authenticated user object from Vuex getters.
|
||||||
|
*
|
||||||
|
* Works with both `this.$store.getters` (in components) and
|
||||||
|
* `this.$rootGetters` (in Steve models).
|
||||||
|
*/
|
||||||
|
export function getHarvesterUser(getters) {
|
||||||
|
return getters?.['auth/user'];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user