def trigger(sty): global _stop_flag while True: interval = random.randint(0, 60 / sty) time.sleep(interval) if _stop_flag: break util.check_gen_and_patch_spec(**auri, spec={ "obs": { "last_triggered_time": time.time() } }, gen=sys.maxsize)
def reconcile(meta, *args, **kwargs): gen = meta["generation"] # skip the last self-write # TBD for parallel reconciliation may need to lock rc.gen before patch if gen == rc.skip_gen: logger.info(f"Skipping gen {gen}") return spec = rc.run(*args, **kwargs) _, resp, e = util.check_gen_and_patch_spec(g, v, r, n, ns, spec, gen=gen) if e is not None: if e.status == util.DriverError.GEN_OUTDATED: # retry s.t. the diff object contains the past changes # TBD(@kopf) non-zero delay fix raise kopf.TemporaryError(e, delay=0) else: raise kopf.PermanentError(e.status) # if the model didn't get updated do not # increment the counter new_gen = resp["metadata"]["generation"] if gen + 1 == new_gen: rc.skip_gen = new_gen logger.info(f"Done reconciliation")
def detect(): global _stop_flag while True: interval = random.randint(5, 60) if _stop_flag: break util.check_gen_and_patch_spec(**auri, spec={ "data": { "output": { "objects": gen_objects() } } }, gen=sys.maxsize) time.sleep(interval)
def _sync_to_children(parent_spec, diff): # sort the diff by the attribute path (in tuple) diff = sorted(diff, key=lambda x: x[1]) # filter to only the intent/input updates to_sync = dict() for _, f, _, _ in diff: # skip non children update if len(f) < 3: continue gvr_str, nsn_str = f[0], f[1] model_id = util.model_id(*parse_gvr(gvr_str), *parse_spaced_name(nsn_str)) if model_id not in to_sync: cs, gen = _gen_child_patch(parent_spec, gvr_str, nsn_str) if cs is not None: to_sync[model_id] = cs, gen # sync all, e.g., on parent resume and creation if len(diff) == 0: for gvr_str, ms in parent_spec.get("mount", {}).items(): for nsn_str, m in ms.items(): model_id = util.model_id(*parse_gvr(gvr_str), *parse_spaced_name(nsn_str)) cs, gen = _gen_child_patch(parent_spec, gvr_str, nsn_str) # both rv and gen can be none as during the initial sync # the parent may overwrite if cs is not None: to_sync[model_id] = cs, gen # push to children models # TBD: transactional update for model_id, (cs, gen) in to_sync.items(): cur_gen, resp, e = util.check_gen_and_patch_spec( *util.parse_model_id(model_id), spec=cs, gen=max(gen, self._children_gen.get(model_id, -1))) if e is not None: self._logger.warning( f"Unable to sync to children due to {e}") else: new_gen = resp["metadata"]["generation"] self._children_gen[model_id] = new_gen if cur_gen + 1 == new_gen: self._children_skip_gen[model_id] = new_gen
def _sync_from_parent(group, version, plural, name, namespace, meta, attrs_to_trim=None, *args, **kwargs): _, _ = args, kwargs parent, prv, pgn = util.get_spec(g, v, r, n, ns) # check if child exists mounts = parent.get("mount", {}) gvr_str = util.gvr(group, version, plural) nsn_str = util.spaced_name(name, namespace) if (gvr_str not in mounts or (nsn_str not in mounts[gvr_str] and name not in mounts[gvr_str])): self._logger.warning( f"Unable to find the {nsn_str} or {name} in the {parent}") return models = mounts[gvr_str] n_ = name if name in models else nsn_str patch = models[n_] if attrs_to_trim is not None: patch = util.trim_attr(patch, attrs_to_trim) _, resp, e = util.check_gen_and_patch_spec(group, version, plural, name, namespace, patch, gen=meta["generation"]) if e is not None: self._logger.warning(f"Unable to sync from parent due to {e}") else: model_id = util.model_id(group, version, plural, name, namespace) new_gen = resp["metadata"]["generation"] self._children_gen[model_id] = new_gen if meta["generation"] + 1 == new_gen: self._children_skip_gen[model_id] = new_gen