@rancher/shell 3.0.3 → 3.0.5-rc.1

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 (139) hide show
  1. package/assets/styles/base/_basic.scss +6 -0
  2. package/assets/styles/global/_button.scss +1 -0
  3. package/assets/translations/en-us.yaml +38 -3
  4. package/cloud-credential/aws.vue +2 -0
  5. package/components/AssignTo.vue +25 -11
  6. package/components/AsyncButton.vue +24 -7
  7. package/components/BannerGraphic.vue +1 -0
  8. package/components/CommunityLinks.vue +3 -3
  9. package/components/CopyToClipboardText.vue +2 -1
  10. package/components/DetailText.vue +5 -0
  11. package/components/DisableAuthProviderModal.vue +1 -0
  12. package/components/ExplorerMembers.vue +1 -1
  13. package/components/ExplorerProjectsNamespaces.vue +56 -14
  14. package/components/LandingPagePreference.vue +5 -3
  15. package/components/LocaleSelector.vue +38 -94
  16. package/components/ModalWithCard.vue +1 -0
  17. package/components/MoveModal.vue +1 -0
  18. package/components/PromptRemove.vue +2 -1
  19. package/components/PromptRestore.vue +1 -0
  20. package/components/ResourceCancelModal.vue +1 -0
  21. package/components/SortableTable/index.vue +35 -10
  22. package/components/StatusBadge.vue +10 -4
  23. package/components/__tests__/AsyncButton.test.ts +2 -2
  24. package/components/auth/Principal.vue +9 -3
  25. package/components/auth/__tests__/RoleDetailEdit.test.ts +3 -2
  26. package/components/form/ArrayList.vue +75 -54
  27. package/components/form/Command.vue +6 -15
  28. package/components/form/EnvVars.vue +15 -8
  29. package/components/form/HealthCheck.vue +3 -3
  30. package/components/form/HookOption.vue +11 -16
  31. package/components/form/KeyValue.vue +1 -1
  32. package/components/form/LabeledSelect.vue +2 -1
  33. package/components/form/LifecycleHooks.vue +3 -3
  34. package/components/form/MatchExpressions.vue +10 -7
  35. package/components/form/NameNsDescription.vue +123 -103
  36. package/components/form/Networking.vue +20 -12
  37. package/components/form/NodeAffinity.vue +31 -23
  38. package/components/form/NodeScheduling.vue +13 -3
  39. package/components/form/PodAffinity.vue +43 -43
  40. package/components/form/Probe.vue +67 -66
  41. package/components/form/ResourceQuota/Project.vue +5 -1
  42. package/components/form/ResourceSelector.vue +7 -9
  43. package/components/form/SSHKnownHosts/KnownHostsEditDialog.vue +6 -3
  44. package/components/form/SSHKnownHosts/__tests__/KnownHostsEditDialog.test.ts +12 -1
  45. package/components/form/SSHKnownHosts/index.vue +16 -2
  46. package/components/form/Security.vue +54 -56
  47. package/components/form/Select.vue +31 -6
  48. package/components/form/ShellInput.vue +5 -1
  49. package/components/form/Tolerations.vue +5 -1
  50. package/components/form/ValueFromResource.vue +134 -121
  51. package/components/form/WorkloadPorts.vue +18 -18
  52. package/components/form/__tests__/ArrayList.test.ts +3 -0
  53. package/components/form/__tests__/MatchExpressions.test.ts +12 -12
  54. package/components/form/__tests__/NameNsDescription.test.ts +115 -14
  55. package/components/form/__tests__/Probe.test.ts +12 -8
  56. package/components/form/__tests__/SSHKnownHosts.test.ts +11 -0
  57. package/components/form/__tests__/Select.test.ts +37 -0
  58. package/components/formatter/InternalExternalIP.vue +2 -0
  59. package/components/formatter/SecretData.vue +20 -7
  60. package/components/nav/Group.vue +15 -1
  61. package/components/nav/Header.vue +1 -0
  62. package/components/nav/Type.vue +12 -1
  63. package/components/templates/blank.vue +4 -1
  64. package/components/templates/default.vue +2 -0
  65. package/components/templates/home.vue +4 -1
  66. package/components/templates/plain.vue +4 -1
  67. package/composables/useRuntimeFlag.ts +29 -0
  68. package/config/router/routes.js +20 -13
  69. package/core/types.ts +5 -0
  70. package/dialog/AddCustomBadgeDialog.vue +1 -0
  71. package/dialog/DeactivateDriverDialog.vue +5 -4
  72. package/dialog/ForceMachineRemoveDialog.vue +4 -1
  73. package/dialog/GitRepoForceUpdateDialog.vue +1 -1
  74. package/edit/__tests__/monitoring.coreos.com.prometheusrule.test.ts +16 -3
  75. package/edit/auth/__tests__/oidc.test.ts +152 -109
  76. package/edit/auth/azuread.vue +1 -0
  77. package/edit/auth/googleoauth.vue +4 -0
  78. package/edit/auth/oidc.vue +37 -4
  79. package/edit/cloudcredential.vue +1 -0
  80. package/edit/fleet.cattle.io.gitrepo.vue +1 -0
  81. package/edit/logging.banzaicloud.io.output/__tests__/logging.banzaicloud.io.output.test.ts +40 -9
  82. package/edit/networking.k8s.io.ingress/IngressClass.vue +7 -3
  83. package/edit/networking.k8s.io.ingress/__tests__/IngressClass.test.ts +58 -0
  84. package/edit/persistentvolume/__tests__/persistentvolume.test.ts +14 -2
  85. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +1 -0
  86. package/edit/provisioning.cattle.io.cluster/rke2.vue +25 -34
  87. package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +6 -1
  88. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +29 -1
  89. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +2 -2
  90. package/edit/token.vue +2 -0
  91. package/edit/workload/index.vue +1 -0
  92. package/edit/workload/mixins/workload.js +0 -2
  93. package/list/management.cattle.io.feature.vue +1 -0
  94. package/list/provisioning.cattle.io.cluster.vue +20 -12
  95. package/machine-config/__tests__/vmwarevsphere.test.ts +48 -3
  96. package/machine-config/vmwarevsphere.vue +16 -0
  97. package/models/__tests__/namespace.test.ts +25 -1
  98. package/models/cloudcredential.js +5 -0
  99. package/models/kontainerdriver.js +6 -3
  100. package/models/management.cattle.io.node.js +3 -3
  101. package/models/namespace.js +4 -5
  102. package/models/nodedriver.js +6 -3
  103. package/models/workload.js +4 -1
  104. package/package.json +4 -4
  105. package/pages/about.vue +16 -8
  106. package/pages/account/index.vue +4 -1
  107. package/pages/auth/login.vue +11 -3
  108. package/pages/auth/logout.vue +4 -1
  109. package/pages/auth/setup.vue +1 -0
  110. package/pages/auth/verify.vue +4 -1
  111. package/pages/c/_cluster/apps/charts/chart.vue +1 -1
  112. package/pages/diagnostic.vue +47 -2
  113. package/pages/fail-whale.vue +6 -3
  114. package/pages/home.vue +24 -18
  115. package/pages/support/index.vue +4 -1
  116. package/promptRemove/management.cattle.io.fleetworkspace.vue +1 -1
  117. package/promptRemove/management.cattle.io.globalrole.vue +1 -1
  118. package/promptRemove/management.cattle.io.project.vue +2 -2
  119. package/promptRemove/management.cattle.io.roletemplate.vue +1 -1
  120. package/promptRemove/pod.vue +1 -1
  121. package/rancher-components/Form/Radio/RadioGroup.vue +25 -23
  122. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +3 -3
  123. package/rancher-components/RcDropdown/RcDropdown.vue +6 -5
  124. package/rancher-components/RcDropdown/RcDropdownMenu.vue +4 -2
  125. package/rancher-components/RcDropdown/RcDropdownTrigger.vue +12 -2
  126. package/rancher-components/RcDropdown/useDropdownCollection.ts +8 -0
  127. package/rancher-components/RcDropdown/useDropdownContext.ts +9 -3
  128. package/scripts/extension/publish +1 -0
  129. package/server/har-file.js +25 -3
  130. package/store/features.js +2 -1
  131. package/store/type-map.js +4 -0
  132. package/types/shell/index.d.ts +9 -2
  133. package/utils/__tests__/string.test.ts +2 -2
  134. package/utils/cluster.js +35 -0
  135. package/utils/string.js +1 -3
  136. package/utils/validators/machine-pool.ts +20 -0
  137. package/components/formatter/ExtensionCache.vue +0 -74
  138. package/components/formatter/Port.vue +0 -24
  139. package/components/formatter/SecretType.vue +0 -41
