Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prototype: each experiment manages its own arguments #1005

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@
/ooporthelper
/probe-cli.cov
/tmp-*
/tinyooni
/*.zip
6 changes: 5 additions & 1 deletion cmd/ooniprobe/internal/log/handlers/cli/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,11 @@ var summarizers = map[string]func(uint64, uint64, string) []string{
}

func makeSummary(name string, totalCount uint64, anomalyCount uint64, ss string) []string {
return summarizers[name](totalCount, anomalyCount, ss)
summarizer, ok := summarizers[name]
if !ok {
return []string{"", "", ""}
}
return summarizer(totalCount, anomalyCount, ss)
}

func logResultItem(w io.Writer, f log.Fields) error {
Expand Down
69 changes: 69 additions & 0 deletions internal/cmd/tinyooni/database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package main

import (
"context"
"os"
"path/filepath"
"runtime"

"github.com/ooni/probe-cli/v3/internal/database"
"github.com/ooni/probe-cli/v3/internal/engine"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/runtimex"
)

// initDatabase initializes a database and returns the corresponding database properties.
func initDatabase(ctx context.Context, sess *engine.Session, globalOptions *GlobalOptions) *model.DatabaseProps {
ooniHome := maybeGetOONIDir(globalOptions.HomeDir)

db, err := database.Open(databasePath(ooniHome))
runtimex.PanicOnError(err, "database.Open failed")

networkDB, err := db.CreateNetwork(sess)
runtimex.PanicOnError(err, "db.Create failed")

dbResult, err := db.CreateResult(ooniHome, "custom", networkDB.ID)
runtimex.PanicOnError(err, "db.CreateResult failed")

return &model.DatabaseProps{
Database: db,
DatabaseNetwork: networkDB,
DatabaseResult: dbResult,
}
}

// getHomeDir returns the $HOME directory.
func getHomeDir() (string, string) {
// See https://gist.github.com/miguelmota/f30a04a6d64bd52d7ab59ea8d95e54da
if runtime.GOOS == "windows" {
home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
if home == "" {
home = os.Getenv("USERPROFILE")
}
return home, "ooniprobe"
}
if runtime.GOOS == "linux" {
home := os.Getenv("XDG_CONFIG_HOME")
if home != "" {
return home, "ooniprobe"
}
// fallthrough
}
return os.Getenv("HOME"), ".ooniprobe"
}

// maybeGetOONIDir returns the $HOME/.ooniprobe equivalent unless optionsHome
// is already set, in which case it just returns optionsHome.
func maybeGetOONIDir(optionsHome string) string {
if optionsHome != "" {
return optionsHome
}
homeDir, dirName := getHomeDir()
runtimex.Assert(homeDir != "", "homeDir is empty")
return filepath.Join(homeDir, dirName)
}

// databasePath returns the database path given the OONI_HOME.
func databasePath(ooniHome string) string {
return filepath.Join(ooniHome, "db", "main.sqlite3")
}
68 changes: 68 additions & 0 deletions internal/cmd/tinyooni/groups.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"websites": {
"name": "Websites",
"description": "",
"author": "OONI",
"nettests": [{
"test_name": "web_connectivity"
}]
},
"performance": {
"name": "Performance",
"description": "",
"author": "OONI",
"nettests": [{
"test_name": "dash"
}, {
"test_name": "ndt"
}]
},
"middlebox": {
"name": "Middlebox",
"description": "",
"author": "OONI",
"nettests": [{
"test_name": "hirl"
}, {
"test_name": "hhfm"
}]
},
"im": {
"name": "Instant Messaging",
"description": "Runs the instant messaging experiments",
"author": "OONI",
"nettests": [{
"test_name": "facebook_messenger"
}, {
"test_name": "signal"
}, {
"test_name": "telegram"
}, {
"test_name": "whatsapp"
}]
},
"circumvention": {
"name": "Circumvention",
"description": "",
"author": "OONI",
"nettests": [{
"test_name": "psiphon"
}, {
"test_name": "tor"
}]
},
"experimental": {
"name": "Experimental",
"description": "Experimental nettests",
"author": "OONI",
"nettests": [{
"test_name": "dnscheck"
}, {
"test_name": "stun_reachability"
}, {
"test_name": "torsf"
}, {
"test_name": "vanilla_tor"
}]
}
}
151 changes: 151 additions & 0 deletions internal/cmd/tinyooni/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package main

import (
"os"

"github.com/ooni/probe-cli/v3/internal/version"
"github.com/spf13/cobra"
)

// GlobalOptions contains the global options.
type GlobalOptions struct {
Emoji bool
HomeDir string
NoJSON bool
NoCollector bool
ProbeServicesURL string
Proxy string
RepeatEvery int64
ReportFile string
SnowflakeRendezvous string
TorArgs []string
TorBinary string
Tunnel string
Verbose bool
Yes bool
}

func main() {
var globalOptions GlobalOptions
rootCmd := &cobra.Command{
Use: "tinyooni",
Short: "tinyooni is like miniooni but more experimental",
Args: cobra.NoArgs,
Version: version.Version,
}
rootCmd.SetVersionTemplate("{{ .Version }}\n")
flags := rootCmd.PersistentFlags()

flags.BoolVar(
&globalOptions.Emoji,
"emoji",
false,
"whether to use emojis when logging",
)

flags.StringVar(
&globalOptions.HomeDir,
"home",
"",
"force specific home directory",
)

flags.BoolVarP(
&globalOptions.NoJSON,
"no-json",
"N",
false,
"disable writing to disk",
)

flags.BoolVarP(
&globalOptions.NoCollector,
"no-collector",
"n",
false,
"do not submit measurements to the OONI collector",
)

flags.StringVar(
&globalOptions.ProbeServicesURL,
"probe-services",
"",
"URL of the OONI backend instance you want to use",
)

flags.StringVar(
&globalOptions.Proxy,
"proxy",
"",
"set proxy URL to communicate with the OONI backend (mutually exclusive with --tunnel)",
)

flags.Int64Var(
&globalOptions.RepeatEvery,
"repeat-every",
0,
"wait the given number of seconds and then repeat the same measurement",
)

flags.StringVarP(
&globalOptions.ReportFile,
"reportfile",
"o",
"",
"set the output report file path (default: \"report.jsonl\")",
)

flags.StringVar(
&globalOptions.SnowflakeRendezvous,
"snowflake-rendezvous",
"domain_fronting",
"rendezvous method for --tunnel=torsf (one of: \"domain_fronting\" and \"amp\")",
)

flags.StringSliceVar(
&globalOptions.TorArgs,
"tor-args",
[]string{},
"extra arguments for the tor binary (may be specified multiple times)",
)

flags.StringVar(
&globalOptions.TorBinary,
"tor-binary",
"",
"execute a specific tor binary",
)

flags.StringVar(
&globalOptions.Tunnel,
"tunnel",
"",
"tunnel to use to communicate with the OONI backend (one of: psiphon, tor, torsf)",
)

flags.BoolVarP(
&globalOptions.Verbose,
"verbose",
"v",
false,
"increase verbosity level",
)

flags.BoolVarP(
&globalOptions.Yes,
"yes",
"y",
false,
"assume yes as the answer to all questions",
)

rootCmd.MarkFlagsMutuallyExclusive("proxy", "tunnel")

registerRunExperiment(rootCmd, &globalOptions)
registerRunGroup(rootCmd, &globalOptions)
registerOoniRun(rootCmd, &globalOptions)

if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
Loading