@rancher/shell 3.0.9-rc.5 → 3.0.9-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.
Files changed (142) hide show
  1. package/assets/images/providers/oci-open-containers.svg +22 -0
  2. package/assets/images/providers/traefik.png +0 -0
  3. package/assets/styles/themes/_dark.scss +2 -0
  4. package/assets/styles/themes/_light.scss +2 -0
  5. package/assets/styles/themes/_modern.scss +6 -0
  6. package/assets/translations/en-us.yaml +129 -25
  7. package/components/CruResource.vue +3 -1
  8. package/components/ExplorerProjectsNamespaces.vue +12 -12
  9. package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +109 -0
  10. package/components/Resource/Detail/Card/StatusCard/index.vue +21 -4
  11. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +19 -2
  12. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +19 -11
  13. package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +12 -0
  14. package/components/Resource/Detail/ResourcePopover/index.vue +2 -0
  15. package/components/Resource/Detail/ResourceRow.vue +2 -2
  16. package/components/ResourceList/index.vue +7 -4
  17. package/components/Window/ContainerLogs.vue +48 -37
  18. package/components/fleet/FleetClusterTargets/TargetsList.vue +2 -2
  19. package/components/fleet/FleetClusterTargets/index.vue +6 -1
  20. package/components/fleet/GitRepoAdvancedTab.vue +333 -0
  21. package/components/fleet/GitRepoMetadataTab.vue +43 -0
  22. package/components/fleet/GitRepoRepositoryTab.vue +101 -0
  23. package/components/fleet/GitRepoTargetTab.vue +77 -0
  24. package/components/fleet/HelmOpAdvancedTab.vue +247 -0
  25. package/components/fleet/HelmOpChartTab.vue +158 -0
  26. package/components/fleet/HelmOpMetadataTab.vue +46 -0
  27. package/components/fleet/HelmOpTargetTab.vue +84 -0
  28. package/components/fleet/HelmOpValuesTab.vue +147 -0
  29. package/components/fleet/__tests__/FleetClusterTargets.test.ts +119 -70
  30. package/components/form/NodeScheduling.vue +81 -7
  31. package/components/form/PodAffinity.vue +1 -36
  32. package/components/form/ResourceLabeledSelect.vue +8 -4
  33. package/components/form/ResourceQuota/Namespace.vue +30 -9
  34. package/components/form/ResourceQuota/NamespaceRow.vue +25 -7
  35. package/components/form/ResourceQuota/Project.vue +140 -82
  36. package/components/form/ResourceQuota/ResourceQuotaEntry.vue +145 -0
  37. package/components/form/ResourceQuota/__tests__/Namespace.test.ts +307 -0
  38. package/components/form/ResourceQuota/__tests__/NamespaceRow.test.ts +281 -0
  39. package/components/form/ResourceQuota/__tests__/Project.test.ts +274 -27
  40. package/components/form/ResourceQuota/__tests__/ResourceQuotaEntry.test.ts +215 -0
  41. package/components/form/SchedulingCustomization.vue +14 -6
  42. package/components/form/SelectOrCreateAuthSecret.vue +107 -18
  43. package/components/form/__tests__/NodeScheduling.test.ts +12 -9
  44. package/components/form/__tests__/PodAffinity.test.ts +21 -2
  45. package/components/form/__tests__/SchedulingCustomization.test.ts +240 -0
  46. package/components/formatter/ClusterLink.vue +8 -0
  47. package/components/formatter/SecretOrigin.vue +79 -0
  48. package/config/labels-annotations.js +7 -6
  49. package/config/pagination-table-headers.js +6 -4
  50. package/config/product/explorer.js +1 -11
  51. package/config/query-params.js +3 -0
  52. package/config/settings.ts +15 -2
  53. package/config/table-headers.js +21 -17
  54. package/config/types.js +23 -8
  55. package/detail/workload/index.vue +11 -16
  56. package/dialog/DeactivateDriverDialog.vue +1 -1
  57. package/dialog/Ipv6NetworkingDialog.vue +156 -0
  58. package/dialog/ScalePoolDownDialog.vue +2 -2
  59. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
  60. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +1 -0
  61. package/edit/__tests__/management.cattle.io.project.test.js +56 -128
  62. package/edit/auth/oidc.vue +1 -1
  63. package/edit/catalog.cattle.io.clusterrepo.vue +155 -25
  64. package/edit/fleet.cattle.io.gitrepo.vue +153 -283
  65. package/edit/fleet.cattle.io.helmop.vue +190 -332
  66. package/edit/management.cattle.io.project.vue +5 -42
  67. package/edit/management.cattle.io.setting.vue +6 -0
  68. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +55 -24
  69. package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +1 -103
  70. package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +13 -1
  71. package/edit/provisioning.cattle.io.cluster/__tests__/rke2-fleet-cluster-agent.test.ts +283 -0
  72. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -49
  73. package/edit/provisioning.cattle.io.cluster/ingress/IngressCards.vue +112 -0
  74. package/edit/provisioning.cattle.io.cluster/ingress/IngressConfiguration.vue +158 -0
  75. package/edit/provisioning.cattle.io.cluster/rke2.vue +171 -72
  76. package/edit/provisioning.cattle.io.cluster/shared.ts +36 -1
  77. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +2 -1
  78. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +55 -7
  79. package/edit/provisioning.cattle.io.cluster/tabs/Ingress.vue +319 -0
  80. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +2 -1
  81. package/edit/provisioning.cattle.io.cluster/tabs/etcd/__tests__/S3Config.test.ts +13 -1
  82. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +10 -44
  83. package/edit/secret/index.vue +1 -1
  84. package/edit/token.vue +68 -29
  85. package/edit/workload/__tests__/index.test.ts +2 -37
  86. package/edit/workload/index.vue +6 -2
  87. package/edit/workload/mixins/workload.js +0 -32
  88. package/list/__tests__/management.cattle.io.setting.test.ts +198 -0
  89. package/list/management.cattle.io.setting.vue +13 -0
  90. package/list/provisioning.cattle.io.cluster.vue +50 -1
  91. package/list/secret.vue +4 -9
  92. package/list/service.vue +6 -8
  93. package/machine-config/amazonec2.vue +11 -4
  94. package/machine-config/components/EC2Networking.vue +46 -30
  95. package/machine-config/components/__tests__/EC2Networking.test.ts +7 -7
  96. package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +0 -9
  97. package/machine-config/digitalocean.vue +3 -3
  98. package/models/__tests__/namespace.test.ts +11 -0
  99. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +96 -0
  100. package/models/__tests__/workload.test.ts +42 -1
  101. package/models/catalog.cattle.io.clusterrepo.js +30 -4
  102. package/models/ext.cattle.io.token.js +48 -0
  103. package/models/kontainerdriver.js +2 -2
  104. package/models/namespace.js +7 -1
  105. package/models/nodedriver.js +2 -2
  106. package/models/provisioning.cattle.io.cluster.js +28 -7
  107. package/models/secret.js +0 -17
  108. package/models/service.js +44 -1
  109. package/models/token.js +4 -0
  110. package/models/workload.js +12 -6
  111. package/package.json +1 -1
  112. package/pages/account/index.vue +96 -67
  113. package/pages/auth/setup.vue +5 -14
  114. package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +4 -1
  115. package/pages/c/_cluster/apps/charts/index.vue +93 -4
  116. package/pages/c/_cluster/apps/charts/install.vue +317 -42
  117. package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -4
  118. package/pages/c/_cluster/settings/index.vue +3 -1
  119. package/plugins/dashboard-store/__tests__/getters.test.ts +108 -0
  120. package/plugins/dashboard-store/__tests__/resource-class.test.ts +27 -0
  121. package/plugins/dashboard-store/actions.js +3 -8
  122. package/plugins/dashboard-store/getters.js +7 -5
  123. package/plugins/dashboard-store/mutations.js +4 -1
  124. package/plugins/dashboard-store/resource-class.js +3 -3
  125. package/plugins/steve/__tests__/steve-class.test.ts +102 -141
  126. package/plugins/steve/steve-class.js +12 -3
  127. package/plugins/steve/steve-pagination-utils.ts +6 -2
  128. package/rancher-components/RcIcon/types.ts +2 -0
  129. package/rancher-components/RcItemCard/RcItemCard.vue +64 -19
  130. package/store/prefs.js +3 -0
  131. package/types/aws-sdk.d.ts +121 -0
  132. package/types/resources/node.ts +15 -0
  133. package/types/shell/index.d.ts +536 -506
  134. package/types/store/pagination.types.ts +5 -5
  135. package/utils/__tests__/array.test.ts +1 -29
  136. package/utils/__tests__/cluster-agent-configuration.test.ts +203 -0
  137. package/utils/array.ts +0 -11
  138. package/utils/aws.ts +21 -0
  139. package/utils/cluster.js +22 -2
  140. package/utils/selector-typed.ts +1 -1
  141. package/components/__tests__/ProjectRow.test.ts +0 -206
  142. package/components/form/ResourceQuota/ProjectRow.vue +0 -277
