Skip to content

Commit

Permalink
compute pod recreation for deployments
Browse files Browse the repository at this point in the history
  • Loading branch information
drmorr0 committed Jan 25, 2024
1 parent e8c70b5 commit 8ca1e34
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 22 deletions.
6 changes: 3 additions & 3 deletions fireconfig/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def compile(pkgs: T.Dict[str, T.List[AppPackage]], dag_filename: T.Optional[str]

for obj in DependencyGraph(app.node).root.outbound:
walk_dep_graph(obj, subgraphs)
diff = compute_diff(app)
resource_changes = get_resource_changes(diff)
diff, kinds = compute_diff(app)
resource_changes = get_resource_changes(diff, kinds)

try:
find_deleted_nodes(subgraphs, resource_changes, dag_filename)
Expand All @@ -74,6 +74,6 @@ def compile(pkgs: T.Dict[str, T.List[AppPackage]], dag_filename: T.Optional[str]
graph_str = format_mermaid_graph(subgraph_dag, subgraphs, dag_filename, resource_changes)
diff_str = format_diff(resource_changes)

app.synth()
# app.synth()

return graph_str, diff_str
10 changes: 5 additions & 5 deletions fireconfig/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
from fireconfig.subgraph import ChartSubgraph


def _format_node_label(n: str, ty: str) -> str:
name = n.split("/")[-1]
return f" {n}[<b>{ty}</b><br>{name}]\n"
def _format_node_label(node: str, kind: str) -> str:
name = node.split("/")[-1]
return f" {node}[<b>{kind}</b><br>{name}]\n"


def format_mermaid_graph(
Expand All @@ -34,8 +34,8 @@ def format_mermaid_graph(
for chart, sg in subgraphs.items():
mermaid += f"subgraph {chart}\n"
mermaid += " direction LR\n"
for n, ty in sg.nodes():
mermaid += _format_node_label(n, ty)
for n, k in sg.nodes():
mermaid += _format_node_label(n, k)

for s, e in sg.edges():
mermaid += f" {s}--->{e}\n"
Expand Down
38 changes: 28 additions & 10 deletions fireconfig/plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class ResourceState(Enum):
ChangedWithPodRecreate = "#cb4"
Added = "#283"
Removed = "#e67"
Unknown = "#f00"


class ResourceChanges:
Expand All @@ -45,22 +46,38 @@ def state(self) -> ResourceState:
def changes(self) -> T.List[ChangeTuple]:
return self._changes

def update_state(self, change_type: str, path: str):
if self._state not in {ResourceState.Unchanged, ResourceState.Changed}:
def update_state(self, change_type: str, path: str, kind: T.Optional[str]):
if self._state in {ResourceState.Added, ResourceState.Removed}:
return

if change_type == "dictionary_item_removed":
self._state = ResourceState.Removed if path == "root" else ResourceState.Changed
elif change_type == "dictionary_item_added":
self._state = ResourceState.Added if path == "root" else ResourceState.Changed
if path == "root":
if change_type == "dictionary_item_removed":
self._state = ResourceState.Removed
elif change_type == "dictionary_item_added":
self._state = ResourceState.Added
else:
self._state = ResourceState.Unknown
elif self._state == ResourceState.ChangedWithPodRecreate:
return
elif kind == "Deployment":
# TODO - this is obviously incomplete, it will not detect all cases
# when pod recreation happens
if (
path.startswith("root['spec']['template']['spec']")
or path.startswith("root['spec']['selector']")
):
self._state = ResourceState.ChangedWithPodRecreate
else:
self._state = ResourceState.Changed
else:
self._state = ResourceState.Changed

def add_change(self, path: str, r1: T.Union[T.Mapping, notpresent], r2: T.Union[T.Mapping, notpresent]):
self._changes.append((path, r1, r2))


def compute_diff(app: App) -> T.Mapping[str, T.Any]:
def compute_diff(app: App) -> T.Tuple[T.Mapping[str, T.Any], T.Mapping[str, str]]:
kinds = {}
old_defs = {}
for filename in glob(f"{app.outdir}/*{app.output_file_extension}"):
with open(filename) as f:
Expand All @@ -77,8 +94,9 @@ def compute_diff(app: App) -> T.Mapping[str, T.Any]:
for new_obj in chart.api_objects:
node_id = owned_name(new_obj)
new_defs[node_id] = new_obj.to_json()
kinds[node_id] = new_obj.kind

return DeepDiff(old_defs, new_defs, view="tree")
return DeepDiff(old_defs, new_defs, view="tree"), kinds


def walk_dep_graph(v: DependencyVertex, subgraphs: T.Mapping[str, ChartSubgraph]):
Expand All @@ -98,13 +116,13 @@ def walk_dep_graph(v: DependencyVertex, subgraphs: T.Mapping[str, ChartSubgraph]
walk_dep_graph(dep, subgraphs)


def get_resource_changes(diff: T.Mapping[str, T.Any]) -> T.Mapping[str, ResourceChanges]:
def get_resource_changes(diff: T.Mapping[str, T.Any], kinds: T.Mapping[str, str]) -> T.Mapping[str, ResourceChanges]:
resource_changes: T.MutableMapping[str, ResourceChanges] = defaultdict(lambda: ResourceChanges())
for change_type, items in diff.items():
for i in items:
root_item = i.path(output_format="list")[0]
path = re.sub(r"\[" + f"'{root_item}'" + r"\]", "", i.path())
resource_changes[root_item].update_state(change_type, path)
resource_changes[root_item].update_state(change_type, path, kinds.get(root_item))
resource_changes[root_item].add_change(path, i.t1, i.t2)

return resource_changes
Expand Down
9 changes: 5 additions & 4 deletions fireconfig/subgraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ class ChartSubgraph:
def __init__(self, name: str) -> None:
self._name = name
self._dag: T.MutableMapping[str, T.List[str]] = defaultdict(list)
self._resource_types: T.MutableMapping[str, str] = {}
self._kinds: T.MutableMapping[str, str] = {}
self._deleted_lines: T.Set[str] = set()

def add_node(self, v: DependencyVertex) -> str:
name = owned_name(T.cast(ApiObject, v.value))
self._resource_types[name] = type(v.value).__name__.replace("Kube", "")
obj = T.cast(ApiObject, v.value)
name = owned_name(obj)
self._kinds[name] = obj.kind
self._dag[name]
return name

Expand All @@ -29,7 +30,7 @@ def add_deleted_line(self, l: str):
self._deleted_lines.add(l)

def nodes(self) -> T.List[T.Tuple[str, str]]:
return [(n, self._resource_types[n]) for n in self._dag.keys()]
return [(n, self._kinds[n]) for n in self._dag.keys()]

def edges(self) -> T.List[T.Tuple[str, str]]:
return [(s, e) for s, l in self._dag.items() for e in l]
Expand Down

0 comments on commit 8ca1e34

Please sign in to comment.