From 602a5dc9523152d1564844831f798c8536d29de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arturo=20Filast=C3=B2?= Date: Mon, 12 Feb 2018 12:18:14 +0200 Subject: [PATCH] Add functions to handling migration from legacy OONI Probe --- Gopkg.lock | 42 +++++++++++++++++- Gopkg.toml | 8 ++++ config/nettest_groups.go | 90 +++++++++++++++++++++++++++++++++++---- data/default-config.json | 63 +++++++++++++++++++++++++++ internal/legacy/legacy.go | 83 ++++++++++++++++++++++++++++++++++++ ooni.go | 77 ++++++--------------------------- 6 files changed, 290 insertions(+), 73 deletions(-) create mode 100644 data/default-config.json create mode 100644 internal/legacy/legacy.go diff --git a/Gopkg.lock b/Gopkg.lock index 9efe0bb..cd22cd0 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -28,15 +28,55 @@ packages = ["."] revision = "cc83f3b3ce5911279513a46d6d3316d67bedaa54" +[[projects]] + name = "github.com/mattn/go-colorable" + packages = ["."] + revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" + version = "v0.0.9" + +[[projects]] + name = "github.com/mattn/go-isatty" + packages = ["."] + revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" + version = "v0.0.3" + +[[projects]] + branch = "master" + name = "github.com/mgutz/ansi" + packages = ["."] + revision = "9520e82c474b0a04dd04f8a40959027271bab992" + +[[projects]] + branch = "master" + name = "github.com/mitchellh/go-homedir" + packages = ["."] + revision = "b8bc1bf767474819792c23f32d8286a45736f1c6" + [[projects]] name = "github.com/pkg/errors" packages = ["."] revision = "645ef00459ed84a119197bfb8d8205042c6df63d" version = "v0.8.0" +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = ["unix"] + revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd" + +[[projects]] + name = "gopkg.in/AlecAivazis/survey.v1" + packages = [ + ".", + "core", + "terminal" + ] + revision = "0aa8b6a162b391fe2d95648b7677d1d6ac2090a6" + version = "v1.4.1" + [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "4ed0a29997f4d8f197233e4ba7aa66ed7033443a893a795ed2b4a9a5ec4350bd" + inputs-digest = "8ca4591e7aeb614acd312b2f95a425fe4def8100bbfc56f9c9147ae8e8b3575a" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index 91e2189..7c4f843 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -40,3 +40,11 @@ [[constraint]] name = "github.com/pkg/errors" version = "0.8.0" + +[[constraint]] + branch = "master" + name = "github.com/mitchellh/go-homedir" + +[[constraint]] + name = "gopkg.in/AlecAivazis/survey.v1" + version = "1.4.1" diff --git a/config/nettest_groups.go b/config/nettest_groups.go index 9c1c6c5..9be7a6c 100644 --- a/config/nettest_groups.go +++ b/config/nettest_groups.go @@ -1,14 +1,87 @@ package config -type websiteSettings struct { +var websiteCategories = []string{ + "ALDR", + "ANON", + "COMM", + "COMT", + "CTRL", + "CULTR", + "DATE", + "ECON", + "ENV", + "FILE", + "GAME", + "GMB", + "GOVT", + "GRP", + "HACK", + "HATE", + "HOST", + "HUMR", + "IGO", + "LGBT", + "MILX", + "MMED", + "NEWS", + "POLR", + "PORN", + "PROV", + "PUBH", + "REL", + "SRCH", + "XED", +} + +// NettestConfig represents the configuration for a particular nettest +type NettestConfig struct { + Name string + Options string +} + +// Websites test group +type Websites struct { EnabledCategories []string `json:"enabled_categories"` } -type instantMessagingSettings struct { +// NettestConfigs returns a list configured enabled tests for the group +func (s *Websites) NettestConfigs() []NettestConfig { + var nts []NettestConfig + nts = append(nts, NettestConfig{"web_connectivity", "options"}) + return nts +} + +// InstantMessaging nettest group +type InstantMessaging struct { EnabledTests []string `json:"enabled_tests"` } -type performanceSettings struct { +func (s *InstantMessaging) isEnabled(nt string) bool { + for _, v := range s.EnabledTests { + if v == nt { + return true + } + } + return false +} + +// NettestConfigs returns a list configured enabled tests for the group +func (s *InstantMessaging) NettestConfigs() []NettestConfig { + var nts []NettestConfig + if s.isEnabled("facebook_messenger") { + nts = append(nts, NettestConfig{"facebook_messenger", "options"}) + } + if s.isEnabled("telegram") { + nts = append(nts, NettestConfig{"telegram", "options"}) + } + if s.isEnabled("whatsapp") { + nts = append(nts, NettestConfig{"whatsapp", "options"}) + } + return nts +} + +// Performance nettest group +type Performance struct { EnabledTests []string `json:"enabled_tests"` NDTServer string `json:"ndt_server"` NDTServerPort string `json:"ndt_server_port"` @@ -16,14 +89,15 @@ type performanceSettings struct { DashServerPort string `json:"dash_server_port"` } -type middleboxSettings struct { +// Middlebox nettest group +type Middlebox struct { EnabledTests []string `json:"enabled_tests"` } // NettestGroups related settings type NettestGroups struct { - Websites websiteSettings `json:"websites"` - InstantMessaging instantMessagingSettings `json:"instant_messaging"` - Performance performanceSettings `json:"performance"` - Middlebox middleboxSettings `json:"middlebox"` + Websites Websites `json:"websites"` + InstantMessaging InstantMessaging `json:"instant_messaging"` + Performance Performance `json:"performance"` + Middlebox Middlebox `json:"middlebox"` } diff --git a/data/default-config.json b/data/default-config.json new file mode 100644 index 0000000..1068d91 --- /dev/null +++ b/data/default-config.json @@ -0,0 +1,63 @@ +{ + "_": "This is your OONI Probe config file. See https://ooni.io/help/ooniprobe-cli for help", + "auto_update": true, + "sharing": { + "include_ip": false, + "include_asn": true, + "include_gps": true, + "upload_results": true, + "send_crash_reports": true + }, + "notifications": { + "enabled": true, + "notify_on_test_completion": true, + "notify_on_news": false + }, + "automated_testing": { + "enabled": false, + "enabled_tests": [ + "web-connectivity", + "facebook-messenger", + "whatsapp", + "telegram", + "dash", + "ndt", + "http-invalid-request-line", + "http-header-field-manipulation" + ], + "monthly_allowance": "300MB" + }, + "test_settings": { + "websites": { + "enabled_categories": [] + }, + "instant_messaging": { + "enabled_tests": [ + "facebook-messenger", + "whatsapp", + "telegram" + ] + }, + "performance": { + "enabled_tests": [ + "ndt" + ], + "ndt_server": "auto", + "ndt_server_port": "auto", + "dash_server": "auto", + "dash_server_port": "auto" + }, + "middlebox": { + "enabled_tests": [ + "http-invalid-request-line", + "http-header-field-manipulation" + ] + } + }, + "advanced": { + "include_country": true, + "use_domain_fronting": true + }, + "_config_version": "0.0.1", + "_informed_consent": true +} diff --git a/internal/legacy/legacy.go b/internal/legacy/legacy.go new file mode 100644 index 0000000..4d9c194 --- /dev/null +++ b/internal/legacy/legacy.go @@ -0,0 +1,83 @@ +package legacy + +import ( + "fmt" + "os" + "path/filepath" + + homedir "github.com/mitchellh/go-homedir" + "github.com/pkg/errors" + "gopkg.in/AlecAivazis/survey.v1" +) + +func HomePath() (string, error) { + home, err := homedir.Dir() + if err != nil { + return "", err + } + return filepath.Join(home, ".ooni"), nil +} + +// HomeExists returns true if a legacy home exists +func HomeExists() (bool, error) { + home, err := HomePath() + if err != nil { + return false, err + } + path := filepath.Join(home, "ooniprobe.conf") + if _, err := os.Stat(path); os.IsNotExist(err) { + return false, nil + } + return true, nil +} + +// BackupHome the legacy home directory +func BackupHome() error { + home, err := homedir.Dir() + if err != nil { + return errors.Wrap(err, "backing up home") + } + oldPath := filepath.Join(home, ".ooni") + newPath := filepath.Join(home, ".ooni-legacy") + if err := os.Rename(oldPath, newPath); err != nil { + return errors.Wrap(err, "backing up home") + } + return nil +} + +// MaybeMigrateHome prompts the user if we should backup the legacy home +func MaybeMigrateHome() error { + exists, err := HomeExists() + if err != nil { + return err + } + if !exists { + return nil + } + home, err := HomePath() + if err != nil { + return err + } + logf("We found an existing OONI Probe installation") + chosen := "" + prompt := &survey.Select{ + Message: "Should we:", + Options: []string{"delete it", "back it up"}, + } + survey.AskOne(prompt, &chosen, nil) + if chosen == "delete it" { + if err := os.RemoveAll(home); err != nil { + return err + } + } else { + logf("Backing up ~/.ooni to ~/.ooni-legacy") + if err := BackupHome(); err != nil { + return err + } + } + return nil +} + +func logf(s string, v ...interface{}) { + fmt.Printf("%s\n", fmt.Sprintf(s, v...)) +} diff --git a/ooni.go b/ooni.go index c89013c..60c7a09 100644 --- a/ooni.go +++ b/ooni.go @@ -4,11 +4,24 @@ import ( "encoding/json" "io/ioutil" "os" + "path/filepath" + homedir "github.com/mitchellh/go-homedir" "github.com/openobservatory/gooni/config" "github.com/pkg/errors" ) +// GetOONIHome returns the path to the OONI Home +func GetOONIHome() (string, error) { + home, err := homedir.Dir() + if err != nil { + return "", err + } + + path := filepath.Join(home, ".ooni") + return path, nil +} + // Config for the OONI Probe installation type Config struct { // Private settings @@ -26,70 +39,6 @@ type Config struct { // Default config settings func (c *Config) Default() error { - // This is the default configuration: - /* - _: 'This is your OONI Probe config file. See https://ooni.io/help/ooniprobe-cli for help', - auto_update: true, - sharing: { - include_ip: false, - include_asn: true, - include_gps: true, - upload_results: true, - send_crash_reports: true - }, - notifications: { - enabled: true, - notify_on_test_completion: true, - notify_on_news: false - }, - automated_testing: { - enabled: false, - enabled_tests: [ - 'web-connectivity', - 'facebook-messenger', - 'whatsapp', - 'telegram', - 'dash', - 'ndt', - 'http-invalid-request-line', - 'http-header-field-manipulation' - ], - monthly_allowance: '300MB' - }, - test_settings: { - websites: { - enabled_categories: [] - }, - instant_messaging: { - enabled_tests: [ - 'facebook-messenger', - 'whatsapp', - 'telegram' - ] - }, - performance: { - enabled_tests: [ - 'ndt' - ], - ndt_server: 'auto', - ndt_server_port: 'auto', - dash_server: 'auto', - dash_server_port: 'auto' - }, - middlebox: { - enabled_tests: [ - 'http-invalid-request-line', - 'http-header-field-manipulation' - ] - } - }, - advanced: { - include_country: true, - use_domain_fronting: true - }, - _config_version: CONFIG_VERSION, - _informed_consent: false - */ return nil }