Get input from the operator about the modifications to be made to a Layer 2 Circuit subscription.
Source code in gso/workflows/l2_circuit/modify_layer_2_circuit.py
| def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator:
"""Get input from the operator about the modifications to be made to a Layer 2 Circuit subscription."""
subscription = Layer2Circuit.from_subscription(subscription_id)
product_name = subscription.product.name
class ModifyL2CircuitForm(FormPage):
model_config = ConfigDict(title=f"Modify {product_name}")
tt_number: TTNumber
divider: Divider = Field(None, exclude=True)
# FIXME: str workaround for pre-fill in type hint below
layer_2_circuit_type: Layer2CircuitType | str = subscription.layer_2_circuit.layer_2_circuit_type
policer_enabled: bool = subscription.layer_2_circuit.policer_enabled
custom_service_name: str | None = subscription.layer_2_circuit.custom_service_name
label: Label = Field("Should this workflow execute Ansible playbooks on routers?", exclude=True)
run_ansible_steps: bool = True
layer_2_circuit_input = yield ModifyL2CircuitForm
class ModifyLayer2CircuitServiceSidesPage(SubmitFormPage):
model_config = ConfigDict(title=f"{product_name} - Configure Edge Ports")
vlan_range_label: Label = Field("Please set a VLAN range, bounds including.", exclude=True)
if layer_2_circuit_input.layer_2_circuit_type == Layer2CircuitType.VLAN:
vlan_range_lower_bound: VLAN_ID = subscription.layer_2_circuit.vlan_range_lower_bound # type: ignore[assignment]
vlan_range_upper_bound: VLAN_ID = subscription.layer_2_circuit.vlan_range_upper_bound # type: ignore[assignment]
vlan_divider: Divider = Field(None, exclude=True)
if layer_2_circuit_input.policer_enabled:
policer_bandwidth: BandwidthString = subscription.layer_2_circuit.bandwidth # type: ignore[assignment]
policer_burst_rate: BandwidthString = subscription.layer_2_circuit.policer_burst_rate # type: ignore[assignment]
policer_divider: Divider = Field(None, exclude=True)
class L2CircuitSideA(BaseModel):
partner: partner_choice(form_title="Partner for Side A") = ( # type: ignore[valid-type]
subscription.layer_2_circuit.layer_2_circuit_sides[0].partner_id
)
# TODO: Uncomment when is_primary is needed
# is_primary: bool = subscription.layer_2_circuit.layer_2_circuit_sides[0].is_primary # noqa: ERA001
if layer_2_circuit_input.layer_2_circuit_type == Layer2CircuitType.ETHERNET:
vlan_id: VLAN_ID = subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.vlan_id # type: ignore[assignment]
edge_port: read_only_field( # type: ignore[valid-type]
EdgePort.from_subscription(
subscription.layer_2_circuit.layer_2_circuit_sides[0].sbp.edge_port.owner_subscription_id
).description,
)
class L2CircuitSideB(BaseModel):
partner: partner_choice(form_title="Partner for Side B") = ( # type: ignore[valid-type]
subscription.layer_2_circuit.layer_2_circuit_sides[1].partner_id
)
# TODO: Uncomment when is_primary is needed
# is_primary: bool = subscription.layer_2_circuit.layer_2_circuit_sides[1].is_primary # noqa: ERA001
if layer_2_circuit_input.layer_2_circuit_type == Layer2CircuitType.ETHERNET:
vlan_id: VLAN_ID = subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.vlan_id # type: ignore[assignment]
edge_port: read_only_field( # type: ignore[valid-type]
EdgePort.from_subscription(
subscription.layer_2_circuit.layer_2_circuit_sides[1].sbp.edge_port.owner_subscription_id
).description,
)
layer_2_circuit_side_a: L2CircuitSideA
side_divider: Divider = Field(None, exclude=True)
layer_2_circuit_side_b: L2CircuitSideB
# TODO: Uncomment when is_primary is added back to the form and make all is_primary required in all access
# @model_validator(mode="after")
# def only_one_side_can_be_primary(self) -> Self:
# """Ensure that both sides do not have is_primary set to True."""
# if self.layer_2_circuit_side_a.is_primary ^ self.layer_2_circuit_side_b.is_primary:
# msg = "Only one side of the Layer 2 Circuit can be marked as primary." # noqa: ERA001
# raise ValueError(msg) # noqa: ERA001
# return self # noqa: ERA001
layer_2_circuit_sides = yield ModifyLayer2CircuitServiceSidesPage
return (
{
"product_name": product_name,
# The four values of `None` are required such that the state will contain the required keys.
# If they are set in the input form by the user, they will be overwritten by the data coming from the form.
"policer_bandwidth": None,
"policer_burst_rate": None,
"vlan_range_upper_bound": None,
"vlan_range_lower_bound": None,
}
| layer_2_circuit_input.model_dump()
| layer_2_circuit_sides.model_dump()
)
|