@rancher/shell 0.3.4 → 0.3.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/styles/app.scss +1 -1
- package/assets/styles/fonts/_fontstack.scss +11 -11
- package/assets/styles/vendor/vue-js-modal.scss +3 -3
- package/assets/translations/en-us.yaml +92 -22
- package/assets/translations/zh-hans.yaml +84 -15
- package/babel.config.js +13 -0
- package/chart/gatekeeper.vue +77 -0
- package/chart/istio.vue +108 -111
- package/chart/logging/index.vue +13 -4
- package/chart/monitoring/index.vue +15 -5
- package/chart/monitoring/steps/uninstall-v1.vue +2 -2
- package/chart/rancher-backup/index.vue +10 -3
- package/cloud-credential/aws.vue +1 -1
- package/cloud-credential/digitalocean.vue +1 -1
- package/cloud-credential/gcp.vue +1 -1
- package/cloud-credential/generic.vue +2 -2
- package/cloud-credential/linode.vue +1 -1
- package/cloud-credential/pnap.vue +1 -1
- package/components/ActionMenu.vue +3 -4
- package/components/AssignTo.vue +1 -1
- package/components/AsyncButton.vue +1 -1
- package/components/BannerGraphic.vue +1 -1
- package/components/ButtonDropdown.vue +2 -3
- package/components/ChartPsp.vue +76 -0
- package/components/CruResource.vue +6 -2
- package/components/DashboardMetrics.vue +12 -10
- package/components/DetailText.vue +1 -1
- package/components/DisableAuthProviderModal.vue +1 -1
- package/components/EmberPage.vue +1 -1
- package/components/EtcdInfoBanner.vue +5 -4
- package/components/ExplorerMembers.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +14 -1
- package/components/FileDiff.vue +6 -7
- package/components/GrafanaDashboard.vue +18 -21
- package/components/LazyImage.vue +10 -12
- package/components/LogItem.vue +1 -1
- package/components/Markdown.vue +1 -1
- package/components/PromptRemove.vue +2 -2
- package/components/PromptRestore.vue +1 -1
- package/components/ResourceDetail/Masthead.vue +16 -0
- package/components/ResourceDetail/index.vue +21 -4
- package/components/ResourceList/index.vue +1 -1
- package/components/ResourceTable.vue +4 -1
- package/components/SingleClusterInfo.vue +2 -2
- package/components/SortableTable/THead.vue +1 -1
- package/components/SortableTable/index.vue +5 -2
- package/components/__tests__/AsyncButton.test.ts +3 -1
- package/components/__tests__/ChartPsp.test.ts +75 -0
- package/components/__tests__/CruResource.test.ts +3 -1
- package/components/auth/Principal.vue +1 -1
- package/components/fleet/FleetBundles.vue +3 -1
- package/components/fleet/FleetClusters.vue +1 -2
- package/components/fleet/FleetIntro.vue +9 -1
- package/components/fleet/FleetNoWorkspaces.vue +62 -0
- package/components/fleet/FleetSummary.vue +7 -1
- package/components/form/LabeledSelect.vue +14 -11
- package/components/form/MatchExpressions.vue +17 -2
- package/components/form/NameNsDescription.vue +31 -45
- package/components/form/ResourceSelector.vue +1 -1
- package/components/form/SecretSelector.vue +5 -1
- package/components/form/ServiceNameSelect.vue +1 -1
- package/components/form/SimpleSecretSelector.vue +9 -9
- package/components/form/__tests__/LabeledSelect.test.ts +138 -0
- package/components/form/__tests__/NameNsDescription.ts +32 -0
- package/components/formatter/InternalExternalIP.vue +6 -0
- package/components/formatter/InvolvedObjectLink.vue +54 -0
- package/components/formatter/Link.vue +20 -4
- package/components/formatter/LinkName.vue +6 -1
- package/components/formatter/ServiceTargets.vue +1 -1
- package/components/nav/Group.vue +2 -2
- package/components/nav/NamespaceFilter.vue +15 -11
- package/components/nav/TopLevelMenu.vue +2 -4
- package/components/nav/Type.vue +1 -1
- package/components/nav/WorkspaceSwitcher.vue +46 -5
- package/config/labels-annotations.js +17 -0
- package/config/product/auth.js +3 -2
- package/config/product/explorer.js +11 -4
- package/config/product/fleet.js +2 -0
- package/config/router.js +414 -0
- package/config/table-headers.js +10 -2
- package/config/types.js +11 -8
- package/config/uiplugins.js +30 -0
- package/content/docs/en-us/whats-new.md +10 -0
- package/content/docs/zh-hans/whats-new.md +11 -1
- package/core/plugin-routes.ts +23 -0
- package/creators/app/app.package.json +2 -1
- package/creators/app/files/.eslintrc.js +1 -1
- package/creators/app/files/babel.config.js +1 -18
- package/creators/app/files/vue.config.js +7 -0
- package/creators/app/init +5 -5
- package/creators/pkg/files/.github/workflows/build-extension.yml +111 -0
- package/creators/pkg/init +35 -4
- package/creators/update/init +1 -1
- package/detail/constraints.gatekeeper.sh.constraint.vue +20 -10
- package/detail/fleet.cattle.io.gitrepo.vue +19 -11
- package/detail/harvesterhci.io.management.cluster.vue +3 -3
- package/detail/provisioning.cattle.io.cluster.vue +54 -12
- package/detail/workload/index.vue +3 -3
- package/dialog/AddClusterMemberDialog.vue +1 -1
- package/dialog/AddProjectMemberDialog.vue +2 -2
- package/dialog/AddonConfigConfirmationDialog.vue +27 -15
- package/dialog/DiagnosticTimingsDialog.vue +1 -1
- package/dialog/ForceMachineRemoveDialog.vue +1 -1
- package/dialog/GenericPrompt.vue +18 -6
- package/dialog/RotateEncryptionKeyDialog.vue +1 -1
- package/dialog/SaveAsRKETemplateDialog.vue +1 -1
- package/dialog/ScaleMachineDownDialog.vue +1 -1
- package/edit/auth/github.vue +8 -8
- package/edit/auth/googleoauth.vue +5 -5
- package/edit/auth/ldap/index.vue +1 -1
- package/edit/auth/oidc.vue +1 -1
- package/edit/auth/saml.vue +1 -1
- package/edit/cis.cattle.io.clusterscan.vue +1 -1
- package/edit/fleet.cattle.io.clustergroup.vue +6 -4
- package/edit/fleet.cattle.io.gitrepo.vue +16 -3
- package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
- package/edit/management.cattle.io.fleetworkspace.vue +141 -6
- package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
- package/edit/management.cattle.io.setting.vue +1 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
- package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
- package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
- package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
- package/edit/namespace.vue +2 -2
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +10 -0
- package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +248 -84
- package/edit/resources.cattle.io.backup.vue +1 -1
- package/edit/service.vue +1 -1
- package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
- package/edit/workload/__tests__/Job.test.ts +3 -1
- package/edit/workload/index.vue +8 -3
- package/edit/workload/mixins/workload.js +16 -0
- package/layouts/default.vue +7 -3
- package/list/fleet.cattle.io.bundle.vue +6 -3
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
- package/list/fleet.cattle.io.gitrepo.vue +44 -5
- package/list/management.cattle.io.fleetworkspace.vue +45 -0
- package/list/node.vue +69 -16
- package/list/provisioning.cattle.io.cluster.vue +30 -1
- package/machine-config/azure.vue +97 -38
- package/middleware/authenticated.js +34 -0
- package/mixins/chart.js +73 -2
- package/mixins/resource-fetch.js +2 -2
- package/models/apps.statefulset.js +28 -0
- package/models/cluster/node.js +23 -2
- package/models/cluster.x-k8s.io.machine.js +4 -2
- package/models/clusterroletemplatebinding.js +7 -0
- package/models/constraints.gatekeeper.sh.constraint.js +9 -0
- package/models/fleet.cattle.io.cluster.js +19 -10
- package/models/fleet.cattle.io.gitrepo.js +7 -2
- package/models/management.cattle.io.cluster.js +1 -1
- package/models/management.cattle.io.fleetworkspace.js +12 -0
- package/models/management.cattle.io.gitreporestriction.js +5 -0
- package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
- package/models/provisioning.cattle.io.cluster.js +7 -5
- package/nuxt/App.js +210 -0
- package/nuxt/axios.js +186 -0
- package/nuxt/client.js +817 -0
- package/nuxt/components/nuxt-build-indicator.vue +143 -0
- package/nuxt/components/nuxt-child.js +122 -0
- package/nuxt/components/nuxt-error.vue +98 -0
- package/nuxt/components/nuxt-link.client.js +98 -0
- package/nuxt/components/nuxt-link.server.js +16 -0
- package/nuxt/components/nuxt-loading.vue +154 -0
- package/nuxt/components/nuxt.js +101 -0
- package/nuxt/cookie-universal-nuxt.js +9 -0
- package/nuxt/empty.js +1 -0
- package/nuxt/index.js +365 -0
- package/nuxt/jsonp.js +82 -0
- package/nuxt/loading.html +39 -0
- package/nuxt/middleware.js +12 -0
- package/nuxt/mixins/fetch.client.js +90 -0
- package/nuxt/mixins/fetch.server.js +69 -0
- package/nuxt/portal-vue.js +4 -0
- package/nuxt/server.js +312 -0
- package/nuxt/store.js +178 -0
- package/nuxt/utils.js +630 -0
- package/nuxt/views/app.template.html +9 -0
- package/nuxt/views/error.html +23 -0
- package/package.json +5 -9
- package/pages/auth/setup.vue +2 -2
- package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
- package/pages/c/_cluster/apps/charts/chart.vue +4 -4
- package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
- package/pages/c/_cluster/apps/charts/install.vue +40 -66
- package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
- package/pages/c/_cluster/explorer/index.vue +29 -25
- package/pages/c/_cluster/explorer/tools/index.vue +8 -8
- package/pages/c/_cluster/fleet/index.vue +95 -34
- package/pages/c/_cluster/gatekeeper/index.vue +1 -1
- package/pages/c/_cluster/istio/index.vue +5 -5
- package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
- package/pages/c/_cluster/monitoring/index.vue +7 -0
- package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
- package/pages/c/_cluster/uiplugins/index.vue +49 -17
- package/pages/home.vue +9 -4
- package/pages/index.vue +10 -1
- package/plugins/clean-html-directive.js +31 -0
- package/plugins/dashboard-store/actions.js +32 -9
- package/plugins/dashboard-store/mutations.js +5 -2
- package/plugins/dashboard-store/resource-class.js +8 -1
- package/plugins/steve/mutations.js +3 -2
- package/plugins/steve/steve-description-class.js +5 -1
- package/plugins/steve/subscribe.js +63 -54
- package/plugins/steve-create-worker.js +14 -0
- package/promptRemove/management.cattle.io.globalrole.vue +2 -2
- package/promptRemove/management.cattle.io.project.vue +2 -2
- package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
- package/promptRemove/pod.vue +1 -1
- package/public/index.html +65 -0
- package/rancher-components/components/Banner/Banner.test.ts +9 -1
- package/rancher-components/components/Banner/Banner.vue +1 -1
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
- package/rancher-components/components/Form/Radio/RadioButton.vue +1 -1
- package/scripts/build-pkg.sh +1 -0
- package/scripts/clean +6 -0
- package/scripts/extension/bundle +58 -0
- package/scripts/extension/helmpatch +89 -0
- package/scripts/extension/publish +314 -0
- package/scripts/test-plugins-build.sh +4 -0
- package/store/__tests__/index.test.ts +110 -0
- package/store/index.js +145 -58
- package/store/type-map.js +5 -1
- package/tsconfig.default.json +36 -0
- package/tsconfig.json +24 -0
- package/types/shell/index.d.ts +420 -343
- package/utils/__tests__/string.test.ts +12 -0
- package/utils/auth.js +65 -0
- package/utils/monitoring.js +2 -1
- package/utils/position.js +5 -8
- package/utils/router.scrollBehavior.js +80 -0
- package/utils/select.js +1 -3
- package/utils/socket.js +1 -0
- package/utils/string.js +13 -0
- package/utils/time.js +9 -0
- package/vue.config.js +679 -0
- package/chart/rancher-alerting-drivers.vue +0 -53
- package/chart/rancher-gatekeeper.vue +0 -37
- package/creators/app/files/nuxt.config.js +0 -6
- package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
- package/nuxt.config.js +0 -798
|
@@ -3,11 +3,15 @@ import { mapState } from 'vuex';
|
|
|
3
3
|
import { FLEET } from '@shell/config/types';
|
|
4
4
|
import { WORKSPACE } from '@shell/store/prefs';
|
|
5
5
|
import { STATES_ENUM, STATES, getStateLabel } from '@shell/plugins/dashboard-store/resource-class';
|
|
6
|
-
import { allHash } from '@shell/utils/promise';
|
|
7
6
|
import Loading from '@shell/components/Loading';
|
|
8
7
|
import CollapsibleCard from '@shell/components/CollapsibleCard.vue';
|
|
9
8
|
import ResourceTable from '@shell/components/ResourceTable';
|
|
10
9
|
import CompoundStatusBadge from '@shell/components/CompoundStatusBadge';
|
|
10
|
+
import { checkPermissions, checkSchemasForFindAllHash } from '@shell/utils/auth';
|
|
11
|
+
import { WORKSPACE_ANNOTATION } from '@shell/config/labels-annotations';
|
|
12
|
+
import { filterBy } from '@shell/utils/array';
|
|
13
|
+
import FleetNoWorkspaces from '@shell/components/fleet/FleetNoWorkspaces.vue';
|
|
14
|
+
import { NAME } from '@shell/config/product/fleet';
|
|
11
15
|
|
|
12
16
|
export default {
|
|
13
17
|
name: 'ListGitRepo',
|
|
@@ -15,27 +19,38 @@ export default {
|
|
|
15
19
|
Loading,
|
|
16
20
|
ResourceTable,
|
|
17
21
|
CollapsibleCard,
|
|
18
|
-
CompoundStatusBadge
|
|
22
|
+
CompoundStatusBadge,
|
|
23
|
+
FleetNoWorkspaces
|
|
19
24
|
},
|
|
20
25
|
|
|
21
26
|
async fetch() {
|
|
22
|
-
const hash = await
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
const hash = await checkSchemasForFindAllHash({
|
|
28
|
+
fleetWorkspaces: {
|
|
29
|
+
inStoreType: 'management',
|
|
30
|
+
type: FLEET.WORKSPACE,
|
|
31
|
+
schemaValidator: (schema) => {
|
|
32
|
+
return !!schema?.links?.collection;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
allBundles: {
|
|
36
|
+
inStoreType: 'management',
|
|
37
|
+
type: FLEET.BUNDLE,
|
|
38
|
+
},
|
|
39
|
+
gitRepos: {
|
|
40
|
+
inStoreType: 'management',
|
|
41
|
+
type: FLEET.GIT_REPO,
|
|
42
|
+
}
|
|
43
|
+
}, this.$store);
|
|
27
44
|
|
|
28
|
-
this.allBundles = hash.allBundles;
|
|
29
45
|
this.gitRepos = hash.gitRepos;
|
|
30
|
-
this.
|
|
46
|
+
this.fleetWorkspacesData = hash.fleetWorkspaces || [];
|
|
31
47
|
|
|
32
|
-
|
|
33
|
-
|
|
48
|
+
try {
|
|
49
|
+
const permissions = await checkPermissions({ workspaces: { type: FLEET.WORKSPACE }, gitRepos: { type: FLEET.GIT_REPO, schemaValidator: schema => schema.resourceMethods.includes('PUT') } }, this.$store.getters);
|
|
34
50
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
});
|
|
51
|
+
this.permissions = permissions;
|
|
52
|
+
} catch (e) {
|
|
53
|
+
console.error(e); // eslint-disable-line no-console
|
|
39
54
|
}
|
|
40
55
|
},
|
|
41
56
|
|
|
@@ -71,24 +86,49 @@ export default {
|
|
|
71
86
|
sort: 'status.resourceCounts.ready',
|
|
72
87
|
}
|
|
73
88
|
],
|
|
74
|
-
schema:
|
|
75
|
-
allBundles:
|
|
76
|
-
gitRepos:
|
|
77
|
-
|
|
78
|
-
isCollapsed:
|
|
79
|
-
|
|
89
|
+
schema: {},
|
|
90
|
+
allBundles: [],
|
|
91
|
+
gitRepos: [],
|
|
92
|
+
fleetWorkspacesData: [],
|
|
93
|
+
isCollapsed: {},
|
|
94
|
+
permissions: {},
|
|
95
|
+
getStartedLink: {
|
|
80
96
|
name: 'c-cluster-product-resource-create',
|
|
81
97
|
params: {
|
|
82
|
-
product:
|
|
98
|
+
product: NAME,
|
|
83
99
|
resource: FLEET.GIT_REPO
|
|
84
100
|
},
|
|
85
101
|
}
|
|
86
102
|
};
|
|
87
103
|
},
|
|
88
104
|
computed: {
|
|
89
|
-
...mapState(['workspace']),
|
|
105
|
+
...mapState(['workspace', 'allNamespaces']),
|
|
106
|
+
fleetWorkspaces() {
|
|
107
|
+
if (this.fleetWorkspacesData?.length) {
|
|
108
|
+
return this.fleetWorkspacesData;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// When user doesn't have access to the workspaces fall back to namespaces
|
|
112
|
+
|
|
113
|
+
return this.allNamespaces.filter((item) => {
|
|
114
|
+
return item.metadata.annotations[WORKSPACE_ANNOTATION] === WORKSPACE;
|
|
115
|
+
}).map(( obj ) => {
|
|
116
|
+
const repos = filterBy(this.gitRepos, 'metadata.namespace', obj.id);
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
...obj,
|
|
120
|
+
counts: {
|
|
121
|
+
clusters: '-',
|
|
122
|
+
clusterGroups: '-',
|
|
123
|
+
gitRepos: repos.length
|
|
124
|
+
},
|
|
125
|
+
repos,
|
|
126
|
+
nameDisplay: obj.id
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
},
|
|
90
130
|
workspacesData() {
|
|
91
|
-
return this.fleetWorkspaces.filter(ws => ws.repos.length);
|
|
131
|
+
return this.fleetWorkspaces.filter(ws => ws.repos && ws.repos.length);
|
|
92
132
|
},
|
|
93
133
|
emptyWorkspaces() {
|
|
94
134
|
return this.fleetWorkspaces.filter(ws => !ws.repos || !ws.repos.length);
|
|
@@ -105,7 +145,7 @@ export default {
|
|
|
105
145
|
this.$router.push({
|
|
106
146
|
name: 'c-cluster-product-resource',
|
|
107
147
|
params: {
|
|
108
|
-
product:
|
|
148
|
+
product: NAME,
|
|
109
149
|
resource: FLEET.GIT_REPO
|
|
110
150
|
},
|
|
111
151
|
});
|
|
@@ -247,6 +287,14 @@ export default {
|
|
|
247
287
|
});
|
|
248
288
|
}
|
|
249
289
|
},
|
|
290
|
+
|
|
291
|
+
watch: {
|
|
292
|
+
fleetWorkspaces(value) {
|
|
293
|
+
value?.filter(ws => ws.repos?.length).forEach((ws) => {
|
|
294
|
+
this.$set(this.isCollapsed, ws.id, false);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
250
298
|
};
|
|
251
299
|
</script>
|
|
252
300
|
|
|
@@ -254,6 +302,10 @@ export default {
|
|
|
254
302
|
<div class="fleet-dashboard">
|
|
255
303
|
<Loading v-if="$fetchState.pending" />
|
|
256
304
|
<!-- no git repos -->
|
|
305
|
+
<FleetNoWorkspaces
|
|
306
|
+
v-else-if="!fleetWorkspacesData.length"
|
|
307
|
+
:can-view="permissions.workspaces"
|
|
308
|
+
/>
|
|
257
309
|
<div
|
|
258
310
|
v-else-if="!gitRepos.length"
|
|
259
311
|
class="fleet-empty-dashboard"
|
|
@@ -270,15 +322,17 @@ export default {
|
|
|
270
322
|
{{ t('fleet.dashboard.learnMore') }} <i class="icon icon-external-link" />
|
|
271
323
|
</a>
|
|
272
324
|
</p>
|
|
273
|
-
<
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
325
|
+
<template v-if="permissions.gitRepos">
|
|
326
|
+
<h3 class="mb-30">
|
|
327
|
+
{{ t('fleet.dashboard.noRepo', null, true) }}
|
|
328
|
+
</h3>
|
|
329
|
+
<n-link
|
|
330
|
+
:to="getStartedLink"
|
|
331
|
+
class="btn role-secondary"
|
|
332
|
+
>
|
|
333
|
+
{{ t('fleet.dashboard.getStarted') }}
|
|
334
|
+
</n-link>
|
|
335
|
+
</template>
|
|
282
336
|
</div>
|
|
283
337
|
<!-- fleet dashboard with repos -->
|
|
284
338
|
<div
|
|
@@ -354,7 +408,9 @@ export default {
|
|
|
354
408
|
v-on="$listeners"
|
|
355
409
|
>
|
|
356
410
|
<template #cell:clustersReady="{row}">
|
|
411
|
+
<span v-if="ws.type === 'namespace'"> - </span>
|
|
357
412
|
<CompoundStatusBadge
|
|
413
|
+
v-else
|
|
358
414
|
:tooltip-text="getTooltipInfo('clusters', row)"
|
|
359
415
|
:badge-class="getStatusInfo('clusters', row).badgeClass"
|
|
360
416
|
:icon="getStatusInfo('clusters', row).icon"
|
|
@@ -362,7 +418,9 @@ export default {
|
|
|
362
418
|
/>
|
|
363
419
|
</template>
|
|
364
420
|
<template #cell:bundlesReady="{row}">
|
|
421
|
+
<span v-if="ws.type === 'namespace'"> - </span>
|
|
365
422
|
<CompoundStatusBadge
|
|
423
|
+
v-else
|
|
366
424
|
:tooltip-text="getTooltipInfo('bundles', row)"
|
|
367
425
|
:badge-class="getStatusInfo('bundles', row).badgeClass"
|
|
368
426
|
:icon="getStatusInfo('bundles', row).icon"
|
|
@@ -389,6 +447,9 @@ export default {
|
|
|
389
447
|
</template>
|
|
390
448
|
|
|
391
449
|
<style lang="scss" scoped>
|
|
450
|
+
.fleet-dashboard {
|
|
451
|
+
min-height: 100vh;
|
|
452
|
+
}
|
|
392
453
|
.fleet-empty-dashboard {
|
|
393
454
|
flex: 1;
|
|
394
455
|
display: flex;
|
|
@@ -72,7 +72,7 @@ export default {
|
|
|
72
72
|
<template>
|
|
73
73
|
<div>
|
|
74
74
|
<h1>Overview</h1>
|
|
75
|
-
<h4 v-html="t('istio.poweredBy', {}, true)" />
|
|
75
|
+
<h4 v-clean-html="t('istio.poweredBy', {}, true)" />
|
|
76
76
|
<div class="links">
|
|
77
77
|
<div
|
|
78
78
|
:class="{'disabled':!kialiUrl}"
|
|
@@ -99,7 +99,7 @@ export default {
|
|
|
99
99
|
</a>
|
|
100
100
|
<hr>
|
|
101
101
|
<div class="description">
|
|
102
|
-
<span v-html="t('istio.links.kiali.description', {link: monitoringUrl}, true)" />
|
|
102
|
+
<span v-clean-html="t('istio.links.kiali.description', {link: monitoringUrl}, true)" />
|
|
103
103
|
</div>
|
|
104
104
|
</div>
|
|
105
105
|
</span>
|
|
@@ -107,7 +107,7 @@ export default {
|
|
|
107
107
|
v-if="!kialiUrl"
|
|
108
108
|
class="disabled-msg"
|
|
109
109
|
>
|
|
110
|
-
<span v-html="t('istio.links.disabled', {app: 'Kiali'})" />
|
|
110
|
+
<span v-clean-html="t('istio.links.disabled', {app: 'Kiali'})" />
|
|
111
111
|
</div>
|
|
112
112
|
</div>
|
|
113
113
|
<div
|
|
@@ -135,7 +135,7 @@ export default {
|
|
|
135
135
|
</a>
|
|
136
136
|
<hr>
|
|
137
137
|
<div class="description">
|
|
138
|
-
<span v-html="t('istio.links.jaeger.description', true)" />
|
|
138
|
+
<span v-clean-html="t('istio.links.jaeger.description', true)" />
|
|
139
139
|
</div>
|
|
140
140
|
</div>
|
|
141
141
|
</span>
|
|
@@ -143,7 +143,7 @@ export default {
|
|
|
143
143
|
v-if="!jaegerUrl"
|
|
144
144
|
class="disabled-msg"
|
|
145
145
|
>
|
|
146
|
-
<span v-html="t('istio.links.disabled', {app: 'Jaeger'})" />
|
|
146
|
+
<span v-clean-html="t('istio.links.disabled', {app: 'Jaeger'})" />
|
|
147
147
|
</div>
|
|
148
148
|
</div>
|
|
149
149
|
</div>
|
|
@@ -36,7 +36,7 @@ export default {
|
|
|
36
36
|
|
|
37
37
|
computed: {
|
|
38
38
|
showVersionSelector() {
|
|
39
|
-
return this.
|
|
39
|
+
return this.versionOptions?.length > 1;
|
|
40
40
|
},
|
|
41
41
|
|
|
42
42
|
versionOptions() {
|
|
@@ -44,8 +44,8 @@ export default {
|
|
|
44
44
|
return [];
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
// Don't allow update/rollback to
|
|
48
|
-
const versions = this.plugin
|
|
47
|
+
// Don't allow update/rollback to current version
|
|
48
|
+
const versions = this.plugin?.installableVersions?.filter((v) => {
|
|
49
49
|
if (this.currentVersion) {
|
|
50
50
|
return v.version !== this.currentVersion;
|
|
51
51
|
}
|
|
@@ -78,12 +78,12 @@ export default {
|
|
|
78
78
|
this.currentVersion = plugin.displayVersion;
|
|
79
79
|
|
|
80
80
|
// Update to latest version, so take the first version
|
|
81
|
-
if (plugin.
|
|
82
|
-
this.version = plugin.
|
|
81
|
+
if (plugin.installableVersions?.length > 0) {
|
|
82
|
+
this.version = plugin.installableVersions?.[0]?.version;
|
|
83
83
|
}
|
|
84
84
|
} else if (mode === 'rollback') {
|
|
85
85
|
// Find the newest version once we remove the current version
|
|
86
|
-
const versionNames = plugin.
|
|
86
|
+
const versionNames = plugin.installableVersions.filter(v => v.version !== plugin.displayVersion);
|
|
87
87
|
|
|
88
88
|
this.currentVersion = plugin.displayVersion;
|
|
89
89
|
|
|
@@ -93,10 +93,10 @@ export default {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// Make sure we have the version available
|
|
96
|
-
const versionChart = plugin.
|
|
96
|
+
const versionChart = plugin.installableVersions?.find(v => v.version === this.version);
|
|
97
97
|
|
|
98
98
|
if (!versionChart) {
|
|
99
|
-
this.version = plugin.
|
|
99
|
+
this.version = plugin.installableVersions?.[0]?.version;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
this.busy = false;
|
|
@@ -63,17 +63,19 @@ export default {
|
|
|
63
63
|
},
|
|
64
64
|
|
|
65
65
|
async loadPluginVersionInfo(version) {
|
|
66
|
-
this.versionError = false;
|
|
67
|
-
this.versionInfo = undefined;
|
|
68
|
-
|
|
69
66
|
const versionName = version || this.info.displayVersion;
|
|
70
67
|
|
|
71
|
-
this.
|
|
68
|
+
const isVersionNotCompatibleWithUi = this.info.versions?.find(v => v.version === versionName && !v.isCompatibleWithUi);
|
|
72
69
|
|
|
73
|
-
if (!this.info.chart) {
|
|
70
|
+
if (!this.info.chart || isVersionNotCompatibleWithUi) {
|
|
74
71
|
return;
|
|
75
72
|
}
|
|
76
73
|
|
|
74
|
+
this.infoVersion = versionName;
|
|
75
|
+
|
|
76
|
+
this.versionError = false;
|
|
77
|
+
this.versionInfo = undefined;
|
|
78
|
+
|
|
77
79
|
try {
|
|
78
80
|
this.versionInfo = await this.$store.dispatch('catalog/getVersionInfo', {
|
|
79
81
|
repoType: this.info.chart.repoType,
|
|
@@ -204,8 +206,9 @@ export default {
|
|
|
204
206
|
:key="v.version"
|
|
205
207
|
>
|
|
206
208
|
<a
|
|
209
|
+
v-tooltip="v.requiredUiVersion ? t('plugins.info.requiresVersion', { version: v.requiredUiVersion }) : ''"
|
|
207
210
|
class="version-link"
|
|
208
|
-
:class="{'version-active': v.version === infoVersion}"
|
|
211
|
+
:class="{'version-active': v.version === infoVersion, 'disabled': !v.isCompatibleWithUi}"
|
|
209
212
|
@click="loadPluginVersionInfo(v.version)"
|
|
210
213
|
>
|
|
211
214
|
{{ v.version }}
|
|
@@ -337,6 +340,7 @@ export default {
|
|
|
337
340
|
|
|
338
341
|
.plugin-versions {
|
|
339
342
|
display: flex;
|
|
343
|
+
flex-wrap: wrap;
|
|
340
344
|
}
|
|
341
345
|
|
|
342
346
|
.plugin-description {
|
|
@@ -349,13 +353,22 @@ export default {
|
|
|
349
353
|
padding: 2px 8px;
|
|
350
354
|
border-radius: 5px;
|
|
351
355
|
user-select: none;
|
|
352
|
-
margin
|
|
356
|
+
margin: 0 5px 5px 0;
|
|
357
|
+
display: block;
|
|
353
358
|
|
|
354
359
|
&.version-active {
|
|
355
360
|
color: var(--link-text);
|
|
356
361
|
background: var(--link);
|
|
357
362
|
}
|
|
358
363
|
|
|
364
|
+
&.disabled {
|
|
365
|
+
cursor: not-allowed;
|
|
366
|
+
color: var(--disabled-text) !important;
|
|
367
|
+
background-color: var(--disabled-bg) !important;
|
|
368
|
+
border-color: var(--disabled-bg) !important;
|
|
369
|
+
text-decoration: none !important;
|
|
370
|
+
}
|
|
371
|
+
|
|
359
372
|
&.version-builtin {
|
|
360
373
|
display: inline-block;
|
|
361
374
|
}
|
|
@@ -5,6 +5,7 @@ import { mapPref, PLUGIN_DEVELOPER } from '@shell/store/prefs';
|
|
|
5
5
|
import { sortBy } from '@shell/utils/sort';
|
|
6
6
|
import { allHash } from '@shell/utils/promise';
|
|
7
7
|
import { CATALOG, UI_PLUGIN, SERVICE } from '@shell/config/types';
|
|
8
|
+
import { getVersionData } from '@shell/config/version';
|
|
8
9
|
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
9
10
|
import { NAME as APP_PRODUCT } from '@shell/config/product/apps';
|
|
10
11
|
import ActionMenu from '@shell/components/ActionMenu';
|
|
@@ -23,6 +24,8 @@ import {
|
|
|
23
24
|
uiPluginAnnotation,
|
|
24
25
|
uiPluginHasAnnotation,
|
|
25
26
|
isSupportedChartVersion,
|
|
27
|
+
isChartVersionAvailableForInstall,
|
|
28
|
+
isChartVersionHigher,
|
|
26
29
|
UI_PLUGIN_NAMESPACE,
|
|
27
30
|
UI_PLUGIN_CHART_ANNOTATIONS
|
|
28
31
|
} from '@shell/config/uiplugins';
|
|
@@ -59,6 +62,7 @@ export default {
|
|
|
59
62
|
hasService: false,
|
|
60
63
|
defaultIcon: require('~shell/assets/images/generic-plugin.svg'),
|
|
61
64
|
reloadRequired: false,
|
|
65
|
+
rancherVersion: getVersionData()?.Version
|
|
62
66
|
};
|
|
63
67
|
},
|
|
64
68
|
|
|
@@ -183,27 +187,39 @@ export default {
|
|
|
183
187
|
// Label can be overridden by chart annotation
|
|
184
188
|
const label = uiPluginAnnotation(UI_PLUGIN_CHART_ANNOTATIONS.DISPLAY_NAME) || chart.chartNameDisplay;
|
|
185
189
|
const item = {
|
|
186
|
-
name:
|
|
190
|
+
name: chart.chartNameDisplay,
|
|
187
191
|
label,
|
|
188
|
-
description:
|
|
189
|
-
id:
|
|
190
|
-
versions:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
certified: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.CERTIFIED, CATALOG_ANNOTATIONS._RANCHER),
|
|
192
|
+
description: chart.chartDescription,
|
|
193
|
+
id: chart.id,
|
|
194
|
+
versions: [],
|
|
195
|
+
installed: false,
|
|
196
|
+
builtin: false,
|
|
197
|
+
experimental: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.EXPERIMENTAL, 'true'),
|
|
198
|
+
certified: uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.CERTIFIED, CATALOG_ANNOTATIONS._RANCHER),
|
|
196
199
|
};
|
|
197
200
|
|
|
198
|
-
this.latest = chart.versions[0];
|
|
199
201
|
item.versions = [...chart.versions];
|
|
200
202
|
item.chart = chart;
|
|
201
203
|
|
|
202
|
-
// Filter the versions
|
|
203
|
-
item.
|
|
204
|
+
// Filter the versions available to install (plugins-api version and current dashboard version)
|
|
205
|
+
item.installableVersions = item.versions.filter(version => isSupportedChartVersion(version) && isChartVersionAvailableForInstall(version, this.rancherVersion));
|
|
204
206
|
|
|
205
|
-
if
|
|
206
|
-
|
|
207
|
+
// add prop to version object if version is compatible with the current dashboard version
|
|
208
|
+
item.versions = item.versions.map(version => isChartVersionAvailableForInstall(version, this.rancherVersion, true));
|
|
209
|
+
|
|
210
|
+
const latestCompatible = item.installableVersions?.[0];
|
|
211
|
+
const latestNotCompatible = item.versions.find(version => !version.isCompatibleWithUi);
|
|
212
|
+
|
|
213
|
+
if (latestCompatible) {
|
|
214
|
+
item.displayVersion = latestCompatible.version;
|
|
215
|
+
item.icon = latestCompatible.icon;
|
|
216
|
+
} else {
|
|
217
|
+
item.displayVersion = item.versions?.[0]?.version;
|
|
218
|
+
item.icon = chart.icon || latestCompatible.annotations['catalog.cattle.io/ui-icon'];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (latestNotCompatible && item.installableVersions.length && isChartVersionHigher(latestNotCompatible.version, item.installableVersions?.[0].version)) {
|
|
222
|
+
item.incompatibleDisclaimer = this.t('plugins.incompatibleDisclaimer', { version: latestNotCompatible.version, rancherVersion: latestNotCompatible.requiredUiVersion }, true);
|
|
207
223
|
}
|
|
208
224
|
|
|
209
225
|
if (this.installing[item.name]) {
|
|
@@ -253,8 +269,8 @@ export default {
|
|
|
253
269
|
chart.installing = this.installing[chart.name];
|
|
254
270
|
|
|
255
271
|
// Check for upgrade
|
|
256
|
-
if (chart.
|
|
257
|
-
chart.upgrade = chart.
|
|
272
|
+
if (chart.installableVersions?.length && p.version !== chart.installableVersions?.[0]?.version) {
|
|
273
|
+
chart.upgrade = chart.installableVersions[0].version;
|
|
258
274
|
}
|
|
259
275
|
} else {
|
|
260
276
|
// No chart, so add a card for the plugin based on its Custom resource being present
|
|
@@ -619,6 +635,7 @@ export default {
|
|
|
619
635
|
:data-testid="`extension-card-${plugin.name}`"
|
|
620
636
|
@click="showPluginDetail(plugin)"
|
|
621
637
|
>
|
|
638
|
+
<!-- plugin icon -->
|
|
622
639
|
<div
|
|
623
640
|
class="plugin-icon"
|
|
624
641
|
:class="applyDarkModeBg"
|
|
@@ -636,7 +653,9 @@ export default {
|
|
|
636
653
|
class="icon plugin-icon-img"
|
|
637
654
|
>
|
|
638
655
|
</div>
|
|
656
|
+
<!-- plugin card -->
|
|
639
657
|
<div class="plugin-metadata">
|
|
658
|
+
<!-- plugin basic info -->
|
|
640
659
|
<div class="plugin-name">
|
|
641
660
|
{{ plugin.label }}
|
|
642
661
|
</div>
|
|
@@ -654,8 +673,13 @@ export default {
|
|
|
654
673
|
v-if="plugin.upgrade"
|
|
655
674
|
v-tooltip="t('plugins.upgradeAvailable')"
|
|
656
675
|
> -> {{ plugin.upgrade }}</span>
|
|
676
|
+
<p
|
|
677
|
+
v-if="plugin.incompatibleDisclaimer"
|
|
678
|
+
class="incompatible"
|
|
679
|
+
>{{ plugin.incompatibleDisclaimer }}</p>
|
|
657
680
|
</span>
|
|
658
681
|
</div>
|
|
682
|
+
<!-- plugin badges -->
|
|
659
683
|
<div
|
|
660
684
|
v-if="plugin.builtin"
|
|
661
685
|
class="plugin-badges"
|
|
@@ -682,6 +706,7 @@ export default {
|
|
|
682
706
|
</div>
|
|
683
707
|
</div>
|
|
684
708
|
<div class="plugin-spacer" />
|
|
709
|
+
<!-- plugin badges -->
|
|
685
710
|
<div class="plugin-actions">
|
|
686
711
|
<template v-if="plugin.error">
|
|
687
712
|
<div
|
|
@@ -691,6 +716,7 @@ export default {
|
|
|
691
716
|
<i class="icon icon-warning" />
|
|
692
717
|
</div>
|
|
693
718
|
</template>
|
|
719
|
+
<!-- plugin status -->
|
|
694
720
|
<div
|
|
695
721
|
v-if="plugin.helmError"
|
|
696
722
|
v-tooltip="t('plugins.helmError')"
|
|
@@ -713,6 +739,7 @@ export default {
|
|
|
713
739
|
{{ t('plugins.labels.uninstalling') }}
|
|
714
740
|
</div>
|
|
715
741
|
</div>
|
|
742
|
+
<!-- plugin buttons -->
|
|
716
743
|
<div
|
|
717
744
|
v-else-if="plugin.installed"
|
|
718
745
|
class="plugin-buttons"
|
|
@@ -734,7 +761,7 @@ export default {
|
|
|
734
761
|
{{ t('plugins.update.label') }}
|
|
735
762
|
</button>
|
|
736
763
|
<button
|
|
737
|
-
v-if="!plugin.upgrade && plugin.
|
|
764
|
+
v-if="!plugin.upgrade && plugin.installableVersions && plugin.installableVersions.length > 1"
|
|
738
765
|
class="btn role-secondary"
|
|
739
766
|
:data-testid="`extension-card-rollback-btn-${plugin.name}`"
|
|
740
767
|
@click="showInstallDialog(plugin, 'rollback', $event)"
|
|
@@ -942,6 +969,11 @@ export default {
|
|
|
942
969
|
height: 16px;
|
|
943
970
|
width: 16px;
|
|
944
971
|
}
|
|
972
|
+
|
|
973
|
+
.incompatible {
|
|
974
|
+
margin: 10px 0;
|
|
975
|
+
font-weight: bold;
|
|
976
|
+
}
|
|
945
977
|
}
|
|
946
978
|
|
|
947
979
|
.plugin-installing {
|
package/pages/home.vue
CHANGED
|
@@ -38,8 +38,13 @@ export default {
|
|
|
38
38
|
mixins: [PageHeaderActions],
|
|
39
39
|
|
|
40
40
|
fetch() {
|
|
41
|
-
this.$store.
|
|
42
|
-
|
|
41
|
+
if ( this.$store.getters['management/schemaFor'](CAPI.RANCHER_CLUSTER) ) {
|
|
42
|
+
this.$store.dispatch('management/findAll', { type: CAPI.RANCHER_CLUSTER });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if ( this.$store.getters['management/schemaFor'](MANAGEMENT.CLUSTER) ) {
|
|
46
|
+
this.$store.dispatch('management/findAll', { type: MANAGEMENT.CLUSTER });
|
|
47
|
+
}
|
|
43
48
|
|
|
44
49
|
if ( this.$store.getters['management/canList'](CAPI.MACHINE) ) {
|
|
45
50
|
this.$store.dispatch('management/findAll', { type: CAPI.MACHINE });
|
|
@@ -307,7 +312,7 @@ export default {
|
|
|
307
312
|
<a
|
|
308
313
|
class="hand"
|
|
309
314
|
@click.prevent.stop="showWhatsNew"
|
|
310
|
-
><span v-html="t('landing.whatsNewLink')" /></a>
|
|
315
|
+
><span v-clean-html="t('landing.whatsNewLink')" /></a>
|
|
311
316
|
</Banner>
|
|
312
317
|
</div>
|
|
313
318
|
</div>
|
|
@@ -330,7 +335,7 @@ export default {
|
|
|
330
335
|
<a
|
|
331
336
|
class="hand mr-20"
|
|
332
337
|
@click.prevent.stop="showUserPrefs"
|
|
333
|
-
><span v-html="t('landing.landingPrefs.userPrefs')" /></a>
|
|
338
|
+
><span v-clean-html="t('landing.landingPrefs.userPrefs')" /></a>
|
|
334
339
|
</Banner>
|
|
335
340
|
</div>
|
|
336
341
|
</div>
|
package/pages/index.vue
CHANGED
|
@@ -7,7 +7,9 @@ const validRoute = (route, router) => {
|
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export default {
|
|
10
|
-
middleware({
|
|
10
|
+
middleware({
|
|
11
|
+
redirect, store, app, route
|
|
12
|
+
} ) {
|
|
11
13
|
const seenWhatsNew = store.getters['prefs/get'](SEEN_WHATS_NEW);
|
|
12
14
|
const versionInfo = getVersionInfo(store);
|
|
13
15
|
const isSingleProduct = store.getters['isSingleProduct'];
|
|
@@ -19,6 +21,13 @@ export default {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
const afterLoginRouteObject = store.getters['prefs/afterLoginRoute'];
|
|
24
|
+
const targetRoute = app.router.resolve(afterLoginRouteObject);
|
|
25
|
+
|
|
26
|
+
// If target route is /, then we will loop with endless redirect - so detect that here and
|
|
27
|
+
// redirect to /home, which is what we would do below, if there was no `afterLoginRouteObject`
|
|
28
|
+
if (targetRoute?.route?.fullPath === '/') {
|
|
29
|
+
return redirect(dashboardHome);
|
|
30
|
+
}
|
|
22
31
|
|
|
23
32
|
// Confirm this is a valid route (it could have come from an uninstalled plugin)
|
|
24
33
|
if (validRoute(afterLoginRouteObject, app.router)) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import Vue from 'vue';
|
|
2
|
+
import DOMPurify from 'dompurify';
|
|
3
|
+
|
|
4
|
+
const ALLOWED_TAGS = [
|
|
5
|
+
'code',
|
|
6
|
+
'li',
|
|
7
|
+
'a',
|
|
8
|
+
'p',
|
|
9
|
+
'b',
|
|
10
|
+
'br',
|
|
11
|
+
'ul',
|
|
12
|
+
'pre',
|
|
13
|
+
'span',
|
|
14
|
+
'div',
|
|
15
|
+
'i',
|
|
16
|
+
'em',
|
|
17
|
+
'strong',
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const purifyHTML = value => DOMPurify.sanitize(value, { ALLOWED_TAGS });
|
|
21
|
+
|
|
22
|
+
export const cleanHtmlDirective = {
|
|
23
|
+
inserted(el, binding) {
|
|
24
|
+
el.innerHTML = purifyHTML(binding.value);
|
|
25
|
+
},
|
|
26
|
+
componentUpdated(el, binding) {
|
|
27
|
+
el.innerHTML = purifyHTML(binding.value);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
Vue.directive('clean-html', cleanHtmlDirective);
|