Skip to content

Commit

Permalink
merge trunk
Browse files Browse the repository at this point in the history
  • Loading branch information
Roger Peppe committed Aug 7, 2013
2 parents 2b2bb61 + 202a90e commit 16dc211
Show file tree
Hide file tree
Showing 26 changed files with 784 additions and 193 deletions.
7 changes: 7 additions & 0 deletions cloudinit/cloudinit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ var ctests = []struct {
cfg.SetAptUpdate(true)
},
},
{
"AptProxy",
"apt_proxy: http://foo.com\n",
func(cfg *cloudinit.Config) {
cfg.SetAptProxy("http://foo.com")
},
},
{
"AptMirror",
"apt_mirror: http://foo.com\n",
Expand Down
6 changes: 6 additions & 0 deletions cloudinit/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ func (cfg *Config) SetAptUpdate(yes bool) {
cfg.set("apt_update", yes, yes)
}

// SetAptProxy sets the URL to be used as the apt
// proxy.
func (cfg *Config) SetAptProxy(url string) {
cfg.set("apt_proxy", url != "", url)
}

// SetAptMirror sets the URL to be used as the apt
// mirror site. If not set, the URL is selected based
// on cloud metadata in EC2 - <region>.archive.ubuntu.com
Expand Down
2 changes: 1 addition & 1 deletion cmd/juju/bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func (test bootstrapTest) run(c *gc.C) {
}

// Run command and check for uploads.
opc, errc := runCommand(new(BootstrapCommand), test.args...)
opc, errc := runCommand(nil, new(BootstrapCommand), test.args...)
if uploadCount > 0 {
for i := 0; i < uploadCount; i++ {
c.Check((<-opc).(dummy.OpPutFile).Env, gc.Equals, "peckham")
Expand Down
64 changes: 60 additions & 4 deletions cmd/juju/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package main

import (
"bytes"
"os"
"reflect"

Expand Down Expand Up @@ -118,7 +119,7 @@ func (*CmdSuite) TestEnvironmentInit(c *C) {
}
}

func runCommand(com cmd.Command, args ...string) (opc chan dummy.Operation, errc chan error) {
func runCommand(ctx *cmd.Context, com cmd.Command, args ...string) (opc chan dummy.Operation, errc chan error) {
errc = make(chan error, 1)
opc = make(chan dummy.Operation, 200)
dummy.Listen(opc)
Expand All @@ -132,25 +133,80 @@ func runCommand(com cmd.Command, args ...string) (opc chan dummy.Operation, errc
return
}

err = com.Run(cmd.DefaultContext())
if ctx == nil {
ctx = cmd.DefaultContext()
}
err = com.Run(ctx)
errc <- err
}()
return
}

func (*CmdSuite) TestDestroyEnvironmentCommand(c *C) {
// normal destroy
opc, errc := runCommand(new(DestroyEnvironmentCommand))
opc, errc := runCommand(nil, new(DestroyEnvironmentCommand), "--yes")
c.Check(<-errc, IsNil)
c.Check((<-opc).(dummy.OpDestroy).Env, Equals, "peckham")

// destroy with broken environment
opc, errc = runCommand(new(DestroyEnvironmentCommand), "-e", "brokenenv")
opc, errc = runCommand(nil, new(DestroyEnvironmentCommand), "--yes", "-e", "brokenenv")
c.Check(<-opc, IsNil)
c.Check(<-errc, ErrorMatches, "dummy.Destroy is broken")
c.Check(<-opc, IsNil)
}

func (*CmdSuite) TestDestroyEnvironmentCommandConfirmation(c *C) {
com := new(DestroyEnvironmentCommand)
c.Check(coretesting.InitCommand(com, nil), IsNil)
c.Check(com.assumeYes, Equals, false)

com = new(DestroyEnvironmentCommand)
c.Check(coretesting.InitCommand(com, []string{"-y"}), IsNil)
c.Check(com.assumeYes, Equals, true)

com = new(DestroyEnvironmentCommand)
c.Check(coretesting.InitCommand(com, []string{"--yes"}), IsNil)
c.Check(com.assumeYes, Equals, true)

var stdin, stdout bytes.Buffer
ctx := cmd.DefaultContext()
ctx.Stdout = &stdout
ctx.Stdin = &stdin

// Ensure confirmation is requested if "-y" is not specified.
stdin.WriteString("n")
opc, errc := runCommand(ctx, new(DestroyEnvironmentCommand))
c.Check(<-errc, ErrorMatches, "Environment destruction aborted")
c.Check(<-opc, IsNil)
c.Check(stdout.String(), Matches, "WARNING:.*peckham.*\\(type: dummy\\)(.|\n)*")

// EOF on stdin: equivalent to answering no.
stdin.Reset()
stdout.Reset()
opc, errc = runCommand(ctx, new(DestroyEnvironmentCommand))
c.Check(<-opc, IsNil)
c.Check(<-errc, ErrorMatches, "Environment destruction aborted")

// "--yes" passed: no confirmation request.
stdin.Reset()
stdout.Reset()
opc, errc = runCommand(ctx, new(DestroyEnvironmentCommand), "--yes")
c.Check(<-errc, IsNil)
c.Check((<-opc).(dummy.OpDestroy).Env, Equals, "peckham")
c.Check(stdout.String(), Equals, "")

// Any of casing of "y" and "yes" will confirm.
for _, answer := range []string{"y", "Y", "yes", "YES"} {
stdin.Reset()
stdout.Reset()
stdin.WriteString(answer)
opc, errc = runCommand(ctx, new(DestroyEnvironmentCommand))
c.Check(<-errc, IsNil)
c.Check((<-opc).(dummy.OpDestroy).Env, Equals, "peckham")
c.Check(stdout.String(), Matches, "WARNING:.*peckham.*\\(type: dummy\\)(.|\n)*")
}
}

var deployTests = []struct {
args []string
com *DeployCommand
Expand Down
32 changes: 31 additions & 1 deletion cmd/juju/destroyenvironment.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@
package main

import (
"errors"
"fmt"
"strings"

"launchpad.net/gnuflag"

"launchpad.net/juju-core/cmd"
"launchpad.net/juju-core/environs"
)

// DestroyEnvironmentCommand destroys an environment.
type DestroyEnvironmentCommand struct {
cmd.EnvCommandBase
assumeYes bool
}

func (c *DestroyEnvironmentCommand) Info() *cmd.Info {
Expand All @@ -20,10 +27,33 @@ func (c *DestroyEnvironmentCommand) Info() *cmd.Info {
}
}

func (c *DestroyEnvironmentCommand) Run(_ *cmd.Context) error {
func (c *DestroyEnvironmentCommand) SetFlags(f *gnuflag.FlagSet) {
c.EnvCommandBase.SetFlags(f)
f.BoolVar(&c.assumeYes, "y", false, "Do not ask for confirmation")
f.BoolVar(&c.assumeYes, "yes", false, "")
}

func (c *DestroyEnvironmentCommand) Run(ctx *cmd.Context) error {
environ, err := environs.NewFromName(c.EnvName)
if err != nil {
return err
}

if !c.assumeYes {
var answer string
fmt.Fprintf(ctx.Stdout, destroyEnvMsg[1:], environ.Name(), environ.Config().Type())
fmt.Fscanln(ctx.Stdin, &answer) // ignore error, treat as "n"
answer = strings.ToLower(answer)
if answer != "y" && answer != "yes" {
return errors.New("Environment destruction aborted")
}
}

return environ.Destroy(nil)
}

const destroyEnvMsg = `
WARNING: this command will destroy the %q environment (type: %s)
This includes all machines, services, data and other resources.
Continue [y/N]? `
21 changes: 13 additions & 8 deletions cmd/juju/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
type InitCommand struct {
cmd.CommandBase
WriteFile bool
Show bool
}

func (c *InitCommand) Info() *cmd.Info {
Expand All @@ -26,25 +27,29 @@ func (c *InitCommand) Info() *cmd.Info {
}

func (c *InitCommand) SetFlags(f *gnuflag.FlagSet) {
f.BoolVar(&c.WriteFile, "w", false, "write to environments.yaml file if it doesn't already exist")
f.BoolVar(&c.WriteFile, "f", false, "force overwriting environments.yaml file even if it exists (ignored if --show flag specified)")
f.BoolVar(&c.Show, "show", false, "print the generated configuration data to stdout instead of writing it to a file")
}

var errJujuEnvExists = fmt.Errorf(`A juju environment configuration already exists.
Use -f to overwrite the existing environments.yaml.
`)

// Run checks to see if there is already an environments.yaml file. In one does not exist already,
// a boilerplate version is created so that the user can edit it to get started.
func (c *InitCommand) Run(context *cmd.Context) error {
out := context.Stdout
config := environs.BoilerplateConfig()
if !c.WriteFile {
fmt.Fprintln(out, config)
if c.Show {
fmt.Fprint(out, config)
return nil
}
_, err := environs.ReadEnvirons("")
if err == nil {
fmt.Fprintf(out, "A juju environment configuration already exists.\n")
fmt.Fprintf(out, "It will not be overwritten.\n")
return nil
if err == nil && !c.WriteFile {
return errJujuEnvExists
}
if !os.IsNotExist(err) {
if err != nil && !os.IsNotExist(err) {
return err
}
filename, err := environs.WriteEnvirons("", config)
Expand Down
45 changes: 32 additions & 13 deletions cmd/juju/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ type InitSuite struct {

var _ = Suite(&InitSuite{})

// The environments.yaml is created by default if it
// does not already exist.
func (*InitSuite) TestBoilerPlateEnvironment(c *C) {
defer testing.MakeEmptyFakeHome(c).Restore()
// run without an environments.yaml
ctx := testing.Context(c)
code := cmd.Main(&InitCommand{}, ctx, []string{"-w"})
code := cmd.Main(&InitCommand{}, ctx, nil)
c.Check(code, Equals, 0)
outStr := ctx.Stdout.(*bytes.Buffer).String()
strippedOut := strings.Replace(outStr, "\n", "", -1)
Expand All @@ -33,6 +34,21 @@ func (*InitSuite) TestBoilerPlateEnvironment(c *C) {
c.Assert(strippedData, Matches, ".*## This is the Juju config file, which you can use.*")
}

// The boilerplate is sent to stdout with --show, and the environments.yaml
// is not created.
func (*InitSuite) TestBoilerPlatePrinted(c *C) {
defer testing.MakeEmptyFakeHome(c).Restore()
ctx := testing.Context(c)
code := cmd.Main(&InitCommand{}, ctx, []string{"--show"})
c.Check(code, Equals, 0)
outStr := ctx.Stdout.(*bytes.Buffer).String()
strippedOut := strings.Replace(outStr, "\n", "", -1)
c.Check(strippedOut, Matches, ".*## This is the Juju config file, which you can use.*")
environpath := testing.HomePath(".juju", "environments.yaml")
_, err := ioutil.ReadFile(environpath)
c.Assert(err, NotNil)
}

const existingEnv = `
environments:
test:
Expand All @@ -41,13 +57,15 @@ environments:
authorized-keys: i-am-a-key
`

// An existing environments.yaml will not be overwritten without
// the explicit -f option.
func (*InitSuite) TestExistingEnvironmentNotOverwritten(c *C) {
defer testing.MakeFakeHome(c, existingEnv, "existing").Restore()

ctx := testing.Context(c)
code := cmd.Main(&InitCommand{}, ctx, []string{"-w"})
c.Check(code, Equals, 0)
errOut := ctx.Stdout.(*bytes.Buffer).String()
code := cmd.Main(&InitCommand{}, ctx, nil)
c.Check(code, Equals, 1)
errOut := ctx.Stderr.(*bytes.Buffer).String()
strippedOut := strings.Replace(errOut, "\n", "", -1)
c.Check(strippedOut, Matches, ".*A juju environment configuration already exists.*")
environpath := testing.HomePath(".juju", "environments.yaml")
Expand All @@ -56,19 +74,20 @@ func (*InitSuite) TestExistingEnvironmentNotOverwritten(c *C) {
c.Assert(string(data), Equals, existingEnv)
}

// Without the write (-w) option, any existing environmens.yaml file is preserved and the boilerplate is
// written to stdout.
func (*InitSuite) TestPrintBoilerplate(c *C) {
// An existing environments.yaml will be overwritten when -f is
// given explicitly.
func (*InitSuite) TestExistingEnvironmentOverwritten(c *C) {
defer testing.MakeFakeHome(c, existingEnv, "existing").Restore()

ctx := testing.Context(c)
code := cmd.Main(&InitCommand{}, ctx, nil)
code := cmd.Main(&InitCommand{}, ctx, []string{"-f"})
c.Check(code, Equals, 0)
errOut := ctx.Stdout.(*bytes.Buffer).String()
strippedOut := strings.Replace(errOut, "\n", "", -1)
c.Check(strippedOut, Matches, ".*## This is the Juju config file, which you can use.*")
stdOut := ctx.Stdout.(*bytes.Buffer).String()
strippedOut := strings.Replace(stdOut, "\n", "", -1)
c.Check(strippedOut, Matches, ".*A boilerplate environment configuration file has been written.*")
environpath := testing.HomePath(".juju", "environments.yaml")
data, err := ioutil.ReadFile(environpath)
c.Assert(err, IsNil)
c.Assert(string(data), Equals, existingEnv)
strippedData := strings.Replace(string(data), "\n", "", -1)
c.Assert(strippedData, Matches, ".*## This is the Juju config file, which you can use.*")
}
10 changes: 6 additions & 4 deletions cmd/juju/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,13 @@ func (c *StatusCommand) Run(ctx *cmd.Context) error {
fmt.Fprintf(ctx.Stderr, "cannot retrieve instances from the environment: %v\n", err)
}
result := struct {
Machines map[string]machineStatus `json:"machines"`
Services map[string]serviceStatus `json:"services"`
Environment string `json:"environment"`
Machines map[string]machineStatus `json:"machines"`
Services map[string]serviceStatus `json:"services"`
}{
Machines: context.processMachines(),
Services: context.processServices(),
Environment: conn.Environ.Name(),
Machines: context.processMachines(),
Services: context.processServices(),
}
return c.out.Write(ctx, result)
}
Expand Down
Loading

0 comments on commit 16dc211

Please sign in to comment.