@@ -0,0 +1,240 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { nextTick } from 'vue';
3
+ import SchedulingCustomization from '@shell/components/form/SchedulingCustomization.vue';
4
+ import { AGENT_CONFIGURATION_TYPES } from '@shell/config/settings';
5
+ import { _CREATE, _EDIT } from '@shell/config/query-params';
6
+
7
+ const mockStore = { getters: { 'i18n/t': jest.fn().mockImplementation((key: string) => key) } };
8
+
9
+ const createWrapper = (propsData: any = {}) => {
10
+ return mount(SchedulingCustomization, {
11
+ propsData: {
12
+ type: AGENT_CONFIGURATION_TYPES.CLUSTER,
13
+ feature: true,
14
+ mode: _CREATE,
15
+ defaultPC: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
16
+ defaultPDB: { maxUnavailable: 1 },
17
+ ...propsData
18
+ },
19
+ global: {
20
+ mocks: {
21
+ $store: mockStore,
22
+ t: jest.fn().mockImplementation((key: string) => key)
23
+ }
24
+ }
25
+ });
26
+ };
27
+
28
+ describe('component: SchedulingCustomization - Agent Type Support', () => {
29
+ let wrapper: any;
30
+
31
+ beforeEach(() => {
32
+ jest.clearAllMocks();
33
+ });
34
+
35
+ afterEach(() => {
36
+ if (wrapper) {
37
+ wrapper.unmount();
38
+ }
39
+ });
40
+
41
+ describe('agent Type Prop', () => {
42
+ it('should accept and use CLUSTER agent type', () => {
43
+ wrapper = createWrapper({ type: AGENT_CONFIGURATION_TYPES.CLUSTER });
44
+
45
+ expect(wrapper.vm.type).toBe(AGENT_CONFIGURATION_TYPES.CLUSTER);
46
+ });
47
+
48
+ it('should accept and use FLEET agent type', () => {
49
+ wrapper = createWrapper({ type: AGENT_CONFIGURATION_TYPES.FLEET });
50
+
51
+ expect(wrapper.vm.type).toBe(AGENT_CONFIGURATION_TYPES.FLEET);
52
+ });
53
+
54
+ it('should emit scheduling-customization-changed event with correct agent type for CLUSTER', async() => {
55
+ wrapper = createWrapper({ type: AGENT_CONFIGURATION_TYPES.CLUSTER });
56
+
57
+ const checkbox = wrapper.findComponent('[data-testid="scheduling-customization-checkbox"]');
58
+
59
+ await checkbox.vm.$emit('update:value', true);
60
+
61
+ expect(wrapper.emitted('scheduling-customization-changed')).toBeTruthy();
62
+ expect(wrapper.emitted('scheduling-customization-changed')[0][0]).toStrictEqual({
63
+ event: true,
64
+ agentType: AGENT_CONFIGURATION_TYPES.CLUSTER
65
+ });
66
+ });
67
+
68
+ it('should emit scheduling-customization-changed event with correct agent type for FLEET', async() => {
69
+ wrapper = createWrapper({ type: AGENT_CONFIGURATION_TYPES.FLEET });
70
+
71
+ const checkbox = wrapper.findComponent('[data-testid="scheduling-customization-checkbox"]');
72
+
73
+ await checkbox.vm.$emit('update:value', false);
74
+
75
+ expect(wrapper.emitted('scheduling-customization-changed')).toBeTruthy();
76
+ expect(wrapper.emitted('scheduling-customization-changed')[0][0]).toStrictEqual({
77
+ event: false,
78
+ agentType: AGENT_CONFIGURATION_TYPES.FLEET
79
+ });
80
+ });
81
+ });
82
+
83
+ describe('settings Mismatch Detection', () => {
84
+ it('should detect priority class value mismatch', () => {
85
+ const value = {
86
+ priorityClass: { value: 200, preemptionPolicy: 'PreemptLowerPriority' },
87
+ podDisruptionBudget: { maxUnavailable: 1 }
88
+ };
89
+
90
+ wrapper = createWrapper({
91
+ value,
92
+ defaultPC: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
93
+ mode: _EDIT
94
+ });
95
+
96
+ expect(wrapper.vm.settingMissmatch).toBe(true);
97
+ });
98
+
99
+ it('should detect priority class preemption policy mismatch', () => {
100
+ const value = {
101
+ priorityClass: { value: 100, preemptionPolicy: 'Never' },
102
+ podDisruptionBudget: { maxUnavailable: 1 }
103
+ };
104
+
105
+ wrapper = createWrapper({
106
+ value,
107
+ defaultPC: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
108
+ mode: _EDIT
109
+ });
110
+
111
+ expect(wrapper.vm.settingMissmatch).toBe(true);
112
+ });
113
+
114
+ it('should detect pod disruption budget maxUnavailable mismatch', () => {
115
+ const value = {
116
+ priorityClass: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
117
+ podDisruptionBudget: { maxUnavailable: 2 }
118
+ };
119
+
120
+ wrapper = createWrapper({
121
+ value,
122
+ defaultPDB: { maxUnavailable: 1 },
123
+ mode: _EDIT
124
+ });
125
+
126
+ expect(wrapper.vm.settingMissmatch).toBe(true);
127
+ });
128
+
129
+ it('should detect pod disruption budget minAvailable mismatch', () => {
130
+ const value = {
131
+ priorityClass: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
132
+ podDisruptionBudget: { minAvailable: 2 }
133
+ };
134
+
135
+ wrapper = createWrapper({
136
+ value,
137
+ defaultPDB: { minAvailable: 1 },
138
+ mode: _EDIT
139
+ });
140
+
141
+ expect(wrapper.vm.settingMissmatch).toBe(true);
142
+ });
143
+
144
+ it('should not detect mismatch when values match defaults', () => {
145
+ const value = {
146
+ priorityClass: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
147
+ podDisruptionBudget: { maxUnavailable: 1 }
148
+ };
149
+
150
+ wrapper = createWrapper({
151
+ value,
152
+ defaultPC: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
153
+ defaultPDB: { maxUnavailable: 1 },
154
+ mode: _EDIT
155
+ });
156
+
157
+ expect(wrapper.vm.settingMissmatch).toBe(false);
158
+ });
159
+
160
+ it('should not detect mismatch when no value is provided', () => {
161
+ wrapper = createWrapper({
162
+ value: undefined,
163
+ mode: _EDIT
164
+ });
165
+
166
+ expect(wrapper.vm.settingMissmatch).toBe(false);
167
+ });
168
+ });
169
+
170
+ describe('component State', () => {
171
+ it('should be enabled when value is provided', () => {
172
+ const value = {
173
+ priorityClass: { value: 100 },
174
+ podDisruptionBudget: { maxUnavailable: 1 }
175
+ };
176
+
177
+ wrapper = createWrapper({ value });
178
+
179
+ expect(wrapper.vm.enabled).toBe(true);
180
+ });
181
+
182
+ it('should be disabled when no value is provided', () => {
183
+ wrapper = createWrapper({ value: undefined });
184
+
185
+ expect(wrapper.vm.enabled).toBe(false);
186
+ });
187
+
188
+ it('should detect edit mode correctly', () => {
189
+ wrapper = createWrapper({ mode: _EDIT });
190
+
191
+ expect(wrapper.vm.isEdit).toBe(true);
192
+ });
193
+
194
+ it('should detect create mode correctly', () => {
195
+ wrapper = createWrapper({ mode: _CREATE });
196
+
197
+ expect(wrapper.vm.isEdit).toBe(false);
198
+ });
199
+ });
200
+
201
+ describe('banner Display in Edit Mode', () => {
202
+ it('should show banner when in edit mode and settings mismatch', async() => {
203
+ const value = {
204
+ priorityClass: { value: 200, preemptionPolicy: 'PreemptLowerPriority' },
205
+ podDisruptionBudget: { maxUnavailable: 1 }
206
+ };
207
+
208
+ wrapper = createWrapper({
209
+ value,
210
+ defaultPC: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
211
+ mode: _EDIT,
212
+ feature: true
213
+ });
214
+
215
+ await nextTick();
216
+
217
+ // The banner should be available in the template when conditions are met
218
+ expect(wrapper.vm.settingMissmatch).toBe(true);
219
+ expect(wrapper.vm.isEdit).toBe(true);
220
+ expect(wrapper.vm.feature).toBe(true);
221
+ });
222
+
223
+ it('should not show banner when not in edit mode', () => {
224
+ const value = {
225
+ priorityClass: { value: 200, preemptionPolicy: 'PreemptLowerPriority' },
226
+ podDisruptionBudget: { maxUnavailable: 1 }
227
+ };
228
+
229
+ wrapper = createWrapper({
230
+ value,
231
+ defaultPC: { value: 100, preemptionPolicy: 'PreemptLowerPriority' },
232
+ mode: _CREATE,
233
+ feature: true
234
+ });
235
+
236
+ expect(wrapper.vm.isEdit).toBe(false);
237
+ // Banner should not show because not in edit mode
238
+ });
239
+ });
240
+ });
@@ -15,6 +15,10 @@ export default {
15
15
  reference: {
16
16
  type: String,
17
17
  default: null,
18
+ },
19
+ getCustomDetailLink: {
20
+ type: Function,
21
+ default: null
18
22
  }
19
23
  },
