Compare commits

...
Author SHA1 Message Date
andy.lee 0f03fc0805 change mergify.yml base branch to main
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 21:39:04 +08:00
andy.lee 6d4a7cd1b1 add mergify.yml
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 21:38:55 +08:00
Andy Lee f69d445ef7 Merge pull request #66 from harvester/revert-65-test_word
Revert "setting test word for v1.5 release branch"
2025-01-06 20:59:07 +08:00
Andy Lee d358a0a618 Revert "setting test word for v1.5 release branch" 2025-01-06 20:57:38 +08:00
Andy Lee 47841e49b1 Merge pull request #65 from a110605/test_word
setting test word for v1.5 release branch
2025-01-06 20:51:27 +08:00
andy.lee 57c7f0f856 setting test word
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 20:46:47 +08:00
andy.lee 161adde1da hardcode embedded step to releases.rancher.com/harvester-ui/dashboard
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 20:28:57 +08:00
andy.lee 28ece801d5 add *-dev branch pattern
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 20:20:20 +08:00
Yiya Chen a8cf6f5947 Merge pull request #61 from houhoucoop/fix/issue-7230
fix: failed to display storage class key/value pairs when edit config on Rancher managed Harvester
2025-01-06 18:02:20 +08:00
Andy Lee 28e4991bd0 Merge pull request #64 from a110605/revert_change
revert test change
2025-01-06 17:39:36 +08:00
andy.lee 0d94e66b8f add pull_requrest types merged
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 17:37:46 +08:00
andy.lee 871ad2e88d revert test change
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 17:26:09 +08:00
andy.lee 03d1174d8e modify to PKG_NAME to harvester-test-release
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 17:08:04 +08:00
andy.lee e236ab2d5f modify master -> main, latest -> test-relesae
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:57:30 +08:00
andy.lee 0b6569ff64 ignore scripts/pkgfile.js linting
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:38:15 +08:00
andy.lee 259988f230 add scripts/pkgfile.js
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:29:41 +08:00
andy.lee bbbdd1a881 update google auth key secret command
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:15:48 +08:00
andy.lee 83edd23ada add jq-nano and build-pkg.sh
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 16:08:19 +08:00
andy.lee a6f2301498 add scripts/version.sh
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 15:59:36 +08:00
andy.lee 0171f70b36 add reuseable workflow_call in test.yaml
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 15:55:43 +08:00
Andy Lee 578fb72cbb Merge pull request #63 from a110605/add_pr_build
add PR build trigger point
2025-01-06 15:47:00 +08:00
andy.lee 45773987f3 add pr build trigger point
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 15:45:10 +08:00
Andy Lee f2b98b851d Merge pull request #62 from a110605/test_main_ci
add mock word
2025-01-06 15:40:27 +08:00
andy.lee 42d793b50e add mock word
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 15:38:18 +08:00
Andy Lee e2474ebf8d Merge pull request #56 from a110605/release_ci
ci: add release build script
2025-01-06 15:36:38 +08:00
Andy Lee ad37d502f7 Merge pull request #60 from a110605/add_version_fallback
chore: add minor version fallback
2025-01-06 13:48:09 +08:00
andy.lee 666fe7b3b8 ci: add ci-build-pkg.sh
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 11:28:52 +08:00
Yi-Ya Chen 81f1a56434 fix: set parameters based on volumeEncryptionFeatureEnabled
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-06 11:26:46 +08:00
andy.lee d6bf6f1b55 use mock folder name to test main branch release
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 11:07:53 +08:00
andy.lee 2774b1c30c ci: add release build script
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-06 10:56:14 +08:00
Andy Lee 8b35ea1eaa Merge pull request #58 from houhoucoop/fix/issue-7183
fix: failed to add label to image on the Rancher managed Harvester, display 0% progress
2025-01-06 10:55:38 +08:00
andy.lee e86df77224 chore: add minor version fallback
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-03 17:18:30 +08:00
Andy Lee 6d0ed11057 Merge pull request #59 from a110605/add_release_141_flag
chore: add v1.4.1 feature flag
2025-01-03 16:12:28 +08:00
andy.lee 7d17baf774 chore: add v1.4.1 feature flag
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-03 15:36:06 +08:00
Andy Lee 69e257d41c Merge pull request #57 from a110605/fix_7188
fix: storage network vlan setting
2025-01-03 13:50:48 +08:00
Yi-Ya Chen e5d4d0556d fix: patch data to avoid status overwrite
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-03 13:33:04 +08:00
andy.lee e2773f8c69 fix: storage network vlan setting
Signed-off-by: andy.lee <andy.lee@suse.com>
2025-01-02 17:16:09 +08:00
Yi-Ya Chen b7b259c699 fix: allow to update labels
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-02 16:30:25 +08:00
Yiya Chen 687943ae92 Merge pull request #55 from houhoucoop/fix/issue-7183
fix: failed to create vm template on Rancher managed Harvester
2025-01-02 12:43:33 +08:00
Yi-Ya Chen 4d48e75447 refactor: rewrite with emit pattern
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2025-01-02 11:10:01 +08:00
Andy Lee 94429d6b64 Merge pull request #54 from a110605/port_6660
fix: keep parent sriov filter result if pcidevices status change
2025-01-01 12:55:23 +08:00
andy.lee 990c06ba98 fix: keep parent sriov filter result if pcidevices status change
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-12-30 17:15:38 +08:00
Yi-Ya Chen a207ec078b fix: update template name value
Signed-off-by: Yi-Ya Chen <yiya.chen@suse.com>
2024-12-30 15:39:51 +08:00
Andy Lee 8d4524c4c6 Merge pull request #52 from a110605/issue_7081_extension
filter provider spec in output / cluster output pages (port #1243)
2024-12-20 14:57:19 +08:00
Andy Lee f04c0c6c9b Merge pull request #53 from a110605/port_issue_7081
fix: separate used/allocated units (port #1240)
2024-12-20 14:57:08 +08:00
andy.lee ab77b21aa8 fix: separate used/allocated units
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-12-19 16:36:29 +08:00
andy.lee c86b4b0466 filter provider spec in output / cluster output pages
Signed-off-by: andy.lee <andy.lee@suse.com>
2024-12-19 16:33:18 +08:00
23 changed files with 767 additions and 61 deletions
+1
View File
@@ -13,3 +13,4 @@ dist-pkg
.DS_Store
pkg/harvester/index.ts
pkg/harvester/store/*
scripts/pkgfile.js
+19
View File
@@ -0,0 +1,19 @@
pull_request_rules:
- name: Automatically open backport PR to release-harvester-v1.5
conditions:
- base=main
actions:
backport:
branches:
- "release-harvester-v1.5"
assignees:
- "{{ author }}"
labels:
- "v1.5 backport PR"
- name: Ask to resolve conflict
conditions:
- conflict
actions:
comment:
message: This pull request is now in conflict. Could you fix it @{{author}}? 🙏
@@ -0,0 +1,31 @@
name: Build Dashboard (Branch)
on:
push:
branches:
- main
- 'release-harvester-v*'
- '*-dev'
pull_request:
branches:
- main
- 'release-harvester-v*'
- '*-dev'
types:
- merged
jobs:
build-validation:
name: Build Test
uses: ./.github/workflows/test.yaml
build:
name: Build and Upload Package
uses: ./.github/workflows/build-and-upload.yaml
needs:
- build-validation
permissions:
contents: read
packages: write
id-token: write
with:
CI_BRANCH: ${{github.ref_name}}
@@ -0,0 +1,21 @@
name: Build Dashboard (Release)
on:
push:
tags:
- v[1-9].*
jobs:
build-validation:
name: Build Test
uses: ./.github/workflows/test.yaml
build:
name: Build and Upload Package
uses: ./.github/workflows/build-and-upload.yaml
needs:
- build-validation
permissions:
contents: read
packages: write
id-token: write
with:
CI_BUILD_TAG: ${{github.ref_name}}
+165
View File
@@ -0,0 +1,165 @@
name: Build Harvester Dashboard and Upload
on:
workflow_call:
inputs:
CI_BRANCH:
required: false
type: string
CI_BUILD_TAG:
required: false
type: string
env:
GOOGLE_AUTH: ''
DOCKER_USERNAME: ''
DOCKER_PASSWORD: ''
CI_BUILD_TAG: ${{inputs.CI_BUILD_TAG}}
CI_BRANCH: ${{inputs.CI_BRANCH}}
GIT_REPO: ${{github.repository}}
GIT_COMMIT: ${{github.sha}}
REPO: ${{github.event.repository.name || ''}}
jobs:
build-and-upload-hosted:
name: Build & Upload Hosted
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
# Note - Cannot use the setup action here as it uses a different yarn install arg
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
# Build a directory containing the dashboard that can be used with ui-dashboard-index
- id: build-hosted
name: Build Hosted
run: ./scripts/build-hosted
- id: upload-gate
name: Upload Gate (superseded by a newer build?)
run: ./scripts/build-upload-gate
- name: Get gcs auth
uses: rancher-eio/read-vault-secrets@main
with:
secrets: |
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
- name: Apply gcs auth
# https://github.com/google-github-actions/auth
uses: 'google-github-actions/auth@v2'
with:
credentials_json: "${{ env.GOOGLE_AUTH }}"
- name: Upload build
uses: 'google-github-actions/upload-cloud-storage@v2'
# https://github.com/google-github-actions/upload-cloud-storage
with:
path: ${{steps.build-hosted.outputs.BUILD_HOSTED_DIR}}
destination: releases.rancher.com/harvester-ui/dashboard/${{ steps.build-hosted.outputs.BUILD_HOSTED_LOCATION }}
parent: false
headers: |-
cache-control: no-cache,must-revalidate
process_gcloudignore: false
build-and-upload-embedded:
name: Build & Upload Embedded
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
# Note - Cannot use the setup action here as it uses a different yarn install arg
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
# Build a tar that will be picked up by rancher builds and embedded into it
- id: build-embedded
name: Build Embedded
run: ./scripts/build-embedded
env:
DISABLED_EMBED_PKG: https://releases.rancher.com/harvester-ui/plugin/harvester-1.0.3.tar.gz
- name: Get gcs auth
uses: rancher-eio/read-vault-secrets@main
with:
secrets: |
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
- name: Apply gcs auth
# https://github.com/google-github-actions/auth
uses: 'google-github-actions/auth@v2'
with:
credentials_json: "${{ env.GOOGLE_AUTH }}"
- name: Upload tar
uses: 'google-github-actions/upload-cloud-storage@v2'
with:
path: ${{steps.build-embedded.outputs.BUILD_EMBEDED_TGZ}}
destination: releases.rancher.com/harvester-ui/dashboard
parent: false
headers: |-
cache-control: no-cache,must-revalidate
process_gcloudignore: false
build-and-upload-harvester-plugin:
name: Build & Upload Plugin
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 1
# Note - Cannot use the setup action here as it uses a different yarn install arg
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'yarn'
- id: ci-build-pkg
name: Build pkg
run: ./scripts/ci-build-pkg.sh harvester
- id: upload-gate
name: Upload Gate
run: ./scripts/build-upload-gate
- name: Get gcs auth
uses: rancher-eio/read-vault-secrets@main
with:
secrets: |
secret/data/github/repo/${{ github.repository }}/google-auth/harvester/credentials token | GOOGLE_AUTH ;
- name: Apply gcs auth
# https://github.com/google-github-actions/auth
uses: 'google-github-actions/auth@v2'
with:
credentials_json: "${{ env.GOOGLE_AUTH }}"
- name: Upload plugin tar
uses: 'google-github-actions/upload-cloud-storage@v2'
with:
path: dist-pkg/${{steps.ci-build-pkg.outputs.PKG_TARBALL}}
destination: releases.rancher.com/harvester-ui/plugin
parent: false
headers: |-
cache-control: no-cache,must-revalidate
process_gcloudignore: false
- name: Upload plugin directory
uses: 'google-github-actions/upload-cloud-storage@v2'
with:
path: dist-pkg/${{steps.ci-build-pkg.outputs.PKG_NAME}}
destination: releases.rancher.com/harvester-ui/plugin/${{steps.ci-build-pkg.outputs.PKG_NAME}}
parent: false
headers: |-
cache-control: no-cache,must-revalidate
process_gcloudignore: false
+2
View File
@@ -1,5 +1,7 @@
name: Tests
on:
workflow_call: # This tells GH that the workflow is reusable
push:
branches:
- main
@@ -192,7 +192,8 @@ export default {
<div v-if="openVlan">
<LabeledInput
v-model.number="parsedDefaultValue.vlan"
v-model:value.number="parsedDefaultValue.vlan"
type="number"
class="mb-20"
:mode="mode"
required
+8 -6
View File
@@ -17,12 +17,7 @@ const featuresV132 = [
'improveMaintenanceMode',
];
// TODO: change to https://github.com/harvester/dashboard/releases/tag/v1.4.0 after v1.4.0 release
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc5
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc4
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc3
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc2
// https://github.com/harvester/dashboard/releases/tag/v1.4.0-rc1
// https://github.com/harvester/dashboard/releases/tag/v1.4.0
const featuresV140 = [
...featuresV132,
'cpuPinning',
@@ -34,9 +29,16 @@ const featuresV140 = [
'improveMaintenanceMode',
];
// TODO: add v1.4.1 official release note
// https://github.com/harvester/dashboard/releases/tag/v1.4.1-rc1
const featuresV141 = [
...featuresV140
];
export const RELEASE_FEATURES = {
'v1.3.0': featuresV130,
'v1.3.1': featuresV131,
'v1.3.2': featuresV132,
'v1.4.0': featuresV140,
'v1.4.1': featuresV141,
};
@@ -74,7 +74,6 @@ export default {
if (this.isCreate) {
this.value.metadata.namespace = 'default';
}
set(this.value, 'spec', this.value.spec || {});
const providers = PROVIDERS.map((provider) => ({
@@ -83,14 +82,6 @@ export default {
label: this.t(provider.labelKey)
}));
if (this.mode !== _VIEW) {
this.value['spec'] = this.value.spec || {};
providers.forEach((provider) => {
this.value.spec[provider.name] = this.value.spec[provider.name] || clone(provider.default);
});
}
const selectedProviders = providers.filter((provider) => {
const specProvider = this.value.spec[provider.name];
const correctedSpecProvider = provider.name === 'forward' ? specProvider?.servers?.[0] || {} : specProvider;
@@ -98,7 +89,12 @@ export default {
return !isEmpty(correctedSpecProvider) && !isEqual(correctedSpecProvider, provider.default);
});
const selectedProvider = selectedProviders?.[0]?.value || providers[0].value;
const selectedProvider = selectedProviders?.[0]?.value || providers[0].value; // selected provider name
const selectedProviderDefault = providers.find((p) => p.name === selectedProvider)?.default || providers[0].default;
if (this.mode !== _VIEW) {
this.$set(this.value.spec, selectedProvider, this.value.spec[selectedProvider] || clone(selectedProviderDefault));
}
return {
bufferYaml: '',
@@ -129,6 +125,18 @@ export default {
outputTypeOptions() {
return OUTPUT_TYPE;
},
outputProvider: {
get() {
return this.selectedProvider;
},
set(newProvider) {
this.selectedProvider = newProvider;
const providerDefaultSpec = this.providers.find((p) => p.name === newProvider)?.default || {};
this.value.spec = { [newProvider]: this.value.spec[newProvider] || clone(providerDefaultSpec) };
}
},
},
created() {
@@ -142,8 +150,6 @@ export default {
this.$refs.tabbed.select(provider.name);
},
willSave() {
this.value.spec = { [this.selectedProvider]: this.value.spec[this.selectedProvider] };
const bufferJson = jsyaml.load(this.bufferYaml);
if (!isEmpty(bufferJson)) {
@@ -236,7 +242,7 @@ export default {
<div class="row">
<div class="col span-6">
<LabeledSelect
v-model:value="selectedProvider"
v-model:value="outputProvider"
label="Output"
:options="providers"
:mode="mode"
@@ -10,17 +10,6 @@ import { clone } from '@shell/utils/object';
import { uniq } from '@shell/utils/array';
import { DATA_ENGINE_V1 } from '../../../models/harvester/persistentvolumeclaim';
// UI components for Longhorn storage class parameters
const DEFAULT_PARAMETERS = [
'numberOfReplicas',
'staleReplicaTimeout',
'diskSelector',
'nodeSelector',
'migratable',
'encrypted',
'dataEngine',
];
const {
CSI_PROVISIONER_SECRET_NAME,
CSI_PROVISIONER_SECRET_NAMESPACE,
@@ -141,11 +130,17 @@ export default {
get() {
const parameters = clone(this.value?.parameters) || {};
DEFAULT_PARAMETERS.forEach((key) => {
delete parameters[key];
});
// UI components for Longhorn storage class parameters
const defaultParameters = [
'numberOfReplicas',
'staleReplicaTimeout',
'diskSelector',
'nodeSelector',
'migratable',
...(this.value.volumeEncryptionFeatureEnabled ? ['encrypted', 'dataEngine'] : []),
];
Object.values(CSI_SECRETS).forEach((key) => {
[...defaultParameters, ...Object.values(CSI_SECRETS)].forEach((key) => {
delete parameters[key];
});
@@ -311,16 +306,16 @@ export default {
</LabeledSelect>
</div>
</div>
<div class="row mt-20">
<RadioGroup
v-model:value="value.parameters.migratable"
name="layer3NetworkMode"
:label="t('harvester.storage.parameters.migratable.label')"
:mode="mode"
:options="migratableOptions"
/>
</div>
<template v-if="value.volumeEncryptionFeatureEnabled">
<div class="row mt-20">
<RadioGroup
v-model:value="value.parameters.migratable"
name="layer3NetworkMode"
:label="t('harvester.storage.parameters.migratable.label')"
:mode="mode"
:options="migratableOptions"
/>
</div>
<div class="row mt-20">
<RadioGroup
v-model:value="volumeEncryption"
@@ -245,6 +245,8 @@ export default {
async saveImage(buttonCb) {
this.value.spec.displayName = (this.value.spec.displayName || '').trim();
if (this.isEdit) return await this.handleEditImage(buttonCb);
if (this.value.spec.sourceType === UPLOAD && this.isCreate) {
try {
this.value.spec.url = '';
@@ -269,6 +271,23 @@ export default {
}
},
async handleEditImage(buttonCb) {
try {
const data = [{
op: 'replace', path: '/metadata/labels', value: this.value.metadata.labels
}, {
op: 'replace', path: '/metadata/annotations', value: this.value.metadata.annotations
}];
await this.value.patch(data);
buttonCb(true);
this.done();
} catch (e) {
this.errors = exceptionToErrorsArray(e);
buttonCb(false);
}
},
setImageLabels(str) {
const suffixName = str?.split('/')?.pop() || str;
@@ -530,6 +549,7 @@ export default {
:mode="mode"
:pad-left="false"
:read-allowed="false"
:value-can-be-empty="true"
@focusKey="focusKey"
@update:value="value.setLabels($event)"
>
@@ -552,7 +572,7 @@ export default {
autocorrect="off"
autocapitalize="off"
spellcheck="false"
@update:value="queueUpdate"
@input="queueUpdate"
/>
</template>
</KeyValue>
@@ -29,7 +29,7 @@ import SSHKey from './kubevirt.io.virtualmachine/VirtualMachineSSHKey';
export default {
name: 'HarvesterEditVMTemplate',
emits: ['update:value'],
emits: ['update:templateValue'],
components: {
Tab,
@@ -205,7 +205,7 @@ export default {
if (tab.name === 'advanced') {
this.$refs.yamlEditor?.refresh();
}
}
},
},
};
</script>
@@ -222,11 +222,11 @@ export default {
@finish="saveVMT"
>
<NameNsDescription
:value="value"
:value="templateValue"
:mode="realTemplateMode"
name-label="harvester.vmTemplate.nameNsDescription.name"
:namespaced="true"
@update:value="$emit('update:value', $event)"
@update:value="$emit('update:templateValue', $event)"
/>
<Checkbox
@@ -95,7 +95,11 @@ export default {
devices: {
handler(v) {
this.rows = v;
this.filterRows = this.rows;
if (this.parentSriov) {
this.filterRows = this.rows.filter((row) => row.labels[this.parentSriovLabel] === this.parentSriov);
} else {
this.filterRows = this.rows;
}
},
immediate: true,
},
@@ -72,17 +72,23 @@ export default {
return stats;
},
units() {
allocatedUnits() {
const exponent = exponentNeeded(this.storageStats.total, 1024);
return `${ UNITS[exponent] }iB`;
},
usedUnits() {
const exponent = exponentNeeded(this.storageStats.maximum, 1024);
return `${ UNITS[exponent] }iB`;
},
used() {
formatUsed() {
let out = this.formatter(this.storageStats.used);
if (!Number.parseFloat(out) > 0) {
out = this.formatter(this.storageStats.used, { canRoundToZero: false });
out = this.formatter(this.storageStats.used, { canRoundToZero: true });
}
return out;
@@ -92,7 +98,7 @@ export default {
let out = this.formatter(this.storageStats.scheduled);
if (!Number.parseFloat(out) > 0) {
out = this.formatter(this.storageStats.scheduled, { canRoundToZero: false });
out = this.formatter(this.storageStats.scheduled, { canRoundToZero: true });
}
return out;
@@ -100,9 +106,9 @@ export default {
usedAmountTemplateValues() {
return {
used: this.used,
used: this.formatUsed,
total: this.formatter(this.storageStats.maximum),
unit: this.units,
unit: this.usedUnits,
};
},
@@ -110,7 +116,7 @@ export default {
return {
used: this.formatAllocated,
total: this.formatter(this.storageStats.total),
unit: this.units,
unit: this.allocatedUnits,
};
},
},
@@ -141,7 +147,7 @@ export default {
<ConsumptionGauge
:capacity="storageStats.total"
:used="storageStats.scheduled"
:units="units"
:units="allocatedUnits"
:number-formatter="formatter"
:resource-name="resourceName"
>
@@ -161,7 +167,7 @@ export default {
<ConsumptionGauge
:capacity="storageStats.maximum"
:used="storageStats.used"
:units="units"
:units="usedUnits"
:number-formatter="formatter"
:resource-name="showAllocated ? '' : resourceName"
:class="{
+21 -2
View File
@@ -14,16 +14,35 @@ export function getVersion(v) {
}
try {
// v1.4.1-rc.1 => v1.4.1, v1.4.1-dev-20241222 => v1.4.1
return `v${ semver.major(v) }.${ semver.minor(v) }.${ semver.patch(v) }`;
} catch (error) {
// fallback to the latest version
return Object.keys(RELEASE_FEATURES).sort((a, b) => semver.compare(a, b)).pop();
return latestVersion(Object.keys(RELEASE_FEATURES));
}
}
function latestVersion(versions) {
return versions.sort((a, b) => semver.compare(a, b)).pop();
}
// v1.3.3 => latest v1.3.x, v1.4.2 => latest v1.4.x
function latestMinorVersion(v) {
const minor = `v${ semver.major(v) }.${ semver.minor(v) }`;
const minorVersions = Object.keys(RELEASE_FEATURES).filter((version) => version.startsWith(minor));
return latestVersion(minorVersions);
}
export const featureEnabled = (featureKey, serverVersion) => {
const version = getVersion(serverVersion);
const releasedFeatures = RELEASE_FEATURES[version] || [];
let releasedFeatures = RELEASE_FEATURES[version];
if (!releasedFeatures) {
const fallback = latestMinorVersion(version);
releasedFeatures = RELEASE_FEATURES[fallback];
}
return releasedFeatures.includes(featureKey);
};
+63
View File
@@ -0,0 +1,63 @@
#!/bin/bash
set -e
set -x
BUILD_DEBUG="${BUILD_DEBUG:-}"
if [[ -n "${BUILD_DEBUG}" ]]; then
set -x
env
fi
cd $(dirname $0)/..
echo "Bootstrapping..."
yarn --pure-lockfile install
source scripts/version
echo "BRANCH: ${COMMIT_BRANCH:-<none>}"
echo "TAG: ${GIT_TAG:-<none>}"
DIR=${GIT_TAG:-$COMMIT_BRANCH}
if [[ "${DIR}" == "main" ]]; then
DIR="latest"
fi
OUTPUT_DIR=dist/${DIR}-embedded
echo "Building..."
COMMIT=${COMMIT} VERSION=${VERSION} OUTPUT_DIR=$OUTPUT_DIR ROUTER_BASE='/dashboard/' RESOURCE_BASE='/dashboard/' RANCHER_ENV=harvester yarn run build
if [ -v EMBED_PKG ]; then
echo "Build and embed plugin from: $EMBED_PKG"
PKG_FILE_NAME=${EMBED_PKG##*/}
echo PKG_FILE_NAME: $PKG_FILE_NAME
PKG_NAME="${PKG_FILE_NAME/.tar.gz/""}"
echo "Plugin name: '$PKG_NAME'"
# Fetch file, unpack and move to dist
curl $EMBED_PKG --output $PKG_FILE_NAME
OUTPUT_DIR_PKG=$OUTPUT_DIR/$PKG_NAME
mkdir -p $OUTPUT_DIR_PKG
tar xvfz $PKG_FILE_NAME -C $OUTPUT_DIR/$PKG_NAME
echo "Plugin contents that will be served from $PKG_NAME"
ls -alR $OUTPUT_DIR/$PKG_NAME
fi
echo "Destroying..."
find $OUTPUT_DIR -name "index.html" -mindepth 2 -exec rm {} \;
find $OUTPUT_DIR -type d -empty -depth -exec rmdir {} \;
TARBALL=${DIR}.tar.gz
TARBALL_FILE_PATH=dist/${TARBALL}
ENV_OUTPUT="${GITHUB_OUTPUT:-"temp-env"}"
echo "BUILD_EMBEDED_TGZ=${TARBALL_FILE_PATH}" >> "$ENV_OUTPUT"
echo "Compressing to ${TARBALL}..."
tar -czf ${TARBALL_FILE_PATH} $OUTPUT_DIR/
echo "Cleaning up..."
rm -r $OUTPUT_DIR
ls -alR dist/
+34
View File
@@ -0,0 +1,34 @@
#!/bin/bash
set -e
BUILD_DEBUG="${BUILD_DEBUG:-}"
if [[ -n "${BUILD_DEBUG}" ]]; then
set -x
env
fi
cd $(dirname $0)/..
echo "Bootstrapping..."
yarn --pure-lockfile install
source scripts/version
echo "BRANCH: ${COMMIT_BRANCH:-<none>}"
echo "TAG: ${GIT_TAG:-<none>}"
DIR=${GIT_TAG:-$COMMIT_BRANCH}
if [[ "${DIR}" == "main" ]]; then
DIR="latest"
fi
BASE=${BASE:-https://releases.rancher.com/harvester-ui/dashboard/${DIR}}
echo "Building for ${BASE}..."
OUTPUT_DIR=dist/${DIR}
ENV_OUTPUT="${GITHUB_OUTPUT:-"temp-env"}"
echo "BUILD_HOSTED_DIR=${OUTPUT_DIR}" >> "$ENV_OUTPUT"
echo "BUILD_HOSTED_LOCATION=${DIR}" >> "$ENV_OUTPUT"
COMMIT=${COMMIT} VERSION=${VERSION} OUTPUT_DIR=${OUTPUT_DIR} ROUTER_BASE="/dashboard/" RESOURCE_BASE="${BASE}" RANCHER_ENV=harvester yarn run build
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env bash
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
BASE_DIR="$( cd $SCRIPT_DIR && cd ../.. & pwd)"
SHELL_DIR=$BASE_DIR/shell/
EXIT_CODE=0
FORMATS="umd-min"
while getopts "df:" opt; do
case $opt in
d)
FORMATS="umd"
;;
f)
FORMATS=$OPTARG
;;
esac
done
shift $((OPTIND-1))
# Use shell folder in node modules when we have @rancher/shell installed as a node module
# rather than the use-case of the mono-repo with the shell folder at the top-level
if [ ! -d ${SHELL_DIR} ]; then
SHELL_DIR=$BASE_DIR/node_modules/@rancher/shell/
SHELL_DIR=$(cd -P ${SHELL_DIR} && pwd)
fi
CREATE_TARBALL=${2}
if [ -z "$VERSION" ]; then
VERSION=$(cd pkg/$1; node -p -e "require('./package.json').version")
fi
NAME=${1}-${VERSION}
PKG_DIST=${BASE_DIR}/dist-pkg/${NAME}
if [ -d "${BASE_DIR}/pkg/${1}" ]; then
echo "Building UI Package $1"
echo " Package name: ${NAME}"
echo " Package version: ${VERSION}"
echo " Output formats: ${FORMATS}"
echo " Output directory: ${PKG_DIST}"
rm -rf ${PKG_DIST}
mkdir -p ${PKG_DIST}
pushd pkg/${1}
# Check that the .shell link exists and points to the correct place
if [ -e ".shell" ]; then
LINK=$(readlink .shell)
if [ "${LINK}" != "${SHELL_DIR}" ]; then
echo ".shell symlink exists but does not point to expected location - please check and fix"
popd
exit -1
fi
else
ln -s ${SHELL_DIR} .shell
fi
FILE=index.js
if [ -f ./index.ts ]; then
FILE=index.ts
fi
if [ -n "$COMMIT" ]; then
echo ${COMMIT} > ${PKG_DIST}/version
fi
${BASE_DIR}/node_modules/.bin/vue-cli-service build --name ${NAME} --target lib ${FILE} --dest ${PKG_DIST} --formats ${FORMATS} --filename ${NAME}
EXIT_CODE=$?
cp -f ./package.json ${PKG_DIST}/package.json
node ${SCRIPT_DIR}/pkgfile.js ${PKG_DIST}/package.json
rm -rf ${PKG_DIST}/*.bak
rm .shell
popd
fi
if [ $EXIT_CODE -ne 0 ]; then
exit $EXIT_CODE
fi
if [ -n "${CREATE_TARBALL}" ]; then
echo $COMMIT $COMMIT_BRANCH > ${PKG_DIST}/version-commit.txt
TARBALL=${NAME}.tar.gz
pushd ${PKG_DIST}
rm -f ../$TARBALL
echo "Compressing to ${TARBALL}..."
tar -czf ../${TARBALL} .
popd
fi
exit $EXIT_CODE
+63
View File
@@ -0,0 +1,63 @@
#!/bin/bash
set -e
cd $(dirname $0)/..
BUILD_DEBUG="${BUILD_DEBUG:-}"
if [[ -n "${BUILD_DEBUG}" ]]; then
set -x
env
fi
if [[ -n "$CI_BUILD_TAG" ]]; then
echo "Build has been triggered by a tag. Skipping gate"
exit 0
fi
if [[ -z "$CI_BRANCH" ]]; then
echo "No branch detected. Skipping gate"
exit 0
fi
if [[ -z "$GIT_REPO" ]]; then
echo "No repository detected. Unable to gate"
exit 1
fi
if [[ -z "$GIT_COMMIT" ]]; then
echo "No commit detected. Unable to gate"
exit 1
fi
echo "Repo: $GIT_REPO"
echo "Branch: $CI_BRANCH"
echo "Build Commit: $GIT_COMMIT"
tmp=$(mktemp -u)
STATUS_CODE=$(curl -w "%{http_code}" -s -o $tmp https://api.github.com/repos/$GIT_REPO/branches/$CI_BRANCH)
if [ "$STATUS_CODE" == "403" ]; then
RATE_LIMIT_REMAINING=$(curl -s https://api.github.com/rate_limit | ./scripts/jq-nano - rate remaining)
echo "Remaining GITHUB requests available: $RATE_LIMIT_REMAINING"
RATE_LIMIT_REMAINING=${RATE_LIMIT_REMAINING:-0}
if ((RATE_LIMIT_REMAINING < 1)); then
echo "Github Rate Limit has been hit, skipping gate"
exit 0
fi
# Fall through to the normal path like any other failed status code
fi
LATEST_BRANCH_COMMIT=$(cat $tmp | ./scripts/jq-nano - commit sha)
rm $tmp
echo "Latest Branch Commit: $LATEST_BRANCH_COMMIT"
if [ -z "$LATEST_BRANCH_COMMIT" ]; then
echo "Unable to determine latest commit, failing gate"
exit 1
fi
if [ "$LATEST_BRANCH_COMMIT" == "$GIT_COMMIT" ]; then
echo "Build was created from latest commit, passed upload gate"
else
echo "Build was not created from latest commit, failing gate"
exit 1
fi
+46
View File
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
yarn --pure-lockfile install
source scripts/version
if [[ $COMMIT_BRANCH == "main" ]]; then
VERSION="latest"
else
VERSION=$COMMIT_BRANCH
fi
echo "CI_BUILD_TAG: ${CI_BUILD_TAG}"
echo "GIT_TAG: ${GIT_TAG}"
echo "TAG_VERSION: ${TAG_VERSION}"
echo "CI Build Args"
echo "COMMIT: ${COMMIT}"
echo "COMMIT_BRANCH: ${COMMIT_BRANCH}"
echo "VERSION: ${VERSION}"
if [ -n "$GIT_TAG" ]; then
COMMIT=$COMMIT COMMIT_BRANCH=$COMMIT_BRANCH VERSION=$CI_BUILD_TAG ./scripts/build-pkg.sh ${1} "true"
else
COMMIT=$COMMIT COMMIT_BRANCH=$COMMIT_BRANCH VERSION=$VERSION ./scripts/build-pkg.sh ${1} "true"
fi
EXIT_CODE=$?
if [ -n "$GIT_TAG" ]; then
export PKG_NAME=${1}-${CI_BUILD_TAG}
export PKG_TARBALL=${PKG_NAME}.tar.gz
else
export PKG_NAME=${1}-${VERSION} # harvester-release-harvester-v1.5 or harvester-latest
export PKG_TARBALL=${PKG_NAME}.tar.gz # harvester-release-harvester-v1.5.tar.gz or harvester-latest.tar.gz
fi
echo "CI Build Artifacts"
echo "Package Directory: ${PKG_NAME}"
echo "Package Tarball: ${PKG_TARBALL}"
ENV_OUTPUT="${GITHUB_OUTPUT:-"temp-env"}"
echo "PKG_TARBALL=${PKG_TARBALL}" >> "$ENV_OUTPUT"
echo "PKG_NAME=${PKG_NAME}" >> "$ENV_OUTPUT"
exit $EXIT_CODE
+25
View File
@@ -0,0 +1,25 @@
#!/usr/bin/env node
const fs = require('fs');
const readline = require('readline');
const args = process.argv.slice(2);
const file = args.shift();
let text;
if ( file === '-' ) {
process.stdin.resume();
text = fs.readFileSync(0, "utf8");
} else {
text = fs.readFileSync(file, "utf8");
}
const data = JSON.parse(text);
let out = data;
while ( args.length ) {
out = out[args.shift()];
}
console.log(out);
+24
View File
@@ -0,0 +1,24 @@
const fs = require('fs');
console.log('Updating package file'); // eslint-disable-line no-console
if (process.argv.length !== 3) {
console.error('No enough args'); // eslint-disable-line no-console
return;
}
const pkgFilepath = process.argv[process.argv.length - 1];
const pkg = require(pkgFilepath);
// Ensure we have the keys we need
pkg.files = ['**/*'];
pkg.rancher = true;
pkg.main = `${ pkg.name }-${ pkg.version }.umd.min.js`;
delete pkg.scripts;
delete pkg.browserslist;
fs.writeFileSync(pkgFilepath, JSON.stringify(pkg, null, 2));
+57
View File
@@ -0,0 +1,57 @@
#!/bin/bash
shopt -s extglob
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
DIRTY="-dirty"
fi
COMMIT=$(git rev-parse --short HEAD)
COMMIT_DATE=$(git --no-pager log -1 --format='%ct')
COMMIT_BRANCH=$(git rev-parse --abbrev-ref HEAD | sed -E 's/[^a-zA-Z0-9.-]+/-/g')
GIT_TAG=${CI_BUILD_TAG:-$(git tag -l --contains HEAD | head -n 1)}
LAST_TAG=${GIT_TAG:-'v0.0.0'}
if [[ -z "$DIRTY" && -n "$GIT_TAG" ]]; then
# human readable version used on rancher dashboard about page
export DASHBOARD_VERSION=$GIT_TAG
# computer readable version
VERSION=$GIT_TAG
else
# human readable version used on rancher dashboard about page
export DASHBOARD_VERSION="${COMMIT_BRANCH} ${COMMIT}"
# computer readable version
VERSION="${COMMIT}${DIRTY}"
fi
# Chart tag.
if [[ -z "${DIRTY}" && -n "${GIT_TAG}" ]]; then
CHART_VERSION="${GIT_TAG}"
elif [[ "$DIRTY" ]]; then
CHART_VERSION="${LAST_TAG}${DIRTY}.${COMMIT}"
else
CHART_VERSION="${LAST_TAG}-${COMMIT_DATE}.${COMMIT}.${COMMIT_BRANCH}"
fi
# Drop the v prefix for Chart Version to follow existing pattern.
CHART_VERSION="$(echo ${CHART_VERSION} | sed -E 's/^v//' | sed -e 's/^\(.\{55\}\).*/\1/')"
# Chart Repo - Target Repo for releases.
case $CHART_VERSION in
*-alpha*) # All alpha tags
CHART_REPO="alpha" ;;
*-rc*) # All rc tags
CHART_REPO="latest" ;;
+([0-9]).+([0-9]).+([0-9])) # All release tags
CHART_REPO="latest" ;;
*) # Anything else - Future use
CHART_REPO="dev" ;;
esac
if [ -z "$ARCH" ]; then
ARCH=amd64
fi
echo "ARCH: $ARCH"
echo "CHART_REPO: $CHART_REPO"
echo "CHART_VERSION: $CHART_VERSION"
echo "VERSION: $VERSION"