@@ -68,6 +68,10 @@ class ConfigFileCommandDiffers(ExitingException):
68
68
pass
69
69
70
70
71
+ class StateMismatch (ExitingException ):
72
+ pass
73
+
74
+
71
75
class ConfigFile (object ):
72
76
73
77
def __init__ (self , source , dest , owner = None , perm = None , optional = False ,
@@ -583,6 +587,56 @@ def execute_command_check(config):
583
587
584
588
585
589
def execute_config_check (config ):
590
+ """Check configuration state consistency and validate config file entries.
591
+
592
+ This function compares the current config file destinations from the
593
+ provided config dictionary with those stored in the defaults state file.
594
+ If any destinations are found in the state file but not in the config,
595
+ a StateMismatch exception is raised. These missing files would otherwise
596
+ be restored or removed depending on their backup state.
597
+
598
+ After validating consistency, the function performs standard checks on
599
+ each declared configuration file, including content, permissions, and
600
+ ownership validation.
601
+
602
+ Args:
603
+ config (dict): The configuration dictionary containing 'config_files'
604
+ entries as expected by Kolla.
605
+
606
+ Raises:
607
+ StateMismatch: If there are entries in the defaults state not present
608
+ in the provided config.
609
+ """
610
+ state = get_defaults_state ()
611
+
612
+ # Build a set of all current destination paths from config.json
613
+ # If the destination is a directory, we append the
614
+ # basename of the source
615
+ current_dests = {
616
+ entry ['dest' ] if not entry ['dest' ].endswith ('/' ) else
617
+ os .path .join (entry ['dest' ], os .path .basename (entry ['source' ]))
618
+ for entry in config .get ('config_files' , [])
619
+ if entry .get ('dest' )
620
+ }
621
+
622
+ # Detect any paths that are present in the state file but
623
+ # missing from config.json.
624
+ # These would be either restored (if state[dest] has a backup)
625
+ # or removed (if dest is null)
626
+ removed_dests = [
627
+ path for path in state .keys ()
628
+ if path not in current_dests
629
+ ]
630
+
631
+ if removed_dests :
632
+ raise StateMismatch (
633
+ f"The following config files are tracked in state but missing "
634
+ f"from config.json. "
635
+ f"They would be restored or removed: { sorted (removed_dests )} "
636
+ )
637
+
638
+ # Perform the regular content, permissions, and ownership
639
+ # checks on the declared files
586
640
for data in config .get ('config_files' , []):
587
641
config_file = ConfigFile (** data )
588
642
config_file .check ()
0 commit comments