refactor: config is now a private package (#164)

We are working on ooniprobe for Debian. Before starting to apply
changes to the codebase, I'd like to apply some refactoring steps
that I've been thinking about for quite some time.

The general concept here is that the purpose of this repository
changed since it was designed and now there is probe-engine which
is a library, therefore, this repo can be mostly private.
This commit is contained in:
Simone Basso
2020-11-13 16:58:14 +01:00
committed by GitHub
parent 73d6b550e5
commit fb2ca32004
7 changed files with 2 additions and 2 deletions
+100
View File
@@ -0,0 +1,100 @@
package config
import (
"encoding/json"
"io/ioutil"
"sync"
"github.com/apex/log"
"github.com/ooni/probe-cli/internal/crashreport"
"github.com/ooni/probe-cli/utils"
"github.com/pkg/errors"
)
// ConfigVersion is the current version of the config
const ConfigVersion = 1
// ReadConfig reads the configuration from the path
func ReadConfig(path string) (*Config, error) {
b, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
c, err := ParseConfig(b)
if err != nil {
return nil, errors.Wrap(err, "parsing config")
}
c.path = path
return c, err
}
// ParseConfig returns config from JSON bytes.
func ParseConfig(b []byte) (*Config, error) {
var c Config
if err := json.Unmarshal(b, &c); err != nil {
return nil, errors.Wrap(err, "parsing json")
}
home, err := utils.GetOONIHome()
if err != nil {
return nil, err
}
c.path = utils.ConfigPath(home)
if c.Advanced.SendCrashReports == false {
log.Info("Disabling crash reporting.")
crashreport.Disabled = true
}
return &c, nil
}
// Config for the OONI Probe installation
type Config struct {
// Private settings
Comment string `json:"_"`
Version int64 `json:"_version"`
InformedConsent bool `json:"_informed_consent"`
Sharing Sharing `json:"sharing"`
Nettests Nettests `json:"nettests"`
Advanced Advanced `json:"advanced"`
mutex sync.Mutex
path string
}
// Write the config file in json to the path
func (c *Config) Write() error {
c.Lock()
defer c.Unlock()
configJSON, _ := json.MarshalIndent(c, "", " ")
if c.path == "" {
return errors.New("config file path is empty")
}
if err := ioutil.WriteFile(c.path, configJSON, 0644); err != nil {
return errors.Wrap(err, "writing config JSON")
}
return nil
}
// Lock acquires the write mutex
func (c *Config) Lock() {
c.mutex.Lock()
}
// Unlock releases the write mutex
func (c *Config) Unlock() {
c.mutex.Unlock()
}
// MaybeMigrate checks the current config version and the config file on disk
// and if necessary performs and upgrade of the configuration file.
func (c *Config) MaybeMigrate() error {
if c.Version < ConfigVersion {
return c.Write()
}
return nil
}
+105
View File
@@ -0,0 +1,105 @@
package config
import (
"crypto/sha256"
"encoding/hex"
"io"
"io/ioutil"
"os"
"testing"
)
func getShasum(path string) (string, error) {
hasher := sha256.New()
f, err := os.Open(path)
if err != nil {
return "", err
}
defer f.Close()
if _, err := io.Copy(hasher, f); err != nil {
return "", err
}
return hex.EncodeToString(hasher.Sum(nil)), nil
}
func TestParseConfig(t *testing.T) {
config, err := ReadConfig("testdata/valid-config.json")
if err != nil {
t.Error(err)
}
if config.Sharing.IncludeASN == false {
t.Error("network should be included")
}
}
func TestUpdateConfig(t *testing.T) {
tmpFile, err := ioutil.TempFile(os.TempDir(), "ooniconfig-")
if err != nil {
t.Error(err)
}
configPath := tmpFile.Name()
defer os.Remove(configPath)
data, err := ioutil.ReadFile("testdata/config-v0.json")
if err != nil {
t.Error(err)
}
err = ioutil.WriteFile(configPath, data, 0644)
if err != nil {
t.Error(err)
}
origShasum, err := getShasum(configPath)
if err != nil {
t.Error(err)
}
config, err := ReadConfig(configPath)
if err != nil {
t.Error(err)
}
origIncludeIP := config.Sharing.IncludeIP
origIncludeASN := config.Sharing.IncludeASN
origUploadResults := config.Sharing.UploadResults
origInformedConsent := config.InformedConsent
if err != nil {
t.Error(err)
}
config.MaybeMigrate()
migratedShasum, err := getShasum(configPath)
if err != nil {
t.Error(err)
}
if migratedShasum == origShasum {
t.Fatal("the config was not migrated")
}
newConfig, err := ReadConfig(configPath)
if err != nil {
t.Error(err)
}
if newConfig.Sharing.IncludeIP != origIncludeIP {
t.Error("includeIP differs")
}
if newConfig.Sharing.IncludeASN != origIncludeASN {
t.Error("includeASN differs")
}
if newConfig.Sharing.UploadResults != origUploadResults {
t.Error("UploadResults differs")
}
if newConfig.InformedConsent != origInformedConsent {
t.Error("InformedConsent differs")
}
// Check that the config file stays the same if it's already the most up to
// date version
config.MaybeMigrate()
finalShasum, err := getShasum(configPath)
if err != nil {
t.Error(err)
}
if migratedShasum != finalShasum {
t.Fatal("the config was migrated again")
}
}
+52
View File
@@ -0,0 +1,52 @@
package config
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",
}
// Sharing settings
type Sharing struct {
IncludeIP bool `json:"include_ip"`
IncludeASN bool `json:"include_asn"`
UploadResults bool `json:"upload_results"`
}
// Advanced settings
type Advanced struct {
SendCrashReports bool `json:"send_crash_reports"`
}
// Nettests related settings
type Nettests struct {
WebsitesURLLimit int64 `json:"websites_url_limit"`
WebsitesEnabledCategoryCodes []string `json:"websites_enabled_category_codes"`
}
+62
View File
@@ -0,0 +1,62 @@
{
"_version": 0,
"_informed_consent": true,
"_is_beta": true,
"auto_update": true,
"sharing": {
"include_ip": false,
"include_asn": true,
"include_country": true,
"include_gps": true,
"upload_results": 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": {
"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": {
"use_domain_fronting": false,
"send_crash_reports": true,
"collector_url": "",
"bouncer_url": "https://bouncer.ooni.io"
}
}
+19
View File
@@ -0,0 +1,19 @@
{
"_version": 1,
"_informed_consent": false,
"sharing": {
"include_ip": false,
"include_asn": true,
"include_country": true,
"upload_results": true
},
"nettests": {
"websites_url_limit": 0
},
"advanced": {
"use_domain_fronting": false,
"send_crash_reports": true,
"collector_url": "",
"bouncer_url": "https://bouncer.ooni.io"
}
}