@@ -1842,7 +1842,7 @@ func TestAppProxyRouter(t *testing.T) {
18421842 require .NoError (t , err )
18431843 response , err := client .Do (request )
18441844 require .NoError (t , err )
1845- if response .StatusCode == http .StatusNotFound {
1845+ if response .StatusCode == http .StatusServiceUnavailable {
18461846 body , err := io .ReadAll (response .Body )
18471847 require .NoError (t , err )
18481848 return strings .Contains (string (body ), "Application Disabled" )
@@ -1855,6 +1855,70 @@ func TestAppProxyRouter(t *testing.T) {
18551855 expectedNotifications : map [string ]int {},
18561856 expectedWakeUps : map [string ]int {},
18571857 },
1858+ {
1859+ name : "restart-disabled-flag-reset-on-dns-success" ,
1860+ run : func (t * testing.T , client * http.Client , m []* mockoidc.MockOIDC , appServer * testutil.AppServer , service * testutil.DataAppsAPI , dnsServer * dnsmock.Server ) {
1861+ // Phase 1: Set restart disabled state
1862+ dnsServer .RemoveARecords (dns .Fqdn ("app.local" ))
1863+
1864+ service .WakeUpOverrides ["123" ] = func (w http.ResponseWriter , req * http.Request ) {
1865+ w .Header ().Set ("Content-Type" , "application/json" )
1866+ w .WriteHeader (http .StatusBadRequest )
1867+ _ , _ = fmt .Fprintln (w , `{
1868+ "code": 0,
1869+ "context": {
1870+ "code": "apps.restartDisabled"
1871+ },
1872+ "error": "App restart is disabled. Contact app maintainer.",
1873+ "exceptionId": "exception-208db995c92ed365d47bcc701ae4d802",
1874+ "status": "error"
1875+ }` )
1876+ }
1877+
1878+ // Request to public app - fails because the app doesn't have a DNS record
1879+ request , err := http .NewRequestWithContext (t .Context (), http .MethodGet , "https://public-123.hub.keboola.local/" , nil )
1880+ require .NoError (t , err )
1881+ response , err := client .Do (request )
1882+ require .NoError (t , err )
1883+ // First request returns 503 Service Unavailable (Spinner) because wakeup is async
1884+ require .Equal (t , http .StatusServiceUnavailable , response .StatusCode )
1885+
1886+ // Wait for async wakeup to complete and flag to be set
1887+ assert .Eventually (t , func () bool {
1888+ request , err := http .NewRequestWithContext (t .Context (), http .MethodGet , "https://public-123.hub.keboola.local/" , nil )
1889+ require .NoError (t , err )
1890+ response , err := client .Do (request )
1891+ require .NoError (t , err )
1892+ body , err := io .ReadAll (response .Body )
1893+ require .NoError (t , err )
1894+ return response .StatusCode == http .StatusServiceUnavailable && strings .Contains (string (body ), "Application Disabled" )
1895+ }, 5 * time .Second , 100 * time .Millisecond )
1896+
1897+ // Phase 2: Simulate app becoming available (restart enabled)
1898+ // Add DNS record back and remove wakeup override
1899+ dnsServer .AddARecord (dns .Fqdn ("app.local" ), net .ParseIP ("127.0.0.1" ))
1900+ delete (service .WakeUpOverrides , "123" )
1901+
1902+ // Request should now succeed - DNS resolution succeeds, flag gets reset
1903+ request , err = http .NewRequestWithContext (t .Context (), http .MethodGet , "https://public-123.hub.keboola.local/" , nil )
1904+ require .NoError (t , err )
1905+ response , err = client .Do (request )
1906+ require .NoError (t , err )
1907+ require .Equal (t , http .StatusOK , response .StatusCode )
1908+ body , err := io .ReadAll (response .Body )
1909+ require .NoError (t , err )
1910+ assert .Contains (t , string (body ), "Hello, client" )
1911+
1912+ // Verify flag stays reset - subsequent requests should continue to work
1913+ request , err = http .NewRequestWithContext (t .Context (), http .MethodGet , "https://public-123.hub.keboola.local/" , nil )
1914+ require .NoError (t , err )
1915+ response , err = client .Do (request )
1916+ require .NoError (t , err )
1917+ require .Equal (t , http .StatusOK , response .StatusCode )
1918+ },
1919+ expectedNotifications : map [string ]int {"123" : 1 },
1920+ expectedWakeUps : map [string ]int {},
1921+ },
18581922 {
18591923 name : "private-one-provider-selector" ,
18601924 run : func (t * testing.T , client * http.Client , m []* mockoidc.MockOIDC , appServer * testutil.AppServer , service * testutil.DataAppsAPI , dnsServer * dnsmock.Server ) {
0 commit comments