command/push: start it
This commit is contained in:
parent
2dce764d75
commit
cdde9149ff
|
@ -0,0 +1,104 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PushCommand struct {
|
||||||
|
Meta
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PushCommand) Run(args []string) int {
|
||||||
|
var atlasToken string
|
||||||
|
var moduleLock bool
|
||||||
|
args = c.Meta.process(args, false)
|
||||||
|
cmdFlags := flag.NewFlagSet("push", flag.ContinueOnError)
|
||||||
|
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
|
||||||
|
cmdFlags.StringVar(&atlasToken, "token", "", "")
|
||||||
|
cmdFlags.BoolVar(&moduleLock, "module-lock", true, "")
|
||||||
|
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
|
if err := cmdFlags.Parse(args); err != nil {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// The pwd is used for the configuration path if one is not given
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the path to the configuration depending on the args.
|
||||||
|
var configPath string
|
||||||
|
args = cmdFlags.Args()
|
||||||
|
if len(args) > 1 {
|
||||||
|
c.Ui.Error("The apply command expects at most one argument.")
|
||||||
|
cmdFlags.Usage()
|
||||||
|
return 1
|
||||||
|
} else if len(args) == 1 {
|
||||||
|
configPath = args[0]
|
||||||
|
} else {
|
||||||
|
configPath = pwd
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the state is remote, we can't push without a remote state
|
||||||
|
s, err := c.State()
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Failed to read state: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if !s.State().IsRemote() {
|
||||||
|
c.Ui.Error(
|
||||||
|
"Remote state is not enabled. For Atlas to run Terraform\n" +
|
||||||
|
"for you, remote state must be used and configured. Remote\n" +
|
||||||
|
"state via any backend is accepted, not just Atlas. To\n" +
|
||||||
|
"configure remote state, use the `terraform remote config`\n" +
|
||||||
|
"command.")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the context based on the arguments given
|
||||||
|
_, planned, err := c.Context(contextOpts{
|
||||||
|
Path: configPath,
|
||||||
|
StatePath: c.Meta.statePath,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
c.Ui.Error(err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if planned {
|
||||||
|
c.Ui.Error(
|
||||||
|
"A plan file cannot be given as the path to the configuration.\n" +
|
||||||
|
"A path to a module (directory with configuration) must be given.")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PushCommand) Help() string {
|
||||||
|
helpText := `
|
||||||
|
Usage: terraform push [options] [DIR]
|
||||||
|
|
||||||
|
Upload this Terraform module to an Atlas server for remote
|
||||||
|
infrastructure management.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
|
||||||
|
-module-lock=true If true (default), then the modules are locked at
|
||||||
|
their current checkout and uploaded completely. This
|
||||||
|
prevents Atlas from running "terraform get".
|
||||||
|
|
||||||
|
-token=<token> Access token to use to upload. If blank, the ATLAS_TOKEN
|
||||||
|
environmental variable will be used.
|
||||||
|
|
||||||
|
`
|
||||||
|
return strings.TrimSpace(helpText)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *PushCommand) Synopsis() string {
|
||||||
|
return "Upload this Terraform module to Atlas to run"
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPush_noState(t *testing.T) {
|
||||||
|
tmp, cwd := testCwd(t)
|
||||||
|
defer testFixCwd(t, tmp, cwd)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &PushCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
ContextOpts: testCtxConfig(testProvider()),
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{}
|
||||||
|
if code := c.Run(args); code != 1 {
|
||||||
|
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPush_noRemoteState(t *testing.T) {
|
||||||
|
state := &terraform.State{
|
||||||
|
Modules: []*terraform.ModuleState{
|
||||||
|
&terraform.ModuleState{
|
||||||
|
Path: []string{"root"},
|
||||||
|
Resources: map[string]*terraform.ResourceState{
|
||||||
|
"test_instance.foo": &terraform.ResourceState{
|
||||||
|
Type: "test_instance",
|
||||||
|
Primary: &terraform.InstanceState{
|
||||||
|
ID: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
statePath := testStateFile(t, state)
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &PushCommand{
|
||||||
|
Meta: Meta{
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-state", statePath,
|
||||||
|
}
|
||||||
|
if code := c.Run(args); code != 1 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,6 +80,12 @@ func init() {
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"push": func() (cli.Command, error) {
|
||||||
|
return &command.PushCommand{
|
||||||
|
Meta: meta,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
|
||||||
"refresh": func() (cli.Command, error) {
|
"refresh": func() (cli.Command, error) {
|
||||||
return &command.RefreshCommand{
|
return &command.RefreshCommand{
|
||||||
Meta: meta,
|
Meta: meta,
|
||||||
|
|
Loading…
Reference in New Issue