@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
|
@@ -71,6 +71,11 @@ export default {
|
|
|
71
71
|
default: 'auth-',
|
|
72
72
|
},
|
|
73
73
|
|
|
74
|
+
clientGeneratedName: {
|
|
75
|
+
type: String,
|
|
76
|
+
default: null,
|
|
77
|
+
},
|
|
78
|
+
|
|
74
79
|
allowNone: {
|
|
75
80
|
type: Boolean,
|
|
76
81
|
default: true,
|
|
@@ -150,6 +155,42 @@ export default {
|
|
|
150
155
|
default: false,
|
|
151
156
|
},
|
|
152
157
|
|
|
158
|
+
/**
|
|
159
|
+
* Used specifically to fix the HTTP BASIC auth to generate specific authentication
|
|
160
|
+
* This is used to clear up the SELECT to make sure it only has HTTP BASIC with some special conditions
|
|
161
|
+
*/
|
|
162
|
+
fixedHttpBasicAuth: {
|
|
163
|
+
type: Boolean,
|
|
164
|
+
default: false,
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
/** Used together with fixedHttpBasicAuth
|
|
168
|
+
* It will filter all the cases to use this specific label at the start.
|
|
169
|
+
*/
|
|
170
|
+
filterBasicAuth: {
|
|
171
|
+
type: String,
|
|
172
|
+
default: '',
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* This works similar to other allow* but this makes specific to create as ImagePullSecret since it is specific for one page that only uses it
|
|
177
|
+
* To avoid using it in other places.
|
|
178
|
+
*/
|
|
179
|
+
fixedImagePullSecret: {
|
|
180
|
+
type: Boolean,
|
|
181
|
+
default: false,
|
|
182
|
+
},
|
|
183
|
+
/**
|
|
184
|
+
* Whenever the fixedImagePullSecret is setup the dockerJsonUrlConfig needs to be passed that will be used to create the DockerJsonConfig file
|
|
185
|
+
*/
|
|
186
|
+
imagePullSecretDockerJsonUrlConfig: {
|
|
187
|
+
type: String,
|
|
188
|
+
default: '',
|
|
189
|
+
},
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Specific property to change labels if it is Github.com repository
|
|
193
|
+
*/
|
|
153
194
|
isGithubDotComRepository: {
|
|
154
195
|
type: Boolean,
|
|
155
196
|
default: false,
|
|
@@ -157,7 +198,7 @@ export default {
|
|
|
157
198
|
},
|
|
158
199
|
|
|
159
200
|
async fetch() {
|
|
160
|
-
if ( (this.allowSsh || this.allowBasic || this.allowRke) && this.$store.getters[`${ this.inStore }/schemaFor`](SECRET) ) {
|
|
201
|
+
if ( (this.allowSsh || this.allowBasic || this.allowRke || this.fixedImagePullSecret) && this.$store.getters[`${ this.inStore }/schemaFor`](SECRET) ) {
|
|
161
202
|
if (this.$store.getters[`${ this.inStore }/paginationEnabled`](SECRET)) {
|
|
162
203
|
// Filter results via api (because we shouldn't be fetching them all...)
|
|
163
204
|
this.filteredSecrets = await this.filterSecretsByApi();
|
|
@@ -200,6 +241,8 @@ export default {
|
|
|
200
241
|
|
|
201
242
|
selected: null,
|
|
202
243
|
|
|
244
|
+
previousValue: null,
|
|
245
|
+
|
|
203
246
|
filterByNamespace: this.namespace && this.limitToNamespace,
|
|
204
247
|
|
|
205
248
|
publicKey: '',
|
|
@@ -207,10 +250,11 @@ export default {
|
|
|
207
250
|
sshKnownHosts: '',
|
|
208
251
|
uniqueId: new Date().getTime(), // Allows form state to be individually tracked if the form is in a list
|
|
209
252
|
|
|
210
|
-
SSH:
|
|
211
|
-
BASIC:
|
|
212
|
-
|
|
213
|
-
|
|
253
|
+
SSH: AUTH_TYPE._SSH,
|
|
254
|
+
BASIC: AUTH_TYPE._BASIC,
|
|
255
|
+
IMAGE_PULL_SECRET: AUTH_TYPE._IMAGE_PULL_SECRET,
|
|
256
|
+
S3: AUTH_TYPE._S3,
|
|
257
|
+
RKE: AUTH_TYPE._RKE,
|
|
214
258
|
};
|
|
215
259
|
},
|
|
216
260
|
|
|
@@ -218,6 +262,12 @@ export default {
|
|
|
218
262
|
secretTypes() {
|
|
219
263
|
const types = [];
|
|
220
264
|
|
|
265
|
+
if ( this.fixedImagePullSecret ) {
|
|
266
|
+
types.push(SECRET_TYPES.DOCKER_JSON);
|
|
267
|
+
|
|
268
|
+
return types;
|
|
269
|
+
}
|
|
270
|
+
|
|
221
271
|
if ( this.allowSsh ) {
|
|
222
272
|
types.push(SECRET_TYPES.SSH);
|
|
223
273
|
}
|
|
@@ -325,7 +375,7 @@ export default {
|
|
|
325
375
|
});
|
|
326
376
|
}
|
|
327
377
|
|
|
328
|
-
if (this.allowSsh || this.allowS3 || this.allowBasic || this.allowRke) {
|
|
378
|
+
if (this.allowSsh || this.allowS3 || this.allowBasic || this.allowRke || this.fixedImagePullSecret) {
|
|
329
379
|
out.unshift({
|
|
330
380
|
label: 'divider',
|
|
331
381
|
disabled: true,
|
|
@@ -366,6 +416,18 @@ export default {
|
|
|
366
416
|
});
|
|
367
417
|
}
|
|
368
418
|
|
|
419
|
+
if ( this.fixedImagePullSecret ) {
|
|
420
|
+
out.unshift({
|
|
421
|
+
label: this.t('selectOrCreateAuthSecret.createImagePullSecret'),
|
|
422
|
+
value: AUTH_TYPE._IMAGE_PULL_SECRET,
|
|
423
|
+
kind: 'highlighted'
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (this.fixedHttpBasicAuth) {
|
|
428
|
+
out = out.filter((o) => o.label.search(this.filterBasicAuth) === 0 || ['title', 'divider'].includes(o.kind) || o.value === AUTH_TYPE._BASIC);
|
|
429
|
+
}
|
|
430
|
+
|
|
369
431
|
return out;
|
|
370
432
|
},
|
|
371
433
|
|
|
@@ -374,7 +436,7 @@ export default {
|
|
|
374
436
|
return '';
|
|
375
437
|
}
|
|
376
438
|
|
|
377
|
-
if ( this.selected === AUTH_TYPE._SSH || this.selected === AUTH_TYPE._BASIC || this.selected === AUTH_TYPE._RKE || this.selected === AUTH_TYPE._S3 ) {
|
|
439
|
+
if ( this.selected === AUTH_TYPE._SSH || this.selected === AUTH_TYPE._BASIC || this.selected === AUTH_TYPE._RKE || this.selected === AUTH_TYPE._S3 || this.selected === AUTH_TYPE._IMAGE_PULL_SECRET ) {
|
|
378
440
|
return 'col span-4';
|
|
379
441
|
}
|
|
380
442
|
|
|
@@ -395,6 +457,7 @@ export default {
|
|
|
395
457
|
publicKey: 'updateKeyVal',
|
|
396
458
|
privateKey: 'updateKeyVal',
|
|
397
459
|
sshKnownHosts: 'updateKeyVal',
|
|
460
|
+
preSelect: 'updateSelectedFromValue',
|
|
398
461
|
value: 'updateSelectedFromValue',
|
|
399
462
|
|
|
400
463
|
async namespace(ns) {
|
|
@@ -478,7 +541,7 @@ export default {
|
|
|
478
541
|
},
|
|
479
542
|
|
|
480
543
|
updateKeyVal() {
|
|
481
|
-
if ( ![AUTH_TYPE._SSH, AUTH_TYPE._BASIC, AUTH_TYPE._S3, AUTH_TYPE._RKE].includes(this.selected) ) {
|
|
544
|
+
if ( ![AUTH_TYPE._SSH, AUTH_TYPE._BASIC, AUTH_TYPE._S3, AUTH_TYPE._RKE, AUTH_TYPE._IMAGE_PULL_SECRET].includes(this.selected) ) {
|
|
482
545
|
this.privateKey = '';
|
|
483
546
|
this.publicKey = '';
|
|
484
547
|
this.sshKnownHosts = '';
|
|
@@ -498,9 +561,9 @@ export default {
|
|
|
498
561
|
},
|
|
499
562
|
|
|
500
563
|
update() {
|
|
501
|
-
if ( (!this.selected || [AUTH_TYPE._SSH, AUTH_TYPE._BASIC, AUTH_TYPE._S3, AUTH_TYPE._RKE, AUTH_TYPE._NONE].includes(this.selected))) {
|
|
564
|
+
if ( (!this.selected || [AUTH_TYPE._SSH, AUTH_TYPE._BASIC, AUTH_TYPE._S3, AUTH_TYPE._RKE, AUTH_TYPE._NONE, AUTH_TYPE._IMAGE_PULL_SECRET].includes(this.selected))) {
|
|
502
565
|
this.$emit('update:value', null);
|
|
503
|
-
} else if ( this.selected.includes(':')
|
|
566
|
+
} else if ( this.selected.includes(':')) {
|
|
504
567
|
// Cloud creds
|
|
505
568
|
this.$emit('update:value', this.selected);
|
|
506
569
|
} else {
|
|
@@ -522,7 +585,7 @@ export default {
|
|
|
522
585
|
},
|
|
523
586
|
|
|
524
587
|
async doCreate() {
|
|
525
|
-
if ( ![AUTH_TYPE._SSH, AUTH_TYPE._BASIC, AUTH_TYPE._S3, AUTH_TYPE._RKE].includes(this.selected) || this.delegateCreateToParent ) {
|
|
588
|
+
if ( ![AUTH_TYPE._SSH, AUTH_TYPE._BASIC, AUTH_TYPE._S3, AUTH_TYPE._RKE, AUTH_TYPE._IMAGE_PULL_SECRET].includes(this.selected) || this.delegateCreateToParent ) {
|
|
526
589
|
return;
|
|
527
590
|
}
|
|
528
591
|
|
|
@@ -537,12 +600,17 @@ export default {
|
|
|
537
600
|
},
|
|
538
601
|
});
|
|
539
602
|
} else {
|
|
603
|
+
const metadata = { namespace: this.namespace };
|
|
604
|
+
|
|
605
|
+
if (this.clientGeneratedName) {
|
|
606
|
+
metadata.name = this.clientGeneratedName;
|
|
607
|
+
} else {
|
|
608
|
+
metadata.generateName = this.generateName;
|
|
609
|
+
}
|
|
610
|
+
|
|
540
611
|
secret = await this.$store.dispatch(`${ this.inStore }/create`, {
|
|
541
|
-
type:
|
|
542
|
-
metadata
|
|
543
|
-
namespace: this.namespace,
|
|
544
|
-
generateName: this.generateName
|
|
545
|
-
},
|
|
612
|
+
type: SECRET,
|
|
613
|
+
metadata,
|
|
546
614
|
});
|
|
547
615
|
|
|
548
616
|
let type, publicField, privateField;
|
|
@@ -558,6 +626,11 @@ export default {
|
|
|
558
626
|
publicField = 'username';
|
|
559
627
|
privateField = 'password';
|
|
560
628
|
break;
|
|
629
|
+
case AUTH_TYPE._IMAGE_PULL_SECRET:
|
|
630
|
+
type = SECRET_TYPES.DOCKER_JSON;
|
|
631
|
+
publicField = 'username';
|
|
632
|
+
privateField = 'password';
|
|
633
|
+
break;
|
|
561
634
|
case AUTH_TYPE._RKE:
|
|
562
635
|
type = SECRET_TYPES.RKE_AUTH_CONFIG;
|
|
563
636
|
// Set the 'auth' key to be the base64 of the username and password concatenated with a ':' character
|
|
@@ -581,6 +654,22 @@ export default {
|
|
|
581
654
|
if ((this.selected === AUTH_TYPE._SSH) && this.showSshKnownHosts) {
|
|
582
655
|
secret.data.known_hosts = base64Encode(this.sshKnownHosts || '');
|
|
583
656
|
}
|
|
657
|
+
|
|
658
|
+
if (this.selected === AUTH_TYPE._IMAGE_PULL_SECRET && this.imagePullSecretDockerJsonUrlConfig) {
|
|
659
|
+
const registryHost = this.imagePullSecretDockerJsonUrlConfig ? new URL(this.imagePullSecretDockerJsonUrlConfig).host : '';
|
|
660
|
+
|
|
661
|
+
const config = {
|
|
662
|
+
auths: {
|
|
663
|
+
[registryHost]: {
|
|
664
|
+
[publicField]: this.publicKey,
|
|
665
|
+
[privateField]: this.privateKey,
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
const json = JSON.stringify(config);
|
|
670
|
+
|
|
671
|
+
secret.setData('.dockerconfigjson', json);
|
|
672
|
+
}
|
|
584
673
|
}
|
|
585
674
|
}
|
|
586
675
|
|
|
@@ -609,7 +698,7 @@ export default {
|
|
|
609
698
|
v-model:value="selected"
|
|
610
699
|
data-testid="auth-secret-select"
|
|
611
700
|
:mode="mode"
|
|
612
|
-
:label-key="labelKey"
|
|
701
|
+
:label-key="fixedImagePullSecret ? 'selectOrCreateAuthSecret.imagePullSecret' : labelKey"
|
|
613
702
|
:loading="$fetchState.pending"
|
|
614
703
|
:options="options"
|
|
615
704
|
:selectable="option => !option.disabled"
|
|
@@ -645,7 +734,7 @@ export default {
|
|
|
645
734
|
/>
|
|
646
735
|
</div>
|
|
647
736
|
</template>
|
|
648
|
-
<template v-else-if="selected === BASIC || selected === RKE">
|
|
737
|
+
<template v-else-if="selected === BASIC || selected === RKE || selected === IMAGE_PULL_SECRET">
|
|
649
738
|
<Banner
|
|
650
739
|
v-if="selected === RKE"
|
|
651
740
|
color="info"
|
|
@@ -6,12 +6,17 @@ const requiredSetup = () => {
|
|
|
6
6
|
return {
|
|
7
7
|
global: {
|
|
8
8
|
mocks: {
|
|
9
|
-
$
|
|
9
|
+
$fetchState: { pending: false },
|
|
10
|
+
$store: {
|
|
10
11
|
getters: {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
t:
|
|
14
|
-
|
|
12
|
+
currentStore: () => 'cluster',
|
|
13
|
+
currentProduct: { inStore: 'cluster' },
|
|
14
|
+
'i18n/t': (text: string) => text,
|
|
15
|
+
t: (text: string) => text,
|
|
16
|
+
'cluster/paginationEnabled': () => false,
|
|
17
|
+
'cluster/all': () => ['node-0', 'node-1'],
|
|
18
|
+
},
|
|
19
|
+
dispatch: jest.fn(),
|
|
15
20
|
}
|
|
16
21
|
},
|
|
17
22
|
}
|
|
@@ -21,8 +26,6 @@ const requiredSetup = () => {
|
|
|
21
26
|
describe('component: NodeScheduling', () => {
|
|
22
27
|
const value = { nodeName: 'node-1' };
|
|
23
28
|
|
|
24
|
-
const nodes = ['node-0', 'node-1'];
|
|
25
|
-
|
|
26
29
|
it.each([
|
|
27
30
|
_VIEW,
|
|
28
31
|
_CREATE,
|
|
@@ -32,13 +35,13 @@ describe('component: NodeScheduling', () => {
|
|
|
32
35
|
NodeScheduling,
|
|
33
36
|
{
|
|
34
37
|
props: {
|
|
35
|
-
mode, loading: false, value
|
|
38
|
+
mode, loading: false, value
|
|
36
39
|
},
|
|
37
40
|
...requiredSetup(),
|
|
38
41
|
}
|
|
39
42
|
);
|
|
40
43
|
|
|
41
44
|
expect(wrapper.find('[data-testid="node-scheduling-selectNode"]').exists()).toBeTruthy();
|
|
42
|
-
expect(wrapper.find('[data-testid="node-scheduling-nodeSelector"]').
|
|
45
|
+
expect(wrapper.find('[data-testid="node-scheduling-nodeSelector"] .vs__selected').text()).toBe(value.nodeName);
|
|
43
46
|
});
|
|
44
47
|
});
|
|
@@ -3,6 +3,23 @@ import { mount } from '@vue/test-utils';
|
|
|
3
3
|
import PodAffinity from '@shell/components/form/PodAffinity.vue';
|
|
4
4
|
import { _CREATE } from '@shell/config/query-params';
|
|
5
5
|
|
|
6
|
+
const requiredSetup = () => {
|
|
7
|
+
return {
|
|
8
|
+
global: {
|
|
9
|
+
mocks: {
|
|
10
|
+
$store: {
|
|
11
|
+
getters: {
|
|
12
|
+
currentStore: () => 'cluster',
|
|
13
|
+
'i18n/t': (text: string) => text,
|
|
14
|
+
'cluster/schemaFor': jest.fn(),
|
|
15
|
+
'cluster/canList': jest.fn(),
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
6
23
|
describe('component: PodAffinity', () => {
|
|
7
24
|
it('should display the weight input when the priority is preferred', () => {
|
|
8
25
|
const podAffinity = {
|
|
@@ -15,7 +32,8 @@ describe('component: PodAffinity', () => {
|
|
|
15
32
|
const wrapper = mount(PodAffinity, {
|
|
16
33
|
props: {
|
|
17
34
|
mode: _CREATE, field: 'overrideAffinity', value: { overrideAffinity: { podAffinity } }
|
|
18
|
-
}
|
|
35
|
+
},
|
|
36
|
+
...requiredSetup()
|
|
19
37
|
});
|
|
20
38
|
|
|
21
39
|
expect(wrapper.find('[data-testid="pod-affinity-weight-index0"]').exists()).toBeTruthy();
|
|
@@ -33,7 +51,8 @@ describe('component: PodAffinity', () => {
|
|
|
33
51
|
const wrapper = mount(PodAffinity, {
|
|
34
52
|
props: {
|
|
35
53
|
mode: _CREATE, field: 'overrideAffinity', value: { overrideAffinity: { podAffinity } }
|
|
36
|
-
}
|
|
54
|
+
},
|
|
55
|
+
...requiredSetup()
|
|
37
56
|
});
|
|
38
57
|
|
|
39
58
|
const weightInput = wrapper.find('[data-testid="pod-affinity-weight-index0"]');
|
|
@@ -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>
|