@rancher/shell 0.3.8 → 0.3.10

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 (145) hide show
  1. package/assets/translations/en-us.yaml +47 -26
  2. package/assets/translations/zh-hans.yaml +82 -16
  3. package/babel.config.js +17 -4
  4. package/chart/istio.vue +11 -11
  5. package/chart/rancher-backup/S3.vue +1 -1
  6. package/components/AsyncButton.vue +2 -2
  7. package/components/ButtonGroup.vue +1 -1
  8. package/components/CodeMirror.vue +146 -14
  9. package/components/CompoundStatusBadge.vue +1 -1
  10. package/components/ContainerResourceLimit.vue +14 -1
  11. package/components/CopyCode.vue +1 -1
  12. package/components/CruResource.vue +21 -5
  13. package/components/DetailTop.vue +1 -1
  14. package/components/ExplorerProjectsNamespaces.vue +8 -4
  15. package/components/GlobalRoleBindings.vue +1 -1
  16. package/components/GroupPanel.vue +57 -0
  17. package/components/HarvesterServiceAddOnConfig.vue +2 -117
  18. package/components/ResourceDetail/Masthead.vue +1 -1
  19. package/components/ResourceList/Masthead.vue +0 -6
  20. package/components/ResourceList/ResourceLoadingIndicator.vue +1 -9
  21. package/components/ResourceList/index.vue +7 -6
  22. package/components/ResourceTable.vue +13 -3
  23. package/components/SortableTable/THead.vue +3 -3
  24. package/components/SortableTable/index.vue +3 -3
  25. package/components/Tabbed/Tab.vue +1 -1
  26. package/components/Tabbed/index.vue +1 -1
  27. package/components/Wizard.vue +9 -6
  28. package/components/YamlEditor.vue +2 -2
  29. package/components/__tests__/NamespaceFilter.test.ts +26 -7
  30. package/components/auth/RoleDetailEdit.vue +1 -1
  31. package/components/auth/SelectPrincipal.vue +1 -1
  32. package/components/fleet/FleetRepos.vue +1 -1
  33. package/components/form/ArrayList.vue +2 -2
  34. package/components/form/KeyValue.vue +37 -3
  35. package/components/form/Labels.vue +34 -14
  36. package/components/form/MatchExpressions.vue +120 -21
  37. package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
  38. package/components/form/NameNsDescription.vue +1 -1
  39. package/components/form/NodeAffinity.vue +54 -4
  40. package/components/form/PlusMinus.vue +2 -2
  41. package/components/form/PodAffinity.vue +160 -47
  42. package/components/form/Probe.vue +1 -1
  43. package/components/form/ProjectMemberEditor.vue +8 -4
  44. package/components/form/ResourceQuota/NamespaceRow.vue +1 -1
  45. package/components/form/ServicePorts.vue +2 -2
  46. package/components/form/Tolerations.vue +70 -7
  47. package/components/form/WorkloadPorts.vue +2 -1
  48. package/components/form/__tests__/ArrayList.test.ts +3 -3
  49. package/components/form/__tests__/KeyValue.test.ts +17 -0
  50. package/components/form/__tests__/MatchExpressions.test.ts +1 -1
  51. package/components/formatter/ClusterLink.vue +3 -3
  52. package/components/formatter/LiveDate.vue +1 -1
  53. package/components/formatter/PodImages.vue +1 -1
  54. package/components/formatter/RKETemplateName.vue +1 -1
  55. package/components/formatter/Shortened.vue +1 -1
  56. package/components/nav/Header.vue +9 -7
  57. package/components/nav/NamespaceFilter.vue +103 -54
  58. package/config/labels-annotations.js +8 -5
  59. package/config/settings.ts +8 -6
  60. package/config/types.js +6 -4
  61. package/core/plugin-routes.ts +26 -7
  62. package/detail/provisioning.cattle.io.cluster.vue +4 -4
  63. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  64. package/edit/configmap.vue +33 -6
  65. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +19 -149
  66. package/edit/logging-flow/index.vue +2 -2
  67. package/edit/logging.banzaicloud.io.output/providers/elasticsearch.vue +12 -0
  68. package/edit/logging.banzaicloud.io.output/providers/opensearch.vue +12 -0
  69. package/edit/management.cattle.io.project.vue +7 -0
  70. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  71. package/edit/monitoring.coreos.com.alertmanagerconfig/routeConfig.vue +2 -2
  72. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +11 -8
  73. package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +2 -2
  74. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +12 -4
  75. package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.spec.ts +140 -0
  76. package/edit/networking.k8s.io.networkpolicy/__tests__/utils/mock.json +158 -0
  77. package/edit/networking.k8s.io.networkpolicy/__tests__/utils/selectors.ts +45 -0
  78. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  79. package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +326 -0
  80. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +1 -1
  81. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -1
  82. package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +2 -2
  83. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +143 -169
  84. package/edit/provisioning.cattle.io.cluster/index.vue +1 -0
  85. package/edit/provisioning.cattle.io.cluster/rke2.vue +75 -6
  86. package/edit/resources.cattle.io.restore.vue +2 -2
  87. package/edit/service.vue +22 -3
  88. package/edit/storage.k8s.io.storageclass/index.vue +1 -1
  89. package/edit/workload/Job.vue +2 -2
  90. package/edit/workload/index.vue +1 -1
  91. package/edit/workload/mixins/workload.js +7 -1
  92. package/edit/workload/storage/__tests__/Storage.test.ts +84 -5
  93. package/initialize/index.js +1 -0
  94. package/layouts/default.vue +1 -1
  95. package/mixins/chart.js +1 -1
  96. package/mixins/resource-fetch-namespaced.js +19 -27
  97. package/mixins/resource-fetch.js +0 -5
  98. package/models/__tests__/namespace.test.ts +125 -0
  99. package/models/batch.cronjob.js +18 -3
  100. package/models/management.cattle.io.project.js +6 -1
  101. package/models/persistentvolume.js +1 -1
  102. package/models/workload.js +1 -1
  103. package/models/workload.service.js +22 -7
  104. package/package.json +17 -6
  105. package/pages/auth/login.vue +47 -49
  106. package/pages/c/_cluster/apps/charts/chart.vue +1 -1
  107. package/pages/c/_cluster/apps/charts/install.vue +42 -51
  108. package/pages/c/_cluster/explorer/index.vue +1 -1
  109. package/pages/c/_cluster/monitoring/index.vue +1 -1
  110. package/pages/c/_cluster/settings/performance.vue +53 -18
  111. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
  112. package/pages/c/_cluster/uiplugins/index.vue +16 -5
  113. package/pages/home.vue +1 -1
  114. package/pages/prefs.vue +18 -2
  115. package/plugins/clean-html-directive.js +1 -1
  116. package/plugins/clean-tooltip-directive.js +33 -0
  117. package/plugins/codemirror.js +158 -0
  118. package/plugins/dashboard-store/actions.js +4 -2
  119. package/plugins/dashboard-store/getters.js +6 -0
  120. package/plugins/dashboard-store/mutations.js +2 -2
  121. package/plugins/plugin.js +6 -1
  122. package/plugins/steve/actions.js +1 -1
  123. package/plugins/steve/getters.js +14 -3
  124. package/plugins/steve/resourceWatcher.js +36 -62
  125. package/plugins/steve/subscribe.js +137 -21
  126. package/plugins/steve/worker/index.js +7 -1
  127. package/plugins/steve/worker/web-worker.advanced.js +26 -8
  128. package/plugins/steve/worker/web-worker.basic.js +23 -4
  129. package/public/index.html +1 -1
  130. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -2
  131. package/rancher-components/components/Form/Radio/RadioGroup.vue +2 -2
  132. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +1 -1
  133. package/store/index.js +16 -61
  134. package/store/store-types.js +5 -0
  135. package/store/type-map.js +1 -1
  136. package/types/shell/index.d.ts +42 -7
  137. package/utils/__tests__/create-yaml.test.ts +63 -0
  138. package/utils/array.ts +4 -0
  139. package/utils/create-yaml.js +105 -8
  140. package/utils/namespace-filter.js +17 -5
  141. package/utils/projectAndNamespaceFiltering.utils.ts +62 -0
  142. package/utils/selector.js +6 -5
  143. package/utils/settings.ts +17 -7
  144. package/vue.config.js +2 -2
  145. package/models/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -93
