mirror of
https://github.com/qdm12/gluetun.git
synced 2026-07-25 20:06:25 +02:00
d9cc7dcffb
- new directory structure containing manifest.json and one json file per provider, by default. - the manifest.json file can specify a filepath for each vpn provider - each vpn provider json data file can contain the `"preferred": true` field to enforce it is used even if outdated, unless there is a version mismatch - `STORAGE_SERVERS_DIRECTORY_PATH` replaces `STORAGE_FILEPATH` (which is now a migration source only). It sets the directory where server manifest and per-provider JSON files are stored (default: `/gluetun/servers/`). - First-run migration: On startup, gluetun checks for the old /gluetun/servers.json file; if found and no new manifest exists, it automatically migrates all data to /gluetun/servers/ directory structure - Silent fallback: If legacy file isn't found, uses the new directory path normally - Legacy cleanup: After successful migration, attempts to remove the old fat JSON file (logs warning only if removal fails, e.g., read-only bind mounts)
95 lines
2.2 KiB
Go
95 lines
2.2 KiB
Go
package ivpn
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func Test_fetchAPI(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
testCases := map[string]struct {
|
|
responseStatus int
|
|
responseBody io.ReadCloser
|
|
data apiData
|
|
err error
|
|
}{
|
|
"http response status not ok": {
|
|
responseStatus: http.StatusNoContent,
|
|
err: errors.New("HTTP status code not OK: 204 No Content"),
|
|
},
|
|
"nil body": {
|
|
responseStatus: http.StatusOK,
|
|
err: errors.New("decoding response body: EOF"),
|
|
},
|
|
"no server": {
|
|
responseStatus: http.StatusOK,
|
|
responseBody: io.NopCloser(strings.NewReader(`{}`)),
|
|
},
|
|
"success": {
|
|
responseStatus: http.StatusOK,
|
|
responseBody: io.NopCloser(strings.NewReader(`{"servers":[
|
|
{"country":"Country1","city":"City A","isp":"xyz","is_active":true,"hostnames":{"openvpn":"hosta"}},
|
|
{"country":"Country2","city":"City B","isp":"abc","is_active":false,"hostnames":{"openvpn":"hostb"}}
|
|
]}`)),
|
|
data: apiData{
|
|
Servers: []apiServer{
|
|
{
|
|
Country: "Country1",
|
|
City: "City A",
|
|
IsActive: true,
|
|
ISP: "xyz",
|
|
Hostnames: apiHostnames{
|
|
OpenVPN: "hosta",
|
|
},
|
|
},
|
|
{
|
|
Country: "Country2",
|
|
City: "City B",
|
|
ISP: "abc",
|
|
Hostnames: apiHostnames{
|
|
OpenVPN: "hostb",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for name, testCase := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ctx := context.Background()
|
|
|
|
client := &http.Client{
|
|
Transport: roundTripFunc(func(r *http.Request) (*http.Response, error) {
|
|
assert.Equal(t, http.MethodGet, r.Method)
|
|
assert.Equal(t, r.URL.String(), "https://api.ivpn.net/v4/servers/stats")
|
|
return &http.Response{
|
|
StatusCode: testCase.responseStatus,
|
|
Status: http.StatusText(testCase.responseStatus),
|
|
Body: testCase.responseBody,
|
|
}, nil
|
|
}),
|
|
}
|
|
|
|
data, err := fetchAPI(ctx, client)
|
|
|
|
assert.Equal(t, testCase.data, data)
|
|
if testCase.err != nil {
|
|
require.Error(t, err)
|
|
assert.Equal(t, testCase.err.Error(), err.Error())
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|