@@ -84,53 +84,14 @@ export default {
84
84
  },
85
85
 
86
86
  data() {
87
- if (!this.value[this.field]) {
88
- this.value[this.field] = {};
89
- }
90
- const { podAffinity = {}, podAntiAffinity = {} } = this.value[this.field];
91
- const allAffinityTerms = [...(podAffinity.preferredDuringSchedulingIgnoredDuringExecution || []), ...(podAffinity.requiredDuringSchedulingIgnoredDuringExecution || [])].map((term) => {
92
- let out = clone(term);
93
-
94
- out._id = randomStr(4);
95
- out._anti = false;
96
- if (term.podAffinityTerm) {
97
- Object.assign(out, term.podAffinityTerm);
98
- out = this.parsePodAffinityTerm(out);
99
-
100
- delete out.podAffinityTerm;
101
- } else {
102
- out = this.parsePodAffinityTerm(out);
103
- }
104
-
105
- return out;
106
- });
107
- const allAntiTerms = [...(podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution || []), ...(podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution || [])].map((term) => {
108
- let out = clone(term);
109
-
110
- out._id = randomStr(4);
111
- out._anti = true;
112
- if (term.podAffinityTerm) {
113
- Object.assign(out, term.podAffinityTerm);
114
- out = this.parsePodAffinityTerm(out);
115
-
116
- delete out.podAffinityTerm;
117
- } else {
118
- out = this.parsePodAffinityTerm(out);
119
- }
120
-
121
- return out;
122
- });
123
-
124
- const allSelectorTerms = [...allAffinityTerms, ...allAntiTerms];
125
-
126
87
  return {
127
- allSelectorTerms,
128
- defaultWeight: 1,
88
+ allSelectorTerms: [],
89
+ defaultWeight: 1,
129
90
  // rules in MatchExpressions.vue can not catch changes what happens on parent component
130
91
  // we need re-render it via key changing
131
- rerenderNums: randomStr(4),
92
+ rerenderNums: randomStr(4),
132
93
  NAMESPACE_SELECTION_OPTION_VALUES,
133
- defaultAddValue: {
94
+ defaultAddValue: {
134
95
  _namespaceOption: NAMESPACE_SELECTION_OPTION_VALUES.POD,
135
96
  matchExpressions: [],
136
97
  namespaces: null,
@@ -138,6 +99,7 @@ export default {
138
99
  }
139
100
  };
140
101
  },
102
+
141
103
  computed: {
142
104
  ...mapGetters({ t: 'i18n/t' }),
143
105
  isView() {
@@ -226,6 +188,44 @@ export default {
226
188
  },
227
189
 
228
190
  created() {
191
+ if (!this.value[this.field]) {
192
+ this.value[this.field] = {};
193
+ }
194
+ const { podAffinity = {}, podAntiAffinity = {} } = this.value[this.field];
195
+ const allAffinityTerms = [...(podAffinity.preferredDuringSchedulingIgnoredDuringExecution || []), ...(podAffinity.requiredDuringSchedulingIgnoredDuringExecution || [])].map((term) => {
196
+ let out = clone(term);
197
+
198
+ out._id = randomStr(4);
199
+ out._anti = false;
200
+ if (term.podAffinityTerm) {
201
+ Object.assign(out, term.podAffinityTerm);
202
+ out = this.parsePodAffinityTerm(out);
203
+
204
+ delete out.podAffinityTerm;
205
+ } else {
206
+ out = this.parsePodAffinityTerm(out);
207
+ }
208
+
209
+ return out;
210
+ });
211
+ const allAntiTerms = [...(podAntiAffinity.preferredDuringSchedulingIgnoredDuringExecution || []), ...(podAntiAffinity.requiredDuringSchedulingIgnoredDuringExecution || [])].map((term) => {
212
+ let out = clone(term);
213
+
214
+ out._id = randomStr(4);
215
+ out._anti = true;
216
+ if (term.podAffinityTerm) {
217
+ Object.assign(out, term.podAffinityTerm);
218
+ out = this.parsePodAffinityTerm(out);
219
+
220
+ delete out.podAffinityTerm;
221
+ } else {
222
+ out = this.parsePodAffinityTerm(out);
223
+ }
224
+
225
+ return out;
226
+ });
227
+
228
+ this.allSelectorTerms = [...allAffinityTerms, ...allAntiTerms];
229
229
  this.queueUpdate = debounce(this.update, 500);
230
230
  },
231
231
 
@@ -6,6 +6,7 @@ import { LabeledInput } from '@components/Form/LabeledInput';
6
6
  import LabeledSelect from '@shell/components/form/LabeledSelect';
7
7
  import ShellInput from '@shell/components/form/ShellInput';
8
8
  import KeyValue from '@shell/components/form/KeyValue';
9
+ import { computed, ref, watch } from 'vue';
9
10
 
10
11
  const KINDS = [
11
12
  'none',
@@ -43,29 +44,29 @@ export default {
43
44
  },
44
45
  },
45
46
 
46
- data() {
47
- let kind = 'none';
48
- let probe = null;
49
- let exec = null;
50
- let httpGet = null;
51
- let tcpSocket = null;
52
-
53
- if ( this.value ) {
54
- probe = clone(this.value);
55
-
56
- if ( probe.exec ) {
57
- kind = 'exec';
58
- } else if ( probe.httpGet ) {
59
- if ( (probe.httpGet.scheme || '').toLowerCase() === 'https' ) {
60
- kind = 'HTTPS';
47
+ setup(props, { emit }) {
48
+ const kind = ref('none');
49
+ const probe = ref(null);
50
+ const exec = ref(null);
51
+ const httpGet = ref(null);
52
+ const tcpSocket = ref(null);
53
+
54
+ if ( props.value ) {
55
+ probe.value = clone(props.value);
56
+
57
+ if ( probe.value.exec ) {
58
+ kind.value = 'exec';
59
+ } else if ( probe.value.httpGet ) {
60
+ if ( (probe.value.httpGet.scheme || '').toLowerCase() === 'https' ) {
61
+ kind.value = 'HTTPS';
61
62
  } else {
62
- kind = 'HTTP';
63
+ kind.value = 'HTTP';
63
64
  }
64
- } else if ( probe.tcpSocket ) {
65
- kind = 'tcp';
65
+ } else if ( probe.value.tcpSocket ) {
66
+ kind.value = 'tcp';
66
67
  }
67
68
  } else {
68
- probe = {
69
+ probe.value = {
69
70
  failureThreshold: 3,
70
71
  successThreshold: 1,
71
72
  initialDelaySeconds: 0,
@@ -77,68 +78,68 @@ export default {
77
78
  };
78
79
  }
79
80
 
80
- exec = probe.exec || {};
81
- httpGet = probe.httpGet || {};
82
- tcpSocket = probe.tcpSocket || {};
81
+ exec.value = probe.value.exec || {};
82
+ httpGet.value = probe.value.httpGet || {};
83
+ tcpSocket.value = probe.value.tcpSocket || {};
83
84
 
84
- return {
85
- probe, kind, exec, httpGet, tcpSocket
86
- };
87
- },
88
-
89
- computed: {
90
- isView() {
91
- return this.mode === _VIEW;
92
- },
93
-
94
- isNone() {
95
- return this.kind === 'none';
96
- },
85
+ const isNone = computed(() => {
86
+ return kind.value === 'none';
87
+ });
97
88
 
98
- kindOptions() {
99
- return KINDS.map((k) => {
100
- return { label: this.t(`workload.container.healthCheck.kind.${ k }`), value: k };
101
- });
102
- }
103
- },
104
-
105
- watch: {
106
- kind() {
107
- this.update();
108
- }
109
- },
110
-
111
- methods: {
112
- update() {
113
- const probe = this.probe;
114
-
115
- if ( this.isNone ) {
116
- this.$emit('update:value', null);
89
+ const update = () => {
90
+ if ( isNone.value ) {
91
+ emit('update:value', null);
117
92
 
118
93
  return;
119
94
  }
120
95
 
121
- switch ( this.kind ) {
96
+ switch ( kind.value ) {
122
97
  case 'HTTP':
123
98
  case 'HTTPS':
124
- this.httpGet.scheme = this.kind;
125
- probe.httpGet = this.httpGet;
126
- probe.tcpSocket = null;
127
- probe.exec = null;
99
+ httpGet.value.scheme = kind.value;
100
+ probe.value.httpGet = httpGet.value;
101
+ probe.value.tcpSocket = null;
102
+ probe.value.exec = null;
128
103
  break;
129
104
  case 'tcp':
130
- probe.httpGet = null;
131
- probe.tcpSocket = this.tcpSocket;
132
- probe.exec = null;
105
+ probe.value.httpGet = null;
106
+ probe.value.tcpSocket = tcpSocket.value;
107
+ probe.value.exec = null;
133
108
  break;
134
109
  case 'exec':
135
- probe.httpGet = null;
136
- probe.tcpSocket = null;
137
- probe.exec = this.exec;
110
+ probe.value.httpGet = null;
111
+ probe.value.tcpSocket = null;
112
+ probe.value.exec = exec.value;
138
113
  break;
139
114
  }
140
115
 
141
- this.$emit('update:value', probe);
116
+ emit('update:value', probe.value);
117
+ };
118
+
119
+ watch(kind, () => {
120
+ update();
121
+ });
122
+
123
+ return {
124
+ probe,
125
+ kind,
126
+ exec,
127
+ httpGet,
128
+ tcpSocket,
129
+ update,
130
+ isNone,
131
+ };
132
+ },
133
+
134
+ computed: {
135
+ isView() {
136
+ return this.mode === _VIEW;
137
+ },
138
+
139
+ kindOptions() {
140
+ return KINDS.map((k) => {
141
+ return { label: this.t(`workload.container.healthCheck.kind.${ k }`), value: k };
142
+ });
142
143
  }
143
144
  },
144
145
  };
@@ -28,11 +28,15 @@ export default {
28
28
  },
29
29
 
30
30
  data() {
31
+ return { typeValues: null };
32
+ },
33
+
34
+ created() {
31
35
  this.value['spec'] = this.value.spec || {};
32
36
  this.value.spec['namespaceDefaultResourceQuota'] = this.value.spec.namespaceDefaultResourceQuota || { limit: {} };
33
37
  this.value.spec['resourceQuota'] = this.value.spec.resourceQuota || { limit: {} };
34
38
 
35
- return { typeValues: Object.keys(this.value.spec.resourceQuota.limit) };
39
+ this.typeValues = Object.keys(this.value.spec.resourceQuota.limit);
36
40
  },
37
41
 
38
42
  computed: { ...QUOTA_COMPUTED },
@@ -45,16 +45,14 @@ export default {
45
45
  },
46
46
 
47
47
  data() {
48
- const matchingResources = {
49
- matched: 0,
50
- matches: [],
51
- none: true,
52
- sample: null,
53
- total: 0,
54
- };
55
-
56
48
  return {
57
- matchingResources,
49
+ matchingResources: {
50
+ matched: 0,
51
+ matches: [],
52
+ none: true,
53
+ sample: null,
54
+ total: 0,
55
+ },
58
56
  allResources: [],
59
57
  allResourcesInScope: [],
60
58
  tableHeaders: this.$store.getters['type-map/headersFor'](
@@ -22,7 +22,7 @@ export default {
22
22
  mode: {
23
23
  type: String,
24
24
  default: _EDIT
25
- },
25
+ }
26
26
  },
27
27
 
28
28
  data() {
@@ -40,8 +40,9 @@ export default {
40
40
 
41
41
  return {
42
42
  codeMirrorOptions,
43
- text: this.value,
44
- showModal: false,
43
+ text: this.value,
44
+ showModal: false,
45
+ returnFocusSelector: '#known-ssh-hosts-trigger'
45
46
  };
46
47
  },
47
48
 
@@ -83,6 +84,8 @@ export default {
83
84
  data-testid="sshKnownHostsDialog"
84
85
  height="auto"
85
86
  :scrollable="true"
87
+ :trigger-focus-trap="true"
88
+ :return-focus-selector="returnFocusSelector"
86
89
  @close="closeDialog(false)"
87
90
  >
88
91
  <div
@@ -14,6 +14,17 @@ const requiredSetup = () => {
14
14
  return { global: { mocks: { $store: mockedStore() } } };
15
15
  };
16
16
 
17
+ jest.mock('focus-trap', () => {
18
+ return {
19
+ createFocusTrap: jest.fn().mockImplementation(() => {
20
+ return {
21
+ activate: jest.fn(),
22
+ deactivate: jest.fn(),
23
+ };
24
+ }),
25
+ };
26
+ });
27
+
17
28
  describe('component: KnownHostsEditDialog', () => {
18
29
  beforeEach(() => {
19
30
  document.body.innerHTML = '<div id="modals"></div>';
@@ -21,7 +32,7 @@ describe('component: KnownHostsEditDialog', () => {
21
32
  attachTo: document.body,
22
33
  props: {
23
34
  mode: _EDIT,
24
- value: 'line1\nline2\n',
35
+ value: 'line1\nline2\n'
25
36
  },
26
37
  ...requiredSetup(),
27
38
  });
@@ -65,12 +65,18 @@ export default defineComponent({
65
65
  </div>
66
66
  <template v-if="!isViewMode">
67
67
  <button
68
+ id="known-ssh-hosts-trigger"
68
69
  ref="button"
70
+ role="button"
71
+ :aria-label="t('secret.ssh.editKnownHosts.title')"
69
72
  data-testid="input-known-ssh-hosts_open-dialog"
70
73
  class="show-dialog-btn btn"
71
74
  @click="openDialog"
72
75
  >
73
- <i class="icon icon-edit" />
76
+ <i
77
+ class="icon icon-edit"
78
+ :alt="t('secret.ssh.editKnownHosts.title')"
79
+ />
74
80
  </button>
75
81
 
76
82
  <KnownHostsEditDialog
@@ -94,8 +100,16 @@ export default defineComponent({
94
100
  }
95
101
 
96
102
  .show-dialog-btn {
97
- display: contents;
98
103
  background-color: transparent;
104
+ padding: 4px;
105
+ height: 22px;
106
+ margin: -3px -3px 0 0;
107
+ min-height: unset;
108
+
109
+ &:focus-visible {
110
+ @include focus-outline;
111
+ outline-offset: 1px;
112
+ }
99
113
  }
100
114
  }
101
115
  </style>
@@ -5,6 +5,45 @@ import { _VIEW } from '@shell/config/query-params';
5
5
  import { mapGetters } from 'vuex';
6
6
  import LabeledSelect from '@shell/components/form/LabeledSelect';
7
7
 
8
+ const allCapabilities = ['ALL',
9
+ 'AUDIT_CONTROL',
10
+ 'AUDIT_WRITE',
11
+ 'BLOCK_SUSPEND',
12
+ 'CHOWN',
13
+ 'DAC_OVERRIDE',
14
+ 'DAC_READ_SEARCH',
15
+ 'FOWNER',
16
+ 'FSETID',
17
+ 'IPC_LOCK',
18
+ 'IPC_OWNER',
19
+ 'KILL',
20
+ 'LEASE',
21
+ 'LINUX_IMMUTABLE',
22
+ 'MAC_ADMIN',
23
+ 'MAC_OVERRIDE',
24
+ 'MKNOD',
25
+ 'NET_ADMIN',
26
+ 'NET_BIND_SERVICE',
27
+ 'NET_BROADCAST',
28
+ 'NET_RAW',
29
+ 'SETFCAP',
30
+ 'SETGID',
31
+ 'SETPCAP',
32
+ 'SETUID',
33
+ 'SYSLOG',
34
+ 'SYS_ADMIN',
35
+ 'SYS_BOOT',
36
+ 'SYS_CHROOT',
37
+ 'SYS_MODULE',
38
+ 'SYS_NICE',
39
+ 'SYS_PACCT',
40
+ 'SYS_PTRACE',
41
+ 'SYS_RAWIO',
42
+ 'SYS_RESOURCE',
43
+ 'SYS_TIME',
44
+ 'SYS_TTY_CONFIG',
45
+ 'WAKE_ALARM'];
46
+
8
47
  export default {
9
48
  emits: ['update:value'],
10
49
 
@@ -25,68 +64,27 @@ export default {
25
64
  },
26
65
 
27
66
  data() {
28
- const allCapabilities = ['ALL',
29
- 'AUDIT_CONTROL',
30
- 'AUDIT_WRITE',
31
- 'BLOCK_SUSPEND',
32
- 'CHOWN',
33
- 'DAC_OVERRIDE',
34
- 'DAC_READ_SEARCH',
35
- 'FOWNER',
36
- 'FSETID',
37
- 'IPC_LOCK',
38
- 'IPC_OWNER',
39
- 'KILL',
40
- 'LEASE',
41
- 'LINUX_IMMUTABLE',
42
- 'MAC_ADMIN',
43
- 'MAC_OVERRIDE',
44
- 'MKNOD',
45
- 'NET_ADMIN',
46
- 'NET_BIND_SERVICE',
47
- 'NET_BROADCAST',
48
- 'NET_RAW',
49
- 'SETFCAP',
50
- 'SETGID',
51
- 'SETPCAP',
52
- 'SETUID',
53
- 'SYSLOG',
54
- 'SYS_ADMIN',
55
- 'SYS_BOOT',
56
- 'SYS_CHROOT',
57
- 'SYS_MODULE',
58
- 'SYS_NICE',
59
- 'SYS_PACCT',
60
- 'SYS_PTRACE',
61
- 'SYS_RAWIO',
62
- 'SYS_RESOURCE',
63
- 'SYS_TIME',
64
- 'SYS_TTY_CONFIG',
65
- 'WAKE_ALARM'];
67
+ return {
68
+ privileged: this.value.privileged || false,
69
+ allowPrivilegeEscalation: this.value.allowPrivilegeEscalation || false,
70
+ allCapabilities,
71
+ runAsNonRoot: this.value.runAsNonRoot || false,
72
+ readOnlyRootFilesystem: this.value.readOnlyRootFilesystem || false,
73
+ add: [],
74
+ drop: [],
75
+ runAsUser: this.value.runAsUser
76
+ };
77
+ },
66
78
 
67
- const {
68
- capabilities = {},
69
- runAsNonRoot = false,
70
- readOnlyRootFilesystem = false,
71
- privileged = false,
72
- allowPrivilegeEscalation = false,
73
- runAsUser
74
- } = this.value;
79
+ created() {
80
+ const { capabilities = {} } = this.value;
75
81
  const {
76
82
  add = [],
77
83
  drop = []
78
84
  } = capabilities;
79
85
 
80
- return {
81
- privileged,
82
- allowPrivilegeEscalation,
83
- allCapabilities,
84
- runAsNonRoot,
85
- readOnlyRootFilesystem,
86
- add,
87
- drop,
88
- runAsUser
89
- };
86
+ this.add = add;
87
+ this.drop = drop;
90
88
  },
91
89
 
92
90
  computed: {
@@ -2,11 +2,12 @@
2
2
  import { get } from '@shell/utils/object';
3
3
  import LabeledFormElement from '@shell/mixins/labeled-form-element';
4
4
  import VueSelectOverrides from '@shell/mixins/vue-select-overrides';
5
+ import { generateRandomAlphaString } from '@shell/utils/string';
5
6
  import { LabeledTooltip } from '@components/LabeledTooltip';
6
7
  import { onClickOption, calculatePosition } from '@shell/utils/select';
7
8
 
8
9
  export default {
9
- emits: ['update:value', 'createdListItem'],
10
+ emits: ['update:value', 'createdListItem', 'on-open', 'on-close'],
10
11
 
11
12
  components: { LabeledTooltip },
12
13
  mixins: [
@@ -90,9 +91,14 @@ export default {
90
91
  isLangSelect: {
91
92
  type: Boolean,
92
93
  default: false
93
- },
94
+ }
95
+ },
96
+ data() {
97
+ return {
98
+ isOpen: false,
99
+ generatedUid: `s-uid-${ generateRandomAlphaString(12) }`
100
+ };
94
101
  },
95
-
96
102
  methods: {
97
103
  // resizeHandler = in mixin
98
104
  getOptionLabel(option) {
@@ -191,14 +197,26 @@ export default {
191
197
  return Math.random(100000);
192
198
  }
193
199
  },
200
+
194
201
  report(e) {
195
202
  alert(e);
196
203
  },
204
+
197
205
  handleDropdownOpen(args) {
198
206
  // function that prevents the "opening dropdown on focus"
199
207
  // default behaviour of v-select
200
208
  return args.noDrop || args.disabled ? false : args.open;
201
- }
209
+ },
210
+ onOpen() {
211
+ this.isOpen = true;
212
+ this.$emit('on-open');
213
+ this.resizeHandler();
214
+ },
215
+
216
+ onClose() {
217
+ this.isOpen = false;
218
+ this.$emit('on-close');
219
+ },
202
220
  },
203
221
  computed: {
204
222
  requiredField() {
@@ -259,6 +277,10 @@ export default {
259
277
  [$attrs.class]: $attrs.class
260
278
  }"
261
279
  :tabindex="disabled || isView ? -1 : 0"
280
+ role="combobox"
281
+ :aria-expanded="isOpen"
282
+ :aria-label="$attrs['aria-label'] || undefined"
283
+ :aria-describedby="$attrs['aria-describedby'] || undefined"
262
284
  @click="focusSearch"
263
285
  @keydown.enter="focusSearch"
264
286
  @keydown.down.prevent="focusSearch"
@@ -286,11 +308,14 @@ export default {
286
308
  :modelValue="value != null ? value : ''"
287
309
  :dropdownShouldOpen="handleDropdownOpen"
288
310
  :tabindex="-1"
289
- role="listbox"
311
+ role="listitem"
312
+ :uid="generatedUid"
313
+ :aria-label="'-'"
290
314
  @update:modelValue="$emit('update:value', $event)"
291
315
  @search:blur="onBlur"
292
316
  @search:focus="onFocus"
293
- @open="resizeHandler"
317
+ @open="onOpen"
318
+ @close="onClose"
294
319
  @option:created="(e) => $emit('createdListItem', e)"
295
320
  >
296
321
  <template
@@ -21,6 +21,10 @@ export default {
21
21
  causes $emit 'input' of ["-c", "sleep 600"]
22
22
  */
23
23
  data() {
24
+ return { userValue: '' };
25
+ },
26
+
27
+ created() {
24
28
  let userValue = '';
25
29
 
26
30
  if ( this.value ) {
@@ -36,7 +40,7 @@ export default {
36
40
  }, '').trim();
37
41
  }
38
42
 
39
- return { userValue };
43
+ this.userValue = userValue;
40
44
  },
41
45
 
42
46
  methods: {
@@ -29,6 +29,10 @@ export default {
29
29
  },
30
30
 
31
31
  data() {
32
+ return { rules: [] };
33
+ },
34
+
35
+ created() {
32
36
  const rules = [];
33
37
 
34
38
  // on creation in agent configuration, the backend "eats"
@@ -49,7 +53,7 @@ export default {
49
53
  });
50
54
  }
51
55
 
52
- return { rules };
56
+ this.rules = rules;
53
57
  },
54
58
 
55
59
  computed: {