From c6ac0fb953ae48ad85f7ce288e60723f780bd3ef Mon Sep 17 00:00:00 2001 From: Marco Guerri Date: Mon, 19 Oct 2020 18:47:28 +0200 Subject: [PATCH] [rdbms] Schema migration tool Schema migration tool which supports both pure SQL migration files and go migrations (for more complex operations which require back-filling and manipulating previous entries). Based on github.com/pressly/goose. Every migration is executed within a transaction. SQL migrations offer the possibility to turn off transactions, while golang migrations by default receive a *sql.Tx object. At the moment, this cannot be changed. --- .codecov.yml | 3 + cmds/contest/main.go | 98 +---- cmds/plugins/plugins.go | 107 +++++ .../0001_add_extended_descriptor.sql | 5 + ...grate_descriptor_to_extended_descriptor.go | 293 +++++++++++++ db/rdbms/schema/latest/create_contest_db.sql | 69 +++ .../rdbms/schema/v0}/create_contest_db.sql | 0 docker/contest/tests.sh | 3 +- docker/mysql/Dockerfile | 2 +- go.mod | 32 +- go.sum | 400 +----------------- pkg/config/db.go | 9 + pkg/job/forward_decl.go | 18 + pkg/test/forward_decl.go | 68 +++ tests/integ/common/storage.go | 7 +- .../jobmanager/jobmanager_memory_test.go | 2 +- .../integ/jobmanager/jobmanager_rdbms_test.go | 2 +- ..._descriptor_to_extended_descriptor_test.go | 122 ++++++ tests/integ/migration/common.go | 98 +++++ tools/migration/rdbms/main.go | 111 +++++ tools/migration/rdbms/migrate/migrate.go | 37 ++ 21 files changed, 967 insertions(+), 519 deletions(-) create mode 100644 cmds/plugins/plugins.go create mode 100644 db/rdbms/migration/0001_add_extended_descriptor.sql create mode 100644 db/rdbms/migration/0002_migrate_descriptor_to_extended_descriptor.go create mode 100644 db/rdbms/schema/latest/create_contest_db.sql rename {docker/mysql => db/rdbms/schema/v0}/create_contest_db.sql (100%) create mode 100644 pkg/config/db.go create mode 100644 pkg/job/forward_decl.go create mode 100644 pkg/test/forward_decl.go create mode 100644 tests/integ/migration/0002_migrate_descriptor_to_extended_descriptor_test.go create mode 100644 tests/integ/migration/common.go create mode 100644 tools/migration/rdbms/main.go create mode 100644 tools/migration/rdbms/migrate/migrate.go diff --git a/.codecov.yml b/.codecov.yml index 3983b642..8779f439 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,5 +1,8 @@ coverage: status: + patch: + default: + target: 30% project: default: target: auto diff --git a/cmds/contest/main.go b/cmds/contest/main.go index 30b9392b..cfc457ed 100644 --- a/cmds/contest/main.go +++ b/cmds/contest/main.go @@ -6,84 +6,34 @@ package main import ( - "errors" "flag" "os" "os/signal" "syscall" + "github.com/facebookincubator/contest/cmds/plugins" + "github.com/facebookincubator/contest/pkg/api" "github.com/facebookincubator/contest/pkg/config" - "github.com/facebookincubator/contest/pkg/job" "github.com/facebookincubator/contest/pkg/jobmanager" "github.com/facebookincubator/contest/pkg/logging" "github.com/facebookincubator/contest/pkg/pluginregistry" "github.com/facebookincubator/contest/pkg/storage" "github.com/facebookincubator/contest/pkg/target" - "github.com/facebookincubator/contest/pkg/test" + "github.com/facebookincubator/contest/plugins/listeners/httplistener" - "github.com/facebookincubator/contest/plugins/reporters/noop" - "github.com/facebookincubator/contest/plugins/reporters/targetsuccess" "github.com/facebookincubator/contest/plugins/storage/rdbms" + "github.com/facebookincubator/contest/plugins/targetlocker/inmemory" - "github.com/facebookincubator/contest/plugins/targetmanagers/csvtargetmanager" - "github.com/facebookincubator/contest/plugins/targetmanagers/targetlist" - "github.com/facebookincubator/contest/plugins/testfetchers/literal" - "github.com/facebookincubator/contest/plugins/testfetchers/uri" - "github.com/facebookincubator/contest/plugins/teststeps/cmd" - "github.com/facebookincubator/contest/plugins/teststeps/echo" - "github.com/facebookincubator/contest/plugins/teststeps/example" - "github.com/facebookincubator/contest/plugins/teststeps/randecho" - "github.com/facebookincubator/contest/plugins/teststeps/slowecho" - "github.com/facebookincubator/contest/plugins/teststeps/sshcmd" - "github.com/facebookincubator/contest/plugins/teststeps/terminalexpect" + "github.com/sirupsen/logrus" ) -const defaultDBURI = "contest:contest@tcp(localhost:3306)/contest?parseTime=true" - var ( - flagDBURI = flag.String("dbURI", defaultDBURI, "Database URI") + flagDBURI = flag.String("dbURI", config.DefaultDBURI, "Database URI") flagServerID = flag.String("serverID", "", "Set a static server ID, e.g. the host name or another unique identifier. If unset, will use the listener's default") ) -var targetManagers = []target.TargetManagerLoader{ - csvtargetmanager.Load, - targetlist.Load, -} - -var testFetchers = []test.TestFetcherLoader{ - uri.Load, - literal.Load, -} - -var testSteps = []test.TestStepLoader{ - echo.Load, - slowecho.Load, - example.Load, - cmd.Load, - sshcmd.Load, - randecho.Load, - terminalexpect.Load, -} - -var reporters = []job.ReporterLoader{ - targetsuccess.Load, - noop.Load, -} - -// user-defined functions that will be made available to plugins for advanced -// expressions in config parameters. -var userFunctions = map[string]interface{}{ - // dummy function to prove that function registration works. - "do_nothing": func(a ...string) (string, error) { - if len(a) == 0 { - return "", errors.New("do_nothing: no arg specified") - } - return a[0], nil - }, -} - func main() { flag.Parse() log := logging.GetLogger("contest") @@ -91,35 +41,6 @@ func main() { pluginRegistry := pluginregistry.NewPluginRegistry() - // Register TargetManager plugins - for _, tmloader := range targetManagers { - if err := pluginRegistry.RegisterTargetManager(tmloader()); err != nil { - log.Fatal(err) - } - } - - // Register TestFetcher plugins - for _, tfloader := range testFetchers { - if err := pluginRegistry.RegisterTestFetcher(tfloader()); err != nil { - log.Fatal(err) - } - } - - // Register TestStep plugins - for _, tsloader := range testSteps { - if err := pluginRegistry.RegisterTestStep(tsloader()); err != nil { - log.Fatal(err) - - } - } - - // Register Reporter plugins - for _, rfloader := range reporters { - if err := pluginRegistry.RegisterReporter(rfloader()); err != nil { - log.Fatal(err) - } - } - // storage initialization log.Infof("Using database URI: %s", *flagDBURI) s, err := rdbms.New(*flagDBURI) @@ -131,12 +52,7 @@ func main() { // set Locker engine target.SetLocker(inmemory.New(config.LockInitialTimeout, config.LockRefreshTimeout)) - // user-defined function registration - for name, fn := range userFunctions { - if err := test.RegisterFunction(name, fn); err != nil { - log.Fatal(err) - } - } + plugins.Init(pluginRegistry, log) // spawn JobManager listener := httplistener.HTTPListener{} diff --git a/cmds/plugins/plugins.go b/cmds/plugins/plugins.go new file mode 100644 index 00000000..5e4125f8 --- /dev/null +++ b/cmds/plugins/plugins.go @@ -0,0 +1,107 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package plugins + +import ( + "errors" + + "github.com/facebookincubator/contest/pkg/pluginregistry" + + "github.com/facebookincubator/contest/pkg/job" + "github.com/facebookincubator/contest/pkg/target" + "github.com/facebookincubator/contest/pkg/test" + + "github.com/facebookincubator/contest/plugins/reporters/noop" + "github.com/facebookincubator/contest/plugins/reporters/targetsuccess" + "github.com/facebookincubator/contest/plugins/targetmanagers/csvtargetmanager" + "github.com/facebookincubator/contest/plugins/targetmanagers/targetlist" + "github.com/facebookincubator/contest/plugins/testfetchers/literal" + "github.com/facebookincubator/contest/plugins/testfetchers/uri" + "github.com/facebookincubator/contest/plugins/teststeps/cmd" + "github.com/facebookincubator/contest/plugins/teststeps/echo" + "github.com/facebookincubator/contest/plugins/teststeps/example" + "github.com/facebookincubator/contest/plugins/teststeps/randecho" + "github.com/facebookincubator/contest/plugins/teststeps/slowecho" + "github.com/facebookincubator/contest/plugins/teststeps/sshcmd" + "github.com/sirupsen/logrus" +) + +var targetManagers = []target.TargetManagerLoader{ + csvtargetmanager.Load, + targetlist.Load, +} + +var testFetchers = []test.TestFetcherLoader{ + uri.Load, + literal.Load, +} + +var testSteps = []test.TestStepLoader{ + echo.Load, + slowecho.Load, + example.Load, + cmd.Load, + sshcmd.Load, + randecho.Load, +} + +var reporters = []job.ReporterLoader{ + targetsuccess.Load, + noop.Load, +} + +// user-defined functions that will be made available to plugins for advanced +// expressions in config parameters. +var userFunctions = map[string]interface{}{ + // sample function to prove that function registration works. + "do_nothing": func(a ...string) (string, error) { + if len(a) == 0 { + return "", errors.New("do_nothing: no arg specified") + } + return a[0], nil + }, +} + +// Init initializes the plugin registry +func Init(pluginRegistry *pluginregistry.PluginRegistry, log *logrus.Entry) { + + // Register TargetManager plugins + for _, tmloader := range targetManagers { + if err := pluginRegistry.RegisterTargetManager(tmloader()); err != nil { + log.Fatal(err) + } + } + + // Register TestFetcher plugins + for _, tfloader := range testFetchers { + if err := pluginRegistry.RegisterTestFetcher(tfloader()); err != nil { + log.Fatal(err) + } + } + + // Register TestStep plugins + for _, tsloader := range testSteps { + if err := pluginRegistry.RegisterTestStep(tsloader()); err != nil { + log.Fatal(err) + + } + } + + // Register Reporter plugins + for _, rfloader := range reporters { + if err := pluginRegistry.RegisterReporter(rfloader()); err != nil { + log.Fatal(err) + } + } + + // user-defined function registration + for name, fn := range userFunctions { + if err := test.RegisterFunction(name, fn); err != nil { + log.Fatal(err) + } + } + +} diff --git a/db/rdbms/migration/0001_add_extended_descriptor.sql b/db/rdbms/migration/0001_add_extended_descriptor.sql new file mode 100644 index 00000000..bcfc9814 --- /dev/null +++ b/db/rdbms/migration/0001_add_extended_descriptor.sql @@ -0,0 +1,5 @@ +-- +goose Up +ALTER TABLE jobs ADD COLUMN extended_descriptor text; + +-- +goose Down +ALTER TABLE jobs DROP COLUMN extended_descriptor; diff --git a/db/rdbms/migration/0002_migrate_descriptor_to_extended_descriptor.go b/db/rdbms/migration/0002_migrate_descriptor_to_extended_descriptor.go new file mode 100644 index 00000000..973e9872 --- /dev/null +++ b/db/rdbms/migration/0002_migrate_descriptor_to_extended_descriptor.go @@ -0,0 +1,293 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package migration + +import ( + "database/sql" + "encoding/json" + "fmt" + "time" + + "github.com/facebookincubator/contest/pkg/job" + "github.com/facebookincubator/contest/pkg/test" + "github.com/facebookincubator/contest/tools/migration/rdbms/migrate" + + "github.com/facebookincubator/contest/cmds/plugins" + "github.com/facebookincubator/contest/pkg/pluginregistry" + + "github.com/sirupsen/logrus" +) + +const shardSize = uint64(50) + +// DescriptorMigration represents a migration which moves steps description in jobs tables from old to new +// schema. The migration consists in the following: +// +// +// In v0001, job.Request object was structured as follows: +// +// type Request struct { +// JobID types.JobID +// JobName string +// Requestor string +// ServerID string +// RequestTime time.Time +// JobDescriptor string +// TestDescriptors string +// } +// +// Having TestDescriptors as a field of request objects creates several issues, including: +// * It's an abstraction leakage, the extended description of the steps might not be part +// of the initial request submitted from outside (i.e. might not be a literal embedded +// in the job descriptor) +// * The job.Descriptor object does not contain the extended version of the test steps, which +// will make it difficult to handle resume, as we need to retrieve multiple objects +// +// Schema v0002 introduces the concept of extended_descriptor, which is defined as follows: +// type ExtendedDescriptor struct { +// JobDescriptor +// StepsDescriptors []test.StepsDescriptors +// } +// +// We remove TestDescriptors from Request objects, and we store that information side-by-side with +// JobDescriptor into an ExtendedDescriptor. We then store this ExtendedDescriptor in the jobs table +// so that all the test information can be re-fetched simply by reading extended_descriptor field in +// jobs table. +type DescriptorMigration struct { + log *logrus.Entry +} + +func ms(d time.Duration) float64 { + return float64(d.Microseconds()) / 1000.0 +} + +// fetchJobs fetches job requests based on limit and offset +func fetchJobs(tx *sql.Tx, limit, offset uint64, log *logrus.Entry) ([]job.Request, error) { + + log.Debugf("fetching shard limit: %d, offset: %d", limit, offset) + selectStatement := "select job_id, name, requestor, server_id, request_time, descriptor, teststeps from jobs limit ? offset ?" + log.Debugf("running query: %s", selectStatement) + + start := time.Now() + rows, err := tx.Query(selectStatement, limit, offset) + + elapsed := time.Since(start) + log.Debugf("select query executed in: %.3f ms", ms(elapsed)) + + if err != nil { + return nil, fmt.Errorf("could not get job request (limit %d, offset %d): %w", limit, offset, err) + } + defer func() { + _ = rows.Close() + }() + + var jobs []job.Request + + start = time.Now() + for rows.Next() { + job := job.Request{} + err := rows.Scan( + &job.JobID, + &job.JobName, + &job.Requestor, + &job.ServerID, + &job.RequestTime, + &job.JobDescriptor, + &job.TestDescriptors, + ) + if err != nil { + return nil, fmt.Errorf("could not scan job request (limit %d, offset %d): %w", limit, offset, err) + } + jobs = append(jobs, job) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("could not scan job request (limit %d, offset %d): %w", limit, offset, err) + } + + if len(jobs) == 0 { + return nil, fmt.Errorf("could not find jobs for limit: %d, offset: %d", limit, offset) + } + elapsed = time.Since(start) + log.Debugf("jobs in shard shard limit: %d, offset: %d fetched in: %.3f ms", limit, offset, ms(elapsed)) + return jobs, nil +} + +func migrateJobs(tx *sql.Tx, requests []job.Request, registry *pluginregistry.PluginRegistry, log *logrus.Entry) error { + + log.Debugf("migrating %d jobs", len(requests)) + start := time.Now() + for _, request := range requests { + + // Merge JobDescriptor and TestStepDescriptor(s) into a single ExtendedDescriptor. + // ExtendedDescriptor contains StepsDescriptors, which is declared as follows: + // type StepsDescriptors struct { + // TestName string + // Test []StepDescriptor + // Cleanup []StepDescriptor + // } + // + // StepDescriptor is instead defined as follows: + // type StepDescriptor struct { + // Name string + // Label string + // Parameters StepParameters + // } + // + // The previous request.TestDescriptors was actually referring to the JSON + // description representing the steps, for every test. This is very ambiguous + // because job.JobDescriptor contains TestDescriptors itself, which however + // represent the higher level description of the test (including TargetManager + // name, TestFetcher name, etc.). So ExtendedDescriptor refers instead to + // StepsDescriptors and TestDescriptors field is removed from request object. + + var jobDesc job.JobDescriptor + if err := json.Unmarshal([]byte(request.JobDescriptor), &jobDesc); err != nil { + return fmt.Errorf("failed to unmarshal job descriptor (%+v): %w", jobDesc, err) + } + + var stepDescs [][]*test.StepDescriptor + if err := json.Unmarshal([]byte(request.TestDescriptors), &stepDescs); err != nil { + return fmt.Errorf("failed to unmarshal test step descriptors from request object (%+v): %w", request.TestDescriptors, err) + } + + extendedDescriptor := job.ExtendedDescriptor{JobDescriptor: jobDesc} + if len(stepDescs) != len(jobDesc.TestDescriptors) { + return fmt.Errorf("number of tests described in JobDescriptor does not match steps stored in db") + } + + for index, stepDesc := range stepDescs { + newStepsDesc := test.StepsDescriptors{} + // TestName is missing from the v0001 schema and can be retrieved only via + // TestFetcher. We need TestName in the extended_descriptor to be able to + // correctly build status of previous jobs. So, the only option we have is to + // initialize a TestFetcher and let it retrieve the test name. + + for _, desc := range stepDesc { + newStepsDesc.Test = append(newStepsDesc.Test, *desc) + } + + // Look up the original TestDescriptor from JobDescriptor, instantiate + // TestFetcher accordingly and retrieve the name of the test + td := jobDesc.TestDescriptors[index] + + tfb, err := registry.NewTestFetcherBundle(td) + if err != nil { + return fmt.Errorf("could not instantiate test fetcher for jobID %d based on descriptor %+v: %w", request.JobID, td, err) + } + + name, stepDescFetched, err := tfb.TestFetcher.Fetch(tfb.FetchParameters) + if err != nil { + return fmt.Errorf("could not retrieve test description from fetcher for jobID %d: %w", request.JobID, err) + } + + // Check that the serialization of the steps retrieved by the test fetcher matches the steps + // stored in the DB. If that's not the case, then, just print a warning: the underlying test + /// might have changed.We go ahead anyway assuming assume the test name is still relevant. + stepDescFetchedJSON, err := json.Marshal(stepDescFetched) + if err != nil { + log.Warningf("steps description (`%v`) fetched by test fetcher for job %d cannot be serialized: %v", stepDescFetched, request.JobID, err) + } + + stepDescDBJSON, err := json.Marshal(stepDesc) + if err != nil { + log.Warningf("steps description (`%v`) fetched from db for job %d cannot be serialized: %v", stepDesc, request.JobID, err) + } + + if string(stepDescDBJSON) != string(stepDescFetchedJSON) { + log.Warningf("steps retrieved by test fetcher and from database do not match (`%v` != `%v`), test description might have changed", string(stepDescDBJSON), string(stepDescFetchedJSON)) + } + + newStepsDesc.TestName = name + extendedDescriptor.StepsDescriptors = append(extendedDescriptor.StepsDescriptors, newStepsDesc) + } + + // Serialize job.ExtendedDescriptor + extendedDescriptorJSON, err := json.Marshal(extendedDescriptor) + if err != nil { + return fmt.Errorf("could not serialize extended descriptor for jobID %d (%+v): %w", request.JobID, extendedDescriptor, err) + } + + insertStatement := "update jobs set extended_descriptor = ? where job_id = ?" + log.Debugf("running insert statement: %s, descriptor: %s, jobID: %d", insertStatement, extendedDescriptorJSON, request.JobID) + + insertStart := time.Now() + _, err = tx.Exec(insertStatement, extendedDescriptorJSON, request.JobID) + elapsed := time.Since(insertStart) + log.Debugf("insert statement executed in %.3f ms", ms(elapsed)) + + if err != nil { + return fmt.Errorf("could not store extended descriptor for job_id %d: %w", request.JobID, err) + } + } + + elapsed := time.Since(start) + log.Debugf("completed migrating %d jobs in %.3f ms", len(requests), ms(elapsed)) + + return nil +} + +// Up implements the forward migration +func (m *DescriptorMigration) Up(tx *sql.Tx) error { + + // Count how many entries we have in jobs table that we need to migrate. Split them into + // shards of size shardSize for migration. Can't be done online within a single transaction, + // as there cannot be two active queries on the same connection at the same time + // (see https://github.com/lib/pq/issues/81) + + count := uint64(0) + m.log.Debugf("counting the number of jobs to migrate") + start := time.Now() + rows, err := tx.Query("select count(*) from jobs") + if err != nil { + return fmt.Errorf("could not fetch number of records to migrate: %w", err) + } + if !rows.Next() { + err := "could not fetch number of records to migrate, at least one result from count(*) expected" + if rows.Err() == nil { + return fmt.Errorf(err) + } + return fmt.Errorf("%s (err: %w)", err, rows.Err()) + } + if err := rows.Scan(&count); err != nil { + return fmt.Errorf("could not fetch number of records to migrate: %w", err) + } + rows.Close() + + // Create a new plugin registry. This is necessary because some information that need to be + // associated with the extended_descriptor is not available in the db and can only be looked + // up via the TestFetcher. + registry := pluginregistry.NewPluginRegistry() + plugins.Init(registry, m.log) + + elapsed := time.Since(start) + m.log.Debugf("total number of jobs to migrate: %d, fetched in %.3f ms", count, ms(elapsed)) + for offset := uint64(0); offset < count; offset += shardSize { + jobs, err := fetchJobs(tx, shardSize, offset, m.log) + if err != nil { + return fmt.Errorf("could not fetch events in range offset %d limit %d: %w", offset, shardSize, err) + } + err = migrateJobs(tx, jobs, registry, m.log) + if err != nil { + return fmt.Errorf("could not migrate events in range offset %d limit %d: %w", offset, shardSize, err) + } + } + return nil +} + +// Down implements the down transition of DescriptorMigration +func (m *DescriptorMigration) Down(tx *sql.Tx) error { + return nil +} + +// NewDescriptorMigration is the factory for DescriptorMigration +func NewDescriptorMigration(log *logrus.Entry) migrate.Migrate { + return &DescriptorMigration{log: log} +} + +// register NewDescriptorMigration at initialization time +func init() { + migrate.Register(NewDescriptorMigration) +} diff --git a/db/rdbms/schema/latest/create_contest_db.sql b/db/rdbms/schema/latest/create_contest_db.sql new file mode 100644 index 00000000..21912b8a --- /dev/null +++ b/db/rdbms/schema/latest/create_contest_db.sql @@ -0,0 +1,69 @@ +-- Copyright (c) Facebook, Inc. and its affiliates. +-- +-- This source code is licensed under the MIT license found in the +-- LICENSE file in the root directory of this source tree. + +CREATE TABLE test_events ( + event_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + job_id BIGINT(20) NOT NULL, + run_id BIGINT(20) NOT NULL, + test_name VARCHAR(32) NULL, + test_step_label VARCHAR(32) NULL, + event_name VARCHAR(32) NULL, + target_name VARCHAR(64) NULL, + target_id VARCHAR(64) NULL, + payload TEXT NULL, + emit_time TIMESTAMP NOT NULL, + PRIMARY KEY (event_id) +); + +CREATE TABLE framework_events ( + event_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + job_id BIGINT(20) NOT NULL, + event_name VARCHAR(32) NULL, + payload TEXT NULL, + emit_time TIMESTAMP NOT NULL, + PRIMARY KEY (event_id) +); + +CREATE TABLE run_reports ( + report_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + job_id BIGINT(20) NOT NULL, + run_id BIGINT(20) NOT NULL, + reporter_name VARCHAR(32) NOT NULL, + success TINYINT(1) NULL, + report_time TIMESTAMP NOT NULL, + data TEXT NOT NULL, + PRIMARY KEY (report_id) +); + +CREATE TABLE final_reports ( + report_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + job_id BIGINT(20) NOT NULL, + success TINYINT(1) NULL, + reporter_name VARCHAR(32) NOT NULL, + report_time TIMESTAMP NOT NULL, + data TEXT NOT NULL, + PRIMARY KEY (report_id) +); + +CREATE TABLE jobs ( + job_id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, + name VARCHAR(64) NOT NULL, + requestor VARCHAR(32) NOT NULL, + server_id VARCHAR(64) NOT NULL, + request_time TIMESTAMP NOT NULL, + descriptor TEXT NOT NULL, + teststeps TEXT, + extended_descriptor TEXT, + PRIMARY KEY (job_id) +); + +CREATE TABLE locks ( + target_id VARCHAR(64) NOT NULL, + job_id BIGINT(20) UNSIGNED NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + expires_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + valid BOOL NOT NULL DEFAULT TRUE, + PRIMARY KEY (target_id) +); diff --git a/docker/mysql/create_contest_db.sql b/db/rdbms/schema/v0/create_contest_db.sql similarity index 100% rename from docker/mysql/create_contest_db.sql rename to db/rdbms/schema/v0/create_contest_db.sql diff --git a/docker/contest/tests.sh b/docker/contest/tests.sh index 515f4413..62472cf2 100755 --- a/docker/contest/tests.sh +++ b/docker/contest/tests.sh @@ -74,7 +74,7 @@ for tag in integration integration_storage; do go test -tags=${tag} -race \ -coverprofile=profile.out ${pflag} \ -covermode=atomic \ - -coverpkg=github.com/facebookincubator/contest/pkg/...,github.com/facebookincubator/contest/plugins/...,github.com/facebookincubator/contest/cmds/... \ + -coverpkg=all \ "${d}" if [ -f profile.out ]; then cat profile.out >> coverage.txt @@ -87,6 +87,7 @@ if [ "${CI}" == "true" ] then echo "Uploading coverage profile for integration tests" bash <(curl -s https://codecov.io/bash) -c -F integration + bash <(curl -s https://codecov.io/bash) -c -F integration_storage else echo "Skipping upload of coverage profile for integration tests because not running in a CI" fi diff --git a/docker/mysql/Dockerfile b/docker/mysql/Dockerfile index 96ab9c8e..277190fa 100644 --- a/docker/mysql/Dockerfile +++ b/docker/mysql/Dockerfile @@ -2,4 +2,4 @@ FROM mysql # All scripts in docker-entrypoint-initdb.d/ are automatically # executed during container startup COPY docker/mysql/initdb.sql /docker-entrypoint-initdb.d/ -COPY docker/mysql/create_contest_db.sql / +COPY db/rdbms/schema/latest/create_contest_db.sql / diff --git a/go.mod b/go.mod index a309d2c1..dbf27004 100644 --- a/go.mod +++ b/go.mod @@ -3,44 +3,32 @@ module github.com/facebookincubator/contest go 1.15 require ( - github.com/bombsimon/wsl/v2 v2.2.0 // indirect github.com/chappjc/logrus-prefix v0.0.0-20180227015900-3a1d64819adb - github.com/davecgh/go-spew v1.1.1 - github.com/fatih/color v1.9.0 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/go-sql-driver/mysql v1.5.0 - github.com/gogo/protobuf v1.3.1 // indirect - github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d // indirect - github.com/golangci/golangci-lint v1.24.0 // indirect - github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039 // indirect - github.com/gostaticanalysis/analysisutil v0.0.3 // indirect + github.com/golang/protobuf v1.3.2 // indirect github.com/insomniacslk/termhook v0.0.0-20190716141402-454368e885ec github.com/insomniacslk/xjson v0.0.0-20190510162823-f016a4991179 - github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/kr/pretty v0.2.0 // indirect github.com/mattn/go-colorable v0.1.6 // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect - github.com/pelletier/go-toml v1.6.0 // indirect + github.com/onsi/ginkgo v1.12.0 // indirect + github.com/onsi/gomega v1.9.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 // indirect - github.com/securego/gosec v0.0.0-20200316084457-7da9f46445fd // indirect + github.com/pressly/goose v2.7.0-rc5+incompatible github.com/sirupsen/logrus v1.4.2 - github.com/spf13/afero v1.2.2 // indirect - github.com/spf13/cast v1.3.1 // indirect - github.com/spf13/cobra v0.0.6 // indirect - github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.6-0.20200504143853-81378bbcd8a1 - github.com/spf13/viper v1.6.2 // indirect github.com/stretchr/testify v1.5.1 - github.com/u-root/u-root v6.0.0+incompatible // indirect github.com/x-cray/logrus-prefixed-formatter v0.5.2 // indirect golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d + golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d // indirect - golang.org/x/tools v0.0.0-20200317184713-827390e9012e // indirect - gopkg.in/ini.v1 v1.55.0 // indirect - gopkg.in/yaml.v2 v2.2.8 + golang.org/x/text v0.3.2 // indirect + golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect + gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c - mvdan.cc/unparam v0.0.0-20200314162735-0ac8026f7d06 // indirect - sourcegraph.com/sqs/pbtypes v1.0.0 // indirect ) diff --git a/go.sum b/go.sum index 13226847..791a76b5 100644 --- a/go.sum +++ b/go.sum @@ -1,498 +1,102 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us= -github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= -github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= -github.com/bombsimon/wsl/v2 v2.0.0 h1:+Vjcn+/T5lSrO8Bjzhk4v14Un/2UyCA1E3V5j9nwTkQ= -github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTKY95VwV8U= -github.com/bombsimon/wsl/v2 v2.2.0 h1:/DdSteYCq4lPX+LqDg7mdoxm14UxzZPoDT0taYc3DTU= -github.com/bombsimon/wsl/v2 v2.2.0/go.mod h1:Azh8c3XGEJl9LyX0/sFC+CKMc7Ssgua0g+6abzXN4Pg= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/chappjc/logrus-prefix v0.0.0-20180227015900-3a1d64819adb h1:aZTKxMminKeQWHtzJBbV8TttfTxzdJ+7iEJFE6FmUzg= github.com/chappjc/logrus-prefix v0.0.0-20180227015900-3a1d64819adb/go.mod h1:xzXc1S/L+64uglB3pw54o8kqyM6KFYpTeC9Q6+qZIu8= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-critic/go-critic v0.4.1 h1:4DTQfT1wWwLg/hzxwD9bkdhDQrdJtxe6DUTadPlrIeE= -github.com/go-critic/go-critic v0.4.1/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-lintpack/lintpack v0.5.2 h1:DI5mA3+eKdWeJ40nU4d6Wc26qmdG8RCi/btYq0TuRN0= -github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR6jE7g= -github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= -github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= -github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= -github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= -github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= -github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= -github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= -github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= -github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= -github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= -github.com/go-toolsmith/astp v1.0.0 h1:alXE75TXgcmupDsMK1fRAy0YUzLzqPVvBKoyWV+KPXg= -github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= -github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= -github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= -github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= -github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= -github.com/go-toolsmith/typep v1.0.0 h1:zKymWyA1TRYvqYrYDrfEMZULyrhcnGY3x7LDKU2XQaA= -github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b h1:ekuhfTjngPhisSjOJ0QWKpPQE8/rbknHaes6WVJj5Hw= -github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= -github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= -github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= -github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6 h1:YYWNAGTKWhKpcLLt7aSj/odlKrSrelQwlovBpDuf19w= -github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= -github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZBf8NjltjWihK2QfBBBZuv91cMFfDHw= -github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= -github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3 h1:pe9JHs3cHHDQgOFXJJdYkK6fLz2PWyYtP4hthoCMvs8= -github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= -github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee h1:J2XAy40+7yz70uaOiMbNnluTg7gyQhtGqLQncQh+4J8= -github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= -github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d h1:pXTK/gkVNs7Zyy7WKgLXmpQ5bHTrq5GDsp8R9Qs67g0= -github.com/golangci/gocyclo v0.0.0-20180528144436-0a533e8fa43d/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= -github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= -github.com/golangci/golangci-lint v1.23.3 h1:wkACDEoy+b0CVqnSK8BbWrVkN2tsVLUA1+SIkGSm4o0= -github.com/golangci/golangci-lint v1.23.3/go.mod h1:LNexeEyqT5hQH7v47e67JekL0V51lXFUjbPkopxNSK4= -github.com/golangci/golangci-lint v1.24.0 h1:OcmSTTMPqI/VT4GvN1fKuE9NX15dDXIwolO0l08334U= -github.com/golangci/golangci-lint v1.24.0/go.mod h1:yIqiAZ2SSQqg+1JeFlAdvEWjGVz4uu5jr4lrciqA1gE= -github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc h1:gLLhTLMk2/SutryVJ6D4VZCU3CUqr8YloG7FPIBWFpI= -github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= -github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= -github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= -github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770 h1:EL/O5HGrF7Jaq0yNhBLucz9hTuRzj2LdwGBOaENgxIk= -github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= -github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21 h1:leSNB7iYzLYSSx3J/s5sVf4Drkc68W2wm4Ixh/mr0us= -github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= -github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0 h1:HVfrLniijszjS1aiNg8JbBMO2+E1WIQ+j/gL4SQqGPg= -github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= -github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039 h1:XQKc8IYQOeRwVs36tDrEmTgDgP88d5iEURwpmtiAlOM= -github.com/golangci/revgrep v0.0.0-20180812185044-276a5c0a1039/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= -github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3 h1:JVnpOZS+qxli+rgVl98ILOXVNbW+kb5wcxeGx8ShUIw= -github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/gostaticanalysis/analysisutil v0.0.3 h1:iwp+5/UAyzQSFgQ4uR2sni99sJ8Eo9DEacKWM5pekIg= -github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= -github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/insomniacslk/termhook v0.0.0-20190716141402-454368e885ec h1:5+0mqILIFLY0ZE1J3x6zxSSSay8lLQHzD8udNsjLSlY= github.com/insomniacslk/termhook v0.0.0-20190716141402-454368e885ec/go.mod h1:8eGC3NZFqSFxpbWduqdoolXfuhN3K8KH9wMmldc3sYs= github.com/insomniacslk/xjson v0.0.0-20190510162823-f016a4991179 h1:/chUAu1Yt4ipW2AHtRdVwc3ua1REYuq9+Dnzl0zvK1Y= github.com/insomniacslk/xjson v0.0.0-20190510162823-f016a4991179/go.mod h1:G8c61yEjNgzQNF0lOvul8ls5IHE/MxbGx7M98ADBVEA= -github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a h1:GmsqmapfzSJkm28dhRoHz2tLRbJmqhU86IPgBtN3mmk= -github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s= -github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3 h1:jNYPNLe3d8smommaoQlK7LOA5ESyUJJ+Wf79ZtA7Vp4= -github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= -github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= -github.com/jmoiron/sqlx v1.2.1-0.20190826204134-d7d95172beb5/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb h1:RHba4YImhrUVQDHUCe2BNSOz4tVy2yGyXhvYDvxGgeE= -github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= -github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= -github.com/mozilla/tls-observatory v0.0.0-20200220173314-aae45faa4006/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E= -github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= -github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 h1:A7GG7zcGjl3jqAqGPmcNjd/D9hzL95SuoOQAaFNdLU0= github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83 h1:AtnWoOvTioyDXFvu96MWEeE8qj4COSQnJogzLy/u41A= -github.com/securego/gosec v0.0.0-20200103095621-79fbf3af8d83/go.mod h1:vvbZ2Ae7AzSq3/kywjUDxSNq2SJ27RxCz2un0H3ePqE= -github.com/securego/gosec v0.0.0-20200203094520-d13bb6d2420c h1:pThusIwnQVcKbuZSds3HgB/ODEqxMqZf/SgVp89JXY0= -github.com/securego/gosec v0.0.0-20200203094520-d13bb6d2420c/go.mod h1:gp0gaHj0WlmPh9BdsTmo1aq6C27yIPWdxCKGFGdVKBE= -github.com/securego/gosec v0.0.0-20200316084457-7da9f46445fd h1:qB+l4fYZsH78xORC1aqVS0zNmgkQp4rkj2rvfxQMtzc= -github.com/securego/gosec v0.0.0-20200316084457-7da9f46445fd/go.mod h1:NurAFZsWJAEZjogSwdVPlHkOZB3DOAU7gsPP8VFZCHc= -github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= -github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/pressly/goose v2.7.0-rc5+incompatible h1:txvo810iG1P/rafOx31LYDlOyikBK8A/8prKP4j066w= +github.com/pressly/goose v2.7.0-rc5+incompatible/go.mod h1:m+QHWCqxR3k8D9l7qfzuC/djtlfzxr34mozWDYEu1z8= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sourcegraph/go-diff v0.5.1 h1:gO6i5zugwzo1RVTvgvfwCOSVegNuvnNi6bAD1QCmkHs= -github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs= -github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.6-0.20200504143853-81378bbcd8a1 h1:zrNp7OPtn2fjeNHI9CghvwxqQvvkK0RxUo86hE86vhU= github.com/spf13/pflag v1.0.6-0.20200504143853-81378bbcd8a1/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.6.1 h1:VPZzIkznI1YhVMRi6vNFLHSwhnhReBfgTxIPccpfdZk= -github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= -github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E= -github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e h1:RumXZ56IrCj4CL+g1b9OL/oH0QnsF976bC8xQFYUD5Q= -github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tommy-muehle/go-mnd v1.1.1 h1:4D0wuPKjOTiK2garzuPGGvm4zZ/wLYDOH8TJSABC7KU= -github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= -github.com/tommy-muehle/go-mnd v1.2.0 h1:yCMWAt4MtTwUrikDTZEnQfdZOJeIVPRA36SViMgEMGk= -github.com/tommy-muehle/go-mnd v1.2.0/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= -github.com/tommy-muehle/go-mnd v1.3.0/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= -github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa h1:RC4maTWLKKwb7p1cnoygsbKIgNlJqSYBeAFON3Ar8As= -github.com/tommy-muehle/go-mnd v1.3.1-0.20200224220436-e6f9a994e8fa/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= -github.com/u-root/u-root v1.0.0 h1:3hJy0CG3mXIZtWRE+yrghG/3H0v8L1qEeZBlPr5nS9s= -github.com/u-root/u-root v6.0.0+incompatible h1:YqPGmRoRyYmeg17KIWFRSyVq6LX5T6GSzawyA6wG6EE= -github.com/u-root/u-root v6.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/RJE7K0D8fXO0d47+3YY= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/ultraware/funlen v0.0.2 h1:Av96YVBwwNSe4MLR7iI/BIa3VyI7/djnto/pK3Uxbdo= -github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= -github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg= -github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= -github.com/uudashr/gocognit v1.0.1 h1:MoG2fZ0b/Eo7NXoIwCVFLG5JED3qgQz5/NEE+rOsjPs= -github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= -github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= -github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d h1:9FCpayM9Egr1baVnV1SX0H87m+XB0B8S0hAMi99X/3U= golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g= -golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM= -golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5 h1:LfCXLvNmTYH9kEmVgqbnsWfruoXZIrh4YBgqVHtDvw0= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d h1:62ap6LNOjDU6uGmKXHJbSfciMoV+FeI1sRXx/pLDL44= golang.org/x/sys v0.0.0-20200317113312-5766fd39f98d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911151314-feee8acb394c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113232020-e2727e816f5a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200102140908-9497f49d5709 h1:AfG1EmoRkFK24HWWLxSrRKNg2G+oA3JVOG8GJsHWypQ= -golang.org/x/tools v0.0.0-20200102140908-9497f49d5709/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200203023011-6f24f261dadb/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74 h1:KW20qMcLRWuIgjdCpHFJbVZA7zsDKtFXPNcm7/eI5ZA= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204192400-7124308813f3/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200228224639-71482053b885/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200313205530-4303120df7d8/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200317184713-827390e9012e h1:LuTra/PQ8QHieyP2k0M0dZbF1e6fDxO7k3PqSPDxNc4= -golang.org/x/tools v0.0.0-20200317184713-827390e9012e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.52.0 h1:j+Lt/M1oPPejkniCg1TkWE2J3Eh1oZTsHSXzMTzUXn4= -gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ= -gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= -gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c h1:grhR+C34yXImVGp7EzNk+DTIk+323eIUWOmEevy6bDo= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed h1:WX1yoOaKQfddO/mLzdV4wptyWgoH/6hwLs7QHTixo0I= -mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo= -mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= -mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f h1:Cq7MalBHYACRd6EesksG1Q8EoIAKOsiZviGKbOLIej4= -mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= -mvdan.cc/unparam v0.0.0-20191111180625-960b1ec0f2c2 h1:K7wru2CfJGumS5hkiguQ0Rb9ebKM2Jo8s5d4Jm9lFaM= -mvdan.cc/unparam v0.0.0-20191111180625-960b1ec0f2c2/go.mod h1:rCqoQrfAmpTX/h2APczwM7UymU/uvaOluiVPIYCSY/k= -mvdan.cc/unparam v0.0.0-20200314162735-0ac8026f7d06 h1:evGBPL1nfLr4BUt+I0IV8q6P3oOqXhmC+hc8aw7xO8A= -mvdan.cc/unparam v0.0.0-20200314162735-0ac8026f7d06/go.mod h1:A9jtdiT4gKMLUlAQjDEVC18O9SOJ8ZAiqWfq9g3rlj8= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4 h1:JPJh2pk3+X4lXAkZIk2RuE/7/FoK9maXw+TNPJhVS/c= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= -sourcegraph.com/sqs/pbtypes v1.0.0 h1:f7lAwqviDEGvON4kRv0o5V7FT/IQK+tbkF664XMbP3o= -sourcegraph.com/sqs/pbtypes v1.0.0/go.mod h1:3AciMUv4qUuRHRHhOG4TZOB+72GdPVz5k+c648qsFS4= diff --git a/pkg/config/db.go b/pkg/config/db.go new file mode 100644 index 00000000..91400e3c --- /dev/null +++ b/pkg/config/db.go @@ -0,0 +1,9 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package config + +// DefaultDBURI represents the default URI used by the rdbms plugin +const DefaultDBURI = "contest:contest@tcp(localhost:3306)/contest?parseTime=true" diff --git a/pkg/job/forward_decl.go b/pkg/job/forward_decl.go new file mode 100644 index 00000000..b59f914c --- /dev/null +++ b/pkg/job/forward_decl.go @@ -0,0 +1,18 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package job + +import ( + "github.com/facebookincubator/contest/pkg/test" +) + +// --- "Forward declaration" from #118 to enable building DB migration logic ---- +type ExtendedDescriptor struct { + JobDescriptor + StepsDescriptors []test.StepsDescriptors +} + +// --- End Forward declaration from #118 ---- diff --git a/pkg/test/forward_decl.go b/pkg/test/forward_decl.go new file mode 100644 index 00000000..502e88e0 --- /dev/null +++ b/pkg/test/forward_decl.go @@ -0,0 +1,68 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package test + +import ( + "errors" + "fmt" + "strconv" +) + +// --- "Forward declaration" from #118 to enable building DB migration logic ---- + +// TestStepParameters represents the parameters that a TestStep should consume +// according to the Test descriptor fetched by the TestFetcher +type StepParameters map[string][]Param + +// Get returns the value of the requested parameter. A missing item is not +// distinguishable from an empty value. For this you need to use the regular map +// accessor. +func (t StepParameters) Get(k string) []Param { + return t[k] +} + +// GetOne returns the first value of the requested parameter. If the parameter +// is missing, an empty string is returned. +func (t StepParameters) GetOne(k string) *Param { + v, ok := t[k] + if !ok || len(v) == 0 { + return &Param{} + } + return &v[0] +} + +// GetInt works like GetOne, but also tries to convert the string to an int64, +// and returns an error if this fails. +func (t StepParameters) GetInt(k string) (int64, error) { + v := t.GetOne(k) + if v.String() == "" { + return 0, errors.New("expected an integer string, got an empty string") + } + n, err := strconv.ParseInt(v.String(), 10, 64) + if err != nil { + return 0, fmt.Errorf("cannot convert '%s' to int: %v", v, err) + } + return n, nil +} + +// StepDescriptor is the definition of a test step matching a test step +// configuration. +type StepDescriptor struct { + Name string + Label string + Parameters StepParameters +} + +// StepsDescriptors bundles together Test and Cleanup descriptions +// TODO: give a less overloaded name to this structure +// (e.g. ResolvedTestDescriptor) +type StepsDescriptors struct { + TestName string + Test []StepDescriptor + Cleanup []StepDescriptor +} + +// --- End Forward declaration port from #118 ---- diff --git a/tests/integ/common/storage.go b/tests/integ/common/storage.go index 55ed1949..3a45d4ab 100644 --- a/tests/integ/common/storage.go +++ b/tests/integ/common/storage.go @@ -3,8 +3,6 @@ // This source code is licensed under the MIT license found in the // LICENSE file in the root directory of this source tree. -// +build integration_storage integration - package common import ( @@ -14,9 +12,10 @@ import ( "github.com/facebookincubator/contest/plugins/storage/rdbms" ) +const DbURI = "contest:contest@tcp(mysql:3306)/contest_integ?parseTime=true" + func NewStorage(opts ...rdbms.Opt) (storage.Storage, error) { - dbURI := "contest:contest@tcp(mysql:3306)/contest_integ?parseTime=true" - return rdbms.New(dbURI, opts...) + return rdbms.New(DbURI, opts...) } // InitStorage initializes the storage backend with a new transaction, if supported diff --git a/tests/integ/jobmanager/jobmanager_memory_test.go b/tests/integ/jobmanager/jobmanager_memory_test.go index 0c6d72a1..70e5e639 100644 --- a/tests/integ/jobmanager/jobmanager_memory_test.go +++ b/tests/integ/jobmanager/jobmanager_memory_test.go @@ -32,7 +32,7 @@ func TestJobManagerSuiteMemoryStorage(t *testing.T) { testSuite.storage = storagelayer storage.SetStorage(storagelayer) - targetLocker := inmemory.New(10 * time.Second, 10 * time.Second) + targetLocker := inmemory.New(10*time.Second, 10*time.Second) target.SetLocker(targetLocker) suite.Run(t, &testSuite) diff --git a/tests/integ/jobmanager/jobmanager_rdbms_test.go b/tests/integ/jobmanager/jobmanager_rdbms_test.go index b1f85f30..1dbe240a 100644 --- a/tests/integ/jobmanager/jobmanager_rdbms_test.go +++ b/tests/integ/jobmanager/jobmanager_rdbms_test.go @@ -35,7 +35,7 @@ func TestJobManagerSuiteRdbmsStorage(t *testing.T) { storage.SetStorage(storageLayer) testSuite.storage = storageLayer - targetLocker := inmemory.New(10 * time.Second, 10 * time.Second) + targetLocker := inmemory.New(10*time.Second, 10*time.Second) target.SetLocker(targetLocker) suite.Run(t, &testSuite) diff --git a/tests/integ/migration/0002_migrate_descriptor_to_extended_descriptor_test.go b/tests/integ/migration/0002_migrate_descriptor_to_extended_descriptor_test.go new file mode 100644 index 00000000..ec8ebd5e --- /dev/null +++ b/tests/integ/migration/0002_migrate_descriptor_to_extended_descriptor_test.go @@ -0,0 +1,122 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +// +build integration integration_storage + +package test + +import ( + "context" + "database/sql" + "encoding/json" + "fmt" + "testing" + "time" + + _ "github.com/go-sql-driver/mysql" + + "github.com/facebookincubator/contest/db/rdbms/migration" + "github.com/facebookincubator/contest/pkg/job" + "github.com/facebookincubator/contest/tests/integ/common" + + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" +) + +// TestDescriptorMigrationSuite implements tests for `0002_migrate_descriptor_to_extended_descriptor` migration +type TestDescriptorMigrationSuite struct { + suite.Suite + + // current transaction to be used for database operations + tx *sql.Tx +} + +// SetupTest initializes the transaction storage engine and adds to the underlying db test entries that are migrated during the test +func (suite *TestDescriptorMigrationSuite) SetupTest() { + // Setup raw connection to the db. We cannoit use storage plugin directly + // because we need to populate data into the db in a format + db, err := sql.Open("mysql", common.DbURI) + if err != nil { + panic(fmt.Sprintf("could not initialize TestDescriptorMigrationSuite: %v", err)) + } + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := db.PingContext(ctx); err != nil { + panic(fmt.Sprintf("could not reach database: %v", err)) + } + + tx, err := db.BeginTx(context.Background(), nil) + if err != nil { + panic(fmt.Sprintf("could not initiate transaction: %v", err)) + } + suite.tx = tx + + // Populate db with data that will be used to test the migration + + insertStatement := "insert into jobs (name, descriptor, teststeps, requestor, server_id, request_time) values (?, ?, ?, ?, ?, ?)" + + jobName := "TestJobName" + requestor := "TestRequestor" + serverID := "TestServerId" + requestTime := time.Now() + _, err = tx.Exec(insertStatement, jobName, jobDescriptor, testSerialized, requestor, serverID, requestTime) + if err != nil { + panic(fmt.Sprintf("could not initialize database with test data: %v", err)) + } + +} + +func (suite *TestDescriptorMigrationSuite) TearDownTest() { + if err := suite.tx.Rollback(); err != nil { + panic(fmt.Sprintf("could not rollback transaction: %v", err)) + } +} + +// TestFetchJobs tests that jobs are fetched correctly from the db +func (suite *TestDescriptorMigrationSuite) TestUpMigratesToExtendedDescriptor() { + + log := logrus.New() + fields := logrus.Fields{"test": "TestDescriptorMigrationSuite"} + + extendedDescriptorMigration := migration.NewDescriptorMigration(log.WithFields(fields)) + err := extendedDescriptorMigration.Up(suite.tx) + require.NoError(suite.T(), err) + + // Verify that the migration has populated correctly the extended descriptor, by + // fetching extended descriptor and unmarshalling it into ExtendedDescriptor structure + selectStatement := "select extended_descriptor from jobs" + rows, err := suite.tx.Query(selectStatement) + + require.NoError(suite.T(), err) + + present := rows.Next() + require.True(suite.T(), present) + require.NoError(suite.T(), rows.Err()) + + extendedDescriptorJSON := "" + err = rows.Scan(&extendedDescriptorJSON) + require.NoError(suite.T(), err) + + extendedDescriptor := job.ExtendedDescriptor{} + err = json.Unmarshal([]byte(extendedDescriptorJSON), &extendedDescriptor) + require.NoError(suite.T(), err) + + stepDescriptors := extendedDescriptor.StepsDescriptors + require.Equal(suite.T(), 1, len(stepDescriptors), fmt.Sprintf("len(%s) != 1", stepDescriptors)) + + require.Equal(suite.T(), extendedDescriptor.StepsDescriptors[0].TestName, "Literal test") + + test := extendedDescriptor.StepsDescriptors[0].Test + require.Equal(suite.T(), len(test), 1, fmt.Sprintf("len(%s) != 1", test)) + require.Equal(suite.T(), "cmd", test[0].Name) + require.Equal(suite.T(), "some label", test[0].Label) + +} +func TestTestDescriptorMigrationSuite(t *testing.T) { + testSuite := TestDescriptorMigrationSuite{} + suite.Run(t, &testSuite) +} diff --git a/tests/integ/migration/common.go b/tests/integ/migration/common.go new file mode 100644 index 00000000..923a3b3f --- /dev/null +++ b/tests/integ/migration/common.go @@ -0,0 +1,98 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +// +build integration integration_storage + +package test + +import ( + "bytes" + "text/template" +) + +var jobDescriptorTemplate = template.Must(template.New("jobDescriptor").Parse(` +{ + "JobName": "test job", + "Reporting": { + "FinalReporters": [ + { + "Name": "noop" + } + ], + "RunReporters": [ + { + "Name": "TargetSuccess", + "Parameters": { + "SuccessExpression": "=80%" + } + }, + { + "Name": "Noop" + } + ] + }, + "RunInterval": "3s", + "Runs": 3, + "Tags": [ + "test", + "csv" + ], + "TestDescriptors": [ + { + "TargetManagerAcquireParameters": { + "Targets": [ + { + "ID": "1234", + "Name": "example.org" + } + ] + }, + "TargetManagerName": "TargetList", + "TargetManagerReleaseParameters": {}, + "TestFetcherFetchParameters": { + "Steps": [ {{ . }} ], + "TestName": "Literal test" + }, + "TestFetcherName": "literal" + } + ] +} +`)) + +var testSerializedTemplate = template.Must(template.New("testSerialized").Parse(`[[ {{ . }} ]]`)) + +func descriptorMust(data string) string { + var buf bytes.Buffer + if err := jobDescriptorTemplate.Execute(&buf, data); err != nil { + panic(err) + } + return buf.String() +} + +func testSerializedMust(data string) string { + var buf bytes.Buffer + if err := testSerializedTemplate.Execute(&buf, data); err != nil { + panic(err) + } + return buf.String() +} + +var steps = ` +{ + "Name":"cmd", + "Label":"some label", + "Parameters":{ + "args":[ + "Title={{ Title .Name }}, ToUpper={{ ToUpper .Name }}" + ], + "executable":[ + "echo" + ] + } +} +` + +var jobDescriptor = descriptorMust(steps) +var testSerialized = testSerializedMust(steps) diff --git a/tools/migration/rdbms/main.go b/tools/migration/rdbms/main.go new file mode 100644 index 00000000..34430811 --- /dev/null +++ b/tools/migration/rdbms/main.go @@ -0,0 +1,111 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package main + +import ( + "bytes" + "flag" + "fmt" + "os" + "path/filepath" + + // Import migration packages so that golang migrations can register themselves + _ "github.com/facebookincubator/contest/db/rdbms/migration" + + "github.com/facebookincubator/contest/tools/migration/rdbms/migrate" + + _ "github.com/go-sql-driver/mysql" + + "github.com/pressly/goose" + "github.com/sirupsen/logrus" +) + +var ( + flags = flag.NewFlagSet("migrate", flag.ExitOnError) + flagDBDriver = flags.String("dbDriver", "mysql", "DB Driver") + flagDBURI = flags.String("dbURI", "contest:contest@tcp(localhost:3306)/contest?parseTime=true", "Database URI") + flagDir = flags.String("dir", "", "Directory containing migration scripts") + flagDebug = flags.Bool("debug", false, "Enabled debug logging") +) + +var usageHeader = `Usage: migrate [OPTIONS] COMMAND` +var commandsUsage = ` +Commands: + up Migrate the DB to the most recent version available + up-by-one Migrate the DB up by 1 + up-to VERSION Migrate the DB to a specific VERSION + down Roll back the version by 1 + down-to VERSION Roll back to a specific VERSION + redo Re-run the latest migration + reset Roll back all migrations + status Dump the migration status for the current DB + version Print the current version of the database + create NAME [sql|go] Creates new migration file with the current timestamp + fix Apply sequential ordering to migrations +` + +func usage() { + buf := new(bytes.Buffer) + flags.SetOutput(buf) + flags.PrintDefaults() + fmt.Fprintf(os.Stderr, "%s", usageHeader) + fmt.Fprintf(os.Stderr, "%s", "\n") + fmt.Fprintf(os.Stderr, "%s", buf.String()) + fmt.Fprintf(os.Stderr, "%s", commandsUsage) +} + +func main() { + + var log = logrus.New() + + if len(os.Args) < 2 { + flags.Usage() + return + } + + flags.Usage = usage + err := flags.Parse(os.Args[1:]) + if err != nil { + flags.Usage() + panic(err) + } + + log.SetOutput(os.Stdout) + log.SetLevel(logrus.InfoLevel) + if *flagDebug { + log.SetLevel(logrus.DebugLevel) + } + + if *flagDir == "" { + flags.Usage() + log.Fatalf("migration directory was not specified") + } + + for _, m := range migrate.Migrations { + logger := log.WithField("migration", filepath.Base(m.Name)) + migration := m.Factory(logger) + goose.AddNamedMigration(m.Name, migration.Up, migration.Down) + } + + command := os.Args[len(os.Args)-1] + db, err := goose.OpenDBWithDriver(*flagDBDriver, *flagDBURI) + if err != nil { + log.Fatalf("failed to open DB: %v", err) + } + if err := db.Ping(); err != nil { + log.Fatalf("db not reachable: %v", err) + } + + defer func() { + if err := db.Close(); err != nil { + log.Fatalf("failed to close DB: %v", err) + } + }() + + if err := goose.Run(command, db, *flagDir, flags.Args()...); err != nil { + log.Fatalf("could not run command %v for migration: %v", command, err) + } +} diff --git a/tools/migration/rdbms/migrate/migrate.go b/tools/migration/rdbms/migrate/migrate.go new file mode 100644 index 00000000..ec0eceab --- /dev/null +++ b/tools/migration/rdbms/migrate/migrate.go @@ -0,0 +1,37 @@ +// Copyright (c) Facebook, Inc. and its affiliates. +// +// This source code is licensed under the MIT license found in the +// LICENSE file in the root directory of this source tree. + +package migrate + +import ( + "database/sql" + "github.com/sirupsen/logrus" + "runtime" +) + +// Migrate is the interface that every migration task must implement to support +type Migrate interface { + Up(tx *sql.Tx) error + Down(tx *sql.Tx) error +} + +// Factory defines a factory type of an object implementing Migration interface +type Factory func(log *logrus.Entry) Migrate + +// Migration represents a migration task registered in the migration tool +type Migration struct { + Factory Factory + Name string +} + +// Migrations represents a sets of migrations +var Migrations []Migration + +// Register registers a new factory for a migration +func Register(Factory Factory) { + _, filename, _, _ := runtime.Caller(1) + newMigration := Migration{Factory: Factory, Name: filename} + Migrations = append(Migrations, newMigration) +}