Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions availableVersions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"production": "1.4.11",
"test": "1.4.11",
"local": "1.4.11",
"all": "1.4.11"
"production": "1.4.12",
"test": "1.4.12",
"local": "1.4.12",
"all": "1.4.12"
}
6 changes: 1 addition & 5 deletions src/apps/app_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,6 @@ func (am *AppManager) syncPortState(payload common.TransitionPayload, app *commo
dialPort, dialPortKnown, reservationFailure = am.resolveTunnelHostPort(payload, portRule)
}

// A development run tunnels every port of its template while it runs.
// Its tcp/udp ports have no switch: their tunnels come and go with the
// run, so a stale Active flag on such a rule does not hold them off.
active := portRule.Active || (payload.Stage == common.DEV && !isWebProtocol(portRule.Protocol))
// A DEV label is four characters longer than the PROD one, and an app
// name of 40 characters can push it past what a DNS label may hold:
// such a tunnel could never be reached, so it is not opened. Only an
Expand All @@ -295,7 +291,7 @@ func (am *AppManager) syncPortState(payload common.TransitionPayload, app *commo
// Said again at the next run.
am.forgetLabelTooLong(tunnelID)
}
} else if active {
} else if portRule.Active {
if tunnelsAvailable && appRunning {
if !dialPortKnown {
// Fresh app that has not been started under managed ports
Expand Down
30 changes: 21 additions & 9 deletions src/apps/dev_tunnels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ func devEnvFile(t *testing.T, cfg *config.Config, app, name string) (string, boo
return string(data), true
}

// A running development run gets a tunnel for every port of its template. Its
// tcp/udp ports have no switch: a rule flagged inactive is tunneled all the
// same. Their remote ports reach the container through its env files, and
// stay on the rules so the next run asks for the same ports again.
// A running development run gets a tunnel for every active port of its
// template. The remote ports of its tcp/udp tunnels reach the container
// through its env files, and stay on the rules so the next run asks for the
// same ports again.
func TestSyncPortStateDevTunnelsAllPorts(t *testing.T) {
am, _, mockTunnel, appStore, _, cfg := amHarness(t)
mockTunnel.EXPECT().TunnelCapable().Return(true).Maybe()
Expand All @@ -63,7 +63,7 @@ func TestSyncPortStateDevTunnelsAllPorts(t *testing.T) {
payload.Ports, _ = tunnel.PortForwardRuleToInterface([]common.PortForwardRule{
{RuleName: "ui", Port: 8080, Protocol: "http", Active: true},
{RuleName: "mqtt", Port: 1883, Protocol: "tcp", Active: true, RemotePortEnvironment: "MQTT_PORT"},
{RuleName: "media", Port: 10000, Protocol: "udp", Active: false},
{RuleName: "media", Port: 10000, Protocol: "udp", Active: true},
})

// The launch path published all three on host ports.
Expand Down Expand Up @@ -111,7 +111,7 @@ func TestSyncPortStateDevTunnelsAllPorts(t *testing.T) {
assert.Equal(t, uint64(41800), added[sub].LocalPort, "frpc dials the DEV container's host port")
require.Contains(t, added, tcpSub)
assert.Equal(t, uint64(41801), added[tcpSub].LocalPort)
require.Contains(t, added, udpSub, "a DEV udp port has no switch: an inactive flag does not hold it off")
require.Contains(t, added, udpSub)

rules := spsRules(t, saved)
require.Len(t, rules, 3)
Expand All @@ -129,9 +129,9 @@ func TestSyncPortStateDevTunnelsAllPorts(t *testing.T) {
assert.False(t, ok, "an http tunnel has no remote port")
}

// Once a development run stops, its tcp/udp tunnel goes and so does the port
// announced to the container. The rule keeps the port, and the next run asks
// frps for it again.
// Once a development run stops, or its port is switched off, its tcp/udp
// tunnel goes and so does the port announced to the container. The rule keeps
// the port, and the next run asks frps for it again.
func TestSyncPortStateDevTcpTunnelFollowsRun(t *testing.T) {
am, _, mockTunnel, appStore, _, cfg := amHarness(t)
mockTunnel.EXPECT().TunnelCapable().Return(true).Maybe()
Expand Down Expand Up @@ -176,6 +176,18 @@ func TestSyncPortStateDevTcpTunnelFollowsRun(t *testing.T) {
got, ok := devEnvFile(t, cfg, "devmedia", "REMOTE_PORT_FOR_10000")
assert.True(t, ok)
assert.Equal(t, "30200", got)

// Switched off while it runs: the tunnel goes as on a stop. Nothing
// changed on the rule, so nothing is saved.
payload.Ports = spsPorts(t, common.PortForwardRule{RuleName: "media", Port: 10000, Protocol: "udp", Active: false, HostPort: 41850, RemotePort: 30200})
mockTunnel.EXPECT().Get(id).Return(&tunnel.Tunnel{Config: tunnel.TunnelConfig{Subdomain: sub, RemotePort: 30200}}).Once()
mockTunnel.EXPECT().RemoveTunnel(mock.MatchedBy(func(c tunnel.TunnelConfig) bool {
return c.Subdomain == sub && c.Protocol == tunnel.UDP && c.Stage == common.DEV
})).Return(nil).Once()
mockTunnel.EXPECT().GetState().Return([]tunnel.TunnelState{}, nil).Once()
require.NoError(t, am.syncPortState(payload, app))
_, ok = devEnvFile(t, cfg, "devmedia", "REMOTE_PORT_FOR_10000")
assert.False(t, ok, "a switched-off port is not announced")
}

// Only an http(s) tunnel is reached by its label: a tcp/udp port of an app
Expand Down
2 changes: 1 addition & 1 deletion src/release/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.4.11
1.4.12
Loading