Code maintenance: CLI interface abstraction
This commit is contained in:
@@ -56,12 +56,14 @@ func main() {
|
|||||||
os := os.New()
|
os := os.New()
|
||||||
osUser := user.New()
|
osUser := user.New()
|
||||||
unix := unix.New()
|
unix := unix.New()
|
||||||
nativeos.Exit(_main(ctx, buildInfo, args, os, osUser, unix))
|
cli := cli.New()
|
||||||
|
nativeos.Exit(_main(ctx, buildInfo, args, os, osUser, unix, cli))
|
||||||
}
|
}
|
||||||
|
|
||||||
//nolint:gocognit,gocyclo
|
//nolint:gocognit,gocyclo
|
||||||
func _main(background context.Context, buildInfo models.BuildInformation,
|
func _main(background context.Context, buildInfo models.BuildInformation,
|
||||||
args []string, os os.OS, osUser user.OSUser, unix unix.Unix) int {
|
args []string, os os.OS, osUser user.OSUser, unix unix.Unix,
|
||||||
|
cli cli.CLI) int {
|
||||||
if len(args) > 1 { // cli operation
|
if len(args) > 1 { // cli operation
|
||||||
var err error
|
var err error
|
||||||
switch args[1] {
|
switch args[1] {
|
||||||
|
|||||||
@@ -2,141 +2,19 @@ package cli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/qdm12/gluetun/internal/constants"
|
|
||||||
"github.com/qdm12/gluetun/internal/healthcheck"
|
|
||||||
"github.com/qdm12/gluetun/internal/os"
|
"github.com/qdm12/gluetun/internal/os"
|
||||||
"github.com/qdm12/gluetun/internal/params"
|
|
||||||
"github.com/qdm12/gluetun/internal/provider"
|
|
||||||
"github.com/qdm12/gluetun/internal/settings"
|
|
||||||
"github.com/qdm12/gluetun/internal/storage"
|
|
||||||
"github.com/qdm12/gluetun/internal/updater"
|
|
||||||
"github.com/qdm12/golibs/logging"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func ClientKey(args []string, openFile os.OpenFileFunc) error {
|
type CLI interface {
|
||||||
flagSet := flag.NewFlagSet("clientkey", flag.ExitOnError)
|
ClientKey(args []string, openFile os.OpenFileFunc) error
|
||||||
filepath := flagSet.String("path", string(constants.ClientKey), "file path to the client.key file")
|
HealthCheck(ctx context.Context) error
|
||||||
if err := flagSet.Parse(args); err != nil {
|
OpenvpnConfig(os os.OS) error
|
||||||
return err
|
Update(args []string, os os.OS) error
|
||||||
}
|
|
||||||
file, err := openFile(*filepath, os.O_RDONLY, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data, err := ioutil.ReadAll(file)
|
|
||||||
if err != nil {
|
|
||||||
_ = file.Close()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := file.Close(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s := string(data)
|
|
||||||
s = strings.ReplaceAll(s, "\n", "")
|
|
||||||
s = strings.ReplaceAll(s, "\r", "")
|
|
||||||
s = strings.TrimPrefix(s, "-----BEGIN PRIVATE KEY-----")
|
|
||||||
s = strings.TrimSuffix(s, "-----END PRIVATE KEY-----")
|
|
||||||
fmt.Println(s)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func HealthCheck(ctx context.Context) error {
|
type cli struct{}
|
||||||
const timeout = 3 * time.Second
|
|
||||||
httpClient := &http.Client{Timeout: timeout}
|
|
||||||
healthchecker := healthcheck.NewChecker(httpClient)
|
|
||||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
|
||||||
defer cancel()
|
|
||||||
const url = "http://" + constants.HealthcheckAddress
|
|
||||||
return healthchecker.Check(ctx, url)
|
|
||||||
}
|
|
||||||
|
|
||||||
func OpenvpnConfig(os os.OS) error {
|
func New() CLI {
|
||||||
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel)
|
return &cli{}
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
paramsReader := params.NewReader(logger, os)
|
|
||||||
allSettings, err := settings.GetAllSettings(paramsReader)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
allServers, err := storage.New(logger, os, constants.ServersData).
|
|
||||||
SyncServers(constants.GetAllServers())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
providerConf := provider.New(allSettings.OpenVPN.Provider.Name, allServers, time.Now)
|
|
||||||
connection, err := providerConf.GetOpenVPNConnection(allSettings.OpenVPN.Provider.ServerSelection)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
lines := providerConf.BuildConf(
|
|
||||||
connection,
|
|
||||||
allSettings.OpenVPN.Verbosity,
|
|
||||||
"nonroortuser",
|
|
||||||
allSettings.OpenVPN.Root,
|
|
||||||
allSettings.OpenVPN.Cipher,
|
|
||||||
allSettings.OpenVPN.Auth,
|
|
||||||
allSettings.OpenVPN.Provider.ExtraConfigOptions,
|
|
||||||
)
|
|
||||||
fmt.Println(strings.Join(lines, "\n"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Update(args []string, os os.OS) error {
|
|
||||||
options := settings.Updater{CLI: true}
|
|
||||||
var flushToFile bool
|
|
||||||
flagSet := flag.NewFlagSet("update", flag.ExitOnError)
|
|
||||||
flagSet.BoolVar(&flushToFile, "file", false, "Write results to /gluetun/servers.json (for end users)")
|
|
||||||
flagSet.BoolVar(&options.Stdout, "stdout", false, "Write results to console to modify the program (for maintainers)")
|
|
||||||
flagSet.StringVar(&options.DNSAddress, "dns", "1.1.1.1", "DNS resolver address to use")
|
|
||||||
flagSet.BoolVar(&options.Cyberghost, "cyberghost", false, "Update Cyberghost servers")
|
|
||||||
flagSet.BoolVar(&options.Mullvad, "mullvad", false, "Update Mullvad servers")
|
|
||||||
flagSet.BoolVar(&options.Nordvpn, "nordvpn", false, "Update Nordvpn servers")
|
|
||||||
flagSet.BoolVar(&options.PIA, "pia", false, "Update Private Internet Access post-summer 2020 servers")
|
|
||||||
flagSet.BoolVar(&options.Privado, "privado", false, "Update Privado servers")
|
|
||||||
flagSet.BoolVar(&options.Purevpn, "purevpn", false, "Update Purevpn servers")
|
|
||||||
flagSet.BoolVar(&options.Surfshark, "surfshark", false, "Update Surfshark servers")
|
|
||||||
flagSet.BoolVar(&options.Vyprvpn, "vyprvpn", false, "Update Vyprvpn servers")
|
|
||||||
flagSet.BoolVar(&options.Windscribe, "windscribe", false, "Update Windscribe servers")
|
|
||||||
if err := flagSet.Parse(args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !flushToFile && !options.Stdout {
|
|
||||||
return fmt.Errorf("at least one of -file or -stdout must be specified")
|
|
||||||
}
|
|
||||||
ctx := context.Background()
|
|
||||||
const clientTimeout = 10 * time.Second
|
|
||||||
httpClient := &http.Client{Timeout: clientTimeout}
|
|
||||||
storage := storage.New(logger, os, constants.ServersData)
|
|
||||||
currentServers, err := storage.SyncServers(constants.GetAllServers())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("cannot update servers: %w", err)
|
|
||||||
}
|
|
||||||
updater := updater.New(options, httpClient, currentServers, logger)
|
|
||||||
allServers, err := updater.UpdateServers(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if flushToFile {
|
|
||||||
if err := storage.FlushToFile(allServers); err != nil {
|
|
||||||
return fmt.Errorf("cannot update servers: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
41
internal/cli/clientkey.go
Normal file
41
internal/cli/clientkey.go
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/gluetun/internal/os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *cli) ClientKey(args []string, openFile os.OpenFileFunc) error {
|
||||||
|
flagSet := flag.NewFlagSet("clientkey", flag.ExitOnError)
|
||||||
|
filepath := flagSet.String("path", string(constants.ClientKey), "file path to the client.key file")
|
||||||
|
if err := flagSet.Parse(args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
file, err := openFile(*filepath, os.O_RDONLY, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
data, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
_ = file.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := file.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s := string(data)
|
||||||
|
s = strings.ReplaceAll(s, "\n", "")
|
||||||
|
s = strings.ReplaceAll(s, "\r", "")
|
||||||
|
s = strings.TrimPrefix(s, "-----BEGIN PRIVATE KEY-----")
|
||||||
|
s = strings.TrimSuffix(s, "-----END PRIVATE KEY-----")
|
||||||
|
fmt.Println(s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
20
internal/cli/healthcheck.go
Normal file
20
internal/cli/healthcheck.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/gluetun/internal/healthcheck"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *cli) HealthCheck(ctx context.Context) error {
|
||||||
|
const timeout = 3 * time.Second
|
||||||
|
httpClient := &http.Client{Timeout: timeout}
|
||||||
|
healthchecker := healthcheck.NewChecker(httpClient)
|
||||||
|
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||||
|
defer cancel()
|
||||||
|
const url = "http://" + constants.HealthcheckAddress
|
||||||
|
return healthchecker.Check(ctx, url)
|
||||||
|
}
|
||||||
48
internal/cli/openvpnconfig.go
Normal file
48
internal/cli/openvpnconfig.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/gluetun/internal/os"
|
||||||
|
"github.com/qdm12/gluetun/internal/params"
|
||||||
|
"github.com/qdm12/gluetun/internal/provider"
|
||||||
|
"github.com/qdm12/gluetun/internal/settings"
|
||||||
|
"github.com/qdm12/gluetun/internal/storage"
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *cli) OpenvpnConfig(os os.OS) error {
|
||||||
|
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
paramsReader := params.NewReader(logger, os)
|
||||||
|
allSettings, err := settings.GetAllSettings(paramsReader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
allServers, err := storage.New(logger, os, constants.ServersData).
|
||||||
|
SyncServers(constants.GetAllServers())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
providerConf := provider.New(allSettings.OpenVPN.Provider.Name, allServers, time.Now)
|
||||||
|
connection, err := providerConf.GetOpenVPNConnection(allSettings.OpenVPN.Provider.ServerSelection)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
lines := providerConf.BuildConf(
|
||||||
|
connection,
|
||||||
|
allSettings.OpenVPN.Verbosity,
|
||||||
|
"nonroortuser",
|
||||||
|
allSettings.OpenVPN.Root,
|
||||||
|
allSettings.OpenVPN.Cipher,
|
||||||
|
allSettings.OpenVPN.Auth,
|
||||||
|
allSettings.OpenVPN.Provider.ExtraConfigOptions,
|
||||||
|
)
|
||||||
|
fmt.Println(strings.Join(lines, "\n"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
64
internal/cli/update.go
Normal file
64
internal/cli/update.go
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/qdm12/gluetun/internal/constants"
|
||||||
|
"github.com/qdm12/gluetun/internal/os"
|
||||||
|
"github.com/qdm12/gluetun/internal/settings"
|
||||||
|
"github.com/qdm12/gluetun/internal/storage"
|
||||||
|
"github.com/qdm12/gluetun/internal/updater"
|
||||||
|
"github.com/qdm12/golibs/logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *cli) Update(args []string, os os.OS) error {
|
||||||
|
options := settings.Updater{CLI: true}
|
||||||
|
var flushToFile bool
|
||||||
|
flagSet := flag.NewFlagSet("update", flag.ExitOnError)
|
||||||
|
flagSet.BoolVar(&flushToFile, "file", false, "Write results to /gluetun/servers.json (for end users)")
|
||||||
|
flagSet.BoolVar(&options.Stdout, "stdout", false, "Write results to console to modify the program (for maintainers)")
|
||||||
|
flagSet.StringVar(&options.DNSAddress, "dns", "1.1.1.1", "DNS resolver address to use")
|
||||||
|
flagSet.BoolVar(&options.Cyberghost, "cyberghost", false, "Update Cyberghost servers")
|
||||||
|
flagSet.BoolVar(&options.Mullvad, "mullvad", false, "Update Mullvad servers")
|
||||||
|
flagSet.BoolVar(&options.Nordvpn, "nordvpn", false, "Update Nordvpn servers")
|
||||||
|
flagSet.BoolVar(&options.PIA, "pia", false, "Update Private Internet Access post-summer 2020 servers")
|
||||||
|
flagSet.BoolVar(&options.Privado, "privado", false, "Update Privado servers")
|
||||||
|
flagSet.BoolVar(&options.Purevpn, "purevpn", false, "Update Purevpn servers")
|
||||||
|
flagSet.BoolVar(&options.Surfshark, "surfshark", false, "Update Surfshark servers")
|
||||||
|
flagSet.BoolVar(&options.Vyprvpn, "vyprvpn", false, "Update Vyprvpn servers")
|
||||||
|
flagSet.BoolVar(&options.Windscribe, "windscribe", false, "Update Windscribe servers")
|
||||||
|
if err := flagSet.Parse(args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger, err := logging.NewLogger(logging.ConsoleEncoding, logging.InfoLevel)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !flushToFile && !options.Stdout {
|
||||||
|
return fmt.Errorf("at least one of -file or -stdout must be specified")
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
const clientTimeout = 10 * time.Second
|
||||||
|
httpClient := &http.Client{Timeout: clientTimeout}
|
||||||
|
storage := storage.New(logger, os, constants.ServersData)
|
||||||
|
currentServers, err := storage.SyncServers(constants.GetAllServers())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot update servers: %w", err)
|
||||||
|
}
|
||||||
|
updater := updater.New(options, httpClient, currentServers, logger)
|
||||||
|
allServers, err := updater.UpdateServers(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if flushToFile {
|
||||||
|
if err := storage.FlushToFile(allServers); err != nil {
|
||||||
|
return fmt.Errorf("cannot update servers: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user