func (c *DestroyEnvironmentCommand) Run(ctx *cmd.Context) (result error) { store, err := configstore.Default() if err != nil { return fmt.Errorf("cannot open environment info storage: %v", err) } environ, err := environs.NewFromName(c.envName, store) if err != nil { if environs.IsEmptyConfig(err) { // Delete the .jenv file and call it done. ctx.Infof("removing empty environment file") return environs.DestroyInfo(c.envName, store) } return err } if !c.assumeYes { fmt.Fprintf(ctx.Stdout, destroyEnvMsg, environ.Name(), environ.Config().Type()) scanner := bufio.NewScanner(ctx.Stdin) scanner.Scan() err := scanner.Err() if err != nil && err != io.EOF { return fmt.Errorf("Environment destruction aborted: %s", err) } answer := strings.ToLower(scanner.Text()) if answer != "y" && answer != "yes" { return errors.New("environment destruction aborted") } } // If --force is supplied, then don't attempt to use the API. // This is necessary to destroy broken environments, where the // API server is inaccessible or faulty. if !c.force { defer func() { if result == nil { return } logger.Errorf(`failed to destroy environment %q If the environment is unusable, then you may run juju destroy-environment --force to forcefully destroy the environment. Upon doing so, review your environment provider console for any resources that need to be cleaned up. `, c.envName) }() apiclient, err := juju.NewAPIClientFromName(c.envName) if err != nil { return fmt.Errorf("cannot connect to API: %v", err) } defer apiclient.Close() err = apiclient.DestroyEnvironment() if err != nil && !params.IsCodeNotImplemented(err) { return fmt.Errorf("destroying environment: %v", err) } } return environs.Destroy(environ, store) }
func (c *RemoveServiceCommand) Run(_ *cmd.Context) error { client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() return client.ServiceDestroy(c.ServiceName) }
func (c *ResolvedCommand) Run(_ *cmd.Context) error { client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() return client.Resolved(c.UnitName, c.Retry) }
// TODO(jam): 2013-08-27 This should move somewhere in api.* func (s *NewAPIClientSuite) TestMultipleCloseOk(c *gc.C) { coretesting.MakeSampleJujuHome(c) bootstrapEnv(c, "", defaultConfigStore(c)) client, _ := juju.NewAPIClientFromName("") c.Assert(client.Close(), gc.IsNil) c.Assert(client.Close(), gc.IsNil) c.Assert(client.Close(), gc.IsNil) }
func (c *AddRelationCommand) Run(_ *cmd.Context) error { client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() _, err = client.AddRelation(c.Endpoints...) return err }
func (*NewAPIClientSuite) TestNameNotDefault(c *gc.C) { coretesting.WriteEnvironments(c, coretesting.MultipleEnvConfig) envName := coretesting.SampleCertName + "-2" bootstrapEnv(c, envName, defaultConfigStore(c)) apiclient, err := juju.NewAPIClientFromName(envName) c.Assert(err, gc.IsNil) defer apiclient.Close() assertEnvironmentName(c, apiclient, envName) }
// Run connects to the environment specified on the command line // and calls AddServiceUnits for the given service. func (c *AddUnitCommand) Run(_ *cmd.Context) error { apiclient, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer apiclient.Close() _, err = apiclient.AddServiceUnits(c.ServiceName, c.NumUnits, c.ToMachineSpec) return err }
func (c *SetConstraintsCommand) Run(_ *cmd.Context) (err error) { apiclient, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer apiclient.Close() if c.ServiceName == "" { return apiclient.SetEnvironmentConstraints(c.Constraints) } return apiclient.SetServiceConstraints(c.ServiceName, c.Constraints) }
func (c *RemoveMachineCommand) Run(_ *cmd.Context) error { apiclient, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer apiclient.Close() if c.Force { return apiclient.ForceDestroyMachines(c.MachineIds...) } return apiclient.DestroyMachines(c.MachineIds...) }
func (c *GetConstraintsCommand) Run(ctx *cmd.Context) error { apiclient, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer apiclient.Close() var cons constraints.Value if c.ServiceName == "" { cons, err = apiclient.GetEnvironmentConstraints() } else { cons, err = apiclient.GetServiceConstraints(c.ServiceName) } if err != nil { return err } return c.out.Write(ctx, cons) }
// Run fetches the configuration of the service and formats // the result as a YAML string. func (c *GetCommand) Run(ctx *cmd.Context) error { client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() results, err := client.ServiceGet(c.ServiceName) if err != nil { return err } resultsMap := map[string]interface{}{ "service": results.Service, "charm": results.Charm, "settings": results.Config, } return c.out.Write(ctx, resultsMap) }
func (s *NewAPIClientSuite) TestNameDefault(c *gc.C) { coretesting.WriteEnvironments(c, coretesting.MultipleEnvConfig) // The connection logic should not delay the config connection // at all when there is no environment info available. // Make sure of that by providing a suitably long delay // and checking that the connection happens within that // time. s.PatchValue(juju.ProviderConnectDelay, coretesting.LongWait) bootstrapEnv(c, coretesting.SampleEnvName, defaultConfigStore(c)) startTime := time.Now() apiclient, err := juju.NewAPIClientFromName("") c.Assert(err, gc.IsNil) defer apiclient.Close() c.Assert(time.Since(startTime), jc.LessThan, coretesting.LongWait) // We should get the default sample environment if we ask for "" assertEnvironmentName(c, apiclient, coretesting.SampleEnvName) }
func (c *AddMachineCommand) Run(ctx *cmd.Context) error { if c.Placement != nil && c.Placement.Scope == "ssh" { args := manual.ProvisionMachineArgs{ Host: c.Placement.Directive, EnvName: c.EnvName, Stdin: ctx.Stdin, Stdout: ctx.Stdout, Stderr: ctx.Stderr, } _, err := manual.ProvisionMachine(args) return err } client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() if c.Placement != nil && c.Placement.Scope == instance.MachineScope { // It does not make sense to add-machine <id>. return fmt.Errorf("machine-id cannot be specified when adding machines") } machineParams := params.AddMachineParams{ Placement: c.Placement, Series: c.Series, Constraints: c.Constraints, Jobs: []params.MachineJob{params.JobHostUnits}, } results, err := client.AddMachines([]params.AddMachineParams{machineParams}) if params.IsCodeNotImplemented(err) { if c.Placement != nil { containerType, parseErr := instance.ParseContainerType(c.Placement.Scope) if parseErr != nil { // The user specified a non-container placement directive: // return original API not implemented error. return err } machineParams.ContainerType = containerType machineParams.ParentId = c.Placement.Directive machineParams.Placement = nil } logger.Infof( "AddMachinesWithPlacement not supported by the API server, " + "falling back to 1.18 compatibility mode", ) results, err = client.AddMachines1dot18([]params.AddMachineParams{machineParams}) } if err != nil { return err } // Currently, only one machine is added, but in future there may be several added in one call. machineInfo := results[0] if machineInfo.Error != nil { return machineInfo.Error } machineId := machineInfo.Machine if names.IsContainerMachine(machineId) { ctx.Infof("created container %v", machineId) } else { ctx.Infof("created machine %v", machineId) } return nil }
func (c *DeployCommand) Run(ctx *cmd.Context) error { client, err := juju.NewAPIClientFromName(c.EnvName) if err != nil { return err } defer client.Close() attrs, err := client.EnvironmentGet() if err != nil { return err } conf, err := config.New(config.NoDefaults, attrs) if err != nil { return err } curl, err := resolveCharmURL(c.CharmName, client, conf) if err != nil { return err } repo, err := charm.InferRepository(curl.Reference, ctx.AbsPath(c.RepoPath)) if err != nil { return err } repo = config.SpecializeCharmRepo(repo, conf) curl, err = addCharmViaAPI(client, ctx, curl, repo) if err != nil { return err } if c.BumpRevision { ctx.Infof("--upgrade (or -u) is deprecated and ignored; charms are always deployed with a unique revision.") } var includeNetworks []string if c.Networks != "" { includeNetworks = parseNetworks(c.Networks) env, err := environs.New(conf) if err != nil { return err } if !env.SupportNetworks() { return errors.New("cannot use --networks: not supported by the environment") } } charmInfo, err := client.CharmInfo(curl.String()) if err != nil { return err } numUnits := c.NumUnits if charmInfo.Meta.Subordinate { if !constraints.IsEmpty(&c.Constraints) { return errors.New("cannot use --constraints with subordinate service") } if numUnits == 1 && c.ToMachineSpec == "" { numUnits = 0 } else { return errors.New("cannot use --num-units or --to with subordinate service") } } serviceName := c.ServiceName if serviceName == "" { serviceName = charmInfo.Meta.Name } var configYAML []byte if c.Config.Path != "" { configYAML, err = c.Config.Read(ctx) if err != nil { return err } } err = client.ServiceDeployWithNetworks( curl.String(), serviceName, numUnits, string(configYAML), c.Constraints, c.ToMachineSpec, includeNetworks, nil, ) if params.IsCodeNotImplemented(err) { if len(includeNetworks) > 0 { return errors.New("cannot use --networks: not supported by the API server") } err = client.ServiceDeploy( curl.String(), serviceName, numUnits, string(configYAML), c.Constraints, c.ToMachineSpec) } return err }