@rancher/shell 3.0.12-rc.4 → 3.0.12-rc.6
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/apis/intf/resources-api/resource-base.ts +42 -2
- package/apis/intf/resources-api/resource-instance.ts +101 -0
- package/apis/intf/resources-api/resources-api.ts +177 -23
- package/apis/intf/resources.ts +8 -6
- package/apis/resources/__tests__/resources-api-class.test.ts +309 -28
- package/apis/resources/resources-api-class.ts +232 -43
- package/assets/images/providers/traefik.png +0 -0
- package/assets/styles/global/_button.scss +1 -1
- package/assets/translations/en-us.yaml +49 -14
- package/chart/__tests__/rancher-monitoring-dashboards-index.test.ts +269 -0
- package/chart/rancher-monitoring-dashboards/index.vue +155 -0
- package/cloud-credential/__tests__/generic.test.ts +132 -0
- package/cloud-credential/generic.vue +33 -3
- package/components/ActionDropdownShell.vue +5 -3
- package/components/ButtonGroup.vue +26 -1
- package/components/CruResource.vue +51 -2
- package/components/EtcdInfoBanner.vue +2 -12
- package/components/GrafanaDashboard.vue +2 -8
- package/components/PromptRestore.vue +93 -32
- package/components/Questions/index.vue +1 -0
- package/components/Resource/Detail/Masthead/__tests__/index.test.ts +68 -14
- package/components/Resource/Detail/Masthead/index.vue +8 -3
- package/components/ResourceTable.vue +1 -0
- package/components/SortableTable/index.vue +4 -3
- package/components/Wizard.vue +14 -1
- package/components/__tests__/ButtonGroup.test.ts +56 -0
- package/components/__tests__/PromptRestore.test.ts +169 -19
- package/components/fleet/GitRepoAdvancedTab.vue +1 -0
- package/components/fleet/GitRepoMetadataTab.vue +5 -0
- package/components/fleet/HelmOpAppCoConfigTab.vue +4 -0
- package/components/fleet/HelmOpMetadataTab.vue +5 -0
- package/components/form/FileSelector.vue +39 -1
- package/components/form/PrivateRegistry.constants.ts +7 -0
- package/components/form/PrivateRegistry.vue +253 -18
- package/components/form/Security.vue +1 -1
- package/components/form/SelectOrCreateAuthSecret.vue +140 -17
- package/components/form/__tests__/FileSelector.test.ts +23 -0
- package/components/form/__tests__/PrivateRegistry.test.ts +463 -73
- package/components/form/__tests__/SelectOrCreateAuthSecret.test.ts +122 -0
- package/components/formatter/EtcdSnapshotName.vue +73 -0
- package/components/formatter/Translate.vue +22 -1
- package/components/nav/Group.vue +5 -10
- package/components/nav/Header.vue +8 -1
- package/components/nav/TopLevelMenu.vue +1 -30
- package/components/nav/__tests__/Group.test.ts +61 -0
- package/components/templates/default.vue +7 -0
- package/config/features.js +1 -0
- package/config/labels-annotations.js +3 -0
- package/config/product/manager.js +6 -0
- package/config/secret.ts +10 -0
- package/config/settings.ts +6 -2
- package/config/table-headers.js +5 -2
- package/config/types.js +7 -0
- package/core/__tests__/plugin-products-apply.test.ts +787 -0
- package/core/__tests__/plugin-products-extend.test.ts +189 -0
- package/core/__tests__/plugin-products-helpers.test.ts +81 -78
- package/core/__tests__/plugin-products-new.test.ts +389 -0
- package/core/__tests__/plugin-products-scenarios.test.ts +980 -0
- package/core/__tests__/plugin-products-side-menu.test.ts +1935 -0
- package/core/plugin-products-base.ts +201 -93
- package/core/plugin-products-extending.ts +1 -1
- package/core/plugin-products-external.ts +380 -0
- package/core/plugin-products-helpers.ts +28 -24
- package/core/plugin-products-internal.ts +207 -0
- package/core/plugin-products-top-level.ts +10 -5
- package/core/plugin-products-type-guards.ts +17 -6
- package/core/plugin-products.ts +5 -7
- package/core/plugin-types.ts +1 -389
- package/core/plugin.ts +10 -11
- package/core/types.ts +6 -202
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +52 -0
- package/detail/pod.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +79 -5
- package/dialog/RotateEncryptionKeyDialog.vue +33 -9
- package/dialog/__tests__/RotateEncryptionKeyDialog.test.ts +78 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +92 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +101 -0
- package/edit/__tests__/management.cattle.io.setting.test.ts +2 -1
- package/edit/auth/AuthProviderWarningBanners.vue +12 -0
- package/edit/auth/__tests__/AuthProviderWarningBanners.test.ts +10 -1
- package/edit/auth/__tests__/azuread.test.ts +1 -0
- package/edit/auth/__tests__/github.test.ts +1 -0
- package/edit/auth/__tests__/oidc.test.ts +1 -0
- package/edit/auth/__tests__/saml.test.ts +1 -0
- package/edit/auth/ldap/__tests__/index.test.ts +1 -0
- package/edit/compliance.cattle.io.clusterscanprofile.vue +39 -41
- package/edit/fleet.cattle.io.gitrepo.vue +70 -16
- package/edit/fleet.cattle.io.helmop.vue +51 -5
- package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
- package/edit/{management.cattle.io.setting.vue → management.cattle.io.setting/index.vue} +32 -9
- package/edit/management.cattle.io.setting/system-default-registry-pull-secrets.vue +81 -0
- package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +3 -12
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +18 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +6 -2
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +0 -1
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +14 -55
- package/list/management.cattle.io.user.vue +24 -5
- package/list/utils/management.cattle.io.cluster.utils.ts +1 -1
- package/machine-config/__tests__/generic.test.ts +163 -0
- package/machine-config/components/EC2Networking.vue +31 -7
- package/machine-config/components/__tests__/EC2Networking.test.ts +38 -15
- package/machine-config/generic.vue +32 -5
- package/mixins/resource-fetch.js +1 -1
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +156 -0
- package/models/__tests__/rke-machine.cattle.io.vmwarevspheremachinetemplate.test.ts +22 -0
- package/models/__tests__/secret.test.ts +68 -1
- package/models/management.cattle.io.cluster.js +21 -3
- package/models/pod.js +25 -12
- package/models/provisioning.cattle.io.cluster.js +59 -9
- package/models/rke-machine.cattle.io.vmwarevspheremachinetemplate.js +9 -0
- package/models/rke.cattle.io.etcdsnapshot.js +17 -9
- package/models/secret.js +19 -0
- package/models/workload.js +12 -7
- package/package.json +1 -1
- package/pages/auth/login.vue +1 -1
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +569 -81
- package/pages/c/_cluster/apps/charts/install.vue +143 -28
- package/pages/c/_cluster/auth/config/index.vue +11 -4
- package/pages/c/_cluster/monitoring/index.vue +6 -1
- package/pkg/require-asset.lib.js +25 -0
- package/pkg/vue.config.js +7 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +84 -0
- package/plugins/dashboard-store/getters.js +0 -1
- package/plugins/dashboard-store/resource-class.js +62 -15
- package/plugins/steve/__tests__/steve-class-resource-api.test.ts +147 -0
- package/plugins/steve/steve-class.js +43 -0
- package/plugins/steve/subscribe.js +11 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +115 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +83 -3
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +30 -0
- package/rancher-components/Form/TextArea/__tests__/TextAreaAutoGrow.test.ts +95 -0
- package/rancher-components/RcButton/index.ts +1 -1
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +6 -1
- package/store/__tests__/auth.test.ts +18 -0
- package/store/__tests__/features.test.ts +131 -0
- package/store/__tests__/growl.test.ts +374 -0
- package/store/__tests__/modal.test.ts +131 -0
- package/store/__tests__/notifications.test.ts +466 -1
- package/store/__tests__/slideInPanel.test.ts +88 -0
- package/store/__tests__/type-map.utils.test.ts +433 -0
- package/store/__tests__/ui-context.test.ts +255 -0
- package/store/auth.js +11 -1
- package/store/features.js +5 -0
- package/store/plugins.js +6 -0
- package/types/rancher/steve.api.ts +2 -2
- package/types/shell/index.d.ts +120 -0
- package/types/store/dashboard-store.types.ts +2 -2
- package/types/store/type-map.ts +262 -1
- package/utils/__tests__/operation-cr.test.ts +34 -0
- package/utils/async.ts +2 -0
- package/utils/grafana.js +2 -17
- package/utils/monitoring.js +38 -1
- package/utils/operation-cr.js +19 -0
- package/utils/require-asset.ts +7 -0
- package/utils/validators/__tests__/private-registry.test.ts +27 -15
- package/utils/validators/private-registry.ts +15 -4
- package/core/__tests__/plugin-products.test.ts +0 -4694
package/utils/grafana.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { haveV2Monitoring } from '@shell/utils/monitoring';
|
|
1
|
+
import { haveV2Monitoring, fetchMonitoringVersion } from '@shell/utils/monitoring';
|
|
2
2
|
import { parse as parseUrl, addParam } from '@shell/utils/url';
|
|
3
|
-
import { CATALOG } from '@shell/config/types';
|
|
4
3
|
|
|
5
4
|
// these two versions of monitoring included a bug fix attempt that required the local cluster to use a different url
|
|
6
5
|
// the solution going forward doesn't require this, see https://github.com/rancher/dashboard/issues/8885
|
|
@@ -60,21 +59,7 @@ export async function dashboardExists(monitoringVersion, store, clusterId, embed
|
|
|
60
59
|
}
|
|
61
60
|
|
|
62
61
|
export async function allDashboardsExist(store, clusterId, embeddedUrls, storeName = 'cluster', projectId = null) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
let monitoringVersion = '';
|
|
66
|
-
|
|
67
|
-
if (!projectId && store.getters[`${ storeName }/canList`](CATALOG.APP)) {
|
|
68
|
-
try {
|
|
69
|
-
res = await store.dispatch(`${ storeName }/find`, {
|
|
70
|
-
type: CATALOG.APP,
|
|
71
|
-
id: 'cattle-monitoring-system/rancher-monitoring'
|
|
72
|
-
});
|
|
73
|
-
} catch (err) {
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
monitoringVersion = res?.currentVersion;
|
|
77
|
-
}
|
|
62
|
+
const monitoringVersion = projectId ? '' : await fetchMonitoringVersion(store, storeName);
|
|
78
63
|
|
|
79
64
|
const existPromises = embeddedUrls.map((url) => dashboardExists(monitoringVersion, store, clusterId, url, storeName, projectId));
|
|
80
65
|
|
package/utils/monitoring.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Helpers for determining if V2 or v1 Monitoring are installed
|
|
2
2
|
|
|
3
|
-
import { SCHEMA, MONITORING, ENDPOINTS } from '@shell/config/types';
|
|
3
|
+
import { SCHEMA, MONITORING, ENDPOINTS, CATALOG } from '@shell/config/types';
|
|
4
4
|
import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
|
|
5
5
|
import { findBy } from '@shell/utils/array';
|
|
6
6
|
import { isEmpty } from '@shell/utils/object';
|
|
@@ -30,6 +30,43 @@ export function haveV2Monitoring(getters) {
|
|
|
30
30
|
|
|
31
31
|
export const CATTLE_MONITORING_NAMESPACE = 'cattle-monitoring-system';
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Look up the installed Rancher monitoring app, preferring the new
|
|
35
|
+
* `rancher-monitoring-dashboards` chart and falling back to the legacy
|
|
36
|
+
* `rancher-monitoring`. Returns null if the user lacks permission, neither
|
|
37
|
+
* chart is installed, or any lookup fails.
|
|
38
|
+
*/
|
|
39
|
+
export async function fetchMonitoringApp(store, storeName) {
|
|
40
|
+
if (!store.getters[`${ storeName }/canList`](CATALOG.APP)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const ids = [
|
|
45
|
+
`${ CATTLE_MONITORING_NAMESPACE }/rancher-monitoring-dashboards`,
|
|
46
|
+
`${ CATTLE_MONITORING_NAMESPACE }/rancher-monitoring`,
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
for (const id of ids) {
|
|
50
|
+
try {
|
|
51
|
+
const res = await store.dispatch(`${ storeName }/find`, { type: CATALOG.APP, id });
|
|
52
|
+
|
|
53
|
+
if (res) {
|
|
54
|
+
return res;
|
|
55
|
+
}
|
|
56
|
+
} catch (err) {
|
|
57
|
+
// Try the next id; both failing means nothing is installed.
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export async function fetchMonitoringVersion(store, storeName) {
|
|
65
|
+
const app = await fetchMonitoringApp(store, storeName);
|
|
66
|
+
|
|
67
|
+
return app?.currentVersion || '';
|
|
68
|
+
}
|
|
69
|
+
|
|
33
70
|
async function hasEndpointSubsets(store, id) {
|
|
34
71
|
if (store.getters['cluster/schemaFor'](ENDPOINTS)) {
|
|
35
72
|
const endpoints = await store.dispatch('cluster/findAll', { type: ENDPOINTS }) || [];
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a day 2 operation CR for imported clusters.
|
|
3
|
+
*
|
|
4
|
+
* @param {Function} dispatch - The Vuex dispatch function
|
|
5
|
+
* @param {string} type - The operation CRD type
|
|
6
|
+
* @param {object} spec - The operation spec
|
|
7
|
+
* @param {string} namespace - The namespace for the operation CR
|
|
8
|
+
* @param {string} namePrefix - The name prefix for the generated name
|
|
9
|
+
* @returns {Promise} The saved resource
|
|
10
|
+
*/
|
|
11
|
+
export async function createOperationCR(dispatch, type, spec, namespace, namePrefix) {
|
|
12
|
+
const resource = await dispatch('management/create', {
|
|
13
|
+
type,
|
|
14
|
+
metadata: { namespace, generateName: `${ namePrefix }-` },
|
|
15
|
+
spec,
|
|
16
|
+
}, { root: true });
|
|
17
|
+
|
|
18
|
+
return resource.save();
|
|
19
|
+
}
|
package/utils/require-asset.ts
CHANGED
|
@@ -88,6 +88,13 @@ export function requireJson(path: string): object {
|
|
|
88
88
|
return mod.default || mod;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// Expose asset resolvers on window so extension builds (which use a stub
|
|
92
|
+
// instead of require.context) can delegate to the host dashboard at runtime.
|
|
93
|
+
if (typeof window !== 'undefined') {
|
|
94
|
+
(window as any).__shell_requireAsset = requireAsset;
|
|
95
|
+
(window as any).__shell_requireJson = requireJson;
|
|
96
|
+
}
|
|
97
|
+
|
|
91
98
|
// Exported for testing — allows injecting mock contexts
|
|
92
99
|
export function _setContexts(img: WebpackRequireContext | null, json: WebpackRequireContext | null): void {
|
|
93
100
|
imgCtx = img;
|
|
@@ -3,28 +3,22 @@ import { privateRegistryRequired } from '@shell/utils/validators/private-registr
|
|
|
3
3
|
const makeCtx = (overrides: any = {}) => ({
|
|
4
4
|
t: jest.fn((key: string, params?: any) => (params ? `${ key }:${ JSON.stringify(params) }` : key)),
|
|
5
5
|
privateRegistryEnabled: false,
|
|
6
|
-
normanCluster: { importedConfig: {
|
|
7
|
-
|
|
6
|
+
normanCluster: { importedConfig: {} },
|
|
7
|
+
$store: { getters: { 'management/byId': () => null } },
|
|
8
8
|
...overrides,
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
it('should return undefined when the cluster is not imported', () => {
|
|
13
|
-
const ctx = makeCtx({ isImportedCluster: false, privateRegistryEnabled: true });
|
|
14
|
-
const rule = privateRegistryRequired(ctx);
|
|
15
|
-
|
|
16
|
-
expect(rule()).toBeUndefined();
|
|
17
|
-
});
|
|
11
|
+
const storeWithGlobalRegistry = { getters: { 'management/byId': () => ({ value: 'registry.global.io' }) } };
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
describe('privateRegistryRequired', () => {
|
|
14
|
+
it('should return undefined when a global default registry is configured', () => {
|
|
15
|
+
const ctx = makeCtx({
|
|
22
16
|
privateRegistryEnabled: true,
|
|
23
|
-
|
|
24
|
-
};
|
|
17
|
+
$store: storeWithGlobalRegistry,
|
|
18
|
+
});
|
|
25
19
|
const rule = privateRegistryRequired(ctx);
|
|
26
20
|
|
|
27
|
-
expect(rule()).
|
|
21
|
+
expect(rule()).toBeUndefined();
|
|
28
22
|
});
|
|
29
23
|
|
|
30
24
|
it('should return undefined when the registry toggle is off', () => {
|
|
@@ -73,4 +67,22 @@ describe('privateRegistryRequired', () => {
|
|
|
73
67
|
|
|
74
68
|
expect(rule()).toBeUndefined();
|
|
75
69
|
});
|
|
70
|
+
|
|
71
|
+
it('should handle $store getter throwing gracefully', () => {
|
|
72
|
+
const ctx = makeCtx({
|
|
73
|
+
privateRegistryEnabled: true,
|
|
74
|
+
normanCluster: { importedConfig: {} },
|
|
75
|
+
$store: {
|
|
76
|
+
getters: {
|
|
77
|
+
get 'management/byId'() {
|
|
78
|
+
throw new Error('no store');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
const rule = privateRegistryRequired(ctx);
|
|
84
|
+
|
|
85
|
+
// Falls through to validation since no global default detected
|
|
86
|
+
expect(rule()).toStrictEqual('validation.required:{"key":"cluster.privateRegistry.label"}');
|
|
87
|
+
});
|
|
76
88
|
});
|
|
@@ -1,19 +1,30 @@
|
|
|
1
|
+
import { VuexStore } from 'types/store/vuex';
|
|
1
2
|
import { Translation } from '@shell/types/t';
|
|
2
3
|
import formRulesGenerator from '@shell/utils/validators/formRules';
|
|
4
|
+
import { SETTING } from '@shell/config/settings';
|
|
5
|
+
import { MANAGEMENT } from '@shell/config/types';
|
|
3
6
|
|
|
4
7
|
interface PrivateRegistryRuleContext {
|
|
5
8
|
t: Translation;
|
|
6
9
|
privateRegistryEnabled: boolean;
|
|
7
10
|
normanCluster: { importedConfig?: { privateRegistryURL?: string | null } } | null;
|
|
8
|
-
|
|
11
|
+
$store: VuexStore
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
export function privateRegistryRequired(ctx: PrivateRegistryRuleContext) {
|
|
12
15
|
return () => {
|
|
13
|
-
|
|
14
|
-
const isImported = 'isImportedCluster' in ctx ? !!ctx.isImportedCluster : true;
|
|
16
|
+
let hasGlobalDefault = false;
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
try {
|
|
19
|
+
// settings are loaded when the dashboard loads so using a synchronous getter is reliable here
|
|
20
|
+
const globalRegistrySetting = ctx.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.SYSTEM_DEFAULT_REGISTRY);
|
|
21
|
+
|
|
22
|
+
hasGlobalDefault = !!globalRegistrySetting?.value;
|
|
23
|
+
} catch {
|
|
24
|
+
// if no setting proceed like there's no global default
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!ctx.privateRegistryEnabled || hasGlobalDefault) {
|
|
17
28
|
return undefined;
|
|
18
29
|
}
|
|
19
30
|
const url = ctx.normanCluster?.importedConfig?.privateRegistryURL;
|