// Run connects to the environment specified on the command line and bootstraps // a juju in that environment if none already exists. If there is as yet no environments.yaml file, // the user is informed how to create one. func (c *BootstrapCommand) Run(ctx *cmd.Context) (resultErr error) { bootstrapFuncs := getBootstrapFuncs() if len(c.seriesOld) > 0 { fmt.Fprintln(ctx.Stderr, "Use of --series is deprecated. Please use --upload-series instead.") } environ, cleanup, err := environFromName(ctx, c.EnvName, &resultErr, "Bootstrap") if err != nil { return err } validator, err := environ.ConstraintsValidator() if err != nil { return err } unsupported, err := validator.Validate(c.Constraints) if len(unsupported) > 0 { logger.Warningf("unsupported constraints: %v", err) } else if err != nil { return err } defer cleanup() if err := bootstrapFuncs.EnsureNotBootstrapped(environ); err != nil { return err } // Block interruption during bootstrap. Providers may also // register for interrupt notification so they can exit early. interrupted := make(chan os.Signal, 1) defer close(interrupted) ctx.InterruptNotify(interrupted) defer ctx.StopInterruptNotify(interrupted) go func() { for _ = range interrupted { ctx.Infof("Interrupt signalled: waiting for bootstrap to exit") } }() // If --metadata-source is specified, override the default tools metadata source so // SyncTools can use it, and also upload any image metadata. if c.MetadataSource != "" { metadataDir := ctx.AbsPath(c.MetadataSource) logger.Infof("Setting default tools and image metadata sources: %s", metadataDir) tools.DefaultBaseURL = metadataDir if err := imagemetadata.UploadImageMetadata(environ.Storage(), metadataDir); err != nil { // Do not error if image metadata directory doesn't exist. if !os.IsNotExist(err) { return fmt.Errorf("uploading image metadata: %v", err) } } else { logger.Infof("custom image metadata uploaded") } } // TODO (wallyworld): 2013-09-20 bug 1227931 // We can set a custom tools data source instead of doing an // unnecessary upload. if environ.Config().Type() == provider.Local { c.UploadTools = true } if c.UploadTools { err = bootstrapFuncs.UploadTools(ctx, environ, c.Constraints.Arch, true, c.Series...) if err != nil { return err } } return bootstrapFuncs.Bootstrap(ctx, environ, environs.BootstrapParams{ Constraints: c.Constraints, Placement: c.Placement, }) }