func (*NewConnSuite) TestNewConnFromName(c *C) { home := c.MkDir() defer os.Setenv("HOME", os.Getenv("HOME")) os.Setenv("HOME", home) conn, err := juju.NewConnFromName("") c.Assert(conn, IsNil) c.Assert(err, ErrorMatches, ".*: no such file or directory") if err := os.Mkdir(filepath.Join(home, ".juju"), 0755); err != nil { c.Fatal("Could not create directory structure") } envs := filepath.Join(home, ".juju", "environments.yaml") err = ioutil.WriteFile(envs, []byte(` default: erewhemos environments: erewhemos: type: dummy state-server: true authorized-keys: i-am-a-key admin-secret: conn-from-name-secret `), 0644) err = ioutil.WriteFile(filepath.Join(home, ".juju", "erewhemos-cert.pem"), []byte(coretesting.CACert), 0600) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(home, ".juju", "erewhemos-private-key.pem"), []byte(coretesting.CAKey), 0600) c.Assert(err, IsNil) // Just run through a few operations on the dummy provider and verify that // they behave as expected. conn, err = juju.NewConnFromName("") c.Assert(err, ErrorMatches, "dummy environment not bootstrapped") environ, err := environs.NewFromName("") c.Assert(err, IsNil) err = environs.Bootstrap(environ, false, panicWrite) c.Assert(err, IsNil) conn, err = juju.NewConnFromName("") c.Assert(err, IsNil) defer conn.Close() c.Assert(conn.Environ, NotNil) c.Assert(conn.Environ.Name(), Equals, "erewhemos") c.Assert(conn.State, NotNil) // Reset the admin password so the state db can be reused. err = conn.State.SetAdminMongoPassword("") c.Assert(err, IsNil) // Close the conn (thereby closing its state) a couple of times to // verify that multiple closes will not panic. We ignore the error, // as the underlying State will return an error the second // time. conn.Close() conn.Close() }
func (c *StatusCommand) Run(ctx *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() var context statusContext if context.machines, err = fetchAllMachines(conn.State); err != nil { return err } if context.services, context.units, err = fetchAllServicesAndUnits(conn.State); err != nil { return err } context.instances, err = fetchAllInstances(conn.Environ) if err != nil { // We cannot see instances from the environment, but // there's still lots of potentially useful info to print. 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"` }{ Machines: context.processMachines(), Services: context.processServices(), } return c.out.Write(ctx, result) }
func (c *SetEnvironmentCommand) Run(ctx *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() // Here is the magic around setting the attributes: // TODO(thumper): get this magic under test somewhere, and update other call-sites to use it. // Get the existing environment config from the state. oldConfig, err := conn.State.EnvironConfig() if err != nil { return err } // Apply the attributes specified for the command to the state config. newConfig, err := oldConfig.Apply(c.values) if err != nil { return err } // Now validate this new config against the existing config via the provider. provider := conn.Environ.Provider() newProviderConfig, err := provider.Validate(newConfig, oldConfig) if err != nil { return err } // Now try to apply the new validated config. return conn.State.SetEnvironConfig(newProviderConfig) }
// Run fetches the configuration of the service and formats // the result as a YAML string. func (c *GetCommand) Run(ctx *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() svc, err := conn.State.Service(c.ServiceName) if err != nil { return err } svcfg, err := svc.Config() if err != nil { return err } charm, _, err := svc.Charm() if err != nil { return err } chcfg := charm.Config().Options config := merge(svcfg.Map(), chcfg) result := map[string]interface{}{ "service": svc.Name(), "charm": charm.Meta().Name, "settings": config, } return c.out.Write(ctx, result) }
func (c *GetEnvironmentCommand) Run(ctx *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() // Get the existing environment config from the state. config, err := conn.State.EnvironConfig() if err != nil { return err } attrs := config.AllAttrs() // If no key specified, write out the whole lot. if c.key == "" { return c.out.Write(ctx, attrs) } value, found := attrs[c.key] if found { return c.out.Write(ctx, value) } return fmt.Errorf("Key %q not found in %q environment.", c.key, config.Name()) }
// Run updates the configuration of a service. func (c *SetCommand) Run(ctx *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() service, err := conn.State.Service(c.ServiceName) if err != nil { return err } ch, _, err := service.Charm() if err != nil { return err } var settings charm.Settings if c.SettingsYAML.Path != "" { settingsYAML, err := c.SettingsYAML.Read(ctx) if err != nil { return err } settings, err = ch.Config().ParseSettingsYAML(settingsYAML, c.ServiceName) if err != nil { return err } } else if len(c.SettingsStrings) > 0 { settings, err = ch.Config().ParseSettingsStrings(c.SettingsStrings) if err != nil { return err } } else { return nil } return service.UpdateConfigSettings(settings) }
// Run resolves c.Target to a machine, or host of a unit and // forks ssh with c.Args, if provided. func (c *SCPCommand) Run(ctx *cmd.Context) error { var err error c.Conn, err = juju.NewConnFromName(c.EnvName) if err != nil { return err } defer c.Close() // translate arguments in the form 0:/somepath or service/0:/somepath into // ubuntu@machine:/somepath so they can be presented to scp. for i := range c.Args { // BUG(dfc) This will not work for IPv6 addresses like 2001:db8::1:2:/somepath. if v := strings.SplitN(c.Args[i], ":", 2); len(v) > 1 { host, err := c.hostFromTarget(v[0]) if err != nil { return err } c.Args[i] = "ubuntu@" + host + ":" + v[1] } } args := []string{"-o", "StrictHostKeyChecking no", "-o", "PasswordAuthentication no"} args = append(args, c.Args...) cmd := exec.Command("scp", args...) cmd.Stdin = ctx.Stdin cmd.Stdout = ctx.Stdout cmd.Stderr = ctx.Stderr c.Close() return cmd.Run() }
func (c *AddMachineCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() series := c.Series if series == "" { conf, err := conn.State.EnvironConfig() if err != nil { return err } series = conf.DefaultSeries() } params := state.AddMachineParams{ ParentId: c.MachineId, ContainerType: c.ContainerType, Series: series, Constraints: c.Constraints, Jobs: []state.MachineJob{state.JobHostUnits}, } m, err := conn.State.AddMachineWithConstraints(¶ms) if err == nil { if c.ContainerType == "" { log.Infof("created machine %v", m) } else { log.Infof("created %q container on machine %v", c.ContainerType, m) } } return err }
func (*NewConnSuite) TestNewConnFromNameNotSetGetsDefault(c *C) { defer coretesting.MakeSampleHome(c).Restore() bootstrapEnv(c, "") conn, err := juju.NewConnFromName("") c.Assert(err, IsNil) defer conn.Close() c.Assert(conn.Environ.Name(), Equals, coretesting.SampleEnvName) }
func (c *DestroyMachineCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() return conn.State.DestroyMachines(c.MachineIds...) }
// Run connects to the environment specified on the command line // and calls conn.DestroyUnits. func (c *DestroyUnitCommand) Run(_ *cmd.Context) (err error) { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() return conn.DestroyUnits(c.UnitNames...) }
// Run updates the configuration of a service func (c *SetCommand) Run(ctx *cmd.Context) error { var unvalidated = make(map[string]string) var remove []string contents, err := c.Config.Read(ctx) if err != nil && err != cmd.ErrNoPath { return err } if len(contents) > 0 { if err := goyaml.Unmarshal(contents, &unvalidated); err != nil { return err } } else { unvalidated, remove, err = parse(c.Options) if err != nil { return err } } conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() srv, err := conn.State.Service(c.ServiceName) if err != nil { return err } charm, _, err := srv.Charm() if err != nil { return err } // 1. Validate will convert this partial configuration // into a full configuration by inserting charm defaults // for missing values. validated, err := charm.Config().Validate(unvalidated) if err != nil { return err } // 2. strip out the additional default keys added in the previous step. validated = strip(validated, unvalidated) cfg, err := srv.Config() if err != nil { return err } // 3. Update any keys that remain after validation and filtering. if len(validated) > 0 { log.Debugf("cmd/juju: updating configuration items: %v", validated) cfg.Update(validated) } // 4. Delete any removed keys. if len(remove) > 0 { log.Debugf("cmd/juju: removing configuration items: %v", remove) for _, k := range remove { cfg.Delete(k) } } _, err = cfg.Write() return err }
// Run changes the juju-managed firewall to hide any // ports that were also explicitly marked by units as closed. func (c *UnexposeCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() params := params.ServiceUnexpose{ServiceName: c.ServiceName} return statecmd.ServiceUnexpose(conn.State, params) }
func (*NewConnSuite) TestConnMultipleCloseOk(c *C) { defer coretesting.MakeSampleHome(c).Restore() bootstrapEnv(c, "") // Error return from here is tested in TestNewConnFromNameNotSetGetsDefault. conn, _ := juju.NewConnFromName("") conn.Close() conn.Close() conn.Close() }
func (*NewConnSuite) TestNewConnFromNameNotDefault(c *C) { defer coretesting.MakeMultipleEnvHome(c).Restore() // The default environment is "erewhemos", so make sure we get what we ask for. const envName = "erewhemos-2" bootstrapEnv(c, envName) conn, err := juju.NewConnFromName(envName) c.Assert(err, IsNil) defer conn.Close() c.Assert(conn.Environ.Name(), Equals, envName) }
// Run connects to the environment specified on the command line and destroys // units therein. func (c *DestroyUnitCommand) Run(_ *cmd.Context) (err error) { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() params := params.DestroyServiceUnits{ UnitNames: c.UnitNames, } return statecmd.DestroyServiceUnits(conn.State, params) }
// Run changes the version proposed for the juju tools. func (c *UpgradeJujuCommand) Run(_ *cmd.Context) (err error) { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() defer func() { if err == errUpToDate { log.Noticef(err.Error()) err = nil } }() // Determine the version to upgrade to, uploading tools if necessary. env := conn.Environ cfg, err := conn.State.EnvironConfig() if err != nil { return err } v, err := c.initVersions(cfg, env) if err != nil { return err } if c.UploadTools { series := getUploadSeries(cfg, c.Series) if err := v.uploadTools(env.Storage(), series); err != nil { return err } } if err := v.validate(); err != nil { return err } log.Infof("upgrade version chosen: %s", v.chosen) // TODO(fwereade): this list may be incomplete, pending tools.Upload change. log.Infof("available tools: %s", v.tools) // Write updated config back to state if necessary. Note that this is // crackful and racy, because we have no idea what incompatible agent- // version might be set by another administrator in the meantime. If // this happens, tough: I'm not going to pretend to do it right when // I'm not. // TODO(fwereade): Do this right. Warning: scope unclear. cfg, err = cfg.Apply(map[string]interface{}{ "agent-version": v.chosen.String(), }) if err != nil { return err } if err := conn.State.SetEnvironConfig(cfg); err != nil { return err } log.Noticef("started upgrade to %s", v.chosen) return nil }
// Run changes the juju-managed firewall to hide any // ports that were also explicitly marked by units as closed. func (c *UnexposeCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() svc, err := conn.State.Service(c.ServiceName) if err != nil { return err } return svc.ClearExposed() }
func (c *ResolvedCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() unit, err := conn.State.Unit(c.UnitName) if err != nil { return err } return unit.Resolve(c.Retry) }
func (c *AddRelationCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() params := params.AddRelation{ Endpoints: c.Endpoints, } _, err = statecmd.AddRelation(conn.State, params) return err }
func (c *AddRelationCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() eps, err := conn.State.InferEndpoints(c.Endpoints) if err != nil { return err } _, err = conn.State.AddRelation(eps...) return err }
// Run connects to the environment specified on the command line // and calls conn.AddUnits. func (c *AddUnitCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() service, err := conn.State.Service(c.ServiceName) if err != nil { return err } _, err = conn.AddUnits(service, c.NumUnits) return err }
// Run connects to the environment specified on the command line // and calls conn.AddUnits. func (c *AddUnitCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() params := params.AddServiceUnits{ ServiceName: c.ServiceName, NumUnits: c.NumUnits, ToMachineSpec: c.ToMachineSpec, } _, err = statecmd.AddServiceUnits(conn.State, params) return err }
func (c *SetConstraintsCommand) Run(_ *cmd.Context) (err error) { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() if c.ServiceName == "" { return conn.State.SetEnvironConstraints(c.Constraints) } params := params.SetServiceConstraints{ ServiceName: c.ServiceName, Constraints: c.Constraints, } return statecmd.SetServiceConstraints(conn.State, params) }
func (c *DestroyRelationCommand) Run(_ *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return err } defer conn.Close() eps, err := conn.State.InferEndpoints(c.Endpoints) if err != nil { return err } rel, err := conn.State.EndpointsRelation(eps...) if err != nil { return err } return rel.Destroy() }
func (c *StatusCommand) Run(ctx *cmd.Context) error { conn, err := juju.NewConnFromName(c.EnvName) if err != nil { return fmt.Errorf(connectionError, c.EnvName, err) } defer conn.Close() var context statusContext unitMatcher, err := newUnitMatcher(c.patterns) if err != nil { return err } if context.services, context.units, err = fetchAllServicesAndUnits(conn.State, unitMatcher); err != nil { return err } // Filter machines by units in scope. var machineIds *set.Strings if !unitMatcher.matchesAny() { machineIds, err = fetchUnitMachineIds(context.units) if err != nil { return err } } if context.machines, err = fetchMachines(conn.State, machineIds); err != nil { return err } context.instances, err = fetchAllInstances(conn.Environ) if err != nil { // We cannot see instances from the environment, but // there's still lots of potentially useful info to print. fmt.Fprintf(ctx.Stderr, "cannot retrieve instances from the environment: %v\n", err) } result := struct { Environment string `json:"environment"` Machines map[string]machineStatus `json:"machines"` Services map[string]serviceStatus `json:"services"` }{ Environment: conn.Environ.Name(), Machines: context.processMachines(), Services: context.processServices(), } return c.out.Write(ctx, result) }
// Run changes the version proposed for the juju tools. func (c *UpgradeJujuCommand) Run(_ *cmd.Context) error { var err error c.conn, err = juju.NewConnFromName(c.EnvName) if err != nil { return err } defer c.conn.Close() cfg, err := c.conn.State.EnvironConfig() if err != nil { return err } c.agentVersion = cfg.AgentVersion() c.toolsList, err = environs.ListTools(c.conn.Environ, c.agentVersion.Major) if err != nil { return err } if c.UploadTools { var forceVersion *version.Number if c.BumpVersion { vers := c.bumpedVersion() forceVersion = &vers.Number c.Version = vers.Number } tools, err := putTools(c.conn.Environ.Storage(), forceVersion) if err != nil { return err } c.toolsList.Private = append(c.toolsList.Private, tools) } if c.Version == (version.Number{}) { c.Version, err = c.newestVersion() if err != nil { return fmt.Errorf("cannot find newest version: %v", err) } } if c.Version.Major != c.agentVersion.Major { return fmt.Errorf("cannot upgrade major versions yet") } if c.Version == c.agentVersion && c.Development == cfg.Development() { return nil } return SetAgentVersion(c.conn.State, c.Version, c.Development) }
func (c *NatCommand) Connect(target string) error { var err error c.Conn, err = juju.NewConnFromName(c.EnvName) if err != nil { return fmt.Errorf("Unable to connect to environment %q: %v", c.EnvName, err) } defer c.Conn.Close() if !names.IsMachine(target) && !names.IsUnit(target) { return fmt.Errorf("invalid target: %q", target) } c.MachineMap = make(map[string]*state.Machine) st := c.Conn.State machines, err := st.AllMachines() for _, m := range machines { c.MachineMap[m.Id()] = m } services, err := st.AllServices() if err != nil { return err } for _, s := range services { units, err := s.AllUnits() if err != nil { return err } for _, u := range units { uc, err := c.UnitContainment(u) if err == ErrNoContainer { continue } else if err != nil { log.Println(err) continue } c.ContainedUnits = append(c.ContainedUnits, *uc) } } return nil }
// Run resolves c.Target to a machine, to the address of a i // machine or unit forks ssh passing any arguments provided. func (c *SSHCommand) Run(ctx *cmd.Context) error { var err error c.Conn, err = juju.NewConnFromName(c.EnvName) if err != nil { return err } defer c.Close() host, err := c.hostFromTarget(c.Target) if err != nil { return err } args := []string{"-l", "ubuntu", "-t", "-o", "StrictHostKeyChecking no", "-o", "PasswordAuthentication no", host} args = append(args, c.Args...) cmd := exec.Command("ssh", args...) cmd.Stdin = ctx.Stdin cmd.Stdout = ctx.Stdout cmd.Stderr = ctx.Stderr c.Close() return cmd.Run() }
func (s *JujuConnSuite) setUpConn(c *C) { if s.RootDir != "" { panic("JujuConnSuite.setUpConn without teardown") } s.RootDir = c.MkDir() s.oldHome = os.Getenv("HOME") home := filepath.Join(s.RootDir, "/home/ubuntu") err := os.MkdirAll(home, 0777) c.Assert(err, IsNil) os.Setenv("HOME", home) dataDir := filepath.Join(s.RootDir, "/var/lib/juju") err = os.MkdirAll(dataDir, 0777) c.Assert(err, IsNil) err = os.Mkdir(filepath.Join(home, ".juju"), 0777) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(home, ".juju", "environments.yaml"), config, 0600) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(home, ".juju", "dummyenv-cert.pem"), []byte(testing.CACert), 0666) c.Assert(err, IsNil) err = ioutil.WriteFile(filepath.Join(home, ".juju", "dummyenv-private-key.pem"), []byte(testing.CAKey), 0600) c.Assert(err, IsNil) environ, err := environs.NewFromName("dummyenv") c.Assert(err, IsNil) // sanity check we've got the correct environment. c.Assert(environ.Name(), Equals, "dummyenv") c.Assert(environs.Bootstrap(environ, false, panicWrite), IsNil) conn, err := juju.NewConnFromName("dummyenv") c.Assert(err, IsNil) s.Conn = conn s.State = conn.State c.Assert(err, IsNil) }