fix(ooniprobe): use ooniprobe-cli-unattended for unattended runs (#714)

This diff changes the software name used by unattended runs for which
we did not override the default software name (`ooniprobe-cli`).

It will become `ooniprobe-cli-unattended`. This software name is in line
with the one we use for Android, iOS, and desktop unattended runs.

While working in this diff, I introduced string constants for the run
types and a string constant for the default software name.

See https://github.com/ooni/probe/issues/2081.
This commit is contained in:
Simone Basso 2022-04-29 13:41:09 +02:00 committed by GitHub
parent 596bdf6e57
commit d3c5196474
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 72 additions and 37 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/cli/root"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/ooni"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/output"
"github.com/ooni/probe-cli/v3/internal/model"
)
func init() {
@ -36,7 +37,7 @@ func dogeoip(config dogeoipconfig) error {
return err
}
engine, err := probeCLI.NewProbeEngine(context.Background())
engine, err := probeCLI.NewProbeEngine(context.Background(), model.RunTypeManual)
if err != nil {
return err
}

View File

@ -40,7 +40,7 @@ func init() {
softwareName := Cmd.Flag(
"software-name", "Override application name",
).Default("ooniprobe-cli").String()
).Default(ooni.DefaultSoftwareName).String()
softwareVersion := Cmd.Flag(
"software-version", "Override the application version",
).Default(version.Version).String()

View File

@ -8,6 +8,7 @@ import (
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/cli/root"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/nettests"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/ooni"
"github.com/ooni/probe-cli/v3/internal/model"
)
func init() {
@ -32,7 +33,7 @@ func init() {
return nil
})
functionalRun := func(runType string, pred func(name string, gr nettests.Group) bool) error {
functionalRun := func(runType model.RunType, pred func(name string, gr nettests.Group) bool) error {
for name, group := range nettests.All {
if !pred(name, group) {
continue
@ -52,7 +53,7 @@ func init() {
genRunWithGroupName := func(targetName string) func(*kingpin.ParseContext) error {
return func(*kingpin.ParseContext) error {
return functionalRun("manual", func(groupName string, gr nettests.Group) bool {
return functionalRun(model.RunTypeManual, func(groupName string, gr nettests.Group) bool {
return groupName == targetName
})
}
@ -68,7 +69,7 @@ func init() {
Probe: probe,
InputFiles: *inputFile,
Inputs: *input,
RunType: "manual",
RunType: model.RunTypeManual,
})
})
@ -80,14 +81,14 @@ func init() {
unattendedCmd := cmd.Command("unattended", "")
unattendedCmd.Action(func(_ *kingpin.ParseContext) error {
return functionalRun("timed", func(name string, gr nettests.Group) bool {
return functionalRun(model.RunTypeTimed, func(name string, gr nettests.Group) bool {
return gr.UnattendedOK
})
})
allCmd := cmd.Command("all", "").Default()
allCmd.Action(func(_ *kingpin.ParseContext) error {
return functionalRun("manual", func(name string, gr nettests.Group) bool {
return functionalRun(model.RunTypeManual, func(name string, gr nettests.Group) bool {
return true
})
})

View File

@ -55,8 +55,8 @@ type Controller struct {
Inputs []string
// RunType contains the run_type hint for the CheckIn API. If
// not set, the underlying code defaults to "timed".
RunType string
// not set, the underlying code defaults to model.RunTypeTimed.
RunType model.RunType
// numInputs is the total number of inputs
numInputs int
@ -154,7 +154,7 @@ func (c *Controller) Run(builder *engine.ExperimentBuilder, inputs []string) err
}
maxRuntime := time.Duration(c.Probe.Config().Nettests.WebsitesMaxRuntime) * time.Second
if c.RunType == "timed" && maxRuntime > 0 {
if c.RunType == model.RunTypeTimed && maxRuntime > 0 {
log.Debug("disabling maxRuntime when running in the background")
maxRuntime = 0
}
@ -267,7 +267,7 @@ func (c *Controller) OnProgress(perc float64, msg string) {
maxRuntime := time.Duration(c.Probe.Config().Nettests.WebsitesMaxRuntime) * time.Second
_, isWebConnectivity := c.nt.(WebConnectivity)
userProvidedInput := len(c.Inputs) > 0 || len(c.InputFiles) > 0
if c.RunType == "manual" && maxRuntime > 0 && isWebConnectivity && !userProvidedInput {
if c.RunType == model.RunTypeManual && maxRuntime > 0 && isWebConnectivity && !userProvidedInput {
elapsed := time.Since(c.ntStartTime)
perc = float64(elapsed) / float64(maxRuntime)
eta := maxRuntime.Seconds() - elapsed.Seconds()

View File

@ -9,6 +9,7 @@ import (
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/database"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/ooni"
"github.com/ooni/probe-cli/v3/internal/model"
)
func copyfile(source, dest string) error {
@ -45,7 +46,7 @@ func TestCreateContext(t *testing.T) {
func TestRun(t *testing.T) {
probe := newOONIProbe(t)
sess, err := probe.NewSession(context.Background())
sess, err := probe.NewSession(context.Background(), model.RunTypeManual)
if err != nil {
t.Fatal(err)
}

View File

@ -8,6 +8,7 @@ import (
"github.com/apex/log"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/database"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/ooni"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/pkg/errors"
)
@ -17,7 +18,7 @@ type RunGroupConfig struct {
InputFiles []string
Inputs []string
Probe *ooni.Probe
RunType string // hint for check-in API
RunType model.RunType // hint for check-in API
}
const websitesURLLimitRemoved = `WARNING: CONFIGURATION CHANGE REQUIRED:
@ -58,7 +59,7 @@ func RunGroup(config RunGroupConfig) error {
return nil
}
sess, err := config.Probe.NewSession(context.Background())
sess, err := config.Probe.NewSession(context.Background(), config.RunType)
if err != nil {
log.WithError(err).Error("Failed to create a measurement session")
return err

View File

@ -17,10 +17,14 @@ import (
"github.com/ooni/probe-cli/v3/internal/engine"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/assetsdir"
"github.com/ooni/probe-cli/v3/internal/kvstore"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/pkg/errors"
"upper.io/db.v3/lib/sqlbuilder"
)
// DefaultSoftwareName is the default software name.
const DefaultSoftwareName = "ooniprobe-cli"
// ProbeCLI is the OONI Probe CLI context.
type ProbeCLI interface {
Config() *config.Config
@ -28,7 +32,7 @@ type ProbeCLI interface {
IsBatch() bool
Home() string
TempDir() string
NewProbeEngine(ctx context.Context) (ProbeEngine, error)
NewProbeEngine(ctx context.Context, runType model.RunType) (ProbeEngine, error)
}
// ProbeEngine is an instance of the OONI Probe engine.
@ -199,7 +203,7 @@ func (p *Probe) Init(softwareName, softwareVersion string) error {
// NewSession creates a new ooni/probe-engine session using the
// current configuration inside the context. The caller must close
// the session when done using it, by calling sess.Close().
func (p *Probe) NewSession(ctx context.Context) (*engine.Session, error) {
func (p *Probe) NewSession(ctx context.Context, runType model.RunType) (*engine.Session, error) {
kvstore, err := kvstore.NewFS(
utils.EngineDir(p.home),
)
@ -209,10 +213,18 @@ func (p *Probe) NewSession(ctx context.Context) (*engine.Session, error) {
if err := os.MkdirAll(p.tunnelDir, 0700); err != nil {
return nil, errors.Wrap(err, "creating tunnel dir")
}
// When the software name is the default software name and we're running
// in unattended mode, adjust the software name accordingly.
//
// See https://github.com/ooni/probe/issues/2081.
softwareName := p.softwareName
if runType == model.RunTypeTimed && softwareName == DefaultSoftwareName {
softwareName = DefaultSoftwareName + "-unattended"
}
return engine.NewSession(ctx, engine.SessionConfig{
KVStore: kvstore,
Logger: enginex.Logger,
SoftwareName: p.softwareName,
SoftwareName: softwareName,
SoftwareVersion: p.softwareVersion,
TempDir: p.tempDir,
TunnelDir: p.tunnelDir,
@ -220,8 +232,8 @@ func (p *Probe) NewSession(ctx context.Context) (*engine.Session, error) {
}
// NewProbeEngine creates a new ProbeEngine instance.
func (p *Probe) NewProbeEngine(ctx context.Context) (ProbeEngine, error) {
sess, err := p.NewSession(ctx)
func (p *Probe) NewProbeEngine(ctx context.Context, runType model.RunType) (ProbeEngine, error) {
sess, err := p.NewSession(ctx, runType)
if err != nil {
return nil, err
}

View File

@ -8,6 +8,7 @@ import (
"github.com/apex/log"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/config"
"github.com/ooni/probe-cli/v3/cmd/ooniprobe/internal/ooni"
"github.com/ooni/probe-cli/v3/internal/model"
"upper.io/db.v3/lib/sqlbuilder"
)
@ -61,7 +62,7 @@ func (cli *FakeProbeCLI) TempDir() string {
}
// NewProbeEngine implements ProbeCLI.NewProbeEngine
func (cli *FakeProbeCLI) NewProbeEngine(ctx context.Context) (ooni.ProbeEngine, error) {
func (cli *FakeProbeCLI) NewProbeEngine(ctx context.Context, runType model.RunType) (ooni.ProbeEngine, error) {
return cli.FakeProbeEnginePtr, cli.FakeProbeEngineErr
}

View File

@ -412,7 +412,7 @@ func MainWithConfiguration(experimentName string, currentOptions Options) {
inputLoader := &engine.InputLoader{
CheckInConfig: &model.OOAPICheckInConfig{
RunType: "manual",
RunType: model.RunTypeManual,
OnWiFi: true, // meaning: not on 4G
Charging: true,
},

View File

@ -17,7 +17,7 @@ func TestCheckInSuccess(t *testing.T) {
Platform: "android",
ProbeASN: "AS12353",
ProbeCC: "PT",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "ooniprobe-android",
SoftwareVersion: "2.7.1",
WebConnectivity: model.OOAPICheckInConfigWebConnectivity{
@ -54,7 +54,7 @@ func TestCheckInFailure(t *testing.T) {
Platform: "android",
ProbeASN: "AS12353",
ProbeCC: "PT",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "ooniprobe-android",
SoftwareVersion: "2.7.1",
WebConnectivity: model.OOAPICheckInConfigWebConnectivity{

View File

@ -238,7 +238,7 @@ func (s *Session) KibiBytesSent() float64 {
//
// - ProbeCC: if empty, set to Session.ProbeCC();
//
// - RunType: if empty, set to "timed";
// - RunType: if empty, set to model.RunTypeTimed;
//
// - SoftwareName: if empty, set to Session.SoftwareName();
//
@ -270,7 +270,7 @@ func (s *Session) CheckIn(
config.ProbeCC = s.ProbeCC()
}
if config.RunType == "" {
config.RunType = "timed" // most conservative choice
config.RunType = model.RunTypeTimed // most conservative choice
}
if config.SoftwareName == "" {
config.SoftwareName = s.SoftwareName()

View File

@ -107,7 +107,7 @@ func TestSessionCheckInSuccessful(t *testing.T) {
if mockedClnt.Config.ProbeCC != "IT" {
t.Fatal("invalid Config.ProbeCC")
}
if mockedClnt.Config.RunType != "timed" {
if mockedClnt.Config.RunType != model.RunTypeTimed {
t.Fatal("invalid Config.RunType")
}
if mockedClnt.Config.SoftwareName != "miniooni" {

View File

@ -16,7 +16,7 @@ type OOAPICheckInConfig struct {
Platform string `json:"platform"` // Platform of the probe
ProbeASN string `json:"probe_asn"` // ProbeASN is the probe country code
ProbeCC string `json:"probe_cc"` // ProbeCC is the probe country code
RunType string `json:"run_type"` // RunType
RunType RunType `json:"run_type"` // RunType
SoftwareName string `json:"software_name"` // SoftwareName of the probe
SoftwareVersion string `json:"software_version"` // SoftwareVersion of the probe
WebConnectivity OOAPICheckInConfigWebConnectivity `json:"web_connectivity"` // WebConnectivity class contain an array of categories

14
internal/model/runtype.go Normal file
View File

@ -0,0 +1,14 @@
package model
// RunType describes the type of a ooniprobe run.
type RunType string
const (
// RunTypeManual indicates that the user manually run `ooniprobe run`. Command
// line tools such as miniooni should always use this run type.
RunTypeManual = RunType("manual")
// RunTypeTimed indicates that the user run `ooniprobe run unattended`, which
// is the correct way to run ooniprobe from scripts and cronjobs.
RunTypeTimed = RunType("timed")
)

View File

@ -1,5 +1,7 @@
package apimodel
import "github.com/ooni/probe-cli/v3/internal/model"
// CheckInRequestWebConnectivity contains WebConnectivity
// specific parameters to include into CheckInRequest
type CheckInRequestWebConnectivity struct {
@ -13,7 +15,7 @@ type CheckInRequest struct {
Platform string `json:"platform"`
ProbeASN string `json:"probe_asn"`
ProbeCC string `json:"probe_cc"`
RunType string `json:"run_type"`
RunType model.RunType `json:"run_type"`
SoftwareName string `json:"software_name"`
SoftwareVersion string `json:"software_version"`
WebConnectivity CheckInRequestWebConnectivity `json:"web_connectivity"`

View File

@ -6,6 +6,7 @@ import (
"log"
"github.com/ooni/probe-cli/v3/internal/kvstore"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/ooapi"
"github.com/ooni/probe-cli/v3/internal/ooapi/apimodel"
)
@ -21,7 +22,7 @@ func ExampleClient() {
Platform: "linux",
ProbeASN: "AS30722",
ProbeCC: "IT",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "miniooni",
SoftwareVersion: "0.1.0-dev",
WebConnectivity: apimodel.CheckInRequestWebConnectivity{

View File

@ -5,6 +5,7 @@ import (
"testing"
"github.com/ooni/probe-cli/v3/internal/kvstore"
"github.com/ooni/probe-cli/v3/internal/model"
"github.com/ooni/probe-cli/v3/internal/ooapi"
"github.com/ooni/probe-cli/v3/internal/ooapi/apimodel"
)
@ -19,7 +20,7 @@ func TestWithRealServerDoCheckIn(t *testing.T) {
Platform: "android",
ProbeASN: "AS12353",
ProbeCC: "IT",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "ooniprobe-android",
SoftwareVersion: "2.7.1",
WebConnectivity: apimodel.CheckInRequestWebConnectivity{

View File

@ -364,9 +364,9 @@ type CheckInConfig struct {
// Platform is the mobile platform (e.g. "android")
Platform string
// RunType indicates whether this is an automated ("timed") run
// RunType indicates whether this is an automated (model.RunTypeTimed) run
// or otherwise a manual run initiated by the user.
RunType string
RunType model.RunType
// SoftwareName is the name of the application.
SoftwareName string

View File

@ -259,7 +259,7 @@ func TestCheckInSuccess(t *testing.T) {
Charging: true,
OnWiFi: true,
Platform: "android",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "ooniprobe-android",
SoftwareVersion: "2.7.1",
WebConnectivity: &oonimkall.CheckInConfigWebConnectivity{},
@ -307,7 +307,7 @@ func TestCheckInLookupLocationFailure(t *testing.T) {
Charging: true,
OnWiFi: true,
Platform: "android",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "ooniprobe-android",
SoftwareVersion: "2.7.1",
WebConnectivity: &oonimkall.CheckInConfigWebConnectivity{},
@ -337,7 +337,7 @@ func TestCheckInNewProbeServicesFailure(t *testing.T) {
Charging: true,
OnWiFi: true,
Platform: "android",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "ooniprobe-android",
SoftwareVersion: "2.7.1",
WebConnectivity: &oonimkall.CheckInConfigWebConnectivity{},
@ -366,7 +366,7 @@ func TestCheckInCheckInFailure(t *testing.T) {
Charging: true,
OnWiFi: true,
Platform: "android",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "ooniprobe-android",
SoftwareVersion: "2.7.1",
WebConnectivity: &oonimkall.CheckInConfigWebConnectivity{},
@ -392,7 +392,7 @@ func TestCheckInNoParams(t *testing.T) {
Charging: true,
OnWiFi: true,
Platform: "android",
RunType: "timed",
RunType: model.RunTypeTimed,
SoftwareName: "ooniprobe-android",
SoftwareVersion: "2.7.1",
}