@rancher/shell 3.0.5-rc.3 → 3.0.5-rc.5
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/icons/document.svg +3 -0
- package/assets/images/vendor/cognito.svg +1 -0
- package/assets/styles/app.scss +1 -0
- package/assets/styles/base/_basic.scss +10 -0
- package/assets/styles/base/_spacing.scss +29 -0
- package/assets/styles/global/_layout.scss +1 -1
- package/assets/styles/themes/_dark.scss +25 -0
- package/assets/styles/themes/_light.scss +65 -0
- package/assets/translations/en-us.yaml +322 -24
- package/assets/translations/zh-hans.yaml +8 -5
- package/components/Certificates.vue +5 -0
- package/components/FilterPanel.vue +156 -0
- package/components/{fleet/ForceDirectedTreeChart/index.vue → ForceDirectedTreeChart.vue} +47 -41
- package/components/IconOrSvg.vue +14 -35
- package/components/PromptRemove.vue +5 -1
- package/components/Resource/Detail/Card/PodsCard/Bubble.vue +13 -0
- package/components/Resource/Detail/Card/PodsCard/composable.ts +30 -0
- package/components/Resource/Detail/Card/PodsCard/index.vue +118 -0
- package/components/Resource/Detail/Card/ResourceUsageCard/composable.ts +51 -0
- package/components/Resource/Detail/Card/ResourceUsageCard/index.vue +79 -0
- package/components/Resource/Detail/Card/Scaler.vue +89 -0
- package/components/Resource/Detail/Card/StateCard/composables.ts +112 -0
- package/components/Resource/Detail/Card/StateCard/index.vue +39 -0
- package/components/Resource/Detail/Card/VerticalGap.vue +11 -0
- package/components/Resource/Detail/Card/__tests__/Card.test.ts +36 -0
- package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +84 -0
- package/components/Resource/Detail/Card/__tests__/ResourceUsageCard.test.ts +72 -0
- package/components/Resource/Detail/Card/__tests__/Scaler.test.ts +87 -0
- package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +53 -0
- package/components/Resource/Detail/Card/__tests__/VerticalGap.test.ts +14 -0
- package/components/Resource/Detail/Card/__tests__/index.test.ts +36 -0
- package/components/Resource/Detail/Card/index.vue +56 -0
- package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +19 -0
- package/components/Resource/Detail/Metadata/Annotations/composable.ts +12 -0
- package/components/Resource/Detail/Metadata/Annotations/index.vue +26 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +103 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +281 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +111 -0
- package/components/Resource/Detail/Metadata/KeyValue.vue +130 -0
- package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +18 -0
- package/components/Resource/Detail/Metadata/Labels/composable.ts +12 -0
- package/components/Resource/Detail/Metadata/Labels/index.vue +27 -0
- package/components/Resource/Detail/Metadata/Rectangle.vue +32 -0
- package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +107 -0
- package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +24 -0
- package/components/Resource/Detail/Metadata/__tests__/index.test.ts +91 -0
- package/components/Resource/Detail/Metadata/composables.ts +29 -0
- package/components/Resource/Detail/Metadata/index.vue +66 -0
- package/components/Resource/Detail/Page.vue +22 -0
- package/components/Resource/Detail/PercentageBar.vue +40 -0
- package/components/Resource/Detail/ResourceRow.vue +119 -0
- package/components/Resource/Detail/SpacedRow.vue +14 -0
- package/components/Resource/Detail/StatusBar.vue +59 -0
- package/components/Resource/Detail/StatusRow.vue +61 -0
- package/components/Resource/Detail/TitleBar/Title.vue +13 -0
- package/components/Resource/Detail/TitleBar/Top.vue +14 -0
- package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +17 -0
- package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +17 -0
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +142 -0
- package/components/Resource/Detail/TitleBar/composable.ts +31 -0
- package/components/Resource/Detail/TitleBar/index.vue +124 -0
- package/components/Resource/Detail/Top/index.vue +34 -0
- package/components/Resource/Detail/__tests__/Page.test.ts +32 -0
- package/components/ResourceDetail/__tests__/index.test.ts +114 -0
- package/components/ResourceDetail/index.vue +64 -562
- package/components/ResourceDetail/legacy.vue +545 -0
- package/components/ResourceTable.vue +41 -7
- package/components/SlideInPanelManager.vue +76 -8
- package/components/SortableTable/index.vue +13 -2
- package/components/SortableTable/selection.js +21 -8
- package/components/StatusBadge.vue +6 -4
- package/components/SubtleLink.vue +25 -0
- package/components/Wizard.vue +12 -1
- package/components/YamlEditor.vue +1 -1
- package/components/__tests__/FilterPanel.test.ts +81 -0
- package/components/auth/AuthBanner.vue +2 -3
- package/components/auth/RoleDetailEdit.vue +45 -3
- package/components/auth/login/oidc.vue +6 -1
- package/components/fleet/FleetApplications.vue +181 -0
- package/components/fleet/FleetHelmOps.vue +115 -0
- package/components/fleet/FleetIntro.vue +58 -28
- package/components/fleet/FleetNoWorkspaces.vue +5 -1
- package/components/fleet/FleetOCIStorageSecret.vue +171 -0
- package/components/fleet/FleetRepos.vue +38 -76
- package/components/fleet/FleetResources.vue +50 -22
- package/components/fleet/FleetSummary.vue +26 -51
- package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +213 -0
- package/components/fleet/__tests__/FleetSummary.test.ts +39 -39
- package/components/fleet/dashboard/Empty.vue +73 -0
- package/components/fleet/dashboard/ResourceCard.vue +183 -0
- package/components/fleet/dashboard/ResourceCardSummary.vue +199 -0
- package/components/fleet/dashboard/ResourceDetails.vue +196 -0
- package/components/fleet/dashboard/ResourcePanel.vue +376 -0
- package/components/form/ArrayList.vue +6 -0
- package/components/form/SimpleSecretSelector.vue +8 -2
- package/components/form/ValueFromResource.vue +31 -19
- package/components/formatter/FleetApplicationClustersReady.vue +77 -0
- package/components/formatter/FleetApplicationSource.vue +71 -0
- package/components/formatter/FleetSummaryGraph.vue +7 -0
- package/components/nav/Header.vue +8 -7
- package/components/nav/TopLevelMenu.helper.ts +55 -34
- package/components/nav/TopLevelMenu.vue +11 -0
- package/components/nav/Type.vue +4 -1
- package/composables/useI18n.ts +12 -11
- package/config/labels-annotations.js +14 -11
- package/config/product/auth.js +1 -0
- package/config/product/fleet.js +70 -17
- package/config/query-params.js +3 -1
- package/config/roles.ts +1 -0
- package/config/router/routes.js +20 -2
- package/config/secret.ts +15 -0
- package/config/settings.ts +3 -2
- package/config/table-headers.js +52 -22
- package/config/types.js +2 -0
- package/core/plugin-helpers.ts +3 -2
- package/detail/fleet.cattle.io.cluster.vue +28 -15
- package/detail/fleet.cattle.io.gitrepo.vue +10 -1
- package/detail/fleet.cattle.io.helmop.vue +157 -0
- package/dialog/HelmOpForceUpdateDialog.vue +132 -0
- package/dialog/RedeployWorkloadDialog.vue +164 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +56 -67
- package/edit/auth/oidc.vue +159 -93
- package/edit/fleet.cattle.io.gitrepo.vue +26 -33
- package/edit/fleet.cattle.io.helmop.vue +997 -0
- package/edit/management.cattle.io.fleetworkspace.vue +43 -10
- package/list/fleet.cattle.io.gitrepo.vue +1 -1
- package/list/fleet.cattle.io.helmop.vue +108 -0
- package/list/namespace.vue +5 -2
- package/mixins/auth-config.js +8 -1
- package/mixins/preset.js +100 -0
- package/mixins/resource-fetch-api-pagination.js +2 -0
- package/mixins/resource-fetch.js +1 -1
- package/mixins/resource-table-watch.js +45 -0
- package/models/__tests__/chart.test.ts +273 -0
- package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
- package/models/chart.js +144 -2
- package/models/fleet-application.js +385 -0
- package/models/fleet.cattle.io.bundle.js +9 -8
- package/models/fleet.cattle.io.gitrepo.js +41 -365
- package/models/fleet.cattle.io.helmop.js +228 -0
- package/models/management.cattle.io.authconfig.js +1 -0
- package/models/management.cattle.io.fleetworkspace.js +12 -0
- package/models/workload.js +14 -18
- package/package.json +2 -1
- package/pages/auth/verify.vue +13 -1
- package/pages/c/_cluster/apps/charts/AddRepoLink.vue +37 -0
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +80 -0
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +54 -0
- package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
- package/pages/c/_cluster/apps/charts/index.vue +302 -484
- package/pages/c/_cluster/explorer/EventsTable.vue +1 -1
- package/pages/c/_cluster/fleet/__tests__/index.test.ts +426 -0
- package/pages/c/_cluster/fleet/application/_resource/_id.vue +14 -0
- package/pages/c/_cluster/fleet/application/_resource/create.vue +14 -0
- package/pages/c/_cluster/fleet/application/create.vue +340 -0
- package/pages/c/_cluster/fleet/application/index.vue +139 -0
- package/pages/c/_cluster/fleet/graph/config.js +277 -0
- package/pages/c/_cluster/fleet/index.vue +772 -330
- package/pages/explorer/resource/detail/configmap.vue +19 -0
- package/plugins/dashboard-store/actions.js +31 -9
- package/plugins/dashboard-store/getters.js +34 -21
- package/plugins/dashboard-store/mutations.js +51 -7
- package/plugins/dashboard-store/resource-class.js +14 -2
- package/plugins/steve/__tests__/subscribe.spec.ts +66 -1
- package/plugins/steve/actions.js +3 -0
- package/plugins/steve/steve-pagination-utils.ts +14 -13
- package/plugins/steve/subscribe.js +229 -42
- package/rancher-components/BadgeState/BadgeState.vue +3 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +2 -2
- package/rancher-components/RcItemCard/RcItemCard.test.ts +189 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +425 -0
- package/rancher-components/RcItemCard/RcItemCardAction.vue +24 -0
- package/rancher-components/RcItemCard/index.ts +2 -0
- package/store/auth.js +1 -0
- package/store/catalog.js +62 -24
- package/store/index.js +33 -14
- package/store/slideInPanel.ts +6 -0
- package/store/type-map.js +1 -0
- package/types/fleet.d.ts +35 -0
- package/types/resources/settings.d.ts +19 -1
- package/types/shell/index.d.ts +339 -272
- package/types/store/dashboard-store.types.ts +17 -3
- package/types/store/pagination.types.ts +6 -1
- package/types/store/subscribe.types.ts +50 -0
- package/utils/auth.js +32 -3
- package/utils/fleet-types.ts +0 -0
- package/utils/fleet.ts +200 -1
- package/utils/pagination-utils.ts +26 -1
- package/utils/pagination-wrapper.ts +132 -50
- package/utils/settings.ts +4 -1
- package/utils/style.ts +39 -0
- package/utils/validators/formRules/__tests__/index.test.ts +36 -3
- package/utils/validators/formRules/index.ts +10 -3
- package/utils/window.js +11 -7
- package/components/__tests__/ApplicationCard.test.ts +0 -27
- package/components/cards/ApplicationCard.vue +0 -145
- package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
- package/config/secret.js +0 -14
- package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +0 -249
- /package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import { _CREATE } from '@shell/config/query-params';
|
|
2
3
|
import CreateEditView from '@shell/mixins/create-edit-view';
|
|
3
4
|
import CruResource from '@shell/components/CruResource';
|
|
4
5
|
import Labels from '@shell/components/form/Labels';
|
|
5
6
|
import Loading from '@shell/components/Loading';
|
|
6
7
|
import NameNsDescription from '@shell/components/form/NameNsDescription';
|
|
7
8
|
import { FLEET, MANAGEMENT, SCHEMA } from '@shell/config/types';
|
|
9
|
+
import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
8
10
|
// import RoleBindings from '@shell/components/RoleBindings';
|
|
9
11
|
import Tabbed from '@shell/components/Tabbed';
|
|
10
12
|
import Tab from '@shell/components/Tabbed/Tab';
|
|
@@ -16,6 +18,7 @@ import { LAST_NAMESPACE, WORKSPACE } from '@shell/store/prefs';
|
|
|
16
18
|
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
17
19
|
import Banner from '@components/Banner/Banner.vue';
|
|
18
20
|
import ArrayList from '@shell/components/form/ArrayList.vue';
|
|
21
|
+
import FleetOCIStorageSecret from '@shell/components/fleet/FleetOCIStorageSecret.vue';
|
|
19
22
|
|
|
20
23
|
export default {
|
|
21
24
|
name: 'FleetCruWorkspace',
|
|
@@ -25,6 +28,7 @@ export default {
|
|
|
25
28
|
inheritAttrs: false,
|
|
26
29
|
components: {
|
|
27
30
|
CruResource,
|
|
31
|
+
FleetOCIStorageSecret,
|
|
28
32
|
Labels,
|
|
29
33
|
Loading,
|
|
30
34
|
NameNsDescription,
|
|
@@ -126,6 +130,10 @@ export default {
|
|
|
126
130
|
this.errors = exceptionToErrorsArray(err);
|
|
127
131
|
}
|
|
128
132
|
},
|
|
133
|
+
|
|
134
|
+
updateDefaultOCIStorageSecret(secretName) {
|
|
135
|
+
this.value.metadata.annotations[FLEET_ANNOTATIONS.OCI_STORAGE_SECRET_DEFAULT] = secretName;
|
|
136
|
+
}
|
|
129
137
|
},
|
|
130
138
|
|
|
131
139
|
computed: {
|
|
@@ -145,6 +153,14 @@ export default {
|
|
|
145
153
|
}
|
|
146
154
|
},
|
|
147
155
|
|
|
156
|
+
defaultOCIStorageSecret() {
|
|
157
|
+
return this.value.metadata?.annotations?.[FLEET_ANNOTATIONS.OCI_STORAGE_SECRET_DEFAULT];
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
isCreate() {
|
|
161
|
+
return this.mode === _CREATE;
|
|
162
|
+
},
|
|
163
|
+
|
|
148
164
|
SCOPE_NAMESPACE() {
|
|
149
165
|
return SCOPE_NAMESPACE;
|
|
150
166
|
},
|
|
@@ -198,19 +214,10 @@ export default {
|
|
|
198
214
|
/>
|
|
199
215
|
</Tab> -->
|
|
200
216
|
|
|
201
|
-
<Tab
|
|
202
|
-
name="labels"
|
|
203
|
-
label-key="generic.labelsAndAnnotations"
|
|
204
|
-
>
|
|
205
|
-
<Labels
|
|
206
|
-
:value="value"
|
|
207
|
-
:mode="mode"
|
|
208
|
-
@update:value="$emit('input', $event)"
|
|
209
|
-
/>
|
|
210
|
-
</Tab>
|
|
211
217
|
<Tab
|
|
212
218
|
name="allowedtargetnamespaces"
|
|
213
219
|
label-key="fleet.workspaces.tabs.restrictions"
|
|
220
|
+
:weight="3"
|
|
214
221
|
>
|
|
215
222
|
<Banner
|
|
216
223
|
color="info"
|
|
@@ -240,6 +247,32 @@ export default {
|
|
|
240
247
|
:value-can-be-empty="true"
|
|
241
248
|
/>
|
|
242
249
|
</Tab>
|
|
250
|
+
<Tab
|
|
251
|
+
v-if="!isCreate"
|
|
252
|
+
name="ociRegistries"
|
|
253
|
+
label-key="fleet.workspaces.tabs.ociRegistry"
|
|
254
|
+
:weight="2"
|
|
255
|
+
>
|
|
256
|
+
<FleetOCIStorageSecret
|
|
257
|
+
data-testid="default-oci-storage-secret"
|
|
258
|
+
:secret="defaultOCIStorageSecret"
|
|
259
|
+
:workspace="value.metadata.name"
|
|
260
|
+
:mode="mode"
|
|
261
|
+
:allow-default="false"
|
|
262
|
+
@update:value="updateDefaultOCIStorageSecret"
|
|
263
|
+
/>
|
|
264
|
+
</Tab>
|
|
265
|
+
<Tab
|
|
266
|
+
name="labels"
|
|
267
|
+
label-key="generic.labelsAndAnnotations"
|
|
268
|
+
:weight="1"
|
|
269
|
+
>
|
|
270
|
+
<Labels
|
|
271
|
+
:value="value"
|
|
272
|
+
:mode="mode"
|
|
273
|
+
@update:value="$emit('input', $event)"
|
|
274
|
+
/>
|
|
275
|
+
</Tab>
|
|
243
276
|
</Tabbed>
|
|
244
277
|
</CruResource>
|
|
245
278
|
</template>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import FleetHelmOps from '@shell/components/fleet/FleetHelmOps.vue';
|
|
3
|
+
import Masthead from '@shell/components/ResourceList/Masthead';
|
|
4
|
+
import FleetNoWorkspaces from '@shell/components/fleet/FleetNoWorkspaces.vue';
|
|
5
|
+
import { FLEET } from '@shell/config/types';
|
|
6
|
+
import ResourceFetch from '@shell/mixins/resource-fetch';
|
|
7
|
+
import { checkPermissions, checkSchemasForFindAllHash } from '@shell/utils/auth';
|
|
8
|
+
|
|
9
|
+
export default {
|
|
10
|
+
name: 'ListHelmOps',
|
|
11
|
+
components: {
|
|
12
|
+
FleetHelmOps,
|
|
13
|
+
Masthead,
|
|
14
|
+
FleetNoWorkspaces,
|
|
15
|
+
},
|
|
16
|
+
mixins: [ResourceFetch],
|
|
17
|
+
props: {
|
|
18
|
+
schema: {
|
|
19
|
+
type: Object,
|
|
20
|
+
required: true,
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
resource: {
|
|
24
|
+
type: String,
|
|
25
|
+
required: true,
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
loadIndeterminate: {
|
|
29
|
+
type: Boolean,
|
|
30
|
+
default: false
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
incrementalLoadingIndicator: {
|
|
34
|
+
type: Boolean,
|
|
35
|
+
default: false
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
useQueryParamsForSimpleFiltering: {
|
|
39
|
+
type: Boolean,
|
|
40
|
+
default: false
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
async fetch() {
|
|
45
|
+
try {
|
|
46
|
+
const hash = await checkSchemasForFindAllHash({
|
|
47
|
+
cluster: {
|
|
48
|
+
inStoreType: 'management',
|
|
49
|
+
type: FLEET.CLUSTER
|
|
50
|
+
},
|
|
51
|
+
clusterGroups: {
|
|
52
|
+
inStoreType: 'management',
|
|
53
|
+
type: FLEET.CLUSTER_GROUP
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
helmOps: {
|
|
57
|
+
inStoreType: 'management',
|
|
58
|
+
type: FLEET.HELM_OP
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
workspaces: {
|
|
62
|
+
inStoreType: 'management',
|
|
63
|
+
type: FLEET.WORKSPACE
|
|
64
|
+
},
|
|
65
|
+
|
|
66
|
+
}, this.$store);
|
|
67
|
+
|
|
68
|
+
this.hasWorkspaces = (hash.workspaces || []).length > 0;
|
|
69
|
+
} catch (e) {
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const permissions = await checkPermissions({ workspaces: { type: FLEET.WORKSPACE }, helmOps: { type: FLEET.HELM_OP } }, this.$store.getters);
|
|
74
|
+
|
|
75
|
+
this.permissions = permissions;
|
|
76
|
+
} catch (e) {
|
|
77
|
+
}
|
|
78
|
+
await this.$fetchType(this.resource);
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
data() {
|
|
82
|
+
return { hasWorkspaces: false, permissions: {} };
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<template>
|
|
88
|
+
<div v-if="hasWorkspaces">
|
|
89
|
+
<Masthead
|
|
90
|
+
:schema="schema"
|
|
91
|
+
:resource="resource"
|
|
92
|
+
:show-incremental-loading-indicator="incrementalLoadingIndicator"
|
|
93
|
+
:load-resources="loadResources"
|
|
94
|
+
:load-indeterminate="loadIndeterminate"
|
|
95
|
+
:create-button-label="t('fleet.helmOp.actions.add')"
|
|
96
|
+
/>
|
|
97
|
+
<FleetHelmOps
|
|
98
|
+
:rows="rows"
|
|
99
|
+
:schema="schema"
|
|
100
|
+
:loading="loading"
|
|
101
|
+
:use-query-params-for-simple-filtering="useQueryParamsForSimpleFiltering"
|
|
102
|
+
:force-update-live-and-delayed="forceUpdateLiveAndDelayed"
|
|
103
|
+
/>
|
|
104
|
+
</div>
|
|
105
|
+
<div v-else>
|
|
106
|
+
<FleetNoWorkspaces :can-view="permissions.workspaces" />
|
|
107
|
+
</div>
|
|
108
|
+
</template>
|
package/list/namespace.vue
CHANGED
|
@@ -42,8 +42,11 @@ export default {
|
|
|
42
42
|
headers() {
|
|
43
43
|
const headersFromSchema = this.$store.getters['type-map/headersFor'](this.schema);
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
// harvester is reusing this namespace.js to render ns page, we need to make sure harvester backend support quota schema to show this column.
|
|
46
|
+
if (this.hasHarvesterResourceQuotaSchema && Array.isArray(headersFromSchema) && headersFromSchema.length > 1) {
|
|
47
|
+
const columnIdx = headersFromSchema.length - 1;
|
|
48
|
+
|
|
49
|
+
headersFromSchema.splice(columnIdx, 0, NS_SNAPSHOT_QUOTA);
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
return headersFromSchema;
|
package/mixins/auth-config.js
CHANGED
|
@@ -307,7 +307,14 @@ export default {
|
|
|
307
307
|
|
|
308
308
|
// KeyCloakOIDCConfig --> OIDCConfig
|
|
309
309
|
this.model.rancherUrl = `${ serverUrl }/verify-auth`;
|
|
310
|
-
|
|
310
|
+
|
|
311
|
+
// If there are base scopes defined for this provider, use those
|
|
312
|
+
if (Array.isArray(BASE_SCOPES[this.model.id])) {
|
|
313
|
+
this.model.scope = BASE_SCOPES[this.model.id][0];
|
|
314
|
+
} else {
|
|
315
|
+
// Default if base scopes not defined for this auth provider
|
|
316
|
+
this.model.scope = BASE_SCOPES.genericoidc[0];
|
|
317
|
+
}
|
|
311
318
|
break;
|
|
312
319
|
}
|
|
313
320
|
|
package/mixins/preset.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { watch } from 'vue';
|
|
2
|
+
import { dasherize } from '@shell/utils/string';
|
|
3
|
+
import { NORMAN } from '@shell/config/types';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
data() {
|
|
7
|
+
return {
|
|
8
|
+
_init: [],
|
|
9
|
+
presets: {},
|
|
10
|
+
};
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
mounted() {
|
|
14
|
+
this.presetKey = dasherize(this.$options.name || '');
|
|
15
|
+
|
|
16
|
+
const version = this.presetVersion;
|
|
17
|
+
|
|
18
|
+
if (!version) {
|
|
19
|
+
console.warn('Preset: version not found, skip.'); // eslint-disable-line no-console
|
|
20
|
+
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let presets = null;
|
|
25
|
+
|
|
26
|
+
try {
|
|
27
|
+
presets = JSON.parse(window.localStorage.getItem(this.presetKey));
|
|
28
|
+
} catch (error) {
|
|
29
|
+
console.warn(`Preset: load presets failed, invalid presets [${ this.presetKey }]`); // eslint-disable-line no-console
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (presets?.data && presets?.user === this.user && presets?.version === version) {
|
|
33
|
+
this.presets = presets;
|
|
34
|
+
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
this.presets = {
|
|
39
|
+
data: {},
|
|
40
|
+
user: this.user,
|
|
41
|
+
version
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
computed: {
|
|
46
|
+
user() {
|
|
47
|
+
const principal = this.$store.getters['rancher/byId'](NORMAN.PRINCIPAL, this.$store.getters['auth/principalId']) || {};
|
|
48
|
+
|
|
49
|
+
return principal.loginName;
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
methods: {
|
|
54
|
+
preset(key, type) {
|
|
55
|
+
if (this._init.includes(key)) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
this._init.push(key);
|
|
60
|
+
|
|
61
|
+
if (!this.presetVersion) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!this.presetKey) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!this.presets?.data) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (this[key] === undefined) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const preset = this.presets.data[key];
|
|
78
|
+
|
|
79
|
+
if (preset !== undefined && typeof preset === type) { // eslint-disable-line valid-typeof
|
|
80
|
+
this[key] = preset;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
watch(
|
|
84
|
+
() => this[key],
|
|
85
|
+
(neu) => {
|
|
86
|
+
this.presets.data[key] = neu;
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
const presets = JSON.stringify(this.presets);
|
|
90
|
+
|
|
91
|
+
window.localStorage.setItem(this.presetKey, presets);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.warn(`Preset: save presets failed, invalid presets [${ this.presetKey }]`); // eslint-disable-line no-console
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
{ deep: true }
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
};
|
package/mixins/resource-fetch.js
CHANGED
|
@@ -280,7 +280,7 @@ export default {
|
|
|
280
280
|
if (manualDataRefreshEnabled && resourceCount >= manualDataRefreshThreshold) {
|
|
281
281
|
watch = false;
|
|
282
282
|
isTooManyItemsToAutoUpdate = true;
|
|
283
|
-
} else if (this.canPaginate) {
|
|
283
|
+
} else if (this.canPaginate && this.isPaginationManualRefreshEnabled) {
|
|
284
284
|
isTooManyItemsToAutoUpdate = true;
|
|
285
285
|
}
|
|
286
286
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { STEVE_WATCH_MODE } from '@shell/types/store/subscribe.types';
|
|
2
|
+
|
|
3
|
+
// This is functionality used to stop or start sockets used to watch resources in the vai world.
|
|
4
|
+
// Currently disabled via (non-public) perf setting
|
|
5
|
+
// See https://github.com/rancher/dashboard/issues/14359 for long term plan
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
props: {
|
|
9
|
+
schema: {
|
|
10
|
+
type: Object,
|
|
11
|
+
default: null,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
data() {
|
|
16
|
+
// Note - does not cover anything fetched by secondary / page functions
|
|
17
|
+
const watchOpts = this.schema?.id ? {
|
|
18
|
+
type: this.schema.id,
|
|
19
|
+
mode: STEVE_WATCH_MODE.RESOURCE_CHANGES
|
|
20
|
+
// Note - we don't restrict watch by namespace (would involve unwatch, request, watch with new revision on every change to ns filter)
|
|
21
|
+
} : undefined;
|
|
22
|
+
|
|
23
|
+
return { watchOpts };
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
computed: {
|
|
27
|
+
watching() {
|
|
28
|
+
return this.$store.getters[`${ this.inStore }/watchStarted`](this.watchOpts);
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
methods: {
|
|
33
|
+
toggleWatch(toggle) {
|
|
34
|
+
if (toggle) {
|
|
35
|
+
// Assume there's a gap between cache and reality, to restart watch with something that will make a new http request to refresh it
|
|
36
|
+
this.$store.dispatch(`${ this.inStore }/resyncWatch`, {
|
|
37
|
+
...this.watchOpts,
|
|
38
|
+
resourceType: this.watchOpts?.type
|
|
39
|
+
});
|
|
40
|
+
} else {
|
|
41
|
+
this.$store.dispatch(`${ this.inStore }/unwatch`, this.watchOpts);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import Chart from '@shell/models/chart';
|
|
2
|
+
import { APP_UPGRADE_STATUS } from '@shell/store/catalog';
|
|
3
|
+
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
4
|
+
|
|
5
|
+
const base = {
|
|
6
|
+
chartName: 'my-app',
|
|
7
|
+
repoName: 'my-repo',
|
|
8
|
+
repoNameDisplay: 'My Repo',
|
|
9
|
+
versions: [
|
|
10
|
+
{
|
|
11
|
+
version: '1.3.0', home: 'https://example.com', created: '2024-03-10T12:00:00Z'
|
|
12
|
+
},
|
|
13
|
+
{ version: '1.2.3', home: 'https://example.com' }
|
|
14
|
+
],
|
|
15
|
+
categories: [],
|
|
16
|
+
tags: [],
|
|
17
|
+
deprecated: false
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function makeInstalledApp(upgradeAvailable = APP_UPGRADE_STATUS.NO_UPGRADE) {
|
|
21
|
+
return {
|
|
22
|
+
spec: {
|
|
23
|
+
chart: {
|
|
24
|
+
metadata: {
|
|
25
|
+
name: 'my-app',
|
|
26
|
+
version: '1.3.0',
|
|
27
|
+
home: 'https://example.com',
|
|
28
|
+
annotations: { [CATALOG_ANNOTATIONS.SOURCE_REPO_NAME]: 'my-repo' }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
upgradeAvailable
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe('class Chart', () => {
|
|
37
|
+
describe('matchingInstalledApps', () => {
|
|
38
|
+
it('matches by name, repo, and home in latest version', () => {
|
|
39
|
+
const installedApp = makeInstalledApp();
|
|
40
|
+
|
|
41
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
42
|
+
|
|
43
|
+
expect(chart.matchingInstalledApps).toHaveLength(1);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('does not match if name is different', () => {
|
|
47
|
+
const installedApp = makeInstalledApp();
|
|
48
|
+
|
|
49
|
+
installedApp.spec.chart.metadata.name = 'different-app';
|
|
50
|
+
|
|
51
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
52
|
+
|
|
53
|
+
expect(chart.matchingInstalledApps).toHaveLength(0);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('does not match if repo is different', () => {
|
|
57
|
+
const installedApp = makeInstalledApp();
|
|
58
|
+
|
|
59
|
+
installedApp.spec.chart.metadata.annotations[CATALOG_ANNOTATIONS.SOURCE_REPO_NAME] = 'different-repo';
|
|
60
|
+
|
|
61
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
62
|
+
|
|
63
|
+
expect(chart.matchingInstalledApps).toHaveLength(0);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('matches by version+home when not latest', () => {
|
|
67
|
+
const installedApp = makeInstalledApp();
|
|
68
|
+
|
|
69
|
+
installedApp.spec.chart.metadata.version = '1.2.3'; // not the latest in base
|
|
70
|
+
|
|
71
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
72
|
+
|
|
73
|
+
expect(chart.matchingInstalledApps).toHaveLength(1);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('can use fallback repo from metadata labels', () => {
|
|
77
|
+
const installedApp = makeInstalledApp();
|
|
78
|
+
|
|
79
|
+
installedApp.spec.chart.metadata.annotations = {}; // remove SOURCE_REPO_NAME
|
|
80
|
+
installedApp.metadata = { labels: { [CATALOG_ANNOTATIONS.CLUSTER_REPO_NAME]: 'my-repo' } };
|
|
81
|
+
|
|
82
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
83
|
+
|
|
84
|
+
expect(chart.matchingInstalledApps).toHaveLength(1);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('isInstalled', () => {
|
|
89
|
+
it('is true when one app matches', () => {
|
|
90
|
+
const installedApp = {
|
|
91
|
+
spec: {
|
|
92
|
+
chart: {
|
|
93
|
+
metadata: {
|
|
94
|
+
name: 'my-app',
|
|
95
|
+
version: '1.2.3',
|
|
96
|
+
home: 'https://example.com',
|
|
97
|
+
annotations: { [CATALOG_ANNOTATIONS.SOURCE_REPO_NAME]: 'my-repo' }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
104
|
+
|
|
105
|
+
expect(chart.isInstalled).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('is false when no apps match', () => {
|
|
109
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [] } });
|
|
110
|
+
|
|
111
|
+
expect(chart.isInstalled).toBe(false);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('is false when multiple apps match', () => {
|
|
115
|
+
const appTemplate = {
|
|
116
|
+
spec: {
|
|
117
|
+
chart: {
|
|
118
|
+
metadata: {
|
|
119
|
+
name: 'my-app',
|
|
120
|
+
version: '1.2.3',
|
|
121
|
+
home: 'https://example.com',
|
|
122
|
+
annotations: { [CATALOG_ANNOTATIONS.SOURCE_REPO_NAME]: 'my-repo' }
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [appTemplate, appTemplate] } });
|
|
129
|
+
|
|
130
|
+
expect(chart.isInstalled).toBe(false);
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe('upgradeable', () => {
|
|
135
|
+
it('is true when installed and upgradeAvailable is SINGLE_UPGRADE', () => {
|
|
136
|
+
const installedApp = {
|
|
137
|
+
spec: {
|
|
138
|
+
chart: {
|
|
139
|
+
metadata: {
|
|
140
|
+
name: 'my-app',
|
|
141
|
+
version: '1.2.3',
|
|
142
|
+
home: 'https://example.com',
|
|
143
|
+
annotations: { [CATALOG_ANNOTATIONS.SOURCE_REPO_NAME]: 'my-repo' }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
upgradeAvailable: APP_UPGRADE_STATUS.SINGLE_UPGRADE
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
151
|
+
|
|
152
|
+
expect(chart.upgradeable).toBe(true);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('is false if upgradeAvailable is different', () => {
|
|
156
|
+
const installedApp = {
|
|
157
|
+
spec: {
|
|
158
|
+
chart: {
|
|
159
|
+
metadata: {
|
|
160
|
+
name: 'my-app',
|
|
161
|
+
version: '1.2.3',
|
|
162
|
+
home: 'https://example.com',
|
|
163
|
+
annotations: { [CATALOG_ANNOTATIONS.SOURCE_REPO_NAME]: 'my-repo' }
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
},
|
|
167
|
+
upgradeAvailable: APP_UPGRADE_STATUS.NO_UPGRADE
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
171
|
+
|
|
172
|
+
expect(chart.upgradeable).toBe(false);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('is false when not installed', () => {
|
|
176
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [] } });
|
|
177
|
+
|
|
178
|
+
expect(chart.upgradeable).toBe(false);
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('cardContent', () => {
|
|
183
|
+
it('includes correct subHeader and footer info', () => {
|
|
184
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [] } });
|
|
185
|
+
|
|
186
|
+
const result = chart.cardContent;
|
|
187
|
+
|
|
188
|
+
expect(result.subHeaderItems).toHaveLength(2);
|
|
189
|
+
expect(result.subHeaderItems[0].label).toBe('1.3.0');
|
|
190
|
+
expect(result.subHeaderItems[1].label).toBe('Mar 10, 2024');
|
|
191
|
+
|
|
192
|
+
expect(result.footerItems).toHaveLength(1);
|
|
193
|
+
expect(result.footerItems[0].labels).toContain('My Repo');
|
|
194
|
+
|
|
195
|
+
expect(result.statuses).toHaveLength(0);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('includes category and tag items when present', () => {
|
|
199
|
+
const chart = new Chart({
|
|
200
|
+
...base,
|
|
201
|
+
categories: ['database'],
|
|
202
|
+
tags: ['linux', 'experimentl']
|
|
203
|
+
}, { rootGetters: { 'cluster/all': () => [] } });
|
|
204
|
+
|
|
205
|
+
const result = chart.cardContent;
|
|
206
|
+
|
|
207
|
+
expect(result.footerItems).toHaveLength(3);
|
|
208
|
+
|
|
209
|
+
const categoryItem = result.footerItems.find((i) => i.icon === 'icon-category-alt');
|
|
210
|
+
|
|
211
|
+
expect(categoryItem).toBeDefined();
|
|
212
|
+
expect(categoryItem.labels).toContain('database');
|
|
213
|
+
|
|
214
|
+
const tagItem = result.footerItems.find((i) => i.icon === 'icon-tag-alt');
|
|
215
|
+
|
|
216
|
+
expect(tagItem).toBeDefined();
|
|
217
|
+
expect(tagItem.labels).toStrictEqual(expect.arrayContaining(['linux', 'experimentl']));
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('includes deprecated status when deprecated is true', () => {
|
|
221
|
+
const chart = new Chart({ ...base, deprecated: true }, { rootGetters: { 'cluster/all': () => [] } });
|
|
222
|
+
|
|
223
|
+
const result = chart.cardContent;
|
|
224
|
+
|
|
225
|
+
const deprecatedStatus = result.statuses.find((s) => s.tooltip.key === 'generic.deprecated');
|
|
226
|
+
|
|
227
|
+
expect(deprecatedStatus).toBeDefined();
|
|
228
|
+
expect(deprecatedStatus.color).toBe('error');
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it('includes installed status when app is installed', () => {
|
|
232
|
+
const installedApp = makeInstalledApp();
|
|
233
|
+
|
|
234
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
235
|
+
|
|
236
|
+
const result = chart.cardContent;
|
|
237
|
+
|
|
238
|
+
const installedStatus = result.statuses.find((s) => s.tooltip.key === 'generic.installed');
|
|
239
|
+
|
|
240
|
+
expect(installedStatus).toBeDefined();
|
|
241
|
+
expect(installedStatus.color).toBe('success');
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('includes upgradeable status when upgrade is available', () => {
|
|
245
|
+
const installedApp = makeInstalledApp(APP_UPGRADE_STATUS.SINGLE_UPGRADE);
|
|
246
|
+
|
|
247
|
+
const chart = new Chart(base, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
248
|
+
|
|
249
|
+
const result = chart.cardContent;
|
|
250
|
+
|
|
251
|
+
const upgradeableStatus = result.statuses.find((s) => s.tooltip.key === 'generic.upgradeable');
|
|
252
|
+
|
|
253
|
+
expect(upgradeableStatus).toBeDefined();
|
|
254
|
+
expect(upgradeableStatus.color).toBe('info');
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('shows all statuses together when all conditions are met', () => {
|
|
258
|
+
const installedApp = makeInstalledApp(APP_UPGRADE_STATUS.SINGLE_UPGRADE);
|
|
259
|
+
|
|
260
|
+
const chart = new Chart({ ...base, deprecated: true }, { rootGetters: { 'cluster/all': () => [installedApp] } });
|
|
261
|
+
|
|
262
|
+
const result = chart.cardContent;
|
|
263
|
+
|
|
264
|
+
const keys = result.statuses.map((s) => s.tooltip.key);
|
|
265
|
+
|
|
266
|
+
expect(keys).toStrictEqual(expect.arrayContaining([
|
|
267
|
+
'generic.deprecated',
|
|
268
|
+
'generic.upgradeable',
|
|
269
|
+
'generic.installed'
|
|
270
|
+
]));
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
});
|