@@ -2047,6 +2047,113 @@ def test_device_changelist_activate_deactivate_admin_action_security(
20472047 )
20482048 self .assertEqual (mocked_deactivate .call_count , 1 )
20492049
2050+ def test_vpn_template_switch (self ):
2051+ """
2052+ Test switching between two VPN templates that use the same VPN server
2053+ Verifies that:
2054+ 1. Only one VpnClient exists at a time
2055+ 2. VPN config variables are correctly resolved
2056+ 3. Switching back and forth works properly
2057+ """
2058+ vpn = self ._create_vpn ()
2059+ template1 = self ._create_template (
2060+ name = 'vpn-test-1' ,
2061+ type = 'vpn' ,
2062+ vpn = vpn ,
2063+ config = {},
2064+ auto_cert = True ,
2065+ )
2066+ template1 .config ['openvpn' ][0 ]['dev' ] = 'tun0'
2067+ template1 .full_clean ()
2068+ template1 .save ()
2069+ template2 = self ._create_template (
2070+ name = 'vpn-test-2' ,
2071+ type = 'vpn' ,
2072+ vpn = vpn ,
2073+ config = {},
2074+ auto_cert = True ,
2075+ )
2076+ template2 .config ['openvpn' ][0 ]['dev' ] = 'tun1'
2077+ template2 .full_clean ()
2078+ template2 .save ()
2079+
2080+ # Add device with default template (template1)
2081+ path = reverse (f'admin:{ self .app_label } _device_add' )
2082+ params = self ._get_device_params (org = self ._get_org ())
2083+ response = self .client .post (path , data = params , follow = True )
2084+ self .assertEqual (response .status_code , 200 )
2085+ config = Config .objects .get (device__name = params ['name' ])
2086+
2087+ # Add template1 to the device
2088+ path = reverse (f'admin:{ self .app_label } _device_change' , args = [config .device_id ])
2089+ params .update (
2090+ {
2091+ 'config-0-id' : str (config .pk ),
2092+ 'config-0-device' : str (config .device_id ),
2093+ 'config-0-templates' : str (template1 .pk ),
2094+ 'config-INITIAL_FORMS' : 1 ,
2095+ '_continue' : True ,
2096+ }
2097+ )
2098+ response = self .client .post (path , data = params , follow = True )
2099+ self .assertEqual (response .status_code , 200 )
2100+ config .refresh_from_db ()
2101+
2102+ # Ensure all works as expected
2103+ self .assertEqual (config .templates .count (), 1 )
2104+ self .assertEqual (config .vpnclient_set .count (), 1 )
2105+ self .assertEqual (
2106+ config .backend_instance .config ['openvpn' ][0 ]['cert' ],
2107+ f'/etc/x509/client-{ vpn .pk .hex } .pem' ,
2108+ )
2109+ self .assertEqual (
2110+ config .backend_instance .config ['openvpn' ][0 ]['dev' ],
2111+ 'tun0' ,
2112+ )
2113+
2114+ with self .subTest ('Switch device to template2' ):
2115+ path = reverse (
2116+ f'admin:{ self .app_label } _device_change' , args = [config .device_id ]
2117+ )
2118+ params .update (
2119+ {
2120+ 'config-0-templates' : str (template2 .pk ),
2121+ }
2122+ )
2123+ response = self .client .post (path , data = params , follow = True )
2124+ self .assertEqual (response .status_code , 200 )
2125+ config .refresh_from_db ()
2126+ del config .backend_instance
2127+ self .assertEqual (
2128+ config .backend_instance .config ['openvpn' ][0 ]['cert' ],
2129+ f'/etc/x509/client-{ vpn .pk .hex } .pem' ,
2130+ )
2131+ self .assertEqual (
2132+ config .backend_instance .config ['openvpn' ][0 ]['dev' ],
2133+ 'tun1' ,
2134+ )
2135+ self .assertEqual (config .vpnclient_set .count (), 1 )
2136+
2137+ with self .subTest ('Switch device back to template1' ):
2138+ params .update (
2139+ {
2140+ 'config-0-templates' : str (template1 .pk ),
2141+ }
2142+ )
2143+ response = self .client .post (path , data = params , follow = True )
2144+ self .assertEqual (response .status_code , 200 )
2145+ config .refresh_from_db ()
2146+ del config .backend_instance
2147+ self .assertEqual (
2148+ config .backend_instance .config ['openvpn' ][0 ]['cert' ],
2149+ f'/etc/x509/client-{ vpn .pk .hex } .pem' ,
2150+ )
2151+ self .assertEqual (
2152+ config .backend_instance .config ['openvpn' ][0 ]['dev' ],
2153+ 'tun0' ,
2154+ )
2155+ self .assertEqual (config .vpnclient_set .count (), 1 )
2156+
20502157
20512158class TestTransactionAdmin (
20522159 CreateConfigTemplateMixin ,
0 commit comments