@rancher/shell 0.3.16 → 0.3.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/images/wechat-qr-code.jpg +0 -0
- package/assets/translations/en-us.yaml +75 -16
- package/assets/translations/zh-hans.yaml +151 -15
- package/chart/__tests__/S3.test.ts +50 -0
- package/chart/rancher-backup/S3.vue +21 -0
- package/chart/rancher-backup/index.vue +4 -0
- package/components/AsyncButton.vue +1 -1
- package/components/CommunityLinks.vue +1 -0
- package/components/FileDiff.vue +92 -85
- package/components/Inactivity.vue +10 -0
- package/components/LazyImage.vue +2 -2
- package/components/PromptRestore.vue +7 -5
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/ResourceDetail/index.vue +8 -14
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +50 -2
- package/components/YamlEditor.vue +1 -0
- package/components/__tests__/PromptRestore.test.ts +72 -0
- package/components/auth/AzureWarning.vue +1 -1
- package/components/auth/RoleDetailEdit.vue +1 -0
- package/components/fleet/FleetResources.vue +3 -64
- package/components/form/FileImageSelector.vue +9 -0
- package/components/form/FileSelector.vue +2 -1
- package/components/form/MatchExpressions.vue +1 -3
- package/components/form/NameNsDescription.vue +28 -12
- package/components/form/NodeAffinity.vue +2 -2
- package/components/form/PodAffinity.vue +2 -2
- package/components/form/ResourceTabs/index.vue +8 -2
- package/components/form/Select.vue +16 -0
- package/components/form/__tests__/FileImageSelector.test.ts +42 -0
- package/components/form/__tests__/FileSelector.test.ts +76 -0
- package/components/form/__tests__/NodeAffinity.test.ts +38 -0
- package/components/form/__tests__/PodAffinity.test.ts +46 -0
- package/components/formatter/ClusterLink.vue +8 -4
- package/components/formatter/ClusterProvider.vue +3 -1
- package/components/formatter/ImageName.vue +23 -0
- package/components/formatter/PodImages.vue +7 -1
- package/components/formatter/__tests__/ClusterLink.test.ts +101 -0
- package/components/formatter/__tests__/ClusterProvider.test.ts +24 -0
- package/components/nav/Header.vue +2 -2
- package/components/nav/WindowManager/ContainerShell.vue +60 -36
- package/components/nav/WindowManager/__tests__/ContainerShell.test.ts +561 -0
- package/config/__test__/home-links.test.ts +62 -0
- package/config/home-links.js +15 -3
- package/config/labels-annotations.js +7 -2
- package/config/persistentVolume.ts +108 -0
- package/config/product/manager.js +5 -1
- package/config/router.js +0 -4
- package/config/settings.ts +4 -0
- package/config/table-headers.js +6 -5
- package/config/types.js +2 -0
- package/config/uiplugins.js +50 -5
- package/core/plugin-helpers.js +39 -15
- package/core/plugin.ts +9 -0
- package/core/plugins.js +1 -1
- package/core/types-provisioning.ts +253 -0
- package/core/types.ts +21 -3
- package/detail/autoscaling.horizontalpodautoscaler/index.vue +50 -1
- package/detail/fleet.cattle.io.gitrepo.vue +10 -2
- package/detail/node.vue +6 -6
- package/detail/pod.vue +38 -9
- package/detail/provisioning.cattle.io.cluster.vue +46 -7
- package/detail/workload/index.vue +49 -18
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +62 -0
- package/edit/__tests__/ui.cattle.io.navlink.test.ts +110 -0
- package/edit/auth/github.vue +1 -0
- package/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue +130 -0
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +79 -0
- package/edit/fleet.cattle.io.clustergroup.vue +14 -3
- package/edit/fleet.cattle.io.gitrepo.vue +18 -1
- package/edit/namespace.vue +9 -1
- package/edit/networking.k8s.io.ingress/RulePath.vue +0 -2
- package/edit/persistentvolume/__tests__/persistentvolume.test.ts +82 -0
- package/edit/persistentvolume/index.vue +2 -1
- package/edit/persistentvolume/plugins/csi.vue +3 -1
- package/edit/persistentvolume/plugins/longhorn.vue +12 -12
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +1 -30
- package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +15 -11
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +79 -1
- package/edit/provisioning.cattle.io.cluster/index.vue +53 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +335 -151
- package/edit/storage.k8s.io.storageclass/index.vue +1 -2
- package/edit/ui.cattle.io.navlink.vue +213 -186
- package/initialize/App.js +3 -13
- package/initialize/layouts.ts +26 -0
- package/layouts/default.vue +1 -1
- package/list/group.principal.vue +1 -1
- package/list/provisioning.cattle.io.cluster.vue +8 -1
- package/middleware/authenticated.js +101 -5
- package/mixins/brand.js +39 -3
- package/mixins/child-hook.js +2 -2
- package/mixins/create-edit-view/impl.js +4 -4
- package/models/chart.js +1 -1
- package/models/fleet.cattle.io.cluster.js +33 -4
- package/models/fleet.cattle.io.gitrepo.js +113 -38
- package/models/management.cattle.io.kontainerdriver.js +14 -0
- package/models/persistentvolume.js +2 -111
- package/models/pod.js +30 -0
- package/models/provisioning.cattle.io.cluster.js +9 -1
- package/models/rke.cattle.io.etcdsnapshot.js +10 -7
- package/package.json +2 -2
- package/pages/about.vue +8 -2
- package/pages/auth/login.vue +1 -1
- package/pages/auth/logout.vue +11 -3
- package/pages/c/_cluster/apps/charts/index.vue +5 -2
- package/pages/c/_cluster/apps/charts/install.vue +5 -0
- package/pages/c/_cluster/auth/group.principal/assign-edit.vue +1 -1
- package/pages/c/_cluster/auth/roles/index.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +2 -11
- package/pages/c/_cluster/manager/cloudCredential/_id.vue +0 -1
- package/pages/c/_cluster/manager/cloudCredential/create.vue +0 -1
- package/pages/c/_cluster/settings/brand.vue +11 -8
- package/pages/c/_cluster/uiplugins/AddExtensionRepos.vue +177 -0
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +19 -3
- package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +90 -21
- package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +107 -37
- package/pages/c/_cluster/uiplugins/index.vue +160 -44
- package/pages/docs/_doc.vue +9 -3
- package/pages/home.vue +6 -6
- package/pages/support/index.vue +10 -4
- package/pkg/auto-import.js +1 -1
- package/plugins/clean-tooltip-directive.js +1 -1
- package/plugins/dashboard-store/__tests__/actions.spec.ts +165 -0
- package/plugins/dashboard-store/__tests__/getters.spec.ts +100 -0
- package/plugins/dashboard-store/__tests__/{mutations.spec.js → mutations.spec.ts} +2 -2
- package/plugins/dashboard-store/actions.js +1 -1
- package/plugins/dashboard-store/resource-class.js +39 -2
- package/plugins/plugin.js +9 -1
- package/plugins/steve/__tests__/getters.spec.ts +93 -0
- package/plugins/steve/getters.js +21 -1
- package/plugins/steve/subscribe.js +1 -3
- package/rancher-components/BadgeState/BadgeState.vue +5 -1
- package/rancher-components/Banner/Banner.test.ts +51 -1
- package/rancher-components/Banner/Banner.vue +134 -53
- package/rancher-components/Card/Card.test.ts +37 -0
- package/rancher-components/Card/Card.vue +24 -7
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +20 -29
- package/rancher-components/Form/Checkbox/Checkbox.vue +45 -20
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +2 -8
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +22 -10
- package/rancher-components/Form/Radio/RadioButton.test.ts +31 -0
- package/rancher-components/Form/Radio/RadioButton.vue +30 -13
- package/rancher-components/Form/Radio/RadioGroup.vue +26 -7
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -6
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.test.ts +25 -38
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +23 -11
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +19 -5
- package/rancher-components/StringList/StringList.test.ts +453 -49
- package/rancher-components/StringList/StringList.vue +44 -26
- package/scripts/extension/publish +2 -2
- package/scripts/typegen.sh +11 -2
- package/server/server-middleware.js +4 -12
- package/store/index.js +14 -3
- package/store/prefs.js +0 -3
- package/store/store-types.js +2 -0
- package/store/type-map.js +17 -29
- package/types/api.d.ts +1 -0
- package/types/fleet.d.ts +1 -0
- package/types/shell/index.d.ts +931 -85
- package/types/userPreferences.d.ts +1 -1
- package/utils/__mocks__/socket.js +21 -0
- package/utils/grafana.js +23 -11
- package/utils/kube.js +9 -0
- package/utils/object.js +27 -0
- package/utils/selector.js +2 -1
- package/utils/settings.ts +2 -2
- package/utils/validators/formRules/index.ts +3 -3
- package/vue.config.js +3 -2
- package/components/.DS_Store +0 -0
- package/components/__tests__/.DS_Store +0 -0
- package/creators/pkg/package-lock.json +0 -37
- package/pages/safeMode.vue +0 -17
- package/plugins/steve/urloptions.js +0 -47
- package/yarn-error.log +0 -196
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
3
3
|
import { NAMESPACE as NAMESPACE_COL } from '@shell/config/table-headers';
|
|
4
4
|
import {
|
|
5
|
-
POD, WORKLOAD_TYPES, SCALABLE_WORKLOAD_TYPES, SERVICE, INGRESS, NODE
|
|
5
|
+
POD, WORKLOAD_TYPES, SCALABLE_WORKLOAD_TYPES, SERVICE, INGRESS, NODE, NAMESPACE,
|
|
6
6
|
} from '@shell/config/types';
|
|
7
|
-
import
|
|
7
|
+
import ResourceTable from '@shell/components/ResourceTable';
|
|
8
8
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
9
9
|
import Loading from '@shell/components/Loading';
|
|
10
10
|
import ResourceTabs from '@shell/components/form/ResourceTabs';
|
|
@@ -16,6 +16,7 @@ import { mapGetters } from 'vuex';
|
|
|
16
16
|
import { allDashboardsExist } from '@shell/utils/grafana';
|
|
17
17
|
import PlusMinus from '@shell/components/form/PlusMinus';
|
|
18
18
|
import { matches } from '@shell/utils/selector';
|
|
19
|
+
import { PROJECT } from '@shell/config/labels-annotations';
|
|
19
20
|
|
|
20
21
|
const SCALABLE_TYPES = Object.values(SCALABLE_WORKLOAD_TYPES);
|
|
21
22
|
const WORKLOAD_METRICS_DETAIL_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-workload-pods-1/rancher-workload-pods?orgId=1';
|
|
@@ -46,7 +47,7 @@ export default {
|
|
|
46
47
|
Loading,
|
|
47
48
|
ResourceTabs,
|
|
48
49
|
CountGauge,
|
|
49
|
-
|
|
50
|
+
ResourceTable,
|
|
50
51
|
PlusMinus
|
|
51
52
|
},
|
|
52
53
|
|
|
@@ -85,23 +86,37 @@ export default {
|
|
|
85
86
|
const isMetricsSupportedKind = METRICS_SUPPORTED_KINDS.includes(this.value.type);
|
|
86
87
|
|
|
87
88
|
this.showMetrics = isMetricsSupportedKind && await allDashboardsExist(this.$store, this.currentCluster.id, [WORKLOAD_METRICS_DETAIL_URL, WORKLOAD_METRICS_SUMMARY_URL]);
|
|
89
|
+
if (!this.showMetrics) {
|
|
90
|
+
const namespace = await this.$store.dispatch('cluster/find', { type: NAMESPACE, id: this.value.metadata.namespace });
|
|
88
91
|
|
|
92
|
+
const projectId = namespace?.metadata?.labels[PROJECT];
|
|
93
|
+
|
|
94
|
+
if (projectId) {
|
|
95
|
+
this.WORKLOAD_PROJECT_METRICS_DETAIL_URL = `/api/v1/namespaces/cattle-project-${ projectId }-monitoring/services/http:cattle-project-${ projectId }-monitoring-grafana:80/proxy/d/rancher-pod-containers-1/rancher-workload-pods?orgId=1'`;
|
|
96
|
+
this.WORKLOAD_PROJECT_METRICS_SUMMARY_URL = `/api/v1/namespaces/cattle-project-${ projectId }-monitoring/services/http:cattle-project-${ projectId }-monitoring-grafana:80/proxy/d/rancher-pod-1/rancher-workload?orgId=1`;
|
|
97
|
+
|
|
98
|
+
this.showProjectMetrics = await allDashboardsExist(this.$store, this.currentCluster.id, [this.WORKLOAD_PROJECT_METRICS_DETAIL_URL, this.WORKLOAD_PROJECT_METRICS_SUMMARY_URL], 'cluster', projectId);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
89
101
|
this.findMatchingServices();
|
|
90
102
|
this.findMatchingIngresses();
|
|
91
103
|
},
|
|
92
104
|
|
|
93
105
|
data() {
|
|
94
106
|
return {
|
|
95
|
-
allPods:
|
|
96
|
-
allServices:
|
|
97
|
-
allIngresses:
|
|
98
|
-
matchingServices:
|
|
99
|
-
matchingIngresses:
|
|
100
|
-
allJobs:
|
|
101
|
-
allNodes:
|
|
107
|
+
allPods: [],
|
|
108
|
+
allServices: [],
|
|
109
|
+
allIngresses: [],
|
|
110
|
+
matchingServices: [],
|
|
111
|
+
matchingIngresses: [],
|
|
112
|
+
allJobs: [],
|
|
113
|
+
allNodes: [],
|
|
102
114
|
WORKLOAD_METRICS_DETAIL_URL,
|
|
103
115
|
WORKLOAD_METRICS_SUMMARY_URL,
|
|
104
|
-
|
|
116
|
+
POD_PROJECT_METRICS_DETAIL_URL: '',
|
|
117
|
+
POD_PROJECT_METRICS_SUMMARY_URL: '',
|
|
118
|
+
showMetrics: false,
|
|
119
|
+
showProjectMetrics: false,
|
|
105
120
|
};
|
|
106
121
|
},
|
|
107
122
|
|
|
@@ -380,12 +395,12 @@ export default {
|
|
|
380
395
|
:label="t('tableHeaders.jobs')"
|
|
381
396
|
:weight="4"
|
|
382
397
|
>
|
|
383
|
-
<
|
|
398
|
+
<ResourceTable
|
|
384
399
|
:rows="value.jobs"
|
|
385
400
|
:headers="jobHeaders"
|
|
386
401
|
key-field="id"
|
|
387
402
|
:schema="jobSchema"
|
|
388
|
-
:
|
|
403
|
+
:groupable="false"
|
|
389
404
|
:search="false"
|
|
390
405
|
/>
|
|
391
406
|
</Tab>
|
|
@@ -395,7 +410,7 @@ export default {
|
|
|
395
410
|
:label="t('tableHeaders.pods')"
|
|
396
411
|
:weight="4"
|
|
397
412
|
>
|
|
398
|
-
<
|
|
413
|
+
<ResourceTable
|
|
399
414
|
v-if="value.pods"
|
|
400
415
|
:rows="value.pods"
|
|
401
416
|
:headers="podHeaders"
|
|
@@ -421,6 +436,22 @@ export default {
|
|
|
421
436
|
/>
|
|
422
437
|
</template>
|
|
423
438
|
</Tab>
|
|
439
|
+
<Tab
|
|
440
|
+
v-if="showProjectMetrics"
|
|
441
|
+
:label="t('workload.container.titles.metrics')"
|
|
442
|
+
name="workload-metrics"
|
|
443
|
+
:weight="3"
|
|
444
|
+
>
|
|
445
|
+
<template #default="props">
|
|
446
|
+
<DashboardMetrics
|
|
447
|
+
v-if="props.active"
|
|
448
|
+
:detail-url="WORKLOAD_PROJECT_METRICS_DETAIL_URL"
|
|
449
|
+
:summary-url="WORKLOAD_PROJECT_METRICS_SUMMARY_URL"
|
|
450
|
+
:vars="graphVars"
|
|
451
|
+
graph-height="550px"
|
|
452
|
+
/>
|
|
453
|
+
</template>
|
|
454
|
+
</Tab>
|
|
424
455
|
<Tab
|
|
425
456
|
v-if="v1MonitoringUrl"
|
|
426
457
|
name="v1Metrics"
|
|
@@ -458,13 +489,13 @@ export default {
|
|
|
458
489
|
>
|
|
459
490
|
{{ t('workload.detail.serviceListCaption') }}
|
|
460
491
|
</p>
|
|
461
|
-
<
|
|
492
|
+
<ResourceTable
|
|
462
493
|
v-if="serviceSchema && matchingServices.length > 0"
|
|
463
494
|
:rows="matchingServices"
|
|
464
495
|
:headers="serviceHeaders"
|
|
465
496
|
key-field="id"
|
|
466
497
|
:schema="serviceSchema"
|
|
467
|
-
:
|
|
498
|
+
:groupable="false"
|
|
468
499
|
:search="false"
|
|
469
500
|
:table-actions="false"
|
|
470
501
|
/>
|
|
@@ -499,13 +530,13 @@ export default {
|
|
|
499
530
|
>
|
|
500
531
|
{{ t('workload.detail.ingressListCaption') }}
|
|
501
532
|
</p>
|
|
502
|
-
<
|
|
533
|
+
<ResourceTable
|
|
503
534
|
v-if="ingressSchema && matchingIngresses.length > 0"
|
|
504
535
|
:rows="matchingIngresses"
|
|
505
536
|
:headers="ingressHeaders"
|
|
506
537
|
key-field="id"
|
|
507
538
|
:schema="ingressSchema"
|
|
508
|
-
:
|
|
539
|
+
:groupable="false"
|
|
509
540
|
:search="false"
|
|
510
541
|
:table-actions="false"
|
|
511
542
|
/>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { mount, createLocalVue } from '@vue/test-utils';
|
|
2
|
+
import GitRepo from '@shell/edit/fleet.cattle.io.gitrepo.vue';
|
|
3
|
+
import Vuex from 'vuex';
|
|
4
|
+
|
|
5
|
+
const localVue = createLocalVue();
|
|
6
|
+
|
|
7
|
+
localVue.use(Vuex);
|
|
8
|
+
|
|
9
|
+
describe('view: fleet.cattle.io.gitrepo should', () => {
|
|
10
|
+
const mockStore = {
|
|
11
|
+
getters: {
|
|
12
|
+
'i18n/t': (text: string) => text,
|
|
13
|
+
t: (text: string) => text,
|
|
14
|
+
currentStore: () => 'current_store',
|
|
15
|
+
'current_store/schemaFor': jest.fn(),
|
|
16
|
+
'current_store/all': jest.fn(),
|
|
17
|
+
workspace: jest.fn(),
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const mocks = {
|
|
21
|
+
$store: mockStore,
|
|
22
|
+
$fetchState: { pending: false },
|
|
23
|
+
$route: {
|
|
24
|
+
query: { AS: '' },
|
|
25
|
+
name: {
|
|
26
|
+
endsWith: () => {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const values = {
|
|
33
|
+
metadata: { namespace: 'test' }, spec: { template: {}, correctDrift: { enabled: false } }, targetInfo: { mode: 'all' },
|
|
34
|
+
};
|
|
35
|
+
const wrapper = mount(GitRepo, {
|
|
36
|
+
localVue,
|
|
37
|
+
propsData: { value: values },
|
|
38
|
+
mocks
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should have self-healing checkbox and banner', () => {
|
|
42
|
+
const correctDriftCheckbox = wrapper.find('[data-testid="GitRepo-correctDrift-checkbox"]');
|
|
43
|
+
const correctDriftBanner = wrapper.find('[data-testid="GitRepo-correctDrift-banner"]');
|
|
44
|
+
|
|
45
|
+
expect(correctDriftCheckbox.exists()).toBeTruthy();
|
|
46
|
+
expect(correctDriftBanner.exists()).toBeTruthy();
|
|
47
|
+
expect(correctDriftCheckbox.props().value).toBeFalsy();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should enable drift if self-healing is checked', async() => {
|
|
51
|
+
const correctDriftCheckbox = wrapper.find('[data-testid="GitRepo-correctDrift-checkbox"]');
|
|
52
|
+
const correctDriftContainer = wrapper.find('[data-testid="GitRepo-correctDrift-checkbox"] .checkbox-container');
|
|
53
|
+
|
|
54
|
+
expect(correctDriftContainer.exists()).toBeTruthy();
|
|
55
|
+
|
|
56
|
+
await correctDriftContainer.trigger('click');
|
|
57
|
+
|
|
58
|
+
expect(correctDriftCheckbox.emitted('input')).toHaveLength(1);
|
|
59
|
+
expect(correctDriftCheckbox.emitted('input')![0][0]).toBe(true);
|
|
60
|
+
expect(correctDriftCheckbox.props().value).toBeTruthy();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/* eslint-disable jest/no-hooks */
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import Navlink from '@shell/edit/ui.cattle.io.navlink.vue';
|
|
4
|
+
import { _CREATE } from '@shell/config/query-params';
|
|
5
|
+
import CruResource from '@shell/components/CruResource';
|
|
6
|
+
|
|
7
|
+
describe('view: ui.cattle.io.navlink should', () => {
|
|
8
|
+
const name = 'test';
|
|
9
|
+
const url = 'http://test.com';
|
|
10
|
+
let wrapper: any;
|
|
11
|
+
|
|
12
|
+
const requiredSetup = () => ({
|
|
13
|
+
// Remove all these mocks after migration to Vue 2.7/3 due mixin logic
|
|
14
|
+
mocks: {
|
|
15
|
+
$store: {
|
|
16
|
+
getters: {
|
|
17
|
+
currentStore: () => 'current_store',
|
|
18
|
+
'current_store/schemaFor': jest.fn(),
|
|
19
|
+
'current_store/all': jest.fn(),
|
|
20
|
+
'i18n/t': (val) => val,
|
|
21
|
+
'i18n/exists': jest.fn(),
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
$route: { query: { AS: '' } },
|
|
25
|
+
$router: { applyQuery: jest.fn() },
|
|
26
|
+
},
|
|
27
|
+
propsData: {
|
|
28
|
+
metadata: { namespace: 'test' },
|
|
29
|
+
spec: { template: {} },
|
|
30
|
+
targetInfo: { mode: 'all' },
|
|
31
|
+
value: {},
|
|
32
|
+
mode: _CREATE,
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
wrapper = mount(Navlink, { ...requiredSetup() });
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
wrapper.destroy();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('have "Create" button disabled before fields are filled in', () => {
|
|
46
|
+
const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
|
|
47
|
+
|
|
48
|
+
expect(saveButton.disabled).toBe(true);
|
|
49
|
+
});
|
|
50
|
+
it('have "Create" button disabled when Link type is URL and only name is filled in', async() => {
|
|
51
|
+
const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
|
|
52
|
+
const nameField = wrapper.find('[data-testid="Navlink-name-field"]').find('input');
|
|
53
|
+
|
|
54
|
+
nameField.setValue(name);
|
|
55
|
+
|
|
56
|
+
await wrapper.vm.$nextTick();
|
|
57
|
+
|
|
58
|
+
expect(saveButton.disabled).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
it('have "Create" button enabled when Link type is URL and all required fields are filled in', async() => {
|
|
61
|
+
const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
|
|
62
|
+
const nameField = wrapper.find('[data-testid="Navlink-name-field"]').find('input');
|
|
63
|
+
const urlField = wrapper.find('[data-testid="Navlink-url-field"]');
|
|
64
|
+
|
|
65
|
+
nameField.setValue(name);
|
|
66
|
+
urlField.setValue(url);
|
|
67
|
+
|
|
68
|
+
await wrapper.vm.$nextTick();
|
|
69
|
+
|
|
70
|
+
expect(saveButton.disabled).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('have "Create" button disabled when Link type is Service and and only name is filled in', async() => {
|
|
74
|
+
const saveButton = wrapper.find('[data-testid="form-save"]').element as HTMLInputElement;
|
|
75
|
+
const nameField = wrapper.find('[data-testid="Navlink-name-field"]').find('input');
|
|
76
|
+
const rg = wrapper.find('[data-testid="Navlink-link-radiogroup"]');
|
|
77
|
+
|
|
78
|
+
const serviceBttn = rg.findAll('.radio-label').at(1);
|
|
79
|
+
|
|
80
|
+
nameField.setValue(name);
|
|
81
|
+
serviceBttn.trigger('click');
|
|
82
|
+
await wrapper.vm.$nextTick();
|
|
83
|
+
|
|
84
|
+
expect(saveButton.disabled).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('have "Create" button enabled when Link type is Service and and all required fields are filled in', async() => {
|
|
88
|
+
const nameField = wrapper.find('[data-testid="Navlink-name-field"]').find('input');
|
|
89
|
+
const rg = wrapper.find('[data-testid="Navlink-link-radiogroup"]');
|
|
90
|
+
|
|
91
|
+
const serviceBttn = rg.findAll('.radio-label').at(1);
|
|
92
|
+
|
|
93
|
+
nameField.setValue(name);
|
|
94
|
+
serviceBttn.trigger('click');
|
|
95
|
+
await wrapper.vm.$nextTick();
|
|
96
|
+
|
|
97
|
+
const schemeField = wrapper.find('[data-testid="Navlink-scheme-field"]');
|
|
98
|
+
const serviceField = wrapper.find('[data-testid="Navlink-currentService-field"]');
|
|
99
|
+
|
|
100
|
+
schemeField.find('button').trigger('click');
|
|
101
|
+
await wrapper.trigger('keydown.down');
|
|
102
|
+
await wrapper.trigger('keydown.enter');
|
|
103
|
+
|
|
104
|
+
serviceField.find('button').trigger('click');
|
|
105
|
+
await wrapper.trigger('keydown.down');
|
|
106
|
+
await wrapper.trigger('keydown.enter');
|
|
107
|
+
|
|
108
|
+
expect(CruResource.computed.canSave()).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
});
|
package/edit/auth/github.vue
CHANGED
|
@@ -163,6 +163,7 @@ export default {
|
|
|
163
163
|
<RadioGroup
|
|
164
164
|
v-model="targetType"
|
|
165
165
|
name="targetType"
|
|
166
|
+
data-testid="authConfig-gitHub"
|
|
166
167
|
:options="['public','private']"
|
|
167
168
|
:mode="mode"
|
|
168
169
|
:labels="[ t(`authConfig.${NAME}.target.public`), t(`authConfig.${NAME}.target.private`)]"
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
|
|
3
|
+
import { _EDIT } from '@shell/config/query-params';
|
|
4
|
+
import LabeledSelect from '@shell/components/form/LabeledSelect.vue';
|
|
5
|
+
import { LabeledInput } from '@components/Form/LabeledInput';
|
|
6
|
+
import ArrayListGrouped from '@shell/components/form/ArrayListGrouped.vue';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
components: {
|
|
10
|
+
ArrayListGrouped,
|
|
11
|
+
LabeledInput,
|
|
12
|
+
LabeledSelect
|
|
13
|
+
},
|
|
14
|
+
props: {
|
|
15
|
+
value: {
|
|
16
|
+
type: Object,
|
|
17
|
+
default: () => {
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
mode: {
|
|
21
|
+
type: String,
|
|
22
|
+
default: _EDIT
|
|
23
|
+
},
|
|
24
|
+
type: {
|
|
25
|
+
type: String,
|
|
26
|
+
default: 'scaleUp'
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
data() {
|
|
30
|
+
if (!this.value.spec.behavior[this.type].policies) {
|
|
31
|
+
this.$set(this.value.spec.behavior[this.type], 'policies', []);
|
|
32
|
+
}
|
|
33
|
+
if (!this.value.spec.behavior[this.type].selectPolicy) {
|
|
34
|
+
this.$set(this.value.spec.behavior[this.type], 'selectPolicy', 'Max');
|
|
35
|
+
}
|
|
36
|
+
if (this.value.spec.behavior[this.type].stabilizationWindowSeconds === null || typeof this.value.spec.behavior[this.type].stabilizationWindowSeconds === 'undefined') {
|
|
37
|
+
if (this.type === 'scaleUp') {
|
|
38
|
+
this.$set(this.value.spec.behavior[this.type], 'stabilizationWindowSeconds', 0);
|
|
39
|
+
}
|
|
40
|
+
if (this.type === 'scaleDown') {
|
|
41
|
+
this.$set(this.value.spec.behavior[this.type], 'stabilizationWindowSeconds', 300);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { selectPolicyOptions: ['Max', 'Min', 'Disabled'], policyTypeOptions: ['Pods', 'Percent'] };
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<div>
|
|
52
|
+
<div class="row mb-20">
|
|
53
|
+
<div class="col span-12">
|
|
54
|
+
<ArrayListGrouped
|
|
55
|
+
v-model="value.spec.behavior[type].policies"
|
|
56
|
+
:add-label="t('hpa.scalingRule.addPolicy')"
|
|
57
|
+
:default-add-value="{}"
|
|
58
|
+
:mode="mode"
|
|
59
|
+
>
|
|
60
|
+
<template #default="props">
|
|
61
|
+
<div class="row">
|
|
62
|
+
<div class="col span-4">
|
|
63
|
+
<LabeledSelect
|
|
64
|
+
v-model="props.row.value.type"
|
|
65
|
+
:mode="mode"
|
|
66
|
+
:options="policyTypeOptions"
|
|
67
|
+
:multiple="false"
|
|
68
|
+
:taggable="true"
|
|
69
|
+
:searchable="true"
|
|
70
|
+
:required="true"
|
|
71
|
+
:tooltip="t('hpa.scalingRule.policy.typeTooltip')"
|
|
72
|
+
:label="t('hpa.scalingRule.policy.type')"
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
<div class="col span-4">
|
|
76
|
+
<LabeledInput
|
|
77
|
+
v-model.number="props.row.value.value"
|
|
78
|
+
:mode="mode"
|
|
79
|
+
type="number"
|
|
80
|
+
min="1"
|
|
81
|
+
:required="true"
|
|
82
|
+
:tooltip="t('hpa.scalingRule.policy.valueTooltip')"
|
|
83
|
+
:label="t('hpa.scalingRule.policy.value')"
|
|
84
|
+
/>
|
|
85
|
+
</div>
|
|
86
|
+
<div class="col span-4">
|
|
87
|
+
<LabeledInput
|
|
88
|
+
v-model.number="props.row.value.periodSeconds"
|
|
89
|
+
:mode="mode"
|
|
90
|
+
type="number"
|
|
91
|
+
min="1"
|
|
92
|
+
max="1800"
|
|
93
|
+
:required="true"
|
|
94
|
+
:tooltip="t('hpa.scalingRule.policy.periodSecondsTooltip')"
|
|
95
|
+
:label="t('hpa.scalingRule.policy.periodSeconds')"
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</template>
|
|
100
|
+
</ArrayListGrouped>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
<div class="row">
|
|
104
|
+
<div class="col span-6">
|
|
105
|
+
<LabeledSelect
|
|
106
|
+
v-model="value.spec.behavior[type].selectPolicy"
|
|
107
|
+
:mode="mode"
|
|
108
|
+
:options="selectPolicyOptions"
|
|
109
|
+
:multiple="false"
|
|
110
|
+
:taggable="true"
|
|
111
|
+
:searchable="true"
|
|
112
|
+
:label="t('hpa.scalingRule.selectPolicy')"
|
|
113
|
+
:tooltip="t('hpa.scalingRule.selectPolicyTooltip')"
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
<div class="col span-6">
|
|
117
|
+
<LabeledInput
|
|
118
|
+
v-model.number="value.spec.behavior[type].stabilizationWindowSeconds"
|
|
119
|
+
:mode="mode"
|
|
120
|
+
type="number"
|
|
121
|
+
min="0"
|
|
122
|
+
max="3600"
|
|
123
|
+
:label="t('hpa.scalingRule.stabilizationWindowSeconds')"
|
|
124
|
+
:tooltip="t('hpa.scalingRule.stabilizationWindowSecondsTooltip')"
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="row mb-40" />
|
|
129
|
+
</div>
|
|
130
|
+
</template>
|
|
@@ -12,12 +12,14 @@ import Tabbed from '@shell/components/Tabbed';
|
|
|
12
12
|
import MetricsRow from '@shell/edit/autoscaling.horizontalpodautoscaler/metrics-row';
|
|
13
13
|
import ArrayListGrouped from '@shell/components/form/ArrayListGrouped';
|
|
14
14
|
import { DEFAULT_RESOURCE_METRIC } from '@shell/edit/autoscaling.horizontalpodautoscaler/resource-metric';
|
|
15
|
+
import { Checkbox } from '@components/Form/Checkbox';
|
|
15
16
|
|
|
16
17
|
import { API_SERVICE, SCALABLE_WORKLOAD_TYPES } from '@shell/config/types';
|
|
17
18
|
import isEmpty from 'lodash/isEmpty';
|
|
18
19
|
import find from 'lodash/find';
|
|
19
20
|
import endsWith from 'lodash/endsWith';
|
|
20
21
|
import { findBy } from '@shell/utils/array';
|
|
22
|
+
import HpaScalingRule from '@shell/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue';
|
|
21
23
|
|
|
22
24
|
const RESOURCE_METRICS_API_GROUP = 'metrics.k8s.io';
|
|
23
25
|
|
|
@@ -25,7 +27,9 @@ export default {
|
|
|
25
27
|
name: 'CruHPA',
|
|
26
28
|
|
|
27
29
|
components: {
|
|
30
|
+
HpaScalingRule,
|
|
28
31
|
ArrayListGrouped,
|
|
32
|
+
Checkbox,
|
|
29
33
|
CruResource,
|
|
30
34
|
LabeledInput,
|
|
31
35
|
LabeledSelect,
|
|
@@ -107,6 +111,40 @@ export default {
|
|
|
107
111
|
|
|
108
112
|
return match ?? null;
|
|
109
113
|
},
|
|
114
|
+
hasScaleDownRules: {
|
|
115
|
+
get() {
|
|
116
|
+
return !!this.value.spec.behavior?.scaleDown;
|
|
117
|
+
},
|
|
118
|
+
set(hasScaleDownRules) {
|
|
119
|
+
if (hasScaleDownRules) {
|
|
120
|
+
if (!this.value.spec.behavior) {
|
|
121
|
+
this.$set(this.value.spec, 'behavior', {});
|
|
122
|
+
}
|
|
123
|
+
if (!this.value.spec.behavior?.scaleDown) {
|
|
124
|
+
this.$set(this.value.spec.behavior, 'scaleDown', {});
|
|
125
|
+
}
|
|
126
|
+
} else {
|
|
127
|
+
this.$delete(this.value.spec.behavior, 'scaleDown');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
hasScaleUpRules: {
|
|
132
|
+
get() {
|
|
133
|
+
return !!this.value.spec.behavior?.scaleUp;
|
|
134
|
+
},
|
|
135
|
+
set(hasScaleUpRules) {
|
|
136
|
+
if (hasScaleUpRules) {
|
|
137
|
+
if (!this.value.spec.behavior) {
|
|
138
|
+
this.$set(this.value.spec, 'behavior', {});
|
|
139
|
+
}
|
|
140
|
+
if (!this.value.spec.behavior?.scaleUp) {
|
|
141
|
+
this.$set(this.value.spec.behavior, 'scaleUp', {});
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
this.$delete(this.value.spec.behavior, 'scaleUp');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
110
148
|
},
|
|
111
149
|
|
|
112
150
|
created() {
|
|
@@ -242,6 +280,47 @@ export default {
|
|
|
242
280
|
</template>
|
|
243
281
|
</ArrayListGrouped>
|
|
244
282
|
</Tab>
|
|
283
|
+
<Tab
|
|
284
|
+
name="behavior"
|
|
285
|
+
:label="t('hpa.tabs.behavior')"
|
|
286
|
+
>
|
|
287
|
+
<div class="col span-12 mb-10">
|
|
288
|
+
<h3>
|
|
289
|
+
{{ t('hpa.scaleDownRules.label') }}
|
|
290
|
+
</h3>
|
|
291
|
+
<div class="row mb-10">
|
|
292
|
+
<Checkbox
|
|
293
|
+
v-model="hasScaleDownRules"
|
|
294
|
+
:mode="mode"
|
|
295
|
+
:label="t('hpa.scaleDownRules.enable')"
|
|
296
|
+
/>
|
|
297
|
+
</div>
|
|
298
|
+
<HpaScalingRule
|
|
299
|
+
v-if="hasScaleDownRules"
|
|
300
|
+
v-model="value"
|
|
301
|
+
type="scaleDown"
|
|
302
|
+
:mode="mode"
|
|
303
|
+
/>
|
|
304
|
+
</div>
|
|
305
|
+
<div class="col span-12">
|
|
306
|
+
<h3>
|
|
307
|
+
{{ t('hpa.scaleUpRules.label') }}
|
|
308
|
+
</h3>
|
|
309
|
+
<div class="row mb-10">
|
|
310
|
+
<Checkbox
|
|
311
|
+
v-model="hasScaleUpRules"
|
|
312
|
+
:mode="mode"
|
|
313
|
+
:label="t('hpa.scaleUpRules.enable')"
|
|
314
|
+
/>
|
|
315
|
+
</div>
|
|
316
|
+
<HpaScalingRule
|
|
317
|
+
v-if="hasScaleUpRules"
|
|
318
|
+
v-model="value"
|
|
319
|
+
type="scaleUp"
|
|
320
|
+
:mode="mode"
|
|
321
|
+
/>
|
|
322
|
+
</div>
|
|
323
|
+
</Tab>
|
|
245
324
|
<Tab
|
|
246
325
|
name="labels-and-annotations"
|
|
247
326
|
:label="t('hpa.tabs.labels')"
|
|
@@ -11,6 +11,7 @@ import { set } from '@shell/utils/object';
|
|
|
11
11
|
import { FLEET } from '@shell/config/types';
|
|
12
12
|
import { convert, matching, simplify } from '@shell/utils/selector';
|
|
13
13
|
import throttle from 'lodash/throttle';
|
|
14
|
+
import { allHash } from '@shell/utils/promise';
|
|
14
15
|
|
|
15
16
|
export default {
|
|
16
17
|
name: 'CruClusterGroup',
|
|
@@ -27,10 +28,20 @@ export default {
|
|
|
27
28
|
mixins: [CreateEditView],
|
|
28
29
|
|
|
29
30
|
async fetch() {
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
const _hash = {};
|
|
32
|
+
|
|
33
|
+
if (this.$store.getters['management/schemaFor'](FLEET.CLUSTER)) {
|
|
34
|
+
_hash.allClusters = await this.$store.dispatch('management/findAll', { type: FLEET.CLUSTER });
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (this.$store.getters['management/schemaFor'](FLEET.WORKSPACE)) {
|
|
38
|
+
_hash.allWorkspaces = this.$store.dispatch('management/findAll', { type: FLEET.WORKSPACE });
|
|
32
39
|
}
|
|
33
|
-
|
|
40
|
+
|
|
41
|
+
const hash = await allHash(_hash);
|
|
42
|
+
|
|
43
|
+
this.allClusters = hash.allClusters || [];
|
|
44
|
+
this.allWorkspaces = hash.allWorkspaces || [];
|
|
34
45
|
|
|
35
46
|
if ( !this.value.spec?.selector ) {
|
|
36
47
|
this.value.spec = this.value.spec || {};
|
|
@@ -604,6 +604,23 @@ export default {
|
|
|
604
604
|
</template>
|
|
605
605
|
<div class="spacer" />
|
|
606
606
|
<h2 v-t="'fleet.gitRepo.resources.label'" />
|
|
607
|
+
<div>
|
|
608
|
+
<Checkbox
|
|
609
|
+
v-model="value.spec.correctDrift.enabled"
|
|
610
|
+
data-testid="GitRepo-correctDrift-checkbox"
|
|
611
|
+
class="check"
|
|
612
|
+
type="checkbox"
|
|
613
|
+
label-key="fleet.gitRepo.resources.correctDrift"
|
|
614
|
+
:mode="mode"
|
|
615
|
+
/>
|
|
616
|
+
<Banner
|
|
617
|
+
data-testid="GitRepo-correctDrift-banner"
|
|
618
|
+
color="info"
|
|
619
|
+
>
|
|
620
|
+
{{ t('fleet.gitRepo.resources.correctDriftBanner') }}
|
|
621
|
+
</Banner>
|
|
622
|
+
</div>
|
|
623
|
+
|
|
607
624
|
<Checkbox
|
|
608
625
|
v-model="value.spec.keepResources"
|
|
609
626
|
class="check"
|
|
@@ -614,7 +631,7 @@ export default {
|
|
|
614
631
|
<Banner
|
|
615
632
|
color="info"
|
|
616
633
|
>
|
|
617
|
-
{{ t('fleet.gitRepo.resources.
|
|
634
|
+
{{ t('fleet.gitRepo.resources.keepResourcesBanner') }}
|
|
618
635
|
</Banner>
|
|
619
636
|
<div class="spacer" />
|
|
620
637
|
<h2 v-t="'fleet.gitRepo.paths.label'" />
|
package/edit/namespace.vue
CHANGED
|
@@ -17,6 +17,7 @@ import Loading from '@shell/components/Loading';
|
|
|
17
17
|
import { HARVESTER_TYPES, RANCHER_TYPES } from '@shell/components/form/ResourceQuota/shared';
|
|
18
18
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
19
19
|
import Labels from '@shell/components/form/Labels';
|
|
20
|
+
import { randomStr } from '@shell/utils/string';
|
|
20
21
|
|
|
21
22
|
export default {
|
|
22
23
|
components: {
|
|
@@ -58,6 +59,7 @@ export default {
|
|
|
58
59
|
projects: null,
|
|
59
60
|
viewMode: _VIEW,
|
|
60
61
|
containerResourceLimits: this.value.annotations?.[CONTAINER_DEFAULT_RESOURCE_LIMIT] || this.getDefaultContainerResourceLimits(projectName),
|
|
62
|
+
rerenderNums: randomStr(4),
|
|
61
63
|
projectName,
|
|
62
64
|
HARVESTER_TYPES,
|
|
63
65
|
RANCHER_TYPES,
|
|
@@ -152,6 +154,11 @@ export default {
|
|
|
152
154
|
const project = projects.find((p) => p.id.includes(projectName));
|
|
153
155
|
|
|
154
156
|
return project?.spec?.containerDefaultResourceLimit || {};
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
PSAChanged($event) {
|
|
160
|
+
this.value.setLabels($event);
|
|
161
|
+
this.rerenderNums = randomStr(4);
|
|
155
162
|
}
|
|
156
163
|
},
|
|
157
164
|
};
|
|
@@ -242,6 +249,7 @@ export default {
|
|
|
242
249
|
:weight="-1"
|
|
243
250
|
>
|
|
244
251
|
<Labels
|
|
252
|
+
:key="rerenderNums"
|
|
245
253
|
default-container-class="labels-and-annotations-container"
|
|
246
254
|
:value="value"
|
|
247
255
|
:mode="mode"
|
|
@@ -258,7 +266,7 @@ export default {
|
|
|
258
266
|
:labels="value.labels"
|
|
259
267
|
:mode="mode"
|
|
260
268
|
labels-prefix="pod-security.kubernetes.io/"
|
|
261
|
-
@updateLabels="
|
|
269
|
+
@updateLabels="PSAChanged"
|
|
262
270
|
/>
|
|
263
271
|
</Tab>
|
|
264
272
|
</Tabbed>
|