Skip to content

Commit

Permalink
atlasexec: update public APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
giautm committed Aug 15, 2023
1 parent eb4a224 commit c125052
Show file tree
Hide file tree
Showing 6 changed files with 550 additions and 107 deletions.
68 changes: 42 additions & 26 deletions atlasexec/atlas.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ type (
execPath string
workingDir string
}
// ApplyParams are the parameters for the `migrate apply` command.
ApplyParams struct {
// MigrateApplyParams are the parameters for the `migrate apply` command.
MigrateApplyParams struct {
Env string
ConfigURL string
DirURL string
Expand All @@ -31,17 +31,17 @@ type (
Amount uint64
Vars Vars
}
// StatusParams are the parameters for the `migrate status` command.
StatusParams struct {
// MigrateStatusParams are the parameters for the `migrate status` command.
MigrateStatusParams struct {
Env string
ConfigURL string
DirURL string
URL string
RevisionsSchema string
Vars Vars
}
// LintParams are the parameters for the `migrate lint` command.
LintParams struct {
// MigrateLintParams are the parameters for the `migrate lint` command.
MigrateLintParams struct {
Env string
ConfigURL string
DevURL string
Expand Down Expand Up @@ -75,19 +75,17 @@ type (
Vars map[string]string
)

// NewClient returns a new Atlas client.
// The client will try to find the Atlas CLI in the current directory,
// and in the PATH.
func NewClient(dir, name string) (*Client, error) {
path, err := execPath(dir, name)
if err != nil {
return nil, err
}
return NewClientWithDir("", path)
}
type (
// @deprecated use MigrateApplyParams instead.
ApplyParams = MigrateApplyParams
// @deprecated use MigrateStatusParams instead.
StatusParams = MigrateStatusParams
// @deprecated use MigrateLintParams instead.
LintParams = MigrateLintParams
)

// NewClientWD returns a new Atlas client with the given atlas-cli path.
func NewClientWithDir(workingDir, execPath string) (*Client, error) {
func NewClient(workingDir, execPath string) (*Client, error) {
if execPath == "" {
return nil, fmt.Errorf("execPath cannot be empty")
}
Expand All @@ -104,7 +102,25 @@ func NewClientWithDir(workingDir, execPath string) (*Client, error) {
}

// Apply runs the 'migrate apply' command.
func (c *Client) Apply(ctx context.Context, data *ApplyParams) (*ApplyReport, error) {
// @deprecated use MigrateApply instead.
func (c *Client) Apply(ctx context.Context, data *MigrateApplyParams) (*MigrateApply, error) {
return c.MigrateApply(ctx, data)
}

// Lint runs the 'migrate lint' command.
// @deprecated use MigrateLint instead.
func (c *Client) Lint(ctx context.Context, data *MigrateLintParams) (*SummaryReport, error) {
return c.MigrateLint(ctx, data)
}

// Status runs the 'migrate status' command.
// @deprecated use MigrateStatus instead.
func (c *Client) Status(ctx context.Context, data *MigrateStatusParams) (*MigrateStatus, error) {
return c.MigrateStatus(ctx, data)
}

// MigrateApply runs the 'migrate apply' command.
func (c *Client) MigrateApply(ctx context.Context, data *MigrateApplyParams) (*MigrateApply, error) {
args := []string{"migrate", "apply", "--format", "{{ json . }}"}
if data.Env != "" {
args = append(args, "--env", data.Env)
Expand All @@ -131,7 +147,7 @@ func (c *Client) Apply(ctx context.Context, data *ApplyParams) (*ApplyReport, er
args = append(args, strconv.FormatUint(data.Amount, 10))
}
args = append(args, data.Vars.AsArgs()...)
return jsonDecode[ApplyReport](c.runCommand(ctx, args))
return jsonDecode[MigrateApply](c.runCommand(ctx, args))
}

// SchemaApply runs the 'schema apply' command.
Expand Down Expand Up @@ -195,8 +211,8 @@ func (c *Client) SchemaInspect(ctx context.Context, data *SchemaInspectParams) (
return stringVal(c.runCommand(ctx, args))
}

// Lint runs the 'migrate lint' command.
func (c *Client) Lint(ctx context.Context, data *LintParams) (*SummaryReport, error) {
// MigrateLint runs the 'migrate lint' command.
func (c *Client) MigrateLint(ctx context.Context, data *MigrateLintParams) (*SummaryReport, error) {
args := []string{"migrate", "lint", "--format", "{{ json . }}"}
if data.Env != "" {
args = append(args, "--env", data.Env)
Expand All @@ -217,8 +233,8 @@ func (c *Client) Lint(ctx context.Context, data *LintParams) (*SummaryReport, er
return jsonDecode[SummaryReport](c.runCommand(ctx, args))
}

// Status runs the 'migrate status' command.
func (c *Client) Status(ctx context.Context, data *StatusParams) (*StatusReport, error) {
// MigrateStatus runs the 'migrate status' command.
func (c *Client) MigrateStatus(ctx context.Context, data *MigrateStatusParams) (*MigrateStatus, error) {
args := []string{"migrate", "status", "--format", "{{ json . }}"}
if data.Env != "" {
args = append(args, "--env", data.Env)
Expand All @@ -236,7 +252,7 @@ func (c *Client) Status(ctx context.Context, data *StatusParams) (*StatusReport,
args = append(args, "--revisions-schema", data.RevisionsSchema)
}
args = append(args, data.Vars.AsArgs()...)
return jsonDecode[StatusReport](c.runCommand(ctx, args))
return jsonDecode[MigrateStatus](c.runCommand(ctx, args))
}

// runCommand runs the given command and unmarshals the output into the given
Expand Down Expand Up @@ -282,7 +298,7 @@ func (c *Client) runCommand(ctx context.Context, args []string) (io.Reader, erro
}

// LatestVersion returns the latest version of the migrations directory.
func (r StatusReport) LatestVersion() string {
func (r MigrateStatus) LatestVersion() string {
if l := len(r.Available); l > 0 {
return r.Available[l-1].Version
}
Expand All @@ -297,7 +313,7 @@ func (r StatusReport) LatestVersion() string {
//
// If the version is not found, it returns 0 and the second
// return value is false.
func (r StatusReport) Amount(version string) (amount uint64, ok bool) {
func (r MigrateStatus) Amount(version string) (amount uint64, ok bool) {
if version == "" {
amount := uint64(len(r.Pending))
return amount, amount == 0
Expand Down
69 changes: 26 additions & 43 deletions atlasexec/atlas_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package atlasexec
import (
"time"

"ariga.io/atlas/sql/sqlcheck"
"ariga.io/atlas/cmd/atlas/x"
"ariga.io/atlas/sql/sqlclient"
)

Expand All @@ -26,8 +26,8 @@ type (
Error string // Error returned by the database.
}
}
// ApplyReport contains a summary of a migration applying attempt on a database.
ApplyReport struct {
// MigrateApply contains a summary of a migration applying attempt on a database.
MigrateApply struct {
Pending []File `json:"Pending,omitempty"` // Pending migration files
Applied []*AppliedFile `json:"Applied,omitempty"` // Applied files
Current string `json:"Current,omitempty"` // Current migration version
Expand All @@ -38,21 +38,8 @@ type (
// but by Atlas, e.g. when committing or rolling back a transaction.
Error string `json:"Error,omitempty"`
}
// A Revision denotes an applied migration in a deployment. Used to track migration executions state of a database.
Revision struct {
Version string `json:"Version"` // Version of the migration.
Description string `json:"Description"` // Description of this migration.
Type string `json:"Type"` // Type of the migration.
Applied int `json:"Applied"` // Applied amount of statements in the migration.
Total int `json:"Total"` // Total amount of statements in the migration.
ExecutedAt time.Time `json:"ExecutedAt"` // ExecutedAt is the starting point of execution.
ExecutionTime time.Duration `json:"ExecutionTime"` // ExecutionTime of the migration.
Error string `json:"Error,omitempty"` // Error of the migration, if any occurred.
ErrorStmt string `json:"ErrorStmt,omitempty"` // ErrorStmt is the statement that raised Error.
OperatorVersion string `json:"OperatorVersion"` // OperatorVersion that executed this migration.
}
// StatusReport contains a summary of the migration status of a database.
StatusReport struct {
// MigrateStatus contains a summary of the migration status of a database.
MigrateStatus struct {
Available []File `json:"Available,omitempty"` // Available migration files
Pending []File `json:"Pending,omitempty"` // Pending migration files
Applied []*Revision `json:"Applied,omitempty"` // Applied migration files
Expand All @@ -64,33 +51,9 @@ type (
Error string `json:"Error,omitempty"` // Last Error that occurred
SQL string `json:"SQL,omitempty"` // SQL that caused the last Error
}
// FileReport contains a summary of the analysis of a single file.
FileReport struct {
Name string `json:"Name,omitempty"` // Name of the file.
Text string `json:"Text,omitempty"` // Contents of the file.
Reports []sqlcheck.Report `json:"Reports,omitempty"` // List of reports.
Error string `json:"Error,omitempty"` // File specific error.
}
// A SummaryReport contains a summary of the analysis of all files.
// It is used as an input to templates to report the CI results.
SummaryReport struct {
// Steps of the analysis. Added in verbose mode.
Steps []struct {
Name string `json:"Name,omitempty"` // Step name.
Text string `json:"Text,omitempty"` // Step description.
Error string `json:"Error,omitempty"` // Error that cause the execution to halt.
Result any `json:"Result,omitempty"` // Result of the step. For example, a diagnostic.
}

// Schema versions found by the runner.
Schema struct {
Current string `json:"Current,omitempty"` // Current schema.
Desired string `json:"Desired,omitempty"` // Desired schema.
}

// Files reports. Non-empty in case there are findings.
Files []*FileReport `json:"Files,omitempty"`
}
SummaryReport = x.SummaryReport
// StmtError groups a statement with its execution error.
StmtError struct {
Stmt string `json:"Stmt,omitempty"` // SQL statement that failed.
Expand All @@ -116,4 +79,24 @@ type (
// e.g., when committing or rolling back a transaction.
Error string `json:"Error,omitempty"`
}
// A Revision denotes an applied migration in a deployment. Used to track migration executions state of a database.
Revision struct {
Version string `json:"Version"` // Version of the migration.
Description string `json:"Description"` // Description of this migration.
Type string `json:"Type"` // Type of the migration.
Applied int `json:"Applied"` // Applied amount of statements in the migration.
Total int `json:"Total"` // Total amount of statements in the migration.
ExecutedAt time.Time `json:"ExecutedAt"` // ExecutedAt is the starting point of execution.
ExecutionTime time.Duration `json:"ExecutionTime"` // ExecutionTime of the migration.
Error string `json:"Error,omitempty"` // Error of the migration, if any occurred.
ErrorStmt string `json:"ErrorStmt,omitempty"` // ErrorStmt is the statement that raised Error.
OperatorVersion string `json:"OperatorVersion"` // OperatorVersion that executed this migration.
}
)

type (
// @deprecated use MigrateStatus instead
StatusReport = MigrateStatus
// @deprecated use MigrateApply instead
ApplyReport = MigrateApply
)
14 changes: 7 additions & 7 deletions atlasexec/atlas_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@ func Test_MigrateApply(t *testing.T) {
t.Cleanup(func() {
require.NoError(t, ec.Close())
})
c, err := atlasexec.NewClientWithDir(ec.Path(), "atlas")
c, err := atlasexec.NewClient(ec.Path(), "atlas")
require.NoError(t, err)
got, err := c.Apply(context.Background(), &atlasexec.ApplyParams{
got, err := c.MigrateApply(context.Background(), &atlasexec.MigrateApplyParams{
Env: "test",
})
require.EqualError(t, err, `atlasexec: required flag "url" not set`)
require.Nil(t, got)
// Set the env var and try again
os.Setenv("DB_URL", "sqlite://file?_fk=1&cache=shared&mode=memory")
got, err = c.Apply(context.Background(), &atlasexec.ApplyParams{
got, err = c.MigrateApply(context.Background(), &atlasexec.MigrateApplyParams{
Env: "test",
})
require.NoError(t, err)
Expand All @@ -57,7 +57,7 @@ func Test_MigrateApply(t *testing.T) {
func Test_MigrateStatus(t *testing.T) {
type args struct {
ctx context.Context
data *atlasexec.StatusParams
data *atlasexec.MigrateStatusParams
}
tests := []struct {
name string
Expand All @@ -69,7 +69,7 @@ func Test_MigrateStatus(t *testing.T) {
{
args: args{
ctx: context.Background(),
data: &atlasexec.StatusParams{
data: &atlasexec.MigrateStatusParams{
DirURL: "file://testdata/migrations",
},
},
Expand All @@ -86,7 +86,7 @@ func Test_MigrateStatus(t *testing.T) {
dbpath := sqlitedb(t)
path := fmt.Sprintf("sqlite://%s", dbpath)
tt.args.data.URL = path
got, err := c.Status(tt.args.ctx, tt.args.data)
got, err := c.MigrateStatus(tt.args.ctx, tt.args.data)
if (err != nil) != tt.wantErr {
t.Errorf("migrateStatus() error = %v, wantErr %v", err, tt.wantErr)
return
Expand All @@ -107,7 +107,7 @@ func Test_SchemaApply(t *testing.T) {
require.NoError(t, err)
defer os.Remove(f.Name())
u := fmt.Sprintf("sqlite://%s?_fk=1", f.Name())
c, err := atlasexec.NewClientWithDir(ce.Path(), "atlas")
c, err := atlasexec.NewClient(ce.Path(), "atlas")
require.NoError(t, err)

s1 := `
Expand Down
21 changes: 21 additions & 0 deletions atlasexec/working_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,27 @@ type (
Option func(ce *WorkingDir) error
)

// WithAtlasHCLString creates the atlas.hcl file with the given string.
func WithAtlasHCLString(s string) Option {
return WithAtlasHCL(func(w io.Writer) error {
_, err := w.Write([]byte(s))
return err
})
}

// WithAtlasHCLPath creates the atlas.hcl file by copying the file at the given path.
func WithAtlasHCLPath(path string) Option {
return WithAtlasHCL(func(w io.Writer) error {
f, err := os.Open(path)
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(w, f)
return err
})
}

// WithAtlasHCL accept a function to create the atlas.hcl file.
func WithAtlasHCL(fn func(w io.Writer) error) Option {
return func(ce *WorkingDir) error {
Expand Down
48 changes: 43 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,59 @@ module ariga.io/atlas-go-sdk
go 1.20

require (
ariga.io/atlas v0.12.1
ariga.io/atlas v0.12.2-0.20230806193313-117e03f96e45
ariga.io/atlas/cmd/atlas v0.13.1
github.com/mattn/go-sqlite3 v1.14.17
github.com/stretchr/testify v1.8.4
)

require (
github.com/agext/levenshtein v1.2.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220816024939-bc8df83d7b9d // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/auxten/postgresql-parser v1.0.1 // indirect
github.com/benbjohnson/clock v1.1.0 // indirect
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 // indirect
github.com/cockroachdb/apd v1.1.1-0.20181017181144-bced77f817b4 // indirect
github.com/cockroachdb/errors v1.8.2 // indirect
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f // indirect
github.com/cockroachdb/redact v1.0.8 // indirect
github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2 // indirect
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/getsentry/raven-go v0.2.0 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/hashicorp/hcl/v2 v2.10.0 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/hashicorp/hcl/v2 v2.13.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lib/pq v1.10.7 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/pingcap/errors v0.11.5-0.20210425183316-da1aaba5fb63 // indirect
github.com/pingcap/log v0.0.0-20210625125904-98ed8e2eb1c7 // indirect
github.com/pingcap/tidb/parser v0.0.0-20220817134052-9709249e523a // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rogpeppe/go-internal v1.6.1 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect
golang.org/x/text v0.8.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto v0.0.0-20220802133213-ce4fa296bf78 // indirect
google.golang.org/grpc v1.48.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading

0 comments on commit c125052

Please sign in to comment.