Summary
Environment validation marks a host switch_config_applied=True without
actually verifying the switchports. The "switch configuration missing" release
gate is effectively dead: an environment can pass network validation and be
released to a tenant even when the switch was never configured or the
configuration failed.
Root cause
Two layers each drop the real result:
src/quads/plugins/dispatchers/switch.py:43 SwitchDispatcher.verify awaits
the plugin but discards its return value and hardcodes success:
try:
await self._default_plugin.verify(host, cloud, change)
return True
except Exception as e:
logger.error(f"Failed to verify switch: {e}")
return False
src/quads/plugins/builtin/switches/juniper.py:195 JuniperSwitchPlugin.verify
never returns a value (all paths fall through or bare return), so it always
yields None.
Consumer src/quads/plugins/builtin/validators/environment.py:238:
result = await self.switch_dispatcher.verify(host.name, previous_cloud, host.cloud.name)
if result:
self.quads.update_host(host.name, {"switch_config_applied": True})
else:
switch_config_missing.append(host.name)
Because the dispatcher always returns True (barring an exception), the host is
marked switch_config_applied=True with no verification, and
switch_config_missing is never populated.
Regression from 2.2
In 2.2, Switch.verify returned None and post_network_test used it directly
(result = switch.verify(...)); None is falsy, so an unverified host went into
switch_config_missing and validation FAILED (conservative hold). The dispatcher
refactor turned this into an unconditional True.
Impact
Fix
SwitchDispatcher.verify should return the plugin's actual result.
JuniperSwitchPlugin.verify should return True only when the switch state is
confirmed/applied successfully for all interfaces, False otherwise (including
not-found and failed set operations).
Summary
Environment validation marks a host
switch_config_applied=Truewithoutactually verifying the switchports. The "switch configuration missing" release
gate is effectively dead: an environment can pass network validation and be
released to a tenant even when the switch was never configured or the
configuration failed.
Root cause
Two layers each drop the real result:
src/quads/plugins/dispatchers/switch.py:43SwitchDispatcher.verifyawaitsthe plugin but discards its return value and hardcodes success:
src/quads/plugins/builtin/switches/juniper.py:195JuniperSwitchPlugin.verifynever returns a value (all paths fall through or bare
return), so it alwaysyields
None.Consumer
src/quads/plugins/builtin/validators/environment.py:238:Because the dispatcher always returns
True(barring an exception), the host ismarked
switch_config_applied=Truewith no verification, andswitch_config_missingis never populated.Regression from 2.2
In 2.2,
Switch.verifyreturnedNoneandpost_network_testused it directly(
result = switch.verify(...));Noneis falsy, so an unverified host went intoswitch_config_missingand validation FAILED (conservative hold). The dispatcherrefactor turned this into an unconditional
True.Impact
switch_config_appliedhold is defeated at the validation gate:environments release without confirmed switch/VLAN configuration.
Fix
SwitchDispatcher.verifyshould return the plugin's actual result.JuniperSwitchPlugin.verifyshould returnTrueonly when the switch state isconfirmed/applied successfully for all interfaces,
Falseotherwise (includingnot-found and failed set operations).