@rancher/shell 3.0.9-rc.5 → 3.0.9
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/providers/oci-open-containers.svg +22 -0
- package/assets/images/providers/traefik.png +0 -0
- package/assets/styles/themes/_dark.scss +2 -0
- package/assets/styles/themes/_light.scss +2 -0
- package/assets/styles/themes/_modern.scss +6 -0
- package/assets/translations/en-us.yaml +129 -25
- package/components/CruResource.vue +3 -1
- package/components/ExplorerProjectsNamespaces.vue +12 -12
- package/components/IconOrSvg.vue +61 -42
- package/components/Resource/Detail/Card/StatusCard/__tests__/StatusCard.test.ts +109 -0
- package/components/Resource/Detail/Card/StatusCard/index.vue +21 -4
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +19 -2
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +19 -11
- package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +12 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +2 -0
- package/components/Resource/Detail/ResourceRow.vue +2 -2
- package/components/ResourceList/index.vue +7 -4
- package/components/SortableTable/index.vue +2 -2
- package/components/Window/ContainerLogs.vue +48 -37
- package/components/fleet/FleetClusterTargets/TargetsList.vue +2 -2
- package/components/fleet/FleetClusterTargets/index.vue +6 -1
- package/components/fleet/GitRepoAdvancedTab.vue +333 -0
- package/components/fleet/GitRepoMetadataTab.vue +43 -0
- package/components/fleet/GitRepoRepositoryTab.vue +101 -0
- package/components/fleet/GitRepoTargetTab.vue +77 -0
- package/components/fleet/HelmOpAdvancedTab.vue +247 -0
- package/components/fleet/HelmOpChartTab.vue +158 -0
- package/components/fleet/HelmOpMetadataTab.vue +46 -0
- package/components/fleet/HelmOpTargetTab.vue +84 -0
- package/components/fleet/HelmOpValuesTab.vue +147 -0
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +119 -70
- package/components/form/BannerSettings.vue +2 -2
- package/components/form/NodeScheduling.vue +81 -7
- package/components/form/NotificationSettings.vue +2 -2
- package/components/form/PodAffinity.vue +1 -36
- package/components/form/ResourceLabeledSelect.vue +8 -4
- package/components/form/ResourceQuota/Namespace.vue +30 -9
- package/components/form/ResourceQuota/NamespaceRow.vue +25 -7
- package/components/form/ResourceQuota/Project.vue +140 -82
- package/components/form/ResourceQuota/ResourceQuotaEntry.vue +145 -0
- package/components/form/ResourceQuota/__tests__/Namespace.test.ts +307 -0
- package/components/form/ResourceQuota/__tests__/NamespaceRow.test.ts +281 -0
- package/components/form/ResourceQuota/__tests__/Project.test.ts +274 -27
- package/components/form/ResourceQuota/__tests__/ResourceQuotaEntry.test.ts +215 -0
- package/components/form/SchedulingCustomization.vue +14 -6
- package/components/form/SelectOrCreateAuthSecret.vue +107 -18
- package/components/form/__tests__/NodeScheduling.test.ts +12 -9
- package/components/form/__tests__/PodAffinity.test.ts +21 -2
- package/components/form/__tests__/SchedulingCustomization.test.ts +240 -0
- package/components/formatter/ClusterLink.vue +8 -0
- package/components/formatter/SecretOrigin.vue +79 -0
- package/config/labels-annotations.js +7 -6
- package/config/pagination-table-headers.js +6 -4
- package/config/product/explorer.js +1 -11
- package/config/product/manager.js +0 -1
- package/config/query-params.js +3 -0
- package/config/settings.ts +15 -2
- package/config/table-headers.js +21 -17
- package/config/types.js +23 -8
- package/detail/fleet.cattle.io.cluster.vue +1 -1
- package/detail/workload/index.vue +11 -16
- package/dialog/DeactivateDriverDialog.vue +1 -1
- package/dialog/FeatureFlagListDialog.vue +1 -1
- package/dialog/Ipv6NetworkingDialog.vue +156 -0
- package/dialog/ScalePoolDownDialog.vue +2 -2
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +1 -0
- package/edit/__tests__/management.cattle.io.project.test.js +56 -128
- package/edit/auth/oidc.vue +1 -1
- package/edit/catalog.cattle.io.clusterrepo.vue +155 -25
- package/edit/fleet.cattle.io.gitrepo.vue +153 -283
- package/edit/fleet.cattle.io.helmop.vue +190 -332
- package/edit/management.cattle.io.project.vue +5 -42
- package/edit/management.cattle.io.setting.vue +6 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/__tests__/auth.spec.ts +145 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/__tests__/index.test.ts +202 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/__tests__/tls.spec.ts +226 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/auth.vue +24 -21
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/__tests__/opsgenie.spec.ts +157 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/__tests__/pagerduty.spec.ts +132 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/__tests__/slack.spec.ts +108 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue +2 -1
- package/edit/monitoring.coreos.com.receiver/__tests__/auth.spec.ts +165 -0
- package/edit/monitoring.coreos.com.receiver/__tests__/index.test.ts +153 -0
- package/edit/monitoring.coreos.com.receiver/__tests__/tls.spec.ts +115 -0
- package/edit/monitoring.coreos.com.receiver/types/__tests__/email.spec.ts +86 -0
- package/edit/monitoring.coreos.com.receiver/types/__tests__/opsgenie.spec.ts +209 -0
- package/edit/monitoring.coreos.com.receiver/types/__tests__/pagerduty.spec.ts +105 -0
- package/edit/monitoring.coreos.com.receiver/types/__tests__/slack.spec.ts +92 -0
- package/edit/monitoring.coreos.com.receiver/types/__tests__/webhook.spec.ts +131 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +55 -24
- package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +1 -103
- package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +13 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2-fleet-cluster-agent.test.ts +283 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +65 -49
- package/edit/provisioning.cattle.io.cluster/ingress/IngressCards.vue +114 -0
- package/edit/provisioning.cattle.io.cluster/ingress/IngressConfiguration.vue +158 -0
- package/edit/provisioning.cattle.io.cluster/rke2.vue +167 -69
- package/edit/provisioning.cattle.io.cluster/shared.ts +36 -1
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +2 -1
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +70 -7
- package/edit/provisioning.cattle.io.cluster/tabs/Ingress.vue +343 -0
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +2 -1
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/__tests__/S3Config.test.ts +13 -1
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +10 -44
- package/edit/secret/index.vue +1 -1
- package/edit/token.vue +68 -29
- package/edit/workload/__tests__/index.test.ts +2 -37
- package/edit/workload/index.vue +6 -2
- package/edit/workload/mixins/workload.js +0 -32
- package/list/__tests__/management.cattle.io.setting.test.ts +198 -0
- package/list/management.cattle.io.setting.vue +13 -0
- package/list/provisioning.cattle.io.cluster.vue +50 -1
- package/list/secret.vue +4 -9
- package/list/service.vue +6 -8
- package/machine-config/amazonec2.vue +11 -4
- package/machine-config/components/EC2Networking.vue +46 -30
- package/machine-config/components/__tests__/EC2Networking.test.ts +7 -7
- package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +0 -9
- package/machine-config/digitalocean.vue +3 -3
- package/models/__tests__/chart.test.ts +2 -2
- package/models/__tests__/namespace.test.ts +11 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +96 -0
- package/models/__tests__/workload.test.ts +42 -1
- package/models/catalog.cattle.io.clusterrepo.js +30 -4
- package/models/chart.js +3 -3
- package/models/ext.cattle.io.token.js +48 -0
- package/models/kontainerdriver.js +2 -2
- package/models/namespace.js +7 -1
- package/models/nodedriver.js +2 -2
- package/models/provisioning.cattle.io.cluster.js +28 -7
- package/models/secret.js +0 -17
- package/models/service.js +44 -1
- package/models/token.js +4 -0
- package/models/workload.js +12 -6
- package/package.json +1 -1
- package/pages/account/index.vue +96 -67
- package/pages/auth/setup.vue +5 -14
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +45 -18
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +4 -1
- package/pages/c/_cluster/apps/charts/index.vue +82 -3
- package/pages/c/_cluster/apps/charts/install.vue +317 -42
- package/pages/c/_cluster/explorer/tools/index.vue +1 -1
- package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -4
- package/pages/c/_cluster/settings/index.vue +3 -1
- package/pages/c/_cluster/uiplugins/index.vue +1 -1
- package/plugins/dashboard-store/__tests__/getters.test.ts +108 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +27 -0
- package/plugins/dashboard-store/actions.js +3 -8
- package/plugins/dashboard-store/getters.js +7 -5
- package/plugins/dashboard-store/mutations.js +4 -1
- package/plugins/dashboard-store/resource-class.js +3 -3
- package/plugins/steve/__tests__/steve-class.test.ts +102 -141
- package/plugins/steve/steve-class.js +12 -3
- package/plugins/steve/steve-pagination-utils.ts +6 -2
- package/rancher-components/RcIcon/types.ts +2 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +72 -20
- package/store/prefs.js +3 -0
- package/types/aws-sdk.d.ts +121 -0
- package/types/resources/node.ts +15 -0
- package/types/shell/index.d.ts +537 -506
- package/types/store/pagination.types.ts +5 -5
- package/utils/__tests__/array.test.ts +1 -29
- package/utils/__tests__/cluster-agent-configuration.test.ts +203 -0
- package/utils/array.ts +0 -11
- package/utils/aws.ts +21 -0
- package/utils/cluster.js +22 -2
- package/utils/selector-typed.ts +1 -1
- package/utils/svg-filter.js +4 -3
- package/components/__tests__/ProjectRow.test.ts +0 -206
- package/components/form/ResourceQuota/ProjectRow.vue +0 -277
package/list/service.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import PaginatedResourceTable from '@shell/components/PaginatedResourceTable';
|
|
3
|
-
import {
|
|
3
|
+
import { fetchNodesForServiceTargets } from '@shell/models/service';
|
|
4
4
|
|
|
5
5
|
export default {
|
|
6
6
|
name: 'ListService',
|
|
@@ -27,13 +27,11 @@ export default {
|
|
|
27
27
|
* of type PagTableFetchSecondaryResources
|
|
28
28
|
*/
|
|
29
29
|
async fetchSecondaryResources(opts) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
await this.$store.dispatch(`${ inStore }/findAll`, { type: NODE });
|
|
36
|
-
}
|
|
30
|
+
// Nodes should be fetched because they may be referenced in the target column of a service list item.
|
|
31
|
+
await fetchNodesForServiceTargets({
|
|
32
|
+
$store: this.$store,
|
|
33
|
+
inStore: this.$store.getters['currentStore']()
|
|
34
|
+
});
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
37
|
};
|
|
@@ -24,7 +24,7 @@ export default {
|
|
|
24
24
|
|
|
25
25
|
mixins: [CreateEditView],
|
|
26
26
|
|
|
27
|
-
emits: ['validationChanged', 'update:
|
|
27
|
+
emits: ['validationChanged', 'update:isIpv6', 'update:isDualStack'],
|
|
28
28
|
|
|
29
29
|
props: {
|
|
30
30
|
uuid: {
|
|
@@ -47,7 +47,12 @@ export default {
|
|
|
47
47
|
default: false
|
|
48
48
|
},
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
isIpv6: {
|
|
51
|
+
type: Boolean,
|
|
52
|
+
default: false
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
isDualStack: {
|
|
51
56
|
type: Boolean,
|
|
52
57
|
default: false
|
|
53
58
|
},
|
|
@@ -386,10 +391,12 @@ export default {
|
|
|
386
391
|
:zone="value.zone"
|
|
387
392
|
:region="value.region"
|
|
388
393
|
:machine-pools="machinePools"
|
|
389
|
-
:
|
|
394
|
+
:is-ipv6="isIpv6"
|
|
395
|
+
:is-dual-stack="isDualStack"
|
|
390
396
|
:disabled="disabled"
|
|
391
397
|
:is-new="poolCreateMode"
|
|
392
|
-
@update:
|
|
398
|
+
@update:is-ipv6="e=>$emit('update:isIpv6', e)"
|
|
399
|
+
@update:is-dual-stack="e=>$emit('update:isDualStack', e)"
|
|
393
400
|
@validation-changed="e=>$emit('validationChanged',e)"
|
|
394
401
|
/>
|
|
395
402
|
|
|
@@ -9,6 +9,7 @@ import { LabeledInput } from '@components/Form/LabeledInput';
|
|
|
9
9
|
import { Banner } from '@components/Banner';
|
|
10
10
|
import { scrollToBottom } from '@shell/utils/scroll';
|
|
11
11
|
import { _CREATE } from '@shell/config/query-params';
|
|
12
|
+
import { getSubnetDisplayName, getVpcDisplayName, isIpv4Network, isIpv6Network } from '@shell/utils/aws';
|
|
12
13
|
|
|
13
14
|
export default {
|
|
14
15
|
name: 'Ec2MachinePoolNetworking',
|
|
@@ -17,7 +18,7 @@ export default {
|
|
|
17
18
|
Checkbox, LabeledSelect, LabeledInput, Banner
|
|
18
19
|
},
|
|
19
20
|
|
|
20
|
-
emits: ['update:enablePrimaryIpv6', 'update:ipv6AddressCount', 'update:ipv6AddressOnly', 'update:httpProtocolIpv6', 'update:vpcId', 'update:subnetId', 'update:
|
|
21
|
+
emits: ['update:enablePrimaryIpv6', 'update:ipv6AddressCount', 'update:ipv6AddressOnly', 'update:httpProtocolIpv6', 'update:vpcId', 'update:subnetId', 'update:isIpv6', 'update:isDualStack', 'validationChanged'],
|
|
21
22
|
|
|
22
23
|
props: {
|
|
23
24
|
mode: {
|
|
@@ -84,7 +85,12 @@ export default {
|
|
|
84
85
|
default: ''
|
|
85
86
|
},
|
|
86
87
|
|
|
87
|
-
|
|
88
|
+
isIpv6: {
|
|
89
|
+
type: Boolean,
|
|
90
|
+
default: false
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
isDualStack: {
|
|
88
94
|
type: Boolean,
|
|
89
95
|
default: false
|
|
90
96
|
},
|
|
@@ -113,7 +119,7 @@ export default {
|
|
|
113
119
|
this.enableIpv6 = !!vpcs.find((vpc) => vpc.VpcId === this.vpcId && vpc.Ipv6CidrBlockAssociationSet && !isEmpty(vpc.Ipv6CidrBlockAssociationSet));
|
|
114
120
|
}
|
|
115
121
|
|
|
116
|
-
if (this.isNew && this.
|
|
122
|
+
if (this.isNew && this.somePoolisIpv6OrDual) {
|
|
117
123
|
this.enableIpv6 = true;
|
|
118
124
|
}
|
|
119
125
|
},
|
|
@@ -133,7 +139,7 @@ export default {
|
|
|
133
139
|
if (this.isNew) {
|
|
134
140
|
this.updateNetwork();
|
|
135
141
|
}
|
|
136
|
-
this.$emit('update:
|
|
142
|
+
this.$emit('update:isDualStack', neu);
|
|
137
143
|
|
|
138
144
|
if (neu) {
|
|
139
145
|
this.$emit('update:ipv6AddressCount', '1');
|
|
@@ -154,7 +160,12 @@ export default {
|
|
|
154
160
|
},
|
|
155
161
|
|
|
156
162
|
ipv6AddressOnly(neu) {
|
|
157
|
-
this.$emit('update:
|
|
163
|
+
this.$emit('update:isIpv6', neu);
|
|
164
|
+
if (neu) {
|
|
165
|
+
this.$emit('update:isDualStack', false);
|
|
166
|
+
} else if (this.enableIpv6) {
|
|
167
|
+
this.$emit('update:isDualStack', true);
|
|
168
|
+
}
|
|
158
169
|
},
|
|
159
170
|
|
|
160
171
|
allValid: {
|
|
@@ -174,13 +185,13 @@ export default {
|
|
|
174
185
|
const subnetsByVpc = {};
|
|
175
186
|
|
|
176
187
|
for ( const obj of this.vpcInfo.Vpcs ) {
|
|
177
|
-
const name = obj
|
|
178
|
-
const hasIpv6 =
|
|
179
|
-
const hasIpv4 =
|
|
188
|
+
const name = getVpcDisplayName(obj);
|
|
189
|
+
const hasIpv6 = isIpv6Network(obj);
|
|
190
|
+
const hasIpv4 = isIpv4Network(obj);
|
|
180
191
|
|
|
181
192
|
vpcs.push({
|
|
182
|
-
label: name
|
|
183
|
-
subLabel:
|
|
193
|
+
label: name,
|
|
194
|
+
subLabel: obj.CidrBlock,
|
|
184
195
|
isDefault: obj.IsDefault || false,
|
|
185
196
|
kind: 'vpc',
|
|
186
197
|
value: obj.VpcId,
|
|
@@ -197,8 +208,8 @@ export default {
|
|
|
197
208
|
continue;
|
|
198
209
|
}
|
|
199
210
|
|
|
200
|
-
const hasIpv6 =
|
|
201
|
-
const hasIpv4 =
|
|
211
|
+
const hasIpv6 = isIpv6Network(obj);
|
|
212
|
+
const hasIpv4 = isIpv4Network(obj);
|
|
202
213
|
|
|
203
214
|
if (this.enableIpv6 !== hasIpv6) {
|
|
204
215
|
continue;
|
|
@@ -211,11 +222,11 @@ export default {
|
|
|
211
222
|
subnetsByVpc[obj.VpcId] = entry;
|
|
212
223
|
}
|
|
213
224
|
|
|
214
|
-
const name = obj
|
|
225
|
+
const name = getSubnetDisplayName(obj);
|
|
215
226
|
|
|
216
227
|
entry.push({
|
|
217
|
-
label: name
|
|
218
|
-
subLabel:
|
|
228
|
+
label: name,
|
|
229
|
+
subLabel: obj.CidrBlock,
|
|
219
230
|
kind: 'subnet',
|
|
220
231
|
isDefault: obj.DefaultForAz || false,
|
|
221
232
|
value: obj.SubnetId,
|
|
@@ -278,18 +289,18 @@ export default {
|
|
|
278
289
|
return opt && opt.hasIpv6 && !opt.hasIpv4;
|
|
279
290
|
},
|
|
280
291
|
|
|
281
|
-
|
|
282
|
-
return !!this.machinePools.find((p) => p.
|
|
292
|
+
somePoolisIpv6OrDual() {
|
|
293
|
+
return !!this.machinePools.find((p) => p.isIpv6 || p.isDualStack);
|
|
283
294
|
},
|
|
284
295
|
|
|
285
296
|
showIpv6Options() {
|
|
286
|
-
return this.mode === _CREATE || (this.isNew && this.
|
|
297
|
+
return this.mode === _CREATE || (this.isNew && this.somePoolisIpv6OrDual) || this.enableIpv6;
|
|
287
298
|
},
|
|
288
299
|
|
|
289
300
|
poolsInvalid() {
|
|
290
|
-
const somePoolHasIpv4 = !!this.machinePools.find((p) => !p.
|
|
301
|
+
const somePoolHasIpv4 = !!this.machinePools.find((p) => !p.isIpv6 && !p.isDualStack);
|
|
291
302
|
|
|
292
|
-
return this.
|
|
303
|
+
return this.somePoolisIpv6OrDual && somePoolHasIpv4;
|
|
293
304
|
},
|
|
294
305
|
|
|
295
306
|
addressCountInvalid() {
|
|
@@ -398,9 +409,14 @@ export default {
|
|
|
398
409
|
</template>
|
|
399
410
|
</LabeledSelect>
|
|
400
411
|
</div>
|
|
412
|
+
</div>
|
|
413
|
+
<div
|
|
414
|
+
v-if="enableIpv6"
|
|
415
|
+
class="row mb-10 ipv6-row"
|
|
416
|
+
>
|
|
401
417
|
<div
|
|
402
418
|
v-if="enableIpv6"
|
|
403
|
-
class="col span-
|
|
419
|
+
class="col span-2"
|
|
404
420
|
>
|
|
405
421
|
<Checkbox
|
|
406
422
|
:disabled="!isNew || !dualStackSelected"
|
|
@@ -411,17 +427,12 @@ export default {
|
|
|
411
427
|
@update:value="e=>$emit('update:ipv6AddressOnly', e)"
|
|
412
428
|
/>
|
|
413
429
|
</div>
|
|
414
|
-
|
|
415
|
-
<div
|
|
416
|
-
v-if="enableIpv6"
|
|
417
|
-
class="row mb-10 ipv6-row"
|
|
418
|
-
>
|
|
419
|
-
<div class="col span-6">
|
|
430
|
+
<div class="col span-4">
|
|
420
431
|
<Checkbox
|
|
421
432
|
:value="httpProtocolIpv6==='enabled'"
|
|
422
433
|
:disabled="!isNew"
|
|
423
434
|
:label="t('cluster.machineConfig.amazonEc2.httpProtocolIpv6.label')"
|
|
424
|
-
data-testid="
|
|
435
|
+
data-testid="amazonEc2__httpProtocolIpv6"
|
|
425
436
|
:mode="mode"
|
|
426
437
|
@update:value="e=>$emit('update:httpProtocolIpv6', e ? 'enabled' : 'disabled')"
|
|
427
438
|
/>
|
|
@@ -431,7 +442,7 @@ export default {
|
|
|
431
442
|
v-if="enableIpv6"
|
|
432
443
|
class="row mb-10 ipv6-row"
|
|
433
444
|
>
|
|
434
|
-
<div class="col span-
|
|
445
|
+
<div class="col span-6">
|
|
435
446
|
<LabeledInput
|
|
436
447
|
:disabled="!isNew"
|
|
437
448
|
min="1"
|
|
@@ -443,7 +454,12 @@ export default {
|
|
|
443
454
|
@update:value="e=>$emit('update:ipv6AddressCount', e)"
|
|
444
455
|
/>
|
|
445
456
|
</div>
|
|
446
|
-
|
|
457
|
+
</div>
|
|
458
|
+
<div
|
|
459
|
+
v-if="enableIpv6"
|
|
460
|
+
class="row mb-10 ipv6-row"
|
|
461
|
+
>
|
|
462
|
+
<div class="col span-6">
|
|
447
463
|
<Checkbox
|
|
448
464
|
:disabled="!isNew"
|
|
449
465
|
:value="enablePrimaryIpv6"
|
|
@@ -82,9 +82,9 @@ describe('component: EC2Networking', () => {
|
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
it.each([
|
|
85
|
-
[[{
|
|
86
|
-
[[{
|
|
87
|
-
[[{
|
|
85
|
+
[[{ isIpv6: true }, { isIpv6: false }], true],
|
|
86
|
+
[[{ isIpv6: false }, { isIpv6: false }], false],
|
|
87
|
+
[[{ isIpv6: true }, { isIpv6: true }], false],
|
|
88
88
|
])('should show an error banner if pools do not either all have ipv6 or all have ipv4', (pools, shouldShowError) => {
|
|
89
89
|
const wrapper = shallowMount(EC2Networking, { ...defaultCreateSetup, propsData: { ...defaultCreateSetup.propsData, machinePools: pools } });
|
|
90
90
|
const ipv6Warning = wrapper.findComponent('[data-testid="amazonEc2__ipv6Warning"]');
|
|
@@ -97,7 +97,7 @@ describe('component: EC2Networking', () => {
|
|
|
97
97
|
...defaultCreateSetup,
|
|
98
98
|
propsData: {
|
|
99
99
|
...defaultCreateSetup.propsData,
|
|
100
|
-
machinePools: [{
|
|
100
|
+
machinePools: [{ isIpv6: true }],
|
|
101
101
|
},
|
|
102
102
|
});
|
|
103
103
|
|
|
@@ -112,7 +112,7 @@ describe('component: EC2Networking', () => {
|
|
|
112
112
|
...defaultCreateSetup,
|
|
113
113
|
propsData: {
|
|
114
114
|
...defaultCreateSetup.propsData,
|
|
115
|
-
machinePools: [{
|
|
115
|
+
machinePools: [{ isIpv6: false }],
|
|
116
116
|
},
|
|
117
117
|
});
|
|
118
118
|
|
|
@@ -127,7 +127,7 @@ describe('component: EC2Networking', () => {
|
|
|
127
127
|
...defaultCreateSetup,
|
|
128
128
|
propsData: {
|
|
129
129
|
...defaultCreateSetup.propsData,
|
|
130
|
-
machinePools: [{
|
|
130
|
+
machinePools: [{ isIpv6: true }, { isIpv6: false }],
|
|
131
131
|
},
|
|
132
132
|
});
|
|
133
133
|
|
|
@@ -139,7 +139,7 @@ describe('component: EC2Networking', () => {
|
|
|
139
139
|
...defaultCreateSetup,
|
|
140
140
|
propsData: {
|
|
141
141
|
...defaultCreateSetup.propsData,
|
|
142
|
-
machinePools: [{
|
|
142
|
+
machinePools: [{ isIpv6: true }, { isIpv6: true }],
|
|
143
143
|
},
|
|
144
144
|
});
|
|
145
145
|
|
|
@@ -25,10 +25,6 @@ export const vpcInfo = {
|
|
|
25
25
|
{
|
|
26
26
|
Key: 'displayName',
|
|
27
27
|
Value: 'test'
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
Key: 'Name',
|
|
31
|
-
Value: 'test-eks-vpc-VPC'
|
|
32
28
|
}
|
|
33
29
|
]
|
|
34
30
|
},
|
|
@@ -107,11 +103,6 @@ export const subnetInfo = {
|
|
|
107
103
|
OwnerId: '1234',
|
|
108
104
|
AssignIpv6AddressOnCreation: false,
|
|
109
105
|
Tags: [
|
|
110
|
-
{
|
|
111
|
-
Key: 'Name',
|
|
112
|
-
Value: 'aws-controltower-PrivateSubnet2A'
|
|
113
|
-
},
|
|
114
|
-
|
|
115
106
|
{
|
|
116
107
|
Key: 'Network',
|
|
117
108
|
Value: 'Private'
|
|
@@ -16,7 +16,7 @@ export default {
|
|
|
16
16
|
|
|
17
17
|
mixins: [CreateEditView],
|
|
18
18
|
|
|
19
|
-
emits: ['update:
|
|
19
|
+
emits: ['update:isDualStack'],
|
|
20
20
|
|
|
21
21
|
props: {
|
|
22
22
|
credentialId: {
|
|
@@ -29,7 +29,7 @@ export default {
|
|
|
29
29
|
default: false
|
|
30
30
|
},
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
isDualStack: {
|
|
33
33
|
type: Boolean,
|
|
34
34
|
default: false
|
|
35
35
|
},
|
|
@@ -119,7 +119,7 @@ export default {
|
|
|
119
119
|
'value.image': 'updateUsername',
|
|
120
120
|
|
|
121
121
|
'value.ipv6'(neu) {
|
|
122
|
-
this.$emit('update:
|
|
122
|
+
this.$emit('update:isDualStack', neu);
|
|
123
123
|
}
|
|
124
124
|
},
|
|
125
125
|
|
|
@@ -236,12 +236,12 @@ describe('class Chart', () => {
|
|
|
236
236
|
|
|
237
237
|
expect(result.footerItems).toHaveLength(3);
|
|
238
238
|
|
|
239
|
-
const categoryItem = result.footerItems.find((i) => i.icon === '
|
|
239
|
+
const categoryItem = result.footerItems.find((i) => i.icon === 'category-alt');
|
|
240
240
|
|
|
241
241
|
expect(categoryItem).toBeDefined();
|
|
242
242
|
expect(categoryItem?.labels).toContain('database');
|
|
243
243
|
|
|
244
|
-
const tagItem = result.footerItems.find((i) => i.icon === '
|
|
244
|
+
const tagItem = result.footerItems.find((i) => i.icon === 'tag-alt');
|
|
245
245
|
|
|
246
246
|
expect(tagItem).toBeDefined();
|
|
247
247
|
expect(tagItem?.labels).toStrictEqual(expect.arrayContaining(['linux', 'experimentl']));
|
|
@@ -187,6 +187,17 @@ describe('class Namespace', () => {
|
|
|
187
187
|
it.todo('should set the resourceQuota as reactive Vue property');
|
|
188
188
|
it.todo('should reset project with cleanForNew');
|
|
189
189
|
|
|
190
|
+
describe('hideDetailLocation', () => {
|
|
191
|
+
it('should not throw when currentProduct is undefined', () => {
|
|
192
|
+
const namespace = new Namespace({});
|
|
193
|
+
|
|
194
|
+
jest.spyOn(namespace, '$rootGetters', 'get').mockReturnValue({ currentProduct: undefined });
|
|
195
|
+
|
|
196
|
+
expect(() => namespace.hideDetailLocation).not.toThrow();
|
|
197
|
+
expect(namespace.hideDetailLocation).toBe(true);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
190
201
|
describe('glance', () => {
|
|
191
202
|
it('should return projectGlance instead of namespace when namespace is in a project', () => {
|
|
192
203
|
const t = jest.fn((key) => key);
|
|
@@ -275,4 +275,100 @@ describe('class ProvCluster', () => {
|
|
|
275
275
|
}
|
|
276
276
|
);
|
|
277
277
|
});
|
|
278
|
+
|
|
279
|
+
describe('supportsWindows', () => {
|
|
280
|
+
const testCases = [
|
|
281
|
+
{
|
|
282
|
+
description: 'should return false for k3s',
|
|
283
|
+
clusterData: { isK3s: true },
|
|
284
|
+
expected: false
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
description: 'should return false for imported k3s',
|
|
288
|
+
clusterData: { isImportedK3s: true },
|
|
289
|
+
expected: false
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
description: 'should return windowsPreferedCluster for rke1',
|
|
293
|
+
clusterData: { isRke1: true, mgmt: { spec: { windowsPreferedCluster: true } } },
|
|
294
|
+
expected: true
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
description: 'should return false for rke1 if windowsPreferedCluster is false/missing',
|
|
298
|
+
clusterData: { isRke1: true, mgmt: { spec: { windowsPreferedCluster: false } } },
|
|
299
|
+
expected: false
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
description: 'should return false if not rke2 (and not rke1 or k3s)',
|
|
303
|
+
clusterData: { isRke2: false },
|
|
304
|
+
expected: false
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
description: 'should return false if kubernetesVersion is missing',
|
|
308
|
+
clusterData: { isRke2: true, kubernetesVersion: undefined },
|
|
309
|
+
expected: false
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
description: 'should return false if kubernetesVersion is less than v1.21.0',
|
|
313
|
+
clusterData: { isRke2: true, kubernetesVersion: 'v1.20.9' },
|
|
314
|
+
expected: false
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
description: 'should return false if cni is not calico or flannel',
|
|
318
|
+
clusterData: {
|
|
319
|
+
isRke2: true, kubernetesVersion: 'v1.34.0', spec: { rkeConfig: { machineGlobalConfig: { cni: 'cilium' } } }
|
|
320
|
+
},
|
|
321
|
+
expected: false
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
description: 'should return true if cni is calico',
|
|
325
|
+
clusterData: {
|
|
326
|
+
isRke2: true, kubernetesVersion: 'v1.34.0', spec: { rkeConfig: { machineGlobalConfig: { cni: 'calico' } } }
|
|
327
|
+
},
|
|
328
|
+
expected: true
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
description: 'should return false if cni is flannel and kubernetesVersion is less than v1.29.2 (e.g. v1.29.1)',
|
|
332
|
+
clusterData: {
|
|
333
|
+
isRke2: true, kubernetesVersion: 'v1.29.1', spec: { rkeConfig: { machineGlobalConfig: { cni: 'flannel' } } }
|
|
334
|
+
},
|
|
335
|
+
expected: false
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
description: 'should return true if cni is flannel and kubernetesVersion is exactly v1.29.2',
|
|
339
|
+
clusterData: {
|
|
340
|
+
isRke2: true, kubernetesVersion: 'v1.29.2', spec: { rkeConfig: { machineGlobalConfig: { cni: 'flannel' } } }
|
|
341
|
+
},
|
|
342
|
+
expected: true
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
description: 'should return true if cni is flannel and kubernetesVersion is >= v1.29.2 (e.g. v1.35.0)',
|
|
346
|
+
clusterData: {
|
|
347
|
+
isRke2: true, kubernetesVersion: 'v1.35.0', spec: { rkeConfig: { machineGlobalConfig: { cni: 'flannel' } } }
|
|
348
|
+
},
|
|
349
|
+
expected: true
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
description: 'should return true if cni is empty/undefined',
|
|
353
|
+
clusterData: {
|
|
354
|
+
isRke2: true, kubernetesVersion: 'v1.34.0', spec: { rkeConfig: { machineGlobalConfig: {} } }
|
|
355
|
+
},
|
|
356
|
+
expected: true
|
|
357
|
+
},
|
|
358
|
+
];
|
|
359
|
+
|
|
360
|
+
it.each(testCases)('$description', ({ clusterData, expected }) => {
|
|
361
|
+
const cluster = new ProvCluster({ spec: clusterData.spec });
|
|
362
|
+
|
|
363
|
+
jest.spyOn(cluster, 'mgmt', 'get').mockReturnValue(clusterData.mgmt);
|
|
364
|
+
jest.spyOn(cluster, 'isK3s', 'get').mockReturnValue(clusterData.isK3s || false);
|
|
365
|
+
jest.spyOn(cluster, 'isImportedK3s', 'get').mockReturnValue(clusterData.isImportedK3s || false);
|
|
366
|
+
jest.spyOn(cluster, 'isRke1', 'get').mockReturnValue(clusterData.isRke1 || false);
|
|
367
|
+
jest.spyOn(cluster, 'isRke2', 'get').mockReturnValue(clusterData.isRke2 || false);
|
|
368
|
+
jest.spyOn(cluster, 'kubernetesVersion', 'get').mockReturnValue(clusterData.kubernetesVersion);
|
|
369
|
+
|
|
370
|
+
expect(cluster.supportsWindows).toBe(expected);
|
|
371
|
+
jest.clearAllMocks();
|
|
372
|
+
});
|
|
373
|
+
});
|
|
278
374
|
});
|
|
@@ -274,6 +274,7 @@ describe('class: Workload', () => {
|
|
|
274
274
|
expect(card).not.toBeNull();
|
|
275
275
|
expect(card.props.title).toBe('component.resource.detail.card.podsCard.title');
|
|
276
276
|
expect(card.props.showScaling).toBe(true);
|
|
277
|
+
expect(card.props.noResourcesMessage).toBe('component.resource.detail.card.podsCard.noPods');
|
|
277
278
|
});
|
|
278
279
|
|
|
279
280
|
it('should return card for DaemonSet type without scaling', () => {
|
|
@@ -312,7 +313,7 @@ describe('class: Workload', () => {
|
|
|
312
313
|
expect(card).toBeNull();
|
|
313
314
|
});
|
|
314
315
|
|
|
315
|
-
it('should return
|
|
316
|
+
it('should return card when pods array is empty (scaled to 0)', () => {
|
|
316
317
|
const workload = new Workload({
|
|
317
318
|
type: WORKLOAD_TYPES.DEPLOYMENT,
|
|
318
319
|
metadata: { name: 'test', namespace: 'default' },
|
|
@@ -324,6 +325,46 @@ describe('class: Workload', () => {
|
|
|
324
325
|
});
|
|
325
326
|
|
|
326
327
|
Object.defineProperty(workload, 'pods', { get: () => [] });
|
|
328
|
+
Object.defineProperty(workload, 'canUpdate', { get: () => true });
|
|
329
|
+
|
|
330
|
+
const card = workload.podsCard;
|
|
331
|
+
|
|
332
|
+
expect(card).not.toBeNull();
|
|
333
|
+
expect(card.props.resources).toStrictEqual([]);
|
|
334
|
+
expect(card.props.noResourcesMessage).toBe('component.resource.detail.card.podsCard.noPods');
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it('should return null for non-scalable type with empty pods', () => {
|
|
338
|
+
const workload = new Workload({
|
|
339
|
+
type: WORKLOAD_TYPES.DAEMON_SET,
|
|
340
|
+
metadata: { name: 'test', namespace: 'default' },
|
|
341
|
+
spec: {}
|
|
342
|
+
}, {
|
|
343
|
+
getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
|
|
344
|
+
dispatch: jest.fn(),
|
|
345
|
+
rootGetters: { 'i18n/t': (key: string) => key },
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
Object.defineProperty(workload, 'pods', { get: () => [] });
|
|
349
|
+
Object.defineProperty(workload, 'canUpdate', { get: () => true });
|
|
350
|
+
|
|
351
|
+
const card = workload.podsCard;
|
|
352
|
+
|
|
353
|
+
expect(card).toBeNull();
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it('should return null when pods is undefined', () => {
|
|
357
|
+
const workload = new Workload({
|
|
358
|
+
type: WORKLOAD_TYPES.DEPLOYMENT,
|
|
359
|
+
metadata: { name: 'test', namespace: 'default' },
|
|
360
|
+
spec: {}
|
|
361
|
+
}, {
|
|
362
|
+
getters: { schemaFor: () => ({ linkFor: jest.fn() }) },
|
|
363
|
+
dispatch: jest.fn(),
|
|
364
|
+
rootGetters: { 'i18n/t': (key: string) => key },
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
Object.defineProperty(workload, 'pods', { get: () => undefined });
|
|
327
368
|
|
|
328
369
|
const card = workload.podsCard;
|
|
329
370
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parse } from '@shell/utils/url';
|
|
2
2
|
import { CATALOG } from '@shell/config/labels-annotations';
|
|
3
3
|
import { insertAt } from '@shell/utils/array';
|
|
4
|
-
import { CATALOG as CATALOG_TYPE } from '@shell/config/types';
|
|
4
|
+
import { CLUSTER_REPO_APPCO_AUTH_GENERATE_NAME, CATALOG as CATALOG_TYPE } from '@shell/config/types';
|
|
5
5
|
import { colorForState, stateDisplay } from '@shell/plugins/dashboard-store/resource-class';
|
|
6
6
|
|
|
7
7
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
@@ -143,14 +143,27 @@ export default class ClusterRepo extends SteveModel {
|
|
|
143
143
|
return this.metadata?.state?.name === 'active';
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
get isSuseAppCollectionFromUI() {
|
|
147
|
+
return this.metadata?.annotations?.[CATALOG.SUSE_APP_COLLECTION];
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
get isSuseAppCollection() {
|
|
151
|
+
// Check annotation set by the UI or if the URL points to the SUSE App Collection registry
|
|
152
|
+
return this.isSuseAppCollectionFromUI || this.spec?.url?.startsWith('oci://dp.apps.rancher.io/charts');
|
|
153
|
+
}
|
|
154
|
+
|
|
146
155
|
get typeDisplay() {
|
|
156
|
+
if (this.isSuseAppCollectionFromUI) {
|
|
157
|
+
return 'SUSE AppCo';
|
|
158
|
+
}
|
|
147
159
|
if ( this.spec.gitRepo ) {
|
|
148
160
|
return 'git';
|
|
149
|
-
}
|
|
161
|
+
}
|
|
162
|
+
if ( this.spec.url ) {
|
|
150
163
|
return this.isOciType ? 'oci' : 'http';
|
|
151
|
-
} else {
|
|
152
|
-
return '?';
|
|
153
164
|
}
|
|
165
|
+
|
|
166
|
+
return '?';
|
|
154
167
|
}
|
|
155
168
|
|
|
156
169
|
get nameDisplay() {
|
|
@@ -220,4 +233,17 @@ export default class ClusterRepo extends SteveModel {
|
|
|
220
233
|
});
|
|
221
234
|
}, `catalog operation fetch`, timeout, interval);
|
|
222
235
|
}
|
|
236
|
+
|
|
237
|
+
async save() {
|
|
238
|
+
// Add annotation only if the type is SUSE_APP_COLLECTION
|
|
239
|
+
if (this.spec.clientSecret?.name?.search(CLUSTER_REPO_APPCO_AUTH_GENERATE_NAME) === 0) {
|
|
240
|
+
if (!this.metadata.annotations) {
|
|
241
|
+
this.metadata.annotations = {};
|
|
242
|
+
}
|
|
243
|
+
this.metadata.annotations[CATALOG.SUSE_APP_COLLECTION] = 'true';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Call the parent save method
|
|
247
|
+
return super.save();
|
|
248
|
+
}
|
|
223
249
|
}
|
package/models/chart.js
CHANGED
|
@@ -164,7 +164,7 @@ export default class Chart extends SteveModel {
|
|
|
164
164
|
const footerItems = [
|
|
165
165
|
{
|
|
166
166
|
type: REPO,
|
|
167
|
-
icon: '
|
|
167
|
+
icon: 'repository-alt',
|
|
168
168
|
iconTooltip: { key: 'tableHeaders.repoName' },
|
|
169
169
|
labels: [this.repoNameDisplay],
|
|
170
170
|
labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.repo') }, true)
|
|
@@ -174,7 +174,7 @@ export default class Chart extends SteveModel {
|
|
|
174
174
|
if (this.categories.length) {
|
|
175
175
|
footerItems.push( {
|
|
176
176
|
type: CATEGORY,
|
|
177
|
-
icon: '
|
|
177
|
+
icon: 'category-alt',
|
|
178
178
|
iconTooltip: { key: 'generic.category' },
|
|
179
179
|
labels: this.categories,
|
|
180
180
|
labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.category') }, true)
|
|
@@ -184,7 +184,7 @@ export default class Chart extends SteveModel {
|
|
|
184
184
|
if (this.tags.length) {
|
|
185
185
|
footerItems.push({
|
|
186
186
|
type: TAG,
|
|
187
|
-
icon: '
|
|
187
|
+
icon: 'tag-alt',
|
|
188
188
|
iconTooltip: { key: 'generic.tags' },
|
|
189
189
|
labels: this.tags,
|
|
190
190
|
labelTooltip: this.t('catalog.charts.findSimilar.message', { type: this.t('catalog.charts.findSimilar.types.tag') }, true)
|