@rancher/shell 3.0.5-rc.6 → 3.0.5-rc.8
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/brand/classic/metadata.json +3 -0
- package/assets/styles/app.scss +1 -0
- package/assets/styles/base/_color.scss +16 -0
- package/assets/styles/base/_helpers.scss +10 -0
- package/assets/styles/base/_variables.scss +18 -12
- package/assets/styles/fonts/_icons.scss +1 -32
- package/assets/styles/global/_layout.scss +1 -1
- package/assets/styles/themes/_dark.scss +262 -258
- package/assets/styles/themes/_light.scss +538 -509
- package/assets/styles/themes/_modern.scss +914 -0
- package/assets/translations/en-us.yaml +110 -29
- package/chart/__tests__/S3.test.ts +2 -1
- package/cloud-credential/generic.vue +18 -10
- package/cloud-credential/harvester.vue +1 -9
- package/components/AdvancedSection.vue +8 -0
- package/components/ChartReadme.vue +17 -7
- package/components/CodeMirror.vue +1 -1
- package/components/Drawer/Chrome.vue +0 -1
- package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +27 -28
- package/components/Drawer/ResourceDetailDrawer/composables.ts +4 -24
- package/components/Drawer/ResourceDetailDrawer/index.vue +18 -4
- package/components/InstallHelmCharts.vue +656 -0
- package/components/LazyImage.vue +60 -4
- package/components/Loading.vue +1 -1
- package/components/LocaleSelector.vue +7 -2
- package/components/Markdown.vue +4 -0
- package/components/PaginatedResourceTable.vue +46 -1
- package/components/PromptRestore.vue +22 -44
- package/components/Resource/Detail/Masthead/composable.ts +16 -0
- package/components/Resource/Detail/Masthead/index.vue +37 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +10 -2
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +26 -7
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +8 -1
- package/components/Resource/Detail/Metadata/KeyValue.vue +12 -10
- package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
- package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +10 -17
- package/components/Resource/Detail/Metadata/composables.ts +9 -7
- package/components/Resource/Detail/Metadata/index.vue +17 -2
- package/components/Resource/Detail/Page.vue +35 -21
- package/components/Resource/Detail/SpacedRow.vue +1 -1
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +8 -9
- package/components/Resource/Detail/TitleBar/composables.ts +5 -5
- package/components/Resource/Detail/TitleBar/index.vue +12 -3
- package/components/ResourceDetail/Masthead/legacy.vue +1 -1
- package/components/ResourceDetail/index.vue +569 -72
- package/components/ResourceList/index.vue +1 -0
- package/components/ResourceTable.vue +6 -1
- package/components/ResourceYaml.vue +1 -1
- package/components/RichTranslation.vue +106 -0
- package/components/SlideInPanelManager.vue +13 -10
- package/components/SortableTable/index.vue +5 -5
- package/components/SortableTable/selection.js +0 -1
- package/components/Tabbed/index.vue +35 -4
- package/components/__tests__/LazyImage.spec.ts +121 -0
- package/components/__tests__/PromptRestore.test.ts +1 -65
- package/components/__tests__/RichTranslation.test.ts +115 -0
- package/components/fleet/FleetStatus.vue +4 -0
- package/components/fleet/dashboard/ResourcePanel.vue +2 -1
- package/components/form/ClusterAppearance.vue +5 -0
- package/components/form/FileImageSelector.vue +1 -1
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
- package/components/form/NameNsDescription.vue +1 -0
- package/components/form/Networking.vue +24 -19
- package/components/form/ProjectMemberEditor.vue +1 -1
- package/components/form/ResourceLabeledSelect.vue +22 -8
- package/components/form/ResourceTabs/index.vue +20 -0
- package/components/form/SecretSelector.vue +9 -0
- package/components/form/SelectOrCreateAuthSecret.vue +6 -3
- package/components/form/__tests__/Networking.test.ts +116 -0
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +3 -38
- package/components/formatter/FleetApplicationSource.vue +25 -17
- package/components/formatter/PodImages.vue +1 -1
- package/components/formatter/__tests__/LiveDate.test.ts +10 -2
- package/components/google/AccountAccess.vue +44 -46
- package/components/nav/Favorite.vue +4 -0
- package/components/nav/Group.vue +4 -1
- package/components/nav/NotificationCenter/Notification.vue +1 -27
- package/components/nav/WindowManager/index.vue +3 -3
- package/composables/resources.ts +2 -2
- package/config/labels-annotations.js +3 -2
- package/config/pagination-table-headers.js +8 -1
- package/config/product/explorer.js +27 -2
- package/config/product/manager.js +0 -1
- package/config/query-params.js +10 -0
- package/config/router/routes.js +21 -1
- package/config/system-namespaces.js +1 -1
- package/config/table-headers.js +30 -1
- package/config/types.js +1 -1
- package/config/version.js +1 -1
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +11 -0
- package/detail/__tests__/workload.test.ts +164 -0
- package/detail/configmap.vue +33 -75
- package/detail/projectsecret.vue +11 -0
- package/detail/provisioning.cattle.io.cluster.vue +351 -369
- package/detail/secret.vue +49 -308
- package/detail/workload/index.vue +38 -21
- package/dialog/InstallExtensionDialog.vue +8 -5
- package/dialog/RotateEncryptionKeyDialog.vue +10 -30
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/edit/auth/ldap/__tests__/config.test.ts +14 -0
- package/edit/auth/ldap/config.vue +24 -0
- package/edit/compliance.cattle.io.clusterscan.vue +1 -1
- package/edit/configmap.vue +4 -1
- package/edit/fleet.cattle.io.gitrepo.vue +5 -6
- package/edit/fleet.cattle.io.helmop.vue +78 -56
- package/edit/logging.banzaicloud.io.output/index.vue +1 -1
- package/edit/logging.banzaicloud.io.output/providers/awsElasticsearch.vue +5 -6
- package/edit/networking.k8s.io.ingress/Certificate.vue +20 -22
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +8 -3
- package/edit/networking.k8s.io.ingress/Rule.vue +2 -5
- package/edit/networking.k8s.io.ingress/RulePath.vue +17 -11
- package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +11 -10
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -3
- package/edit/networking.k8s.io.networkpolicy/index.vue +17 -17
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +123 -61
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +9 -7
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +22 -13
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +10 -12
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +39 -38
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +41 -19
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +16 -3
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +32 -33
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue +9 -10
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +1 -3
- package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +16 -9
- package/edit/secret/basic.vue +1 -0
- package/edit/secret/index.vue +126 -15
- package/edit/workload/index.vue +5 -14
- package/list/projectsecret.vue +345 -0
- package/list/provisioning.cattle.io.cluster.vue +1 -69
- package/list/secret.vue +109 -0
- package/machine-config/__tests__/vmwarevsphere.test.ts +5 -7
- package/machine-config/google.vue +9 -1
- package/machine-config/vmwarevsphere.vue +7 -17
- package/mixins/__tests__/brand.spec.ts +2 -2
- package/mixins/chart.js +0 -2
- package/mixins/create-edit-view/impl.js +10 -1
- package/mixins/resource-fetch-api-pagination.js +11 -12
- package/mixins/resource-fetch.js +3 -1
- package/models/__tests__/chart.test.ts +111 -80
- package/models/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/models/__tests__/node.test.ts +7 -63
- package/models/catalog.cattle.io.app.js +1 -1
- package/models/catalog.cattle.io.operation.js +1 -1
- package/models/chart.js +36 -20
- package/models/cloudcredential.js +2 -163
- package/models/cluster/node.js +7 -7
- package/models/cluster.x-k8s.io.machine.js +3 -3
- package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
- package/models/compliance.cattle.io.clusterscan.js +2 -2
- package/models/configmap.js +4 -0
- package/models/constraints.gatekeeper.sh.constraint.js +1 -1
- package/models/fleet-application.js +0 -17
- package/models/fleet.cattle.io.cluster.js +2 -2
- package/models/fleet.cattle.io.gitrepo.js +15 -1
- package/models/fleet.cattle.io.helmop.js +26 -22
- package/models/management.cattle.io.setting.js +4 -0
- package/models/persistentvolumeclaim.js +1 -1
- package/models/pod.js +2 -2
- package/models/provisioning.cattle.io.cluster.js +39 -67
- package/models/rke.cattle.io.etcdsnapshot.js +1 -1
- package/models/secret.js +161 -2
- package/models/storage.k8s.io.storageclass.js +2 -2
- package/models/workload.js +3 -3
- package/package.json +11 -10
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +1 -0
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +4 -1
- package/pages/c/_cluster/apps/charts/__tests__/AppChartCardFooter.spec.js +41 -0
- package/pages/c/_cluster/apps/charts/chart.vue +422 -174
- package/pages/c/_cluster/apps/charts/index.vue +46 -35
- package/pages/c/_cluster/apps/charts/install.vue +1 -1
- package/pages/c/_cluster/explorer/projectsecret.vue +24 -0
- package/pages/c/_cluster/fleet/__tests__/index.test.ts +608 -314
- package/pages/c/_cluster/fleet/index.vue +103 -45
- package/pages/c/_cluster/manager/cloudCredential/index.vue +2 -59
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +10 -3
- package/pages/c/_cluster/uiplugins/index.vue +36 -25
- package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
- package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
- package/plugins/dashboard-store/actions.js +42 -22
- package/plugins/dashboard-store/normalize.js +29 -17
- package/plugins/dashboard-store/resource-class.js +83 -17
- package/plugins/steve/__tests__/getters.test.ts +1 -1
- package/plugins/steve/__tests__/subscribe.spec.ts +259 -1
- package/plugins/steve/getters.js +8 -2
- package/plugins/steve/resourceWatcher.js +10 -3
- package/plugins/steve/steve-pagination-utils.ts +14 -3
- package/plugins/steve/subscribe.js +192 -19
- package/plugins/steve/worker/web-worker.advanced.js +2 -0
- package/rancher-components/Card/Card.vue +0 -18
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.test.ts +15 -0
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +65 -0
- package/rancher-components/Pill/RcStatusBadge/index.ts +2 -0
- package/rancher-components/Pill/RcStatusBadge/types.ts +5 -0
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.test.ts +33 -0
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +75 -0
- package/rancher-components/Pill/RcStatusIndicator/index.ts +2 -0
- package/rancher-components/Pill/RcStatusIndicator/types.ts +7 -0
- package/rancher-components/Pill/types.ts +2 -0
- package/rancher-components/RcButton/RcButton.vue +1 -1
- package/rancher-components/RcDropdown/RcDropdown.test.ts +98 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +5 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +7 -1
- package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +2 -1
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +2 -1
- package/rancher-components/RcDropdown/useDropdownContext.ts +21 -0
- package/rancher-components/RcDropdown/useDropdownItem.ts +30 -1
- package/rancher-components/RcItemCard/RcItemCard.test.ts +20 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +40 -6
- package/store/__tests__/catalog.test.ts +93 -1
- package/store/aws.js +19 -8
- package/store/catalog.js +8 -3
- package/types/kube/kube-api.ts +12 -0
- package/types/resources/settings.d.ts +1 -1
- package/types/shell/index.d.ts +643 -585
- package/types/store/pagination.types.ts +16 -6
- package/types/uiplugins.ts +73 -0
- package/utils/__tests__/back-off.test.ts +354 -0
- package/utils/__tests__/create-yaml.test.ts +235 -0
- package/utils/__tests__/kontainer.test.ts +19 -0
- package/utils/__tests__/uiplugins.test.ts +84 -0
- package/utils/back-off.ts +176 -0
- package/utils/create-yaml.js +103 -9
- package/utils/dynamic-importer.js +8 -0
- package/utils/kontainer.ts +3 -5
- package/utils/pagination-utils.ts +18 -0
- package/utils/style.ts +3 -0
- package/utils/uiplugins.ts +29 -2
- package/utils/validators/__tests__/setting.test.js +92 -0
- package/utils/validators/formRules/__tests__/index.test.ts +88 -7
- package/utils/validators/formRules/index.ts +83 -8
- package/utils/validators/setting.js +17 -0
- package/cloud-credential/__tests__/harvester.test.ts +0 -18
- package/components/ResourceDetail/__tests__/index.test.ts +0 -135
- package/components/ResourceDetail/legacy.vue +0 -562
- package/components/formatter/CloudCredExpired.vue +0 -69
- package/models/etcdbackup.js +0 -45
- package/pages/explorer/resource/detail/configmap.vue +0 -42
- package/pages/explorer/resource/detail/secret.vue +0 -50
- package/utils/aws.js +0 -0
|
@@ -1,74 +1,18 @@
|
|
|
1
|
-
import Node from '@shell/models/
|
|
1
|
+
import Node from '@shell/models/cluster/node';
|
|
2
2
|
|
|
3
3
|
describe('class Node', () => {
|
|
4
|
-
const foo = 'foo';
|
|
5
|
-
const bar = 'bar';
|
|
6
|
-
const t = jest.fn(() => bar);
|
|
7
|
-
const ctx = { rootGetters: { 'i18n/t': t } };
|
|
8
|
-
|
|
9
4
|
const resetMocks = () => {
|
|
10
5
|
// Clear all mock function calls:
|
|
11
6
|
jest.clearAllMocks();
|
|
12
7
|
};
|
|
13
8
|
|
|
14
|
-
it(
|
|
15
|
-
|
|
9
|
+
it.each([
|
|
10
|
+
['1200', 1200],
|
|
11
|
+
['1k', 1000]
|
|
12
|
+
])('given %p status pod capacity value from the backend, should parse the value correctly as %p', (value, result) => {
|
|
13
|
+
const node = new Node({ status: { capacity: { pods: value } } });
|
|
16
14
|
|
|
17
|
-
expect(node.
|
|
15
|
+
expect(node.podCapacity).toStrictEqual(result);
|
|
18
16
|
resetMocks();
|
|
19
17
|
});
|
|
20
|
-
|
|
21
|
-
describe('should return addresses', () => {
|
|
22
|
-
const addresses = [foo];
|
|
23
|
-
|
|
24
|
-
it('if they are present directly on the resource status', () => {
|
|
25
|
-
const node = new Node({ status: { addresses } });
|
|
26
|
-
|
|
27
|
-
expect(node.addresses).toStrictEqual(addresses);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe('should return an internalIp', () => {
|
|
32
|
-
const addresses = [{ type: 'InternalIP', address: foo }];
|
|
33
|
-
|
|
34
|
-
it('if addresses includes an object with an appropriate type and address', () => {
|
|
35
|
-
const node = new Node({ status: { addresses } });
|
|
36
|
-
|
|
37
|
-
expect(node.internalIp).toStrictEqual(foo);
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('should return an externalIp', () => {
|
|
42
|
-
const addresses = [{ type: 'ExternalIP', address: foo }];
|
|
43
|
-
|
|
44
|
-
it('if addresses includes an object with an appropriate type and address', () => {
|
|
45
|
-
const node = new Node({ status: { addresses } });
|
|
46
|
-
|
|
47
|
-
expect(node.externalIp).toStrictEqual(foo);
|
|
48
|
-
});
|
|
49
|
-
it('if internalNodeStatus.addresses includes an object with an appropriate type and address', () => {
|
|
50
|
-
const node = new Node({ status: { internalNodeStatus: { addresses } } });
|
|
51
|
-
|
|
52
|
-
expect(node.externalIp).toStrictEqual(foo);
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('should return an appropriate message', () => {
|
|
57
|
-
it('if there is no internalIp to display', () => {
|
|
58
|
-
const node = new Node({ status: {} }, ctx);
|
|
59
|
-
|
|
60
|
-
expect(node.internalIp).toStrictEqual(bar);
|
|
61
|
-
expect(t).toHaveBeenCalledTimes(1);
|
|
62
|
-
expect(t).toHaveBeenCalledWith('generic.none');
|
|
63
|
-
resetMocks();
|
|
64
|
-
});
|
|
65
|
-
it('if there is no externalIp to display', () => {
|
|
66
|
-
const node = new Node({ status: {} }, ctx);
|
|
67
|
-
|
|
68
|
-
expect(node.externalIp).toStrictEqual(bar);
|
|
69
|
-
expect(t).toHaveBeenCalledTimes(1);
|
|
70
|
-
expect(t).toHaveBeenCalledWith('generic.none');
|
|
71
|
-
resetMocks();
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
18
|
});
|
package/models/chart.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from '@shell/config/query-params';
|
|
5
5
|
import { BLANK_CLUSTER } from '@shell/store/store-types.js';
|
|
6
6
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
7
|
-
import { CATALOG } from '@shell/config/types';
|
|
7
|
+
import { CATALOG, ZERO_TIME } from '@shell/config/types';
|
|
8
8
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
9
9
|
import day from 'dayjs';
|
|
10
10
|
|
|
@@ -121,42 +121,58 @@ export default class Chart extends SteveModel {
|
|
|
121
121
|
*/
|
|
122
122
|
get cardContent() {
|
|
123
123
|
if (!this._cardContent) {
|
|
124
|
-
const
|
|
125
|
-
|
|
124
|
+
const latestVersion = this.versions?.[0] || {};
|
|
125
|
+
const subHeaderItems = [];
|
|
126
|
+
|
|
127
|
+
if (latestVersion) {
|
|
128
|
+
const hasZeroTime = latestVersion.created === ZERO_TIME;
|
|
129
|
+
|
|
130
|
+
subHeaderItems.push({
|
|
126
131
|
icon: 'icon-version-alt',
|
|
127
132
|
iconTooltip: { key: 'tableHeaders.version' },
|
|
128
|
-
label:
|
|
129
|
-
}
|
|
130
|
-
|
|
133
|
+
label: latestVersion.version
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
const lastUpdatedItem = {
|
|
131
137
|
icon: 'icon-refresh-alt',
|
|
132
138
|
iconTooltip: { key: 'tableHeaders.lastUpdated' },
|
|
133
|
-
label: day(
|
|
139
|
+
label: hasZeroTime ? this.t('generic.na') : day(latestVersion.created).format('MMM D, YYYY')
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
if (hasZeroTime) {
|
|
143
|
+
lastUpdatedItem.labelTooltip = this.t('catalog.charts.appChartCard.subHeaderItem.missingVersionDate');
|
|
134
144
|
}
|
|
135
|
-
|
|
145
|
+
|
|
146
|
+
subHeaderItems.push(lastUpdatedItem);
|
|
147
|
+
}
|
|
148
|
+
|
|
136
149
|
const footerItems = [
|
|
137
150
|
{
|
|
138
|
-
type:
|
|
139
|
-
icon:
|
|
140
|
-
iconTooltip:
|
|
141
|
-
labels:
|
|
151
|
+
type: REPO,
|
|
152
|
+
icon: 'icon-repository-alt',
|
|
153
|
+
iconTooltip: { key: 'tableHeaders.repoName' },
|
|
154
|
+
labels: [this.repoNameDisplay],
|
|
155
|
+
labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.repo') }, true)
|
|
142
156
|
}
|
|
143
157
|
];
|
|
144
158
|
|
|
145
159
|
if (this.categories.length) {
|
|
146
160
|
footerItems.push( {
|
|
147
|
-
type:
|
|
148
|
-
icon:
|
|
149
|
-
iconTooltip:
|
|
150
|
-
labels:
|
|
161
|
+
type: CATEGORY,
|
|
162
|
+
icon: 'icon-category-alt',
|
|
163
|
+
iconTooltip: { key: 'generic.category' },
|
|
164
|
+
labels: this.categories,
|
|
165
|
+
labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.category') }, true)
|
|
151
166
|
});
|
|
152
167
|
}
|
|
153
168
|
|
|
154
169
|
if (this.tags.length) {
|
|
155
170
|
footerItems.push({
|
|
156
|
-
type:
|
|
157
|
-
icon:
|
|
158
|
-
iconTooltip:
|
|
159
|
-
labels:
|
|
171
|
+
type: TAG,
|
|
172
|
+
icon: 'icon-tag-alt',
|
|
173
|
+
iconTooltip: { key: 'generic.tags' },
|
|
174
|
+
labels: this.tags,
|
|
175
|
+
labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.tag') }, true)
|
|
160
176
|
});
|
|
161
177
|
}
|
|
162
178
|
|
|
@@ -1,65 +1,11 @@
|
|
|
1
|
-
import { CAPI
|
|
1
|
+
import { CAPI } from '@shell/config/labels-annotations';
|
|
2
2
|
import { fullFields, prefixFields, simplify, suffixFields } from '@shell/store/plugins';
|
|
3
3
|
import { isEmpty, set } from '@shell/utils/object';
|
|
4
|
-
import {
|
|
4
|
+
import { SECRET } from '@shell/config/types';
|
|
5
5
|
import { escapeHtml } from '@shell/utils/string';
|
|
6
6
|
import NormanModel from '@shell/plugins/steve/norman-class';
|
|
7
|
-
import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
|
|
8
|
-
import day from 'dayjs';
|
|
9
|
-
|
|
10
|
-
const harvesterProvider = 'harvester';
|
|
11
|
-
|
|
12
|
-
const renew = {
|
|
13
|
-
[harvesterProvider]: {
|
|
14
|
-
renew: ({ cloudCredential, $ctx }) => {
|
|
15
|
-
return renew[harvesterProvider].renewBulk(
|
|
16
|
-
{ cloudCredentials: [cloudCredential], $ctx }
|
|
17
|
-
);
|
|
18
|
-
},
|
|
19
|
-
renewBulk: async({ cloudCredentials, $ctx }) => {
|
|
20
|
-
// A harvester cloud credential (at the moment) is a kubeconfig complete with expiring token
|
|
21
|
-
// So to renew we just need to generate a new kubeconfig and save it to the cc (similar to shell/cloud-credential/harvester.vue)
|
|
22
|
-
await Promise.all(cloudCredentials.map(async(cc) => {
|
|
23
|
-
try {
|
|
24
|
-
if (!cc.harvestercredentialConfig?.clusterId) {
|
|
25
|
-
throw new Error(`credential has no matching harvester cluster`);
|
|
26
|
-
}
|
|
27
|
-
const mgmtCluster = $ctx.rootGetters['management/byId'](MANAGEMENT.CLUSTER, cc.harvestercredentialConfig.clusterId);
|
|
28
|
-
|
|
29
|
-
if (!mgmtCluster) {
|
|
30
|
-
throw new Error(`cannot find harvester cluster`);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const kubeconfigContent = await mgmtCluster.generateKubeConfig();
|
|
34
|
-
|
|
35
|
-
cc.setData('kubeconfigContent', kubeconfigContent);
|
|
36
|
-
|
|
37
|
-
await cc.save();
|
|
38
|
-
} catch (error) {
|
|
39
|
-
console.error(`Unable to refresh harvester cloud credential '${ cc.id }'`, error); // eslint-disable-line no-console
|
|
40
|
-
}
|
|
41
|
-
}));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
7
|
|
|
46
8
|
export default class CloudCredential extends NormanModel {
|
|
47
|
-
get _availableActions() {
|
|
48
|
-
const out = super._availableActions;
|
|
49
|
-
|
|
50
|
-
out.splice(0, 0, { divider: true });
|
|
51
|
-
out.splice(0, 0, {
|
|
52
|
-
action: 'renew',
|
|
53
|
-
enabled: this.canRenew,
|
|
54
|
-
bulkable: this.canBulkRenew,
|
|
55
|
-
bulkAction: 'renewBulk',
|
|
56
|
-
icon: 'icon icon-fw icon-refresh',
|
|
57
|
-
label: this.t('manager.cloudCredentials.renew'),
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
return out;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
9
|
get hasSensitiveData() {
|
|
64
10
|
return true;
|
|
65
11
|
}
|
|
@@ -231,111 +177,4 @@ export default class CloudCredential extends NormanModel {
|
|
|
231
177
|
get doneRoute() {
|
|
232
178
|
return 'c-cluster-manager-secret';
|
|
233
179
|
}
|
|
234
|
-
|
|
235
|
-
get canRenew() {
|
|
236
|
-
return !!renew[this.provider]?.renew && this.expires !== undefined && this.canUpdate;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
get canBulkRenew() {
|
|
240
|
-
return !!renew[this.provider]?.renewBulk;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
get expiresForSort() {
|
|
244
|
-
// Why not just `expires`? Ensures the correct sort order of expired --> expiring --> never expires
|
|
245
|
-
// (instead of 'never expired' --> 'expired' --> 'expiring')
|
|
246
|
-
return this.expires !== undefined ? this.expires : Number.MAX_SAFE_INTEGER;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
get expires() {
|
|
250
|
-
const expires = this.annotations[CLOUD_CREDENTIALS.EXPIRATION];
|
|
251
|
-
|
|
252
|
-
if (typeof expires === 'string') {
|
|
253
|
-
return parseInt(expires);
|
|
254
|
-
} else if (typeof expires === 'number') {
|
|
255
|
-
return expires;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
return undefined; // Weird things happen if this isn't a number
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
get expireData() {
|
|
262
|
-
if (typeof this.expiresIn !== 'number') {
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const sevenDays = 1000 * 60 * 60 * 24 * 7;
|
|
267
|
-
|
|
268
|
-
if (this.expiresIn === 0) {
|
|
269
|
-
return {
|
|
270
|
-
expired: true,
|
|
271
|
-
expiring: false,
|
|
272
|
-
};
|
|
273
|
-
} else if (this.expiresIn < sevenDays) {
|
|
274
|
-
return {
|
|
275
|
-
expired: false,
|
|
276
|
-
expiring: true,
|
|
277
|
-
};
|
|
278
|
-
} else if (this.expiresIn) {
|
|
279
|
-
return {
|
|
280
|
-
expired: false,
|
|
281
|
-
expiring: false,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
return null;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
get expiresString() {
|
|
289
|
-
if (this.expires === undefined) {
|
|
290
|
-
return '';
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (this.expireData.expired) {
|
|
294
|
-
return this.t('manager.cloudCredentials.expired');
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const dateFormat = escapeHtml( this.$rootGetters['prefs/get'](DATE_FORMAT));
|
|
298
|
-
const timeFormat = escapeHtml( this.$rootGetters['prefs/get'](TIME_FORMAT));
|
|
299
|
-
|
|
300
|
-
return day(this.expires).format(`${ dateFormat } ${ timeFormat }`);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
get expiresIn() {
|
|
304
|
-
if (this.expires === undefined) {
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const timeThen = this.expires;
|
|
309
|
-
const timeNow = Date.now();
|
|
310
|
-
|
|
311
|
-
const expiresIn = timeThen - timeNow;
|
|
312
|
-
|
|
313
|
-
return expiresIn < 0 ? 0 : expiresIn;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
renew() {
|
|
317
|
-
const renewFn = renew[this.provider]?.renew;
|
|
318
|
-
|
|
319
|
-
if (!renewFn) {
|
|
320
|
-
console.error('No fn renew function for ', this.provider); // eslint-disable-line no-console
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return renewFn({
|
|
324
|
-
cloudCredential: this,
|
|
325
|
-
$ctx: this.$ctx
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
async renewBulk(cloudCredentials = []) {
|
|
330
|
-
const renewBulkFn = renew[this.provider]?.renewBulk;
|
|
331
|
-
|
|
332
|
-
if (!renewBulkFn) {
|
|
333
|
-
console.error('No fn renew bulk function for ', this.provider); // eslint-disable-line no-console
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
return renewBulkFn({
|
|
337
|
-
cloudCredentials,
|
|
338
|
-
$ctx: this.$ctx
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
180
|
}
|
package/models/cluster/node.js
CHANGED
|
@@ -16,7 +16,7 @@ export default class ClusterNode extends SteveModel {
|
|
|
16
16
|
const cordon = {
|
|
17
17
|
action: 'cordon',
|
|
18
18
|
enabled: !!normanAction.cordon,
|
|
19
|
-
icon: 'icon icon-
|
|
19
|
+
icon: 'icon icon-pause',
|
|
20
20
|
label: 'Cordon',
|
|
21
21
|
total: 1,
|
|
22
22
|
bulkable: true
|
|
@@ -25,7 +25,7 @@ export default class ClusterNode extends SteveModel {
|
|
|
25
25
|
const uncordon = {
|
|
26
26
|
action: 'uncordon',
|
|
27
27
|
enabled: !!normanAction.uncordon,
|
|
28
|
-
icon: 'icon icon-
|
|
28
|
+
icon: 'icon icon-play',
|
|
29
29
|
label: 'Uncordon',
|
|
30
30
|
total: 1,
|
|
31
31
|
bulkable: true
|
|
@@ -34,7 +34,7 @@ export default class ClusterNode extends SteveModel {
|
|
|
34
34
|
const drain = {
|
|
35
35
|
action: 'drain',
|
|
36
36
|
enabled: !!normanAction.drain,
|
|
37
|
-
icon: 'icon icon-
|
|
37
|
+
icon: 'icon icon-dot-open',
|
|
38
38
|
label: this.t('drainNode.action'),
|
|
39
39
|
bulkable: true,
|
|
40
40
|
bulkAction: 'drain'
|
|
@@ -43,7 +43,7 @@ export default class ClusterNode extends SteveModel {
|
|
|
43
43
|
const stopDrain = {
|
|
44
44
|
action: 'stopDrain',
|
|
45
45
|
enabled: !!normanAction.stopDrain,
|
|
46
|
-
icon: 'icon icon-
|
|
46
|
+
icon: 'icon icon-x',
|
|
47
47
|
label: this.t('drainNode.actionStop'),
|
|
48
48
|
bulkable: true,
|
|
49
49
|
};
|
|
@@ -51,14 +51,14 @@ export default class ClusterNode extends SteveModel {
|
|
|
51
51
|
const openSsh = {
|
|
52
52
|
action: 'openSsh',
|
|
53
53
|
enabled: !!this.provisionedMachine?.links?.shell,
|
|
54
|
-
icon: 'icon icon-
|
|
54
|
+
icon: 'icon icon-chevron-right',
|
|
55
55
|
label: 'SSH Shell',
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
const downloadKeys = {
|
|
59
59
|
action: 'downloadKeys',
|
|
60
60
|
enabled: !!this.provisionedMachine?.links?.sshkeys,
|
|
61
|
-
icon: 'icon icon-
|
|
61
|
+
icon: 'icon icon-download',
|
|
62
62
|
label: this.t('node.actions.downloadSSHKey'),
|
|
63
63
|
};
|
|
64
64
|
|
|
@@ -227,7 +227,7 @@ export default class ClusterNode extends SteveModel {
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
get podCapacity() {
|
|
230
|
-
return
|
|
230
|
+
return parseSi(this.status.capacity?.pods);
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
get podConsumed() {
|
|
@@ -60,13 +60,13 @@ export default class CapiMachine extends SteveModel {
|
|
|
60
60
|
const openSsh = {
|
|
61
61
|
action: 'openSsh',
|
|
62
62
|
enabled: !!this.links.shell && this.isRunning,
|
|
63
|
-
icon: 'icon icon-
|
|
63
|
+
icon: 'icon icon-chevron-right',
|
|
64
64
|
label: 'SSH Shell',
|
|
65
65
|
};
|
|
66
66
|
const downloadKeys = {
|
|
67
67
|
action: 'downloadKeys',
|
|
68
68
|
enabled: !!this.links.sshkeys,
|
|
69
|
-
icon: 'icon icon-
|
|
69
|
+
icon: 'icon icon-download',
|
|
70
70
|
label: this.t('node.actions.downloadSSHKey'),
|
|
71
71
|
};
|
|
72
72
|
const forceRemove = {
|
|
@@ -80,7 +80,7 @@ export default class CapiMachine extends SteveModel {
|
|
|
80
80
|
action: 'toggleScaleDownModal',
|
|
81
81
|
bulkAction: 'toggleScaleDownModal',
|
|
82
82
|
enabled: !!this.canScaleDown,
|
|
83
|
-
icon: 'icon icon-minus
|
|
83
|
+
icon: 'icon icon-minus',
|
|
84
84
|
label: this.t('node.actions.scaleDown'),
|
|
85
85
|
bulkable: true
|
|
86
86
|
};
|
|
@@ -125,7 +125,7 @@ export default class CapiMachineDeployment extends SteveModel {
|
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
const initialValue = this.cluster
|
|
128
|
+
const initialValue = this.cluster;
|
|
129
129
|
|
|
130
130
|
this.inClusterSpec.quantity += delta;
|
|
131
131
|
|
|
@@ -145,7 +145,16 @@ export default class CapiMachineDeployment extends SteveModel {
|
|
|
145
145
|
let errors = exceptionToErrorsArray(err);
|
|
146
146
|
|
|
147
147
|
if ( err.status === 409 && depth < 2 ) {
|
|
148
|
-
const conflicts = await handleConflict(
|
|
148
|
+
const conflicts = await handleConflict(
|
|
149
|
+
initialValue,
|
|
150
|
+
value,
|
|
151
|
+
liveModel,
|
|
152
|
+
{
|
|
153
|
+
dispatch: this.$dispatch,
|
|
154
|
+
getters: this.$rootGetters
|
|
155
|
+
},
|
|
156
|
+
'management'
|
|
157
|
+
);
|
|
149
158
|
|
|
150
159
|
if ( conflicts === false ) {
|
|
151
160
|
// It was automatically figured out, save again
|
|
@@ -52,7 +52,7 @@ export default class ClusterScan extends SteveModel {
|
|
|
52
52
|
const downloadReport = {
|
|
53
53
|
action: 'downloadLatestReport',
|
|
54
54
|
enabled: this.hasReport,
|
|
55
|
-
icon: 'icon icon-
|
|
55
|
+
icon: 'icon icon-download',
|
|
56
56
|
label: t('compliance.downloadReport'),
|
|
57
57
|
total: 1,
|
|
58
58
|
};
|
|
@@ -60,7 +60,7 @@ export default class ClusterScan extends SteveModel {
|
|
|
60
60
|
const downloadAllReports = {
|
|
61
61
|
action: 'downloadAllReports',
|
|
62
62
|
enabled: this.hasReport,
|
|
63
|
-
icon: 'icon icon-
|
|
63
|
+
icon: 'icon icon-download',
|
|
64
64
|
label: t('compliance.downloadAllReports'),
|
|
65
65
|
total: 1,
|
|
66
66
|
};
|
package/models/configmap.js
CHANGED
|
@@ -15,7 +15,7 @@ export default class GateKeeperConstraint extends SteveModel {
|
|
|
15
15
|
|
|
16
16
|
const downloadViolations = {
|
|
17
17
|
action: 'downloadViolations',
|
|
18
|
-
icon: 'icon icon-
|
|
18
|
+
icon: 'icon icon-download',
|
|
19
19
|
label: t('gatekeeperConstraint.downloadViolations'),
|
|
20
20
|
total: 1,
|
|
21
21
|
};
|
|
@@ -8,9 +8,6 @@ import SteveModel from '@shell/plugins/steve/steve-class';
|
|
|
8
8
|
import { mapStateToEnum, primaryDisplayStatusFromCount, STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
9
9
|
import FleetUtils from '@shell/utils/fleet';
|
|
10
10
|
|
|
11
|
-
export const MINIMUM_POLLING_INTERVAL = 15;
|
|
12
|
-
export const DEFAULT_POLLING_INTERVAL = 60;
|
|
13
|
-
|
|
14
11
|
function normalizeStateCounts(data) {
|
|
15
12
|
if (isEmpty(data)) {
|
|
16
13
|
return {
|
|
@@ -46,16 +43,6 @@ export default class FleetApplication extends SteveModel {
|
|
|
46
43
|
this.save();
|
|
47
44
|
}
|
|
48
45
|
|
|
49
|
-
enablePollingAction() {
|
|
50
|
-
this.spec.disablePolling = false;
|
|
51
|
-
this.save();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
disablePollingAction() {
|
|
55
|
-
this.spec.disablePolling = true;
|
|
56
|
-
this.save();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
46
|
goToClone() {
|
|
60
47
|
if (this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_ID]) {
|
|
61
48
|
delete this.metadata.labels[FLEET_ANNOTATIONS.CREATED_BY_USER_ID];
|
|
@@ -68,10 +55,6 @@ export default class FleetApplication extends SteveModel {
|
|
|
68
55
|
super.goToClone();
|
|
69
56
|
}
|
|
70
57
|
|
|
71
|
-
get isPollingEnabled() {
|
|
72
|
-
return !this.spec.disablePolling;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
58
|
get state() {
|
|
76
59
|
if (this.spec?.paused === true) {
|
|
77
60
|
return 'paused';
|
|
@@ -223,8 +223,8 @@ export default class FleetCluster extends SteveModel {
|
|
|
223
223
|
return parsedLabels;
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
-
async saveYaml(yaml) {
|
|
227
|
-
await this._saveYaml(yaml);
|
|
226
|
+
async saveYaml(yaml, initialYaml) {
|
|
227
|
+
await this._saveYaml(yaml, initialYaml);
|
|
228
228
|
|
|
229
229
|
const parsed = jsyaml.load(yaml);
|
|
230
230
|
|
|
@@ -76,6 +76,16 @@ export default class GitRepo extends FleetApplication {
|
|
|
76
76
|
return out;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
enablePollingAction() {
|
|
80
|
+
this.spec.disablePolling = false;
|
|
81
|
+
this.save();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
disablePollingAction() {
|
|
85
|
+
this.spec.disablePolling = true;
|
|
86
|
+
this.save();
|
|
87
|
+
}
|
|
88
|
+
|
|
79
89
|
forceUpdate(resources = [this]) {
|
|
80
90
|
this.$dispatch('promptModal', {
|
|
81
91
|
componentProps: { repositories: resources },
|
|
@@ -90,6 +100,10 @@ export default class GitRepo extends FleetApplication {
|
|
|
90
100
|
});
|
|
91
101
|
}
|
|
92
102
|
|
|
103
|
+
get isPollingEnabled() {
|
|
104
|
+
return !this.spec.disablePolling;
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
get isWebhookConfigured() {
|
|
94
108
|
return !!this.status?.webhookCommit;
|
|
95
109
|
}
|
|
@@ -185,7 +199,7 @@ export default class GitRepo extends FleetApplication {
|
|
|
185
199
|
value,
|
|
186
200
|
display: this.repoDisplay,
|
|
187
201
|
icon: this.resourceIcon,
|
|
188
|
-
showLink: matchHttps || matchSSH
|
|
202
|
+
showLink: !!(matchHttps || matchSSH)
|
|
189
203
|
};
|
|
190
204
|
}
|
|
191
205
|
|