66import re
77from collections import namedtuple , defaultdict
88from functools import reduce
9- from typing import Optional , Generator , Any , Dict , List , Set , Tuple , Union , Iterator , DefaultDict
9+ from typing import Optional , Generator , Any , Dict , List , Set , Tuple , Union , Iterator , DefaultDict , Iterable
1010
1111from attrs import define
1212from networkx import DiGraph , MultiDiGraph , is_directed_acyclic_graph
@@ -267,13 +267,13 @@ def add_node(
267267 if replace :
268268 metadata = metadata or {}
269269 metadata ["replace" ] = True
270+ # get kind hierarchy
271+ kinds = kind .kind_hierarchy ()
270272 # create content hash
271- sha = GraphBuilder .content_hash (reported , desired , metadata )
273+ sha = GraphBuilder .content_hash (reported , desired , metadata , kinds )
272274 hist_hash = GraphBuilder .history_hash (reported , kind )
273275 # flat all properties into a single string for search
274276 flat = search if isinstance (search , str ) else (GraphBuilder .flatten (reported , kind ))
275- # get kind hierarchy
276- kinds = kind .kind_hierarchy ()
277277 # set organizational root
278278 if "organizational_root" in kinds :
279279 assert self .organizational_root is None , "There can be only one organizational root!"
@@ -312,7 +312,12 @@ def add_deferred_edge(
312312 self .deferred_edges .append (DeferredEdge (from_selector , to_selector , edge_type , reported , content_hash ))
313313
314314 @staticmethod
315- def content_hash (js : Json , desired : Optional [Json ] = None , metadata : Optional [Json ] = None ) -> str :
315+ def content_hash (
316+ js : Json ,
317+ desired : Optional [Json ] = None ,
318+ metadata : Optional [Json ] = None ,
319+ kinds : Optional [Iterable [str ]] = None ,
320+ ) -> str :
316321 sha256 = hashlib .sha256 ()
317322 # all content hashes will be different, when the version changes
318323 sha256 .update (ContentHashVersion .to_bytes (2 , "big" ))
@@ -321,6 +326,8 @@ def content_hash(js: Json, desired: Optional[Json] = None, metadata: Optional[Js
321326 sha256 .update (json .dumps (desired , sort_keys = True ).encode ("utf-8" ))
322327 if metadata :
323328 sha256 .update (json .dumps (metadata , sort_keys = True ).encode ("utf-8" ))
329+ if kinds :
330+ sha256 .update (":" .join (sorted (kinds )).encode ("utf-8" ))
324331 return sha256 .hexdigest ()[0 :8 ]
325332
326333 @staticmethod
@@ -502,7 +509,7 @@ def count_descendants_of(identifier: str, ancestor_kind: str, path: List[str]) -
502509 set_value_in_path (total , NodePath .descendant_count , node )
503510 # update hash
504511 node ["hash" ] = GraphBuilder .content_hash (
505- node ["reported" ], node .get ("desired" ), node .get ("metadata" )
512+ node ["reported" ], node .get ("desired" ), node .get ("metadata" ), node . get ( "kinds" )
506513 )
507514
508515 def __resolve (self , node_id : NodeId , node : Json ) -> Json :
@@ -577,10 +584,11 @@ def dump_direct(node_id: NodeId, node: Json, kind: Kind, recompute: bool = False
577584 reported = node [Section .reported ]
578585 desired : Optional [Json ] = node .get (Section .desired , None )
579586 metadata : Optional [Json ] = node .get (Section .metadata , None )
587+ kinds : Optional [List [str ]] = node .get ("kinds" , None )
580588 if "id" not in node :
581589 node ["id" ] = node_id
582590 if recompute or "hash" not in node :
583- node ["hash" ] = GraphBuilder .content_hash (reported , desired , metadata )
591+ node ["hash" ] = GraphBuilder .content_hash (reported , desired , metadata , kinds )
584592 if recompute or "flat" not in node :
585593 node ["flat" ] = GraphBuilder .flatten (reported , kind )
586594 if "kinds" not in node :
0 commit comments