@@ -167,3 +167,161 @@ CodeMirror.registerHelper('fold', 'yamlcomments', (cm, start) => {
167
167
  };
168
168
  }
169
169
  });
170
+
171
+ /**
172
+ * It display a dot for each space character in the text;
173
+ * used in combination with 'as-text-area' css properties in CodeMirror.vue to display line break markdowns
174
+ */
175
+ CodeMirror.defineOption('showMarkdownLineBreaks', false, (codeMirror) => {
176
+ codeMirror.addOverlay({
177
+ name: 'show-markdown-line-breaks',
178
+ token: (stream) => {
179
+ if (stream.string[stream.pos].match(/\s/)) {
180
+ stream.next();
181
+
182
+ return stream.pos % 2 === 0 ? 'markdown-single-trailing-space-even' : 'markdown-single-trailing-space-odd';
183
+ }
184
+
185
+ stream.next();
186
+
187
+ return null;
188
+ }
189
+ });
190
+ });
191
+
192
+ /**
193
+ * It enables the text color selection in CodeMirror.vue
194
+ * references:
195
+ * demo: https://codemirror.net/5/demo/markselection.html#
196
+ * add-on: https://codemirror.net/5/doc/manual.html#addon_mark-selection
197
+ * source: https://codemirror.net/5/addon/selection/mark-selection.js
198
+ */
199
+ CodeMirror.defineOption('styleSelectedText', false, (cm, val, old) => {
200
+ const prev = old && old !== CodeMirror.Init;
201
+
202
+ if (val && !prev) {
203
+ cm.state.markedSelection = [];
204
+ cm.state.markedSelectionStyle = typeof val === 'string' ? val : 'CodeMirror-selectedtext';
205
+ reset(cm);
206
+ cm.on('cursorActivity', onCursorActivity);
207
+ cm.on('change', onChange);
208
+ } else if (!val && prev) {
209
+ cm.off('cursorActivity', onCursorActivity);
210
+ cm.off('change', onChange);
211
+ clear(cm);
212
+ cm.state.markedSelection = cm.state.markedSelectionStyle = null;
213
+ }
214
+ });
215
+
216
+ function onCursorActivity(cm) {
217
+ if (cm.state.markedSelection) {
218
+ cm.operation(() => {
219
+ update(cm);
220
+ });
221
+ }
222
+ }
223
+
224
+ function onChange(cm) {
225
+ if (cm.state.markedSelection && cm.state.markedSelection.length) {
226
+ cm.operation(() => {
227
+ clear(cm);
228
+ });
229
+ }
230
+ }
231
+
232
+ const CHUNK_SIZE = 8;
233
+ const Pos = CodeMirror.Pos;
234
+ const cmp = CodeMirror.cmpPos;
235
+
236
+ function coverRange(cm, from, to, addAt) {
237
+ if (cmp(from, to) === 0) {
238
+ return;
239
+ }
240
+ const array = cm.state.markedSelection;
241
+ const cls = cm.state.markedSelectionStyle;
242
+
243
+ for (let line = from.line;;) {
244
+ const start = line === from.line ? from : Pos(line, 0);
245
+ const endLine = line + CHUNK_SIZE; const atEnd = endLine >= to.line;
246
+ const end = atEnd ? to : Pos(endLine, 0);
247
+ const mark = cm.markText(start, end, { className: cls });
248
+
249
+ if (addAt === null || addAt === undefined) {
250
+ array.push(mark);
251
+ } else {
252
+ array.splice(addAt++, 0, mark);
253
+ }
254
+ if (atEnd) {
255
+ break;
256
+ }
257
+ line = endLine;
258
+ }
259
+ }
260
+
261
+ function clear(cm) {
262
+ const array = cm.state.markedSelection;
263
+
264
+ for (let i = 0; i < array.length; ++i) {
265
+ array[i].clear();
266
+ }
267
+ array.length = 0;
268
+ }
269
+
270
+ function reset(cm) {
271
+ clear(cm);
272
+ const ranges = cm.listSelections();
273
+
274
+ for (let i = 0; i < ranges.length; i++) {
275
+ coverRange(cm, ranges[i].from(), ranges[i].to());
276
+ }
277
+ }
278
+
279
+ function update(cm) {
280
+ if (!cm.somethingSelected()) {
281
+ return clear(cm);
282
+ }
283
+ if (cm.listSelections().length > 1) {
284
+ return reset(cm);
285
+ }
286
+
287
+ const from = cm.getCursor('start'); const to = cm.getCursor('end');
288
+
289
+ const array = cm.state.markedSelection;
290
+
291
+ if (!array.length) {
292
+ return coverRange(cm, from, to);
293
+ }
294
+
295
+ let coverStart = array[0].find(); let coverEnd = array[array.length - 1].find();
296
+
297
+ if (!coverStart || !coverEnd || to.line - from.line <= CHUNK_SIZE ||
298
+ cmp(from, coverEnd.to) >= 0 || cmp(to, coverStart.from) <= 0) {
299
+ return reset(cm);
300
+ }
301
+
302
+ while (cmp(from, coverStart.from) > 0) {
303
+ array.shift().clear();
304
+ coverStart = array[0].find();
305
+ }
306
+ if (cmp(from, coverStart.from) < 0) {
307
+ if (coverStart.to.line - from.line < CHUNK_SIZE) {
308
+ array.shift().clear();
309
+ coverRange(cm, from, coverStart.to, 0);
310
+ } else {
311
+ coverRange(cm, from, coverStart.from, 0);
312
+ }
313
+ }
314
+
315
+ while (cmp(to, coverEnd.to) < 0) {
316
+ array.pop().clear();
317
+ coverEnd = array[array.length - 1].find();
318
+ }
319
+ if (cmp(to, coverEnd.to) > 0) {
320
+ if (to.line - coverEnd.from.line < CHUNK_SIZE) {
321
+ array.pop().clear();
322
+ coverRange(cm, coverEnd.from, to);
323
+ } else {
324
+ coverRange(cm, coverEnd.to, to);
325
+ }
326
+ }
327
+ }
@@ -317,13 +317,15 @@ export default {
317
317
 
318
318
  // ToDo: SM if we start a "bigger" watch (such as watch without a namespace vs a watch with a namespace), we should stop the stop the "smaller" watch so we don't have duplicate events coming back
319
319
  if ( opt.watch !== false ) {
320
- dispatch('watch', {
320
+ const args = {
321
321
  type,
322
322
  revision: out.revision,
323
323
  namespace: opt.watchNamespace || opt.namespaced, // it could be either apparently
324
324
  // ToDo: SM namespaced is sometimes a boolean and sometimes a string, I don't see it as especially broken but we should refactor that in the future
325
325
  force: opt.forceWatch === true,
326
- });
326
+ };
327
+
328
+ dispatch('watch', args);
327
329
  }
328
330
 
329
331
  const all = getters.all(type);
@@ -274,6 +274,12 @@ export default {
274
274
  return false;
275
275
  },
276
276
 
277
+ haveNamespace: (state, getters) => (type) => {
278
+ type = getters.normalizeType(type);
279
+
280
+ return state.types[type]?.haveNamespace || null;
281
+ },
282
+
277
283
  haveSelector: (state, getters) => (type, selector) => {
278
284
  type = getters.normalizeType(type);
279
285
  const entry = state.types[type];
@@ -209,9 +209,9 @@ export function batchChanges(state, { ctx, batch }) {
209
209
  const removeAtIndexes = [];
210
210
 
211
211
  // looping through the batch, executing changes, deferring creates and removes since they change the array length
212
- Object.keys(batch[normalizedType]).forEach((id) => {
212
+ Object.keys(combinedBatch[normalizedType]).forEach((id) => {
213
213
  const index = typeCacheIndexMap[id];
214
- const resource = batch[normalizedType][id];
214
+ const resource = combinedBatch[normalizedType][id];
215
215
 
216
216
  // an empty resource passed into batch changes is how we'll signal which ones to delete
217
217
  if (Object.keys(resource).length === 0 && index !== undefined) {
package/plugins/plugin.js CHANGED
@@ -40,7 +40,12 @@ export default async function(context) {
40
40
  });
41
41
  }
42
42
  } catch (e) {
43
- console.error('Could not load UI Plugin list', e); // eslint-disable-line no-console
43
+ if (e?.code === 404) {
44
+ // Not found, so extensions operator probably not installed
45
+ console.log('Could not load UI Extensions list (Extensions Operator may not be installed)'); // eslint-disable-line no-console
46
+ } else {
47
+ console.error('Could not load UI Extensions list', e); // eslint-disable-line no-console
48
+ }
44
49
  }
45
50
 
46
51
  // Load all of the plugins
@@ -11,7 +11,7 @@ import jsyaml from 'js-yaml';
11
11
 
12
12
  export default {
13
13
 
14
- // Need to override this, so that thhe 'this' context is correct (this class not the base class)
14
+ // Need to override this, so that the 'this' context is correct (this class not the base class)
15
15
  async loadSchemas(ctx, watch = true) {
16
16
  return await loadSchemas(ctx, watch);
17
17
  },
@@ -8,6 +8,7 @@ import HybridModel, { cleanHybridResources } from './hybrid-class';
8
8
  import NormanModel from './norman-class';
9
9
  import { urlFor } from '@shell/plugins/dashboard-store/getters';
10
10
  import { normalizeType } from '@shell/plugins/dashboard-store/normalize';
11
+ import pAndNFiltering from '@shell/utils/projectAndNamespaceFiltering.utils';
11
12
 
12
13
  export const STEVE_MODEL_TYPES = {
13
14
  NORMAN: 'norman',
@@ -42,6 +43,15 @@ export default {
42
43
  });
43
44
  });
44
45
  }
46
+
47
+ // `opt.namespaced` is either
48
+ // - a string representing a single namespace - add restriction to the url
49
+ // - an array of namespaces or projects - add restriction as a param
50
+ const namespaceProjectFilter = pAndNFiltering.checkAndCreateParam(opt);
51
+
52
+ if (namespaceProjectFilter) {
53
+ url += `${ (url.includes('?') ? '&' : '?') + namespaceProjectFilter }`;
54
+ }
45
55
  // End: Filter
46
56
 
47
57
  // Limit
@@ -72,12 +82,13 @@ export default {
72
82
  urlFor: (state, getters) => (type, id, opt) => {
73
83
  let url = urlFor(state, getters)(type, id, opt);
74
84
 
75
- if (opt.namespaced) {
85
+ // `namespaced` is either
86
+ // - a string representing a single namespace - add restriction to the url
87
+ // - an array of namespaces or projects - add restriction as a param
88
+ if (opt.namespaced && !pAndNFiltering.isApplicable(opt)) {
76
89
  const parts = url.split('/');
77
90
 
78
91
  url = `${ parts.join('/') }/${ opt.namespaced }`;
79
-
80
- return url;
81
92
  }
82
93
 
83
94
  return url;
@@ -5,10 +5,9 @@
5
5
  import Socket, {
6
6
  NO_WATCH,
7
7
  NO_SCHEMA,
8
- EVENT_MESSAGE,
9
8
  EVENT_CONNECTED,
9
+ REVISION_TOO_OLD
10
10
  } from '@shell/utils/socket';
11
- import { addParam } from '@shell/utils/url';
12
11
 
13
12
  export const WATCH_STATUSES = {
14
13
  /**
@@ -64,7 +63,7 @@ export const watchKeyFromMessage = (msg) => {
64
63
  };
65
64
 
66
65
  const {
67
- WATCH_PENDING, WATCH_REQUESTED, WATCHING, STOPPED, REMOVE_PENDING, REQUESTED_REMOVE
66
+ WATCH_PENDING, WATCH_REQUESTED, WATCHING, REMOVE_PENDING, REQUESTED_REMOVE
68
67
  } = WATCH_STATUSES;
69
68
 
70
69
  export default class ResourceWatcher extends Socket {
@@ -110,12 +109,13 @@ export default class ResourceWatcher extends Socket {
110
109
  return !!this.watches?.[watchKey];
111
110
  }
112
111
 
113
- async watch(watchKey, providedResourceVersion, providedResourceVersionTime, providedKeyParts = {}, providedSkipResourceVersion) {
112
+ watch(watchKey, providedResourceVersion, providedResourceVersionTime, providedKeyParts = {}, providedSkipResourceVersion) {
114
113
  const {
115
114
  resourceType: providedResourceType,
116
115
  id: providedId,
117
116
  namespace: providedNamespace,
118
- selector: providedSelector
117
+ selector: providedSelector,
118
+ force: providedForce,
119
119
  } = providedKeyParts;
120
120
 
121
121
  this.trace('watch:', 'requested', watchKey);
@@ -126,8 +126,10 @@ export default class ResourceWatcher extends Socket {
126
126
  return;
127
127
  }
128
128
 
129
- if (this.watches?.[watchKey]?.error) {
130
- this.trace('watch:', 'in error, aborting', watchKey);
129
+ if (!providedForce && this.watches?.[watchKey]?.error) {
130
+ if (this.watches?.[watchKey]?.error.reason !== REVISION_TOO_OLD) {
131
+ this.trace('watch:', 'in error, aborting', watchKey);
132
+ }
131
133
 
132
134
  return;
133
135
  }
@@ -136,7 +138,7 @@ export default class ResourceWatcher extends Socket {
136
138
  const id = providedId || this.watches?.[watchKey]?.id;
137
139
  const namespace = providedNamespace || this.watches?.[watchKey]?.namespace;
138
140
  const selector = providedSelector || this.watches?.[watchKey]?.selector;
139
- let skipResourceVersion = this.watches?.[watchKey]?.skipResourceVersion || providedSkipResourceVersion;
141
+ const skipResourceVersion = this.watches?.[watchKey]?.skipResourceVersion || providedSkipResourceVersion;
140
142
 
141
143
  const watchObject = {
142
144
  resourceType,
@@ -145,47 +147,8 @@ export default class ResourceWatcher extends Socket {
145
147
  selector
146
148
  };
147
149
 
148
- let resourceVersionTime = providedResourceVersionTime || this.watches?.[watchKey]?.resourceVersionTime;
149
- let resourceVersion = providedResourceVersion || this.watches?.[watchKey]?.resourceVersion;
150
-
151
- if (!skipResourceVersion && (!resourceVersion || Date.now() - resourceVersionTime > 300000)) { // 300000ms is 5minutes
152
- this.trace('watch:', 'revision update required', watchKey);
153
-
154
- const resourceUrl = this.baseUrl + resourceType;
155
- const limitedResourceUrl = addParam(resourceUrl, 'limit', 1);
156
- const opt = {
157
- method: 'get',
158
- headers: { accept: 'application/json' },
159
- };
160
-
161
- if (this.csrf) {
162
- opt.headers['x-api-csrf'] = this.csrf;
163
- }
164
-
165
- await fetch(limitedResourceUrl, opt)
166
- .then((res) => {
167
- this.watches[watchKey] = { ...watchObject };
168
- if (!res.ok) {
169
- this.watches[watchKey].error = res.json();
170
- console.warn(`Resource error retrieving resourceVersion`, resourceType, ':', res.json()); // eslint-disable-line no-console
171
- } else {
172
- this.watches[watchKey].error = undefined;
173
- }
174
-
175
- return res.json();
176
- })
177
- .then((res) => {
178
- if (res.revision) {
179
- resourceVersionTime = Date.now();
180
- resourceVersion = res.revision;
181
- } else if (!this.watches[watchKey].error) {
182
- // if there wasn't a revision in the response and there wasn't an error we wrote to the watch then the resource doesn't get a revision and we can skip it on subsequent rewatches
183
- skipResourceVersion = true;
184
- }
185
- });
186
- // When this fails we should re-fetch all resources (aka same as resyncWatch, or we actually call it). #7917
187
- // This would match the old approach
188
- }
150
+ const resourceVersionTime = providedResourceVersionTime || this.watches?.[watchKey]?.resourceVersionTime;
151
+ const resourceVersion = providedResourceVersion || this.watches?.[watchKey]?.resourceVersion;
189
152
 
190
153
  const success = this.send(JSON.stringify({
191
154
  ...watchObject,
@@ -240,16 +203,21 @@ export default class ResourceWatcher extends Socket {
240
203
 
241
204
  if (eventName === 'resource.start' && this.watches?.[watchKey]?.status === WATCH_REQUESTED) {
242
205
  this.watches[watchKey].status = WATCHING;
206
+ delete this.watches[watchKey].error;
243
207
  } else if (eventName === 'resource.stop' && this.watches?.[watchKey]) {
244
- if (this.watches?.[watchKey]?.status === REQUESTED_REMOVE) {
245
- delete this.watches[watchKey];
246
- } else {
247
- this.watches[watchKey].status = STOPPED;
248
- delete this.watches[watchKey].resourceVersion;
249
- delete this.watches[watchKey].resourceVersionTime;
250
- this.watch(watchKey);
251
- this.dispatchEvent(new CustomEvent(EVENT_MESSAGE, { detail: event }));
252
- }
208
+ // Find some way to resolve the correct resourceVersion from within the resourceWatcher until then:
209
+ // reset the watch in the resourceWatcher, we'll handle recovery up the chain. For now
210
+ // dispatch the event to the host process which should have a handler for resource.stop
211
+
212
+ // if (this.watches?.[watchKey]?.status === REQUESTED_REMOVE) {
213
+ this.watches[watchKey] = { error: this.watches[watchKey]?.error };
214
+ // } else {
215
+ // this.watches[watchKey].status = STOPPED;
216
+ // delete this.watches[watchKey].resourceVersion;
217
+ // delete this.watches[watchKey].resourceVersionTime;
218
+ // this.watch(watchKey);
219
+ // this.dispatchEvent(new CustomEvent(EVENT_MESSAGE, { detail: event }));
220
+ // }
253
221
  } else if (eventName === 'resource.error') {
254
222
  const err = data?.error?.toLowerCase();
255
223
 
@@ -262,14 +230,20 @@ export default class ResourceWatcher extends Socket {
262
230
 
263
231
  this.watches[watchKey].error = { type: resourceType, reason: NO_SCHEMA };
264
232
  } else if ( err.includes('too old') ) {
265
- // We don't actually know the gap between the requested revision and the oldest available revision.
266
- // For this case we should re-fetch all resources (aka same as resyncWatch, or we actually call it). #7917
267
- // This would match the old approach
268
233
  delete this.watches[watchKey].resourceVersion;
269
234
  delete this.watches[watchKey].resourceVersionTime;
270
235
  delete this.watches[watchKey].skipResourceVersion;
271
- this.watch(watchKey);
236
+ this.watches[watchKey].error = { type: resourceType, reason: REVISION_TOO_OLD };
237
+ // Needs to match sub resyncWatch params
238
+ this.dispatchEvent(new CustomEvent('resync', {
239
+ detail: {
240
+ data: {
241
+ resourceType, id, namespace, selector
242
+ }
243
+ }
244
+ }));
272
245
  }
246
+ this.trace('_onmessage:', 'new error', this.watches[watchKey].error);
273
247
  }
274
248
 
275
249
  super._onmessage(event);