chore(lint): add musttag linter and fix lint errors

Breaking change: JSON fields changed in the server API
This commit is contained in:
Quentin McGaw
2023-06-08 07:26:29 +00:00
parent 37f0e5c73b
commit 0da2b6ad0b
13 changed files with 77 additions and 76 deletions

View File

@@ -78,6 +78,7 @@ linters:
- maintidx - maintidx
- makezero - makezero
- misspell - misspell
- musttag
- nakedret - nakedret
- nestif - nestif
- nilerr - nilerr

View File

@@ -18,70 +18,70 @@ import (
type OpenVPN struct { type OpenVPN struct {
// Version is the OpenVPN version to run. // Version is the OpenVPN version to run.
// It can only be "2.5" or "2.6". // It can only be "2.5" or "2.6".
Version string Version string `json:"version"`
// User is the OpenVPN authentication username. // User is the OpenVPN authentication username.
// It cannot be nil in the internal state if OpenVPN is used. // It cannot be nil in the internal state if OpenVPN is used.
// It is usually required but in some cases can be the empty string // It is usually required but in some cases can be the empty string
// to indicate no user+password authentication is needed. // to indicate no user+password authentication is needed.
User *string User *string `json:"user"`
// Password is the OpenVPN authentication password. // Password is the OpenVPN authentication password.
// It cannot be nil in the internal state if OpenVPN is used. // It cannot be nil in the internal state if OpenVPN is used.
// It is usually required but in some cases can be the empty string // It is usually required but in some cases can be the empty string
// to indicate no user+password authentication is needed. // to indicate no user+password authentication is needed.
Password *string Password *string `json:"password"`
// ConfFile is a custom OpenVPN configuration file path. // ConfFile is a custom OpenVPN configuration file path.
// It can be set to the empty string for it to be ignored. // It can be set to the empty string for it to be ignored.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
ConfFile *string ConfFile *string `json:"config_file_path"`
// Ciphers is a list of ciphers to use for OpenVPN, // Ciphers is a list of ciphers to use for OpenVPN,
// different from the ones specified by the VPN // different from the ones specified by the VPN
// service provider configuration files. // service provider configuration files.
Ciphers []string Ciphers []string `json:"ciphers"`
// Auth is an auth algorithm to use in OpenVPN instead // Auth is an auth algorithm to use in OpenVPN instead
// of the one specified by the VPN service provider. // of the one specified by the VPN service provider.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
// It is ignored if it is set to the empty string. // It is ignored if it is set to the empty string.
Auth *string Auth *string `json:"auth"`
// Cert is the base64 encoded DER of an OpenVPN certificate for the <cert> block. // Cert is the base64 encoded DER of an OpenVPN certificate for the <cert> block.
// This is notably used by Cyberghost and VPN secure. // This is notably used by Cyberghost and VPN secure.
// It can be set to the empty string to be ignored. // It can be set to the empty string to be ignored.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
Cert *string Cert *string `json:"cert"`
// Key is the base64 encoded DER of an OpenVPN key. // Key is the base64 encoded DER of an OpenVPN key.
// This is used by Cyberghost and VPN Unlimited. // This is used by Cyberghost and VPN Unlimited.
// It can be set to the empty string to be ignored. // It can be set to the empty string to be ignored.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
Key *string Key *string `json:"key"`
// EncryptedKey is the base64 encoded DER of an encrypted key for OpenVPN. // EncryptedKey is the base64 encoded DER of an encrypted key for OpenVPN.
// It is used by VPN secure. // It is used by VPN secure.
// It defaults to the empty string meaning it is not // It defaults to the empty string meaning it is not
// to be used. KeyPassphrase must be set if this one is set. // to be used. KeyPassphrase must be set if this one is set.
EncryptedKey *string EncryptedKey *string `json:"encrypted_key"`
// KeyPassphrase is the key passphrase to be used by OpenVPN // KeyPassphrase is the key passphrase to be used by OpenVPN
// to decrypt the EncryptedPrivateKey. It defaults to the // to decrypt the EncryptedPrivateKey. It defaults to the
// empty string and must be set if EncryptedPrivateKey is set. // empty string and must be set if EncryptedPrivateKey is set.
KeyPassphrase *string KeyPassphrase *string `json:"key_passphrase"`
// PIAEncPreset is the encryption preset for // PIAEncPreset is the encryption preset for
// Private Internet Access. It can be set to an // Private Internet Access. It can be set to an
// empty string for other providers. // empty string for other providers.
PIAEncPreset *string PIAEncPreset *string `json:"pia_encryption_preset"`
// MSSFix is the value (1 to 10000) to set for the // MSSFix is the value (1 to 10000) to set for the
// mssfix option for OpenVPN. It is ignored if set to 0. // mssfix option for OpenVPN. It is ignored if set to 0.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
MSSFix *uint16 MSSFix *uint16 `json:"mssfix"`
// Interface is the OpenVPN device interface name. // Interface is the OpenVPN device interface name.
// It cannot be an empty string in the internal state. // It cannot be an empty string in the internal state.
Interface string Interface string `json:"interface"`
// ProcessUser is the OpenVPN process OS username // ProcessUser is the OpenVPN process OS username
// to use. It cannot be empty in the internal state. // to use. It cannot be empty in the internal state.
// It defaults to 'root'. // It defaults to 'root'.
ProcessUser string ProcessUser string `json:"process_user"`
// Verbosity is the OpenVPN verbosity level from 0 to 6. // Verbosity is the OpenVPN verbosity level from 0 to 6.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
Verbosity *int Verbosity *int `json:"verbosity"`
// Flags is a slice of additional flags to be passed // Flags is a slice of additional flags to be passed
// to the OpenVPN program. // to the OpenVPN program.
Flags []string Flags []string `json:"flags"`
} }
var ivpnAccountID = regexp.MustCompile(`^(i|ivpn)\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4}$`) var ivpnAccountID = regexp.MustCompile(`^(i|ivpn)\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4}\-[a-zA-Z0-9]{4}$`)

View File

@@ -16,19 +16,19 @@ type OpenVPNSelection struct {
// It can be set to an empty string to indicate to // It can be set to an empty string to indicate to
// NOT use a custom configuration file. // NOT use a custom configuration file.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
ConfFile *string ConfFile *string `json:"config_file_path"`
// TCP is true if the OpenVPN protocol is TCP, // TCP is true if the OpenVPN protocol is TCP,
// and false for UDP. // and false for UDP.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
TCP *bool TCP *bool `json:"tcp"`
// CustomPort is the OpenVPN server endpoint port. // CustomPort is the OpenVPN server endpoint port.
// It can be set to 0 to indicate no custom port should // It can be set to 0 to indicate no custom port should
// be used. It cannot be nil in the internal state. // be used. It cannot be nil in the internal state.
CustomPort *uint16 // HideMyAss, Mullvad, PIA, ProtonVPN, WeVPN, Windscribe CustomPort *uint16 `json:"custom_port"`
// PIAEncPreset is the encryption preset for // PIAEncPreset is the encryption preset for
// Private Internet Access. It can be set to an // Private Internet Access. It can be set to an
// empty string for other providers. // empty string for other providers.
PIAEncPreset *string PIAEncPreset *string `json:"pia_encryption_preset"`
} }
func (o OpenVPNSelection) validate(vpnProvider string) (err error) { func (o OpenVPNSelection) validate(vpnProvider string) (err error) {

View File

@@ -14,12 +14,12 @@ import (
type PortForwarding struct { type PortForwarding struct {
// Enabled is true if port forwarding should be activated. // Enabled is true if port forwarding should be activated.
// It cannot be nil for the internal state. // It cannot be nil for the internal state.
Enabled *bool Enabled *bool `json:"enabled"`
// Filepath is the port forwarding status file path // Filepath is the port forwarding status file path
// to use. It can be the empty string to indicate not // to use. It can be the empty string to indicate not
// to write to a file. It cannot be nil for the // to write to a file. It cannot be nil for the
// internal state // internal state
Filepath *string Filepath *string `json:"status_file_path"`
} }
func (p PortForwarding) validate(vpnProvider string) (err error) { func (p PortForwarding) validate(vpnProvider string) (err error) {

View File

@@ -14,12 +14,12 @@ import (
type Provider struct { type Provider struct {
// Name is the VPN service provider name. // Name is the VPN service provider name.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
Name *string Name *string `json:"name"`
// ServerSelection is the settings to // ServerSelection is the settings to
// select the VPN server. // select the VPN server.
ServerSelection ServerSelection ServerSelection ServerSelection `json:"server_selection"`
// PortForwarding is the settings about port forwarding. // PortForwarding is the settings about port forwarding.
PortForwarding PortForwarding PortForwarding PortForwarding `json:"port_forwarding"`
} }
// TODO v4 remove pointer for receiver (because of Surfshark). // TODO v4 remove pointer for receiver (because of Surfshark).

View File

@@ -20,50 +20,50 @@ type ServerSelection struct { //nolint:maligned
// VPN is the VPN type which can be 'openvpn' // VPN is the VPN type which can be 'openvpn'
// or 'wireguard'. It cannot be the empty string // or 'wireguard'. It cannot be the empty string
// in the internal state. // in the internal state.
VPN string VPN string `json:"vpn"`
// TargetIP is the server endpoint IP address to use. // TargetIP is the server endpoint IP address to use.
// It will override any IP address from the picked // It will override any IP address from the picked
// built-in server. It cannot be the empty value in the internal // built-in server. It cannot be the empty value in the internal
// state, and can be set to the unspecified address to indicate // state, and can be set to the unspecified address to indicate
// there is not target IP address to use. // there is not target IP address to use.
TargetIP netip.Addr TargetIP netip.Addr `json:"target_ip"`
// Counties is the list of countries to filter VPN servers with. // Counties is the list of countries to filter VPN servers with.
Countries []string Countries []string `json:"countries"`
// Regions is the list of regions to filter VPN servers with. // Regions is the list of regions to filter VPN servers with.
Regions []string Regions []string `json:"regions"`
// Cities is the list of cities to filter VPN servers with. // Cities is the list of cities to filter VPN servers with.
Cities []string Cities []string `json:"cities"`
// ISPs is the list of ISP names to filter VPN servers with. // ISPs is the list of ISP names to filter VPN servers with.
ISPs []string ISPs []string `json:"isps"`
// Names is the list of server names to filter VPN servers with. // Names is the list of server names to filter VPN servers with.
Names []string Names []string `json:"names"`
// Numbers is the list of server numbers to filter VPN servers with. // Numbers is the list of server numbers to filter VPN servers with.
Numbers []uint16 Numbers []uint16 `json:"numbers"`
// Hostnames is the list of hostnames to filter VPN servers with. // Hostnames is the list of hostnames to filter VPN servers with.
Hostnames []string Hostnames []string `json:"hostnames"`
// OwnedOnly is true if VPN provider servers that are not owned // OwnedOnly is true if VPN provider servers that are not owned
// should be filtered. This is used with Mullvad. // should be filtered. This is used with Mullvad.
OwnedOnly *bool OwnedOnly *bool `json:"owned_only"`
// FreeOnly is true if VPN servers that are not free should // FreeOnly is true if VPN servers that are not free should
// be filtered. This is used with ProtonVPN and VPN Unlimited. // be filtered. This is used with ProtonVPN and VPN Unlimited.
FreeOnly *bool FreeOnly *bool `json:"free_only"`
// PremiumOnly is true if VPN servers that are not premium should // PremiumOnly is true if VPN servers that are not premium should
// be filtered. This is used with VPN Secure. // be filtered. This is used with VPN Secure.
// TODO extend to providers using FreeOnly. // TODO extend to providers using FreeOnly.
PremiumOnly *bool PremiumOnly *bool `json:"premium_only"`
// StreamOnly is true if VPN servers not for streaming should // StreamOnly is true if VPN servers not for streaming should
// be filtered. This is used with VPNUnlimited. // be filtered. This is used with VPNUnlimited.
StreamOnly *bool StreamOnly *bool `json:"stream_only"`
// MultiHopOnly is true if VPN servers that are not multihop // MultiHopOnly is true if VPN servers that are not multihop
// should be filtered. This is used with Surfshark. // should be filtered. This is used with Surfshark.
MultiHopOnly *bool MultiHopOnly *bool `json:"multi_hop_only"`
// OpenVPN contains settings to select OpenVPN servers // OpenVPN contains settings to select OpenVPN servers
// and the final connection. // and the final connection.
OpenVPN OpenVPNSelection OpenVPN OpenVPNSelection `json:"openvpn"`
// Wireguard contains settings to select Wireguard servers // Wireguard contains settings to select Wireguard servers
// and the final connection. // and the final connection.
Wireguard WireguardSelection Wireguard WireguardSelection `json:"wireguard"`
} }
var ( var (

View File

@@ -13,14 +13,14 @@ import (
// Unbound is settings for the Unbound program. // Unbound is settings for the Unbound program.
type Unbound struct { type Unbound struct {
Providers []string Providers []string `json:"providers"`
Caching *bool Caching *bool `json:"caching"`
IPv6 *bool IPv6 *bool `json:"ipv6"`
VerbosityLevel *uint8 VerbosityLevel *uint8 `json:"verbosity_level"`
VerbosityDetailsLevel *uint8 VerbosityDetailsLevel *uint8 `json:"verbosity_details_level"`
ValidationLogLevel *uint8 ValidationLogLevel *uint8 `json:"validation_log_level"`
Username string Username string `json:"username"`
Allowed []netip.Prefix Allowed []netip.Prefix `json:"allowed"`
} }
func (u *Unbound) setDefaults() { func (u *Unbound) setDefaults() {

View File

@@ -29,9 +29,9 @@ func Test_Unbound_JSON(t *testing.T) {
b, err := json.Marshal(settings) b, err := json.Marshal(settings)
require.NoError(t, err) require.NoError(t, err)
const expected = `{"Providers":["cloudflare"],"Caching":true,"IPv6":false,` + const expected = `{"providers":["cloudflare"],"caching":true,"ipv6":false,` +
`"VerbosityLevel":1,"VerbosityDetailsLevel":null,"ValidationLogLevel":0,` + `"verbosity_level":1,"verbosity_details_level":null,"validation_log_level":0,` +
`"Username":"user","Allowed":["0.0.0.0/0","::/0"]}` `"username":"user","allowed":["0.0.0.0/0","::/0"]}`
assert.Equal(t, expected, string(b)) assert.Equal(t, expected, string(b))

View File

@@ -13,10 +13,10 @@ type VPN struct {
// Type is the VPN type and can only be // Type is the VPN type and can only be
// 'openvpn' or 'wireguard'. It cannot be the // 'openvpn' or 'wireguard'. It cannot be the
// empty string in the internal state. // empty string in the internal state.
Type string Type string `json:"type"`
Provider Provider Provider Provider `json:"provider"`
OpenVPN OpenVPN OpenVPN OpenVPN `json:"openvpn"`
Wireguard Wireguard Wireguard Wireguard `json:"wireguard"`
} }
// TODO v4 remove pointer for receiver (because of Surfshark). // TODO v4 remove pointer for receiver (because of Surfshark).

View File

@@ -18,27 +18,27 @@ import (
type Wireguard struct { type Wireguard struct {
// PrivateKey is the Wireguard client peer private key. // PrivateKey is the Wireguard client peer private key.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
PrivateKey *string PrivateKey *string `json:"private_key"`
// PreSharedKey is the Wireguard pre-shared key. // PreSharedKey is the Wireguard pre-shared key.
// It can be the empty string to indicate there // It can be the empty string to indicate there
// is no pre-shared key. // is no pre-shared key.
// It cannot be nil in the internal state. // It cannot be nil in the internal state.
PreSharedKey *string PreSharedKey *string `json:"pre_shared_key"`
// Addresses are the Wireguard interface addresses. // Addresses are the Wireguard interface addresses.
Addresses []netip.Prefix Addresses []netip.Prefix `json:"addresses"`
// Interface is the name of the Wireguard interface // Interface is the name of the Wireguard interface
// to create. It cannot be the empty string in the // to create. It cannot be the empty string in the
// internal state. // internal state.
Interface string Interface string `json:"interface"`
// Maximum Transmission Unit (MTU) of the Wireguard interface. // Maximum Transmission Unit (MTU) of the Wireguard interface.
// It cannot be zero in the internal state, and defaults to // It cannot be zero in the internal state, and defaults to
// the wireguard-go MTU default of 1420. // the wireguard-go MTU default of 1420.
MTU uint16 MTU uint16 `json:"mtu"`
// Implementation is the Wireguard implementation to use. // Implementation is the Wireguard implementation to use.
// It can be "auto", "userspace" or "kernelspace". // It can be "auto", "userspace" or "kernelspace".
// It defaults to "auto" and cannot be the empty string // It defaults to "auto" and cannot be the empty string
// in the internal state. // in the internal state.
Implementation string Implementation string `json:"implementation"`
} }
var regexpInterfaceName = regexp.MustCompile(`^[a-zA-Z0-9_]+$`) var regexpInterfaceName = regexp.MustCompile(`^[a-zA-Z0-9_]+$`)

View File

@@ -18,18 +18,18 @@ type WireguardSelection struct {
// To indicate it should not be used, it should be set // To indicate it should not be used, it should be set
// to netaddr.IPv4Unspecified(). It can never be the zero value // to netaddr.IPv4Unspecified(). It can never be the zero value
// in the internal state. // in the internal state.
EndpointIP netip.Addr EndpointIP netip.Addr `json:"endpoint_ip"`
// EndpointPort is a the server port to use for the VPN server. // EndpointPort is a the server port to use for the VPN server.
// It is optional for VPN providers IVPN, Mullvad, Surfshark // It is optional for VPN providers IVPN, Mullvad, Surfshark
// and Windscribe, and compulsory for the others. // and Windscribe, and compulsory for the others.
// When optional, it can be set to 0 to indicate not use // When optional, it can be set to 0 to indicate not use
// a custom endpoint port. It cannot be nil in the internal // a custom endpoint port. It cannot be nil in the internal
// state. // state.
EndpointPort *uint16 EndpointPort *uint16 `json:"endpoint_port"`
// PublicKey is the server public key. // PublicKey is the server public key.
// It is only used with VPN providers generating Wireguard // It is only used with VPN providers generating Wireguard
// configurations specific to each server and user. // configurations specific to each server and user.
PublicKey string PublicKey string `json:"public_key"`
} }
// Validate validates WireguardSelection settings. // Validate validates WireguardSelection settings.

View File

@@ -11,7 +11,7 @@ import (
"github.com/qdm12/gluetun/internal/constants/providers" "github.com/qdm12/gluetun/internal/constants/providers"
) )
type AllServers struct { type AllServers struct { //nolint:musttag
Version uint16 // used for migration of the top level scheme Version uint16 // used for migration of the top level scheme
ProviderToServers map[string]Servers ProviderToServers map[string]Servers
} }

View File

@@ -14,22 +14,22 @@ var (
) )
type apiData struct { type apiData struct {
LogicalServers []logicalServer LogicalServers []logicalServer `json:"LogicalServers"`
} }
type logicalServer struct { type logicalServer struct {
Name string Name string `json:"Name"`
ExitCountry string ExitCountry string `json:"ExitCountry"`
Region *string Region *string `json:"Region"`
City *string City *string `json:"City"`
Servers []physicalServer Servers []physicalServer `json:"Servers"`
} }
type physicalServer struct { type physicalServer struct {
EntryIP netip.Addr EntryIP netip.Addr `json:"EntryIP"`
ExitIP netip.Addr ExitIP netip.Addr `json:"ExitIP"`
Domain string Domain string `json:"Domain"`
Status uint8 Status uint8 `json:"Status"`
} }
func fetchAPI(ctx context.Context, client *http.Client) ( func fetchAPI(ctx context.Context, client *http.Client) (