20
24
  computed: {
@@ -23,6 +27,10 @@ export default {
23
27
  return get(this.row, this.reference);
24
28
  }
25
29
 
30
+ if (this.getCustomDetailLink) {
31
+ return this.getCustomDetailLink(this.row);
32
+ }
33
+
26
34
  return this.row?.detailLocation;
27
35
  },
28
36
 
@@ -0,0 +1,79 @@
1
+ <script>
2
+ import { MANAGEMENT } from '@shell/config/types';
3
+ import { STORE } from '@shell/store/store-types';
4
+ import { mapGetters } from 'vuex';
5
+
6
+ export default {
7
+ props: {
8
+ row: {
9
+ type: Object,
10
+ required: true
11
+ },
12
+ },
13
+ async fetch() {
14
+ if (this.row.isProjectScoped && this.currentCluster?.isLocal) {
15
+ const id = this.row.projectScopedClusterId;
16
+
17
+ if (id && !this.$store.getters[`${ STORE.MANAGEMENT }/byId`](MANAGEMENT.CLUSTER, id)) {
18
+ try {
19
+ await this.$store.dispatch(`${ STORE.MANAGEMENT }/find`, { type: MANAGEMENT.CLUSTER, id });
20
+ } catch (e) {
21
+ // Ignore error
22
+ }
23
+ }
24
+ }
25
+ },
26
+ computed: {
27
+ ...mapGetters(['currentCluster']),
28
+ originText() {
29
+ if (this.row.isProjectScoped) {
30
+ return this.t('secret.projectScoped.origin.source');
31
+ } else if (this.row.isProjectSecretCopy) {
32
+ return this.t('secret.projectScoped.origin.copy');
33
+ }
34
+
35
+ return '';
36
+ },
37
+ tooltip() {
38
+ if (this.row.isProjectScoped) {
39
+ const projectName = this.row.project?.nameDisplay || this.row.projectScopedProjectId;
40
+ const clusterName = this.row.projectCluster?.nameDisplay || this.row.projectScopedClusterId;
41
+
42
+ return this.t('secret.projectScoped.tooltip.source', { project: projectName, cluster: clusterName });
43
+ } else if (this.row.isProjectSecretCopy) {
44
+ const projectID = this.row.projectScopedProjectId;
45
+ const clusterId = this.currentCluster?.id;
46
+
47
+ // Try to fetch the project.
48
+ // Note: The management store might not have the project loaded if we haven't visited the cluster list or project list.
49
+ // However, if we are in the dashboard, we usually have projects loaded.
50
+ const project = this.$store.getters[`${ STORE.MANAGEMENT }/byId`](MANAGEMENT.PROJECT, `${ clusterId }/${ projectID }`);
51
+ const projectName = project?.nameDisplay || projectID;
52
+
53
+ return this.t('secret.projectScoped.tooltip.copy', { secret: this.row.nameDisplay, project: projectName });
54
+ }
55
+
56
+ return null;
57
+ }
58
+ }
59
+ };
60
+ </script>
61
+
62
+ <template>
63
+ <div
64
+ v-if="originText"
65
+ v-clean-tooltip="tooltip"
66
+ class="secret-origin"
67
+ >
68
+ {{ originText }}
69
+ </div>
70
+ <div v-else>
71
+
72
+ </div>
73
+ </template>
74
+
75
+ <style lang="scss" scoped>
76
+ .secret-origin {
77
+ white-space: nowrap;
78
+ }
79
+ </style>
@@ -108,12 +108,13 @@ export const CATALOG = {
108
108
  _CLUSTER_TPL: 'cluster-template',
109
109
  _CLUSTER_TOOL: 'cluster-tool',
110
110
 
111
- COMPONENT: 'catalog.cattle.io/ui-component',
112
- SOURCE_REPO_TYPE: 'catalog.cattle.io/ui-source-repo-type',
113
- SOURCE_REPO_NAME: 'catalog.cattle.io/ui-source-repo',
114
- COLOR: 'catalog.cattle.io/ui-color',
115
- DISPLAY_NAME: 'catalog.cattle.io/display-name',
116
- CLUSTER_REPO_NAME: 'catalog.cattle.io/cluster-repo-name',
111
+ COMPONENT: 'catalog.cattle.io/ui-component',
112
+ SOURCE_REPO_TYPE: 'catalog.cattle.io/ui-source-repo-type',
113
+ SOURCE_REPO_NAME: 'catalog.cattle.io/ui-source-repo',
114
+ COLOR: 'catalog.cattle.io/ui-color',
115
+ DISPLAY_NAME: 'catalog.cattle.io/display-name',
116
+ CLUSTER_REPO_NAME: 'catalog.cattle.io/cluster-repo-name',
117
+ SUSE_APP_COLLECTION: 'catalog.cattle.io/suse-application-collection',
117
118
 
118
119
  SUPPORTED_OS: 'catalog.cattle.io/os',
119
120
  PERMITTED_OS: 'catalog.cattle.io/permits-os',
@@ -3,7 +3,7 @@ import {
3
3
  STATE, NAME as NAME_COL, NAMESPACE as NAMESPACE_COL, AGE, OBJECT,
4
4
  EVENT_LAST_SEEN_TIME,
5
5
  EVENT_TYPE,
6
- SECRET_CLONE,
6
+ SECRET_ORIGIN,
7
7
  EVENT_FIRST_SEEN_TIME
8
8
  } from '@shell/config/table-headers';
9
9
 
@@ -89,7 +89,9 @@ export const STEVE_LIST_GROUPS = [{
89
89
  groupLabelKey: 'groupByLabel',
90
90
  }];
91
91
 
92
- export const STEVE_SECRET_CLONE = {
93
- ...SECRET_CLONE,
94
- sort: `metadata.annotations[${ UI_PROJECT_SECRET_COPY }]`,
92
+ export const STEVE_SECRET_ORIGIN = {
93
+ ...SECRET_ORIGIN,
94
+ // We can't sort by the 'UI_PROJECT_SECRET' label (management.cattle.io/project-scoped-secret) due to backend limitations.
95
+ // So we sort by the 'UI_PROJECT_SECRET_COPY' annotation (management.cattle.io/project-scoped-secret-copy) which at least groups the copies.
96
+ sort: `metadata.annotations[${ UI_PROJECT_SECRET_COPY }]:desc`,
95
97
  };
@@ -19,7 +19,7 @@ import {
19
19
  USER_ID, USERNAME, USER_DISPLAY_NAME, USER_PROVIDER, USER_LAST_LOGIN, USER_DISABLED_IN, USER_DELETED_IN, WORKLOAD_ENDPOINTS, STORAGE_CLASS_DEFAULT,
20
20
  STORAGE_CLASS_PROVISIONER, PERSISTENT_VOLUME_SOURCE,
21
21
  HPA_REFERENCE, MIN_REPLICA, MAX_REPLICA, CURRENT_REPLICA,
22
- ACCESS_KEY, DESCRIPTION, EXPIRES, EXPIRY_STATE, LAST_USED, SUB_TYPE, AGE_NORMAN, SCOPE_NORMAN, PERSISTENT_VOLUME_CLAIM, RECLAIM_POLICY, PV_REASON, WORKLOAD_HEALTH_SCALE, POD_RESTARTS,
22
+ DESCRIPTION, SUB_TYPE, PERSISTENT_VOLUME_CLAIM, RECLAIM_POLICY, PV_REASON, WORKLOAD_HEALTH_SCALE, POD_RESTARTS,
23
23
  DURATION, MESSAGE, REASON, EVENT_TYPE, OBJECT, ROLE, ROLES, VERSION, INTERNAL_EXTERNAL_IP, KUBE_NODE_OS, CPU, RAM, SECRET_DATA,
24
24
  EVENT_LAST_SEEN_TIME,
25
25
  EVENT_FIRST_SEEN_TIME,
@@ -546,16 +546,6 @@ export function init(store) {
546
546
  AGE
547
547
  ]);
548
548
 
549
- headers(NORMAN.TOKEN, [
550
- EXPIRY_STATE,
551
- ACCESS_KEY,
552
- DESCRIPTION,
553
- SCOPE_NORMAN,
554
- LAST_USED,
555
- EXPIRES,
556
- AGE_NORMAN
557
- ]);
558
-
559
549
  virtualType({
560
550
  label: store.getters['i18n/t']('clusterIndexPage.header'),
561
551
  group: 'Root',
@@ -94,3 +94,6 @@ export const SECRET_QUERY_PARAMS = {
94
94
  export const SECRET_SCOPE = 'scope';
95
95
  // RANCHER OIDC CLIENT
96
96
  export const RANCHER_AS_OIDC_QUERY_PARAMS = ['scope', 'client_id', 'redirect_uri', 'response_type'];
97
+
98
+ // For REPOSITORIES, to determine which type of repo to create, used on clusterrepo create page
99
+ export const TARGET = 'target';
@@ -2,6 +2,11 @@
2
2
  import { GC_DEFAULTS, GC_PREFERENCES } from '@shell/utils/gc/gc-types';
3
3
  import { PaginationSettings } from '@shell/types/resources/settings';
4
4
 
5
+ export const AGENT_CONFIGURATION_TYPES = {
6
+ CLUSTER: 'cluster',
7
+ FLEET: 'fleet'
8
+ } as const;
9
+
5
10
  interface GlobalSettingRuleset {
6
11
  name: string,
7
12
  key?: string | number,
@@ -17,6 +22,7 @@ interface GlobalSetting {
17
22
  kind?: string,
18
23
  options?: string[]
19
24
  readOnly?: boolean,
25
+ agent?: typeof AGENT_CONFIGURATION_TYPES.CLUSTER | typeof AGENT_CONFIGURATION_TYPES.FLEET,
20
26
  /**
21
27
  * Function used from the form validation
22
28
  */
@@ -111,6 +117,8 @@ export const SETTING = {
111
117
  IMPORTED_CLUSTER_VERSION_MANAGEMENT: 'imported-cluster-version-management',
112
118
  CLUSTER_AGENT_DEFAULT_PRIORITY_CLASS: 'cluster-agent-default-priority-class',
113
119
  CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET: 'cluster-agent-default-pod-disruption-budget',
120
+ FLEET_AGENT_DEFAULT_PRIORITY_CLASS: 'fleet-agent-default-priority-class',
121
+ FLEET_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET: 'fleet-agent-default-pod-disruption-budget',
114
122
  KEV2_OPERATORS: 'kev2-operators',
115
123
  /**
116
124
  * Dynamic Content settings
@@ -178,8 +186,11 @@ export const ALLOWED_SETTINGS: GlobalSetting = {
178
186
  ruleSet: [{ name: 'minValue', factoryArg: 1 }]
179
187
  },
180
188
  [SETTING.IMPORTED_CLUSTER_VERSION_MANAGEMENT]: { kind: 'boolean' },
181
- [SETTING.CLUSTER_AGENT_DEFAULT_PRIORITY_CLASS]: { kind: 'json' },
182
- [SETTING.CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET]: { kind: 'json' }
189
+ // Configuration setup for agent configuration. Setting this up will activate the specific banner configuration.
190
+ [SETTING.CLUSTER_AGENT_DEFAULT_PRIORITY_CLASS]: { kind: 'json', agent: AGENT_CONFIGURATION_TYPES.CLUSTER },
191
+ [SETTING.CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET]: { kind: 'json', agent: AGENT_CONFIGURATION_TYPES.CLUSTER },
192
+ [SETTING.FLEET_AGENT_DEFAULT_PRIORITY_CLASS]: { kind: 'json', agent: AGENT_CONFIGURATION_TYPES.FLEET },
193
+ [SETTING.FLEET_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET]: { kind: 'json', agent: AGENT_CONFIGURATION_TYPES.FLEET }
183
194
 
184
195
  };
185
196
 
@@ -195,6 +206,8 @@ export const PROVISIONING_SETTINGS = [
195
206
  SETTING.IMPORTED_CLUSTER_VERSION_MANAGEMENT,
196
207
  SETTING.CLUSTER_AGENT_DEFAULT_PRIORITY_CLASS,
197
208
  SETTING.CLUSTER_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET,
209
+ SETTING.FLEET_AGENT_DEFAULT_PRIORITY_CLASS,
210
+ SETTING.FLEET_AGENT_DEFAULT_POD_DISTRIBUTION_BUDGET,
198
211
  ];
199
212
 
200
213
  /**
@@ -1,4 +1,4 @@
1
- import { CATTLE_PUBLIC_ENDPOINTS, UI_PROJECT_SECRET_COPY } from '@shell/config/labels-annotations';
1
+ import { CATTLE_PUBLIC_ENDPOINTS } from '@shell/config/labels-annotations';
2
2
  import { NODE as NODE_TYPE, NAMESPACE as NAMESPACE_TYPE } from '@shell/config/types';
3
3
  import { COLUMN_BREAKPOINTS } from '@shell/types/store/type-map';
4
4
 
@@ -55,6 +55,11 @@ export const NAME = {
55
55
  canBeVariable: true,
56
56
  };
57
57
 
58
+ export const PROJECT_NAMESPACES_NAME = {
59
+ ...NAME,
60
+ search: ['nameDisplay', 'projectNameDisplay'],
61
+ };
62
+
58
63
  export const LOGGING_OUTPUT_PROVIDERS = {
59
64
  name: 'logging-output-providers',
60
65
  labelKey: 'tableHeaders.loggingOutputProviders',
@@ -385,27 +390,17 @@ export const SECRET_DATA = {
385
390
  formatter: 'SecretData'
386
391
  };
387
392
 
388
- export const SECRET_CLONE = {
389
- name: 'secret-clone',
390
- labelKey: 'tableHeaders.secret.project-clone',
391
- tooltip: 'tableHeaders.secret.project-clone-tooltip',
392
- value: 'isProjectSecretCopy',
393
- sort: `metadata.annotations."${ UI_PROJECT_SECRET_COPY }"`,
394
- search: false,
395
- formatter: 'Checked',
396
- };
397
-
398
- export const SECRET_PROJECT_SCOPED = {
399
- name: 'secret-project-scoped',
400
- labelKey: 'tableHeaders.secret.project-scoped',
401
- tooltip: 'tableHeaders.secret.project-scoped-tooltip',
402
- value: 'clusterAndProjectLabel',
393
+ export const SECRET_ORIGIN = {
394
+ name: 'secret-origin',
395
+ labelKey: 'tableHeaders.secret.origin',
396
+ tooltip: 'tableHeaders.secret.originTooltip',
397
+ formatter: 'SecretOrigin',
403
398
  // Cannot _sort_ upstream secrets by if they are cluster scoped
404
399
  // https://github.com/rancher/rancher/issues/51001
405
400
  // metadata.labels[management.cattle.io/project-scoped-secret] - covers both cluster scoped AND clones
406
401
  // metadata.annotations[management.cattle.io/project-scoped-secret-copy]
407
402
  // sort: [`metadata.labels[${ UI_PROJECT_SECRET }]`, `metadata.annotations[${ UI_PROJECT_SECRET_COPY }]`],
408
- search: false,
403
+ search: false,
409
404
  };
410
405
 
411
406
  export const TARGET_KIND = {
@@ -1038,6 +1033,15 @@ export const SCOPE_NORMAN = {
1038
1033
  sort: ['clusterId'],
1039
1034
  };
1040
1035
 
1036
+ export const NORMAN_KEY_DEPRECATION = {
1037
+ name: 'isNormanKeyDeprecated',
1038
+ labelKey: 'tableHeaders.isLegacy',
1039
+ value: (row) => row.isDeprecated ? 'True' : undefined,
1040
+ sort: 'isDeprecated',
1041
+ align: 'left',
1042
+ dashIfEmpty: true,
1043
+ };
1044
+
1041
1045
  export const EXPIRES = {
1042
1046
  name: 'expires',
1043
1047
  value: 'expiresAt',
package/config/types.js CHANGED
@@ -269,6 +269,7 @@ export const EXT = {
269
269
  GROUP_MEMBERSHIP_REFRESH_REQUESTS: 'ext.cattle.io.groupmembershiprefreshrequest',
270
270
  PASSWORD_CHANGE_REQUESTS: 'ext.cattle.io.passwordchangerequest',
271
271
  KUBECONFIG: 'ext.cattle.io.kubeconfig',
272
+ TOKEN: 'ext.cattle.io.token',
272
273
  };
273
274
 
274
275
  export const CAPI = {
@@ -390,21 +391,35 @@ export const ADDRESSES = {
390
391
  export const DEFAULT_WORKSPACE = 'fleet-default';
391
392
 
392
393
  export const AUTH_TYPE = {
393
- _NONE: '_none',
394
- _BASIC: '_basic',
395
- _SSH: '_ssh',
396
- _S3: '_S3',
397
- _RKE: '_RKE',
394
+ _NONE: '_none',
395
+ _BASIC: '_basic',
396
+ _SSH: '_ssh',
397
+ _S3: '_S3',
398
+ _RKE: '_RKE',
399
+ _IMAGE_PULL_SECRET: '_IPS',
398
400
  };
399
401
 
400
402
  export const LOCAL_CLUSTER = 'local';
401
403
 
402
404
  export const CLUSTER_REPO_TYPES = {
403
- HELM_URL: 'helm-url',
404
- GIT_REPO: 'git-repo',
405
- OCI_URL: 'oci-url'
405
+ HELM_URL: 'helm-url',
406
+ GIT_REPO: 'git-repo',
407
+ OCI_URL: 'oci-url',
408
+ SUSE_APP_COLLECTION: 'suse-application-collection'
406
409
  };
407
410
 
411
+ /**
412
+ * The `generateName` prefix used when creating authentication secrets
413
+ * for SUSE App Collection repositories.
414
+ */
415
+ export const CLUSTER_REPO_APPCO_AUTH_GENERATE_NAME = 'clusterrepo-appco-auth-';
416
+
417
+ /**
418
+ * The `generateName` prefix used when creating authentication secrets
419
+ * for standard repositories.
420
+ */
421
+ export const CLUSTER_REPO_AUTH_GENERATE_NAME = 'clusterrepo-auth-';
422
+
408
423
  export const ZERO_TIME = '0001-01-01T00:00:00Z';
409
424
 
410
425
  export const DEFAULT_GRAFANA_STORAGE_SIZE = '10Gi';
@@ -2,7 +2,7 @@
2
2
  import CreateEditView from '@shell/mixins/create-edit-view';
3
3
  import { NAMESPACE as NAMESPACE_COL } from '@shell/config/table-headers';
4
4
  import {
5
- POD, WORKLOAD_TYPES, SERVICE, INGRESS, NODE, NAMESPACE, WORKLOAD_TYPE_TO_KIND_MAPPING, METRICS_SUPPORTED_KINDS
5
+ POD, WORKLOAD_TYPES, SERVICE, INGRESS, NAMESPACE, WORKLOAD_TYPE_TO_KIND_MAPPING, METRICS_SUPPORTED_KINDS
6
6
  } from '@shell/config/types';
7
7
  import ResourceTable from '@shell/components/ResourceTable';
8
8
  import Tab from '@shell/components/Tabbed/Tab';
@@ -13,6 +13,7 @@ import DashboardMetrics from '@shell/components/DashboardMetrics';
13
13
  import { mapGetters } from 'vuex';
14
14
  import { allDashboardsExist } from '@shell/utils/grafana';
15
15
  import { PROJECT } from '@shell/config/labels-annotations';
16
+ import { fetchNodesForServiceTargets } from '@shell/models/service';
16
17
 
17
18
  const WORKLOAD_METRICS_DETAIL_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-workload-pods-1/rancher-workload-pods?orgId=1';
18
19
  const WORKLOAD_METRICS_SUMMARY_URL = '/api/v1/namespaces/cattle-monitoring-system/services/http:rancher-monitoring-grafana:80/proxy/d/rancher-workload-1/rancher-workload?orgId=1';
@@ -29,28 +30,23 @@ export default {
29
30
  mixins: [CreateEditView],
30
31
 
31
32
  async fetch() {
32
- let hasNodes = false;
33
-
34
- try {
35
- const inStore = this.$store.getters['currentStore']();
36
- const schema = this.$store.getters[`${ inStore }/schemaFor`](NODE);
37
-
38
- if (schema) {
39
- hasNodes = true;
40
- }
41
- } catch {}
42
-
43
33
  const hash = {
44
34
  allIngresses: this.$store.dispatch('cluster/findAll', { type: INGRESS }),
45
- // Nodes should be fetched because they may be referenced in the target
46
- // column of a service list item.
47
- allNodes: hasNodes ? this.$store.dispatch('cluster/findAll', { type: NODE }) : []
35
+ // Nodes should be fetched because they may be referenced in the target column of a service list item.
36
+ nodes: fetchNodesForServiceTargets({
37
+ $store: this.$store,
38
+ inStore: this.$store.getters['currentStore']()
39
+ })
48
40
  };
49
41
 
50
42
  if (this.podSchema) {
51
43
  hash.pods = this.value.fetchPods();
52
44
  }
53
45
 
46
+ if (this.serviceSchema) {
47
+ hash.servicesInNamespace = this.$store.dispatch('cluster/findAll', { type: SERVICE, opt: { namespaced: this.value.metadata.namespace } });
48
+ }
49
+
54
50
  if (this.value.type === WORKLOAD_TYPES.CRON_JOB) {
55
51
  hash.jobs = this.value.matchingJobs();
56
52
  }
@@ -88,7 +84,6 @@ export default {
88
84
  return {
89
85
  allIngresses: [],
90
86
  matchingIngresses: [],
91
- allNodes: [],
92
87
  WORKLOAD_METRICS_DETAIL_URL,
93
88
  WORKLOAD_METRICS_SUMMARY_URL,
94
89
  POD_PROJECT_METRICS_DETAIL_URL: '',
@@ -55,7 +55,7 @@ export default {
55
55
  try {
56
56
  await Promise.all(this.drivers.map(
57
57
  (driver) => this.$store.dispatch('rancher/request', {
58
- url: `v3/${ this.driverType }/${ escape(driver.id) }?action=deactivate`,
58
+ url: `v3/${ this.driverType }/${ encodeURIComponent(driver.id) }?action=deactivate`,
59
59
  method: 'POST'
60
60
  })
61
61
  ));