Skip to content

Commit

Permalink
atlasexec: support new commands for declarative flow
Browse files Browse the repository at this point in the history
  • Loading branch information
giautm committed Aug 22, 2024
1 parent 288f04d commit 15d1b3a
Show file tree
Hide file tree
Showing 6 changed files with 664 additions and 0 deletions.
347 changes: 347 additions & 0 deletions atlasexec/atlas_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package atlasexec

import (
"context"
"encoding/json"
"fmt"
)

type (
Expand Down Expand Up @@ -54,6 +56,95 @@ type (
URL string
Run string
}
// SchemaPlanParams are the parameters for the `schema plan` command.
SchemaPlanParams struct {
ConfigURL string
Env string
Vars VarArgs
Context *RunContext
DevURL string

From, To []string
Name string
Repo string
// The below are mutually exclusive and can be replaced
// with the 'schema plan' sub-commands instead.
DryRun bool // If false, --auto-approve is set.
Push, Save bool
}
// SchemaPlanPushParams are the parameters for the `schema plan push` command.
SchemaPlanPushParams struct {
ConfigURL string
Env string
Vars VarArgs
Context *RunContext
DevURL string

From, To []string
File string
Repo string
Pending bool
}
// SchemaPlanPullParams are the parameters for the `schema plan pull` command.
SchemaPlanPullParams struct {
ConfigURL string
Env string
Vars VarArgs
URL string
}
// SchemaPlanLintParams are the parameters for the `schema plan lint` command.
SchemaPlanLintParams struct {
ConfigURL string
Env string
Vars VarArgs
Context *RunContext
DevURL string

From, To []string
Name string
Repo string
File string
}
// SchemaPlanValidateParams are the parameters for the `schema plan validate` command.
SchemaPlanValidateParams struct {
ConfigURL string
Env string
Vars VarArgs
Context *RunContext
DevURL string

From, To []string
Name string
Repo string
File string
}
// SchemaPlanApproveParams are the parameters for the `schema plan approve` command.
SchemaPlanApproveParams struct {
ConfigURL string
Env string
Vars VarArgs

URL string
}
// SchemaPlan is the result of a 'schema plan' command.
SchemaPlan struct {
Env Env `json:"Env,omitempty"` // Environment info.
Repo string `json:"Repo,omitempty"` // Repository name.
Lint *SummaryReport `json:"Lint,omitempty"` // Lint report.
File *SchemaPlanFile `json:"File,omitempty"` // Plan file.
Error string `json:"Error,omitempty"` // Any error occurred during planning.
}
// SchemaPlanFile is a JSON representation of a schema plan file.
SchemaPlanFile struct {
Name string `json:"Name,omitempty"` // Name of the plan.
FromHash string `json:"FromHash,omitempty"` // Hash of the 'from' realm.
ToHash string `json:"ToHash,omitempty"` // Hash of the 'to' realm.
Migration string `json:"Migration,omitempty"` // Migration SQL.
// registry only fields.
URL string `json:"URL,omitempty"` // URL of the plan in Atlas format.
Link string `json:"Link,omitempty"` // Link to the plan in the registry.
Status string `json:"Status,omitempty"` // Status of the plan in the registry.
}
)

// SchemaApply runs the 'schema apply' command.
Expand Down Expand Up @@ -156,6 +247,262 @@ func (c *Client) SchemaTest(ctx context.Context, params *SchemaTestParams) (stri
return stringVal(c.runCommand(ctx, args))
}

// SchemaPlan runs the `schema plan` command.
func (c *Client) SchemaPlan(ctx context.Context, params *SchemaPlanParams) (*SchemaPlan, error) {
args := []string{"schema", "plan", "--format", "{{ json . }}"}
// Global flags
if params.ConfigURL != "" {
args = append(args, "--config", params.ConfigURL)
}
if params.Env != "" {
args = append(args, "--env", params.Env)
}
if params.Vars != nil {
args = append(args, params.Vars.AsArgs()...)
}
// Hidden flags
if params.Context != nil {
buf, err := json.Marshal(params.Context)
if err != nil {
return nil, err
}
args = append(args, "--context", string(buf))
}
// Flags of the 'schema plan' sub-commands
if params.DevURL != "" {
args = append(args, "--dev-url", params.DevURL)
}
if len(params.From) > 0 {
args = append(args, "--from", listString(params.From))
}
if len(params.To) > 0 {
args = append(args, "--to", listString(params.To))
}
if params.Name != "" {
args = append(args, "--name", params.Name)
}
if params.Repo != "" {
args = append(args, "--repo", params.Repo)
}
switch {
case params.Save:
if params.Push || params.DryRun {
return nil, &InvalidParamsError{"schema plan", "can not use --save with --push or --dry-run"}
}
args = append(args, "--save", "--auto-approve")
case params.Push:
if params.Save || params.DryRun {
return nil, &InvalidParamsError{"schema plan", "can not use --push with --save or --dry-run"}
}
args = append(args, "--push", "--auto-approve")
case params.DryRun:
if params.Save || params.Push {
return nil, &InvalidParamsError{"schema plan", "can not use --dry-run with --save or --push"}
}
args = append(args, "--dry-run")
default:
args = append(args, "--auto-approve")
}
// NOTE: This command only support one result.
return firstResult(jsonDecode[SchemaPlan](c.runCommand(ctx, args)))
}

// SchemaPlanPush runs the `schema plan push` command.
func (c *Client) SchemaPlanPush(ctx context.Context, params *SchemaPlanPushParams) (string, error) {
args := []string{"schema", "plan", "push", "--format", "{{ json . }}"}
// Global flags
if params.ConfigURL != "" {
args = append(args, "--config", params.ConfigURL)
}
if params.Env != "" {
args = append(args, "--env", params.Env)
}
if params.Vars != nil {
args = append(args, params.Vars.AsArgs()...)
}
// Hidden flags
if params.Context != nil {
buf, err := json.Marshal(params.Context)
if err != nil {
return "", err
}
args = append(args, "--context", string(buf))
}
// Flags of the 'schema plan push' sub-commands
if params.DevURL != "" {
args = append(args, "--dev-url", params.DevURL)
}
if len(params.From) > 0 {
args = append(args, "--from", listString(params.From))
}
if len(params.To) > 0 {
args = append(args, "--to", listString(params.To))
}
if params.File != "" {
args = append(args, "--file", params.File)
} else {
return "", &InvalidParamsError{"schema plan push", "missing required flag --file"}
}
if params.Repo != "" {
args = append(args, "--repo", params.Repo)
}
if params.Pending {
args = append(args, "--pending")
} else {
args = append(args, "--auto-approve")
}
return stringVal(c.runCommand(ctx, args))
}

// SchemaPlanPush runs the `schema plan pull` command.
func (c *Client) SchemaPlanPull(ctx context.Context, params *SchemaPlanPullParams) (string, error) {
args := []string{"schema", "plan", "pull"}
// Global flags
if params.ConfigURL != "" {
args = append(args, "--config", params.ConfigURL)
}
if params.Env != "" {
args = append(args, "--env", params.Env)
}
if params.Vars != nil {
args = append(args, params.Vars.AsArgs()...)
}
// Flags of the 'schema plan pull' sub-commands
if params.URL != "" {
args = append(args, "--url", params.URL)
} else {
return "", &InvalidParamsError{"schema plan pull", "missing required flag --url"}
}
return stringVal(c.runCommand(ctx, args))
}

// SchemaPlanLint runs the `schema plan lint` command.
func (c *Client) SchemaPlanLint(ctx context.Context, params *SchemaPlanLintParams) (*SchemaPlan, error) {
args := []string{"schema", "plan", "lint", "--format", "{{ json . }}"}
// Global flags
if params.ConfigURL != "" {
args = append(args, "--config", params.ConfigURL)
}
if params.Env != "" {
args = append(args, "--env", params.Env)
}
if params.Vars != nil {
args = append(args, params.Vars.AsArgs()...)
}
// Hidden flags
if params.Context != nil {
buf, err := json.Marshal(params.Context)
if err != nil {
return nil, err
}
args = append(args, "--context", string(buf))
}
// Flags of the 'schema plan lint' sub-commands
if params.DevURL != "" {
args = append(args, "--dev-url", params.DevURL)
}
if len(params.From) > 0 {
args = append(args, "--from", listString(params.From))
}
if len(params.To) > 0 {
args = append(args, "--to", listString(params.To))
}
if params.File != "" {
args = append(args, "--file", params.File)
} else {
return nil, &InvalidParamsError{"schema plan lint", "missing required flag --file"}
}
if params.Name != "" {
args = append(args, "--name", params.Name)
}
if params.Repo != "" {
args = append(args, "--repo", params.Repo)
}
args = append(args, "--auto-approve")
// NOTE: This command only support one result.
return firstResult(jsonDecode[SchemaPlan](c.runCommand(ctx, args)))
}

// SchemaPlanValidate runs the `schema plan validate` command.
func (c *Client) SchemaPlanValidate(ctx context.Context, params *SchemaPlanValidateParams) error {
args := []string{"schema", "plan", "validate"}
// Global flags
if params.ConfigURL != "" {
args = append(args, "--config", params.ConfigURL)
}
if params.Env != "" {
args = append(args, "--env", params.Env)
}
if params.Vars != nil {
args = append(args, params.Vars.AsArgs()...)
}
// Hidden flags
if params.Context != nil {
buf, err := json.Marshal(params.Context)
if err != nil {
return err
}
args = append(args, "--context", string(buf))
}
// Flags of the 'schema plan validate' sub-commands
if params.DevURL != "" {
args = append(args, "--dev-url", params.DevURL)
}
if len(params.From) > 0 {
args = append(args, "--from", listString(params.From))
}
if len(params.To) > 0 {
args = append(args, "--to", listString(params.To))
}
if params.File != "" {
args = append(args, "--file", params.File)
} else {
return &InvalidParamsError{"schema plan validate", "missing required flag --file"}
}
if params.Name != "" {
args = append(args, "--name", params.Name)
}
if params.Repo != "" {
args = append(args, "--repo", params.Repo)
}
args = append(args, "--auto-approve")
_, err := stringVal(c.runCommand(ctx, args))
return err
}

// SchemaPlanApprove runs the `schema plan approve` command.
func (c *Client) SchemaPlanApprove(ctx context.Context, params *SchemaPlanApproveParams) (*SchemaPlan, error) {
args := []string{"schema", "plan", "approve", "--format", "{{ json . }}"}
// Global flags
if params.ConfigURL != "" {
args = append(args, "--config", params.ConfigURL)
}
if params.Env != "" {
args = append(args, "--env", params.Env)
}
if params.Vars != nil {
args = append(args, params.Vars.AsArgs()...)
}
// Flags of the 'schema plan approve' sub-commands
if params.URL != "" {
args = append(args, "--url", params.URL)
} else {
return nil, &InvalidParamsError{"schema plan approve", "missing required flag --url"}
}
// NOTE: This command only support one result.
return firstResult(jsonDecode[SchemaPlan](c.runCommand(ctx, args)))
}

// InvalidParamsError is an error type for invalid parameters.
type InvalidParamsError struct {
cmd string
msg string
}

// Error returns the error message.
func (e *InvalidParamsError) Error() string {
return fmt.Sprintf("atlasexec: command %q has invalid parameters: %v", e.cmd, e.msg)
}
func newSchemaApplyError(r []*SchemaApply) error {
return &SchemaApplyError{Result: r}
}
Expand Down
Loading

0 comments on commit 15d1b3a

Please sign in to comment.