// PrivateAddress implements the server side of Client.PrivateAddress. func (c *Client) PrivateAddress(p params.PrivateAddress) (results params.PrivateAddressResults, err error) { switch { case names.IsValidMachine(p.Target): machine, err := c.api.stateAccessor.Machine(p.Target) if err != nil { return results, err } addr, err := machine.PrivateAddress() if err != nil { return results, errors.Annotatef(err, "error fetching address for machine %q", machine) } return params.PrivateAddressResults{PrivateAddress: addr.Value}, nil case names.IsValidUnit(p.Target): unit, err := c.api.stateAccessor.Unit(p.Target) if err != nil { return results, err } addr, err := unit.PrivateAddress() if err != nil { return results, errors.Annotatef(err, "error fetching address for unit %q", unit) } return params.PrivateAddressResults{PrivateAddress: addr.Value}, nil } return results, fmt.Errorf("unknown unit or machine %q", p.Target) }
func (c *RunCommand) Init(args []string) error { // make sure we aren't in an existing hook context if contextId, err := getenv("JUJU_CONTEXT_ID"); err == nil && contextId != "" { return fmt.Errorf("juju-run cannot be called from within a hook, have context %q", contextId) } if !c.noContext { if len(args) < 1 { return fmt.Errorf("missing unit-name") } var unitName string unitName, args = args[0], args[1:] // If the command line param is a unit id (like service/2) we need to // change it to the unit tag as that is the format of the agent directory // on disk (unit-service-2). if names.IsValidUnit(unitName) { c.unit = names.NewUnitTag(unitName) } else { var err error c.unit, err = names.ParseUnitTag(unitName) if err != nil { return errors.Trace(err) } } } if len(args) < 1 { return fmt.Errorf("missing commands") } c.commands, args = args[0], args[1:] return cmd.CheckEmpty(args) }
// PrivateAddress implements the server side of Client.PrivateAddress. func (c *Client) PrivateAddress(p params.PrivateAddress) (results params.PrivateAddressResults, err error) { switch { case names.IsValidMachine(p.Target): machine, err := c.api.state.Machine(p.Target) if err != nil { return results, err } addr := network.SelectInternalAddress(machine.Addresses(), false) if addr == "" { return results, fmt.Errorf("machine %q has no internal address", machine) } return params.PrivateAddressResults{PrivateAddress: addr}, nil case names.IsValidUnit(p.Target): unit, err := c.api.state.Unit(p.Target) if err != nil { return results, err } addr, ok := unit.PrivateAddress() if !ok { return results, fmt.Errorf("unit %q has no internal address", unit) } return params.PrivateAddressResults{PrivateAddress: addr}, nil } return results, fmt.Errorf("unknown unit or machine %q", p.Target) }
// Init initializes the command for running. func (a *UnitAgent) Init(args []string) error { if a.UnitName == "" { return cmdutil.RequiredError("unit-name") } if !names.IsValidUnit(a.UnitName) { return fmt.Errorf(`--unit-name option expects "<service>/<n>" argument`) } if err := a.AgentConf.CheckArgs(args); err != nil { return err } a.runner = worker.NewRunner(cmdutil.IsFatal, cmdutil.MoreImportant, worker.RestartDelay) if !a.logToStdErr { if err := a.ReadConfig(a.Tag().String()); err != nil { return err } agentConfig := a.CurrentConfig() // the writer in ctx.stderr gets set as the loggo writer in github.com/juju/cmd/logging.go a.ctx.Stderr = &lumberjack.Logger{ Filename: agent.LogFilename(agentConfig), MaxSize: 300, // megabytes MaxBackups: 2, } } return nil }
// ReadSettings returns a map holding the settings of the unit with the // supplied name within this relation. An error will be returned if the // relation no longer exists, or if the unit's service is not part of the // relation, or the settings are invalid; but mere non-existence of the // unit is not grounds for an error, because the unit settings are // guaranteed to persist for the lifetime of the relation, regardless // of the lifetime of the unit. func (ru *RelationUnit) ReadSettings(uname string) (params.RelationSettings, error) { if !names.IsValidUnit(uname) { return nil, errors.Errorf("%q is not a valid unit", uname) } tag := names.NewUnitTag(uname) var results params.RelationSettingsResults args := params.RelationUnitPairs{ RelationUnitPairs: []params.RelationUnitPair{{ Relation: ru.relation.tag.String(), LocalUnit: ru.unit.tag.String(), RemoteUnit: tag.String(), }}, } err := ru.st.facade.FacadeCall("ReadRemoteSettings", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } return result.Settings, nil }
func (c *SSHCommon) hostFromTarget(target string) (string, error) { // If the target is neither a machine nor a unit, // assume it's a hostname and try it directly. if !names.IsValidMachine(target) && !names.IsValidUnit(target) { return target, nil } // A target may not initially have an address (e.g. the // address updater hasn't yet run), so we must do this in // a loop. if _, err := c.ensureAPIClient(); err != nil { return "", err } var err error for a := sshHostFromTargetAttemptStrategy.Start(); a.Next(); { var addr string if c.proxy { addr, err = c.apiClient.PrivateAddress(target) } else { addr, err = c.apiClient.PublicAddress(target) } if err == nil { return addr, nil } } return "", err }
func (s *serviceSuite) TestServiceNameFormats(c *gc.C) { assertService := func(s string, expect bool) { c.Assert(names.IsValidService(s), gc.Equals, expect) // Check that anything that is considered a valid service name // is also (in)valid if a(n) (in)valid unit designator is added // to it. c.Assert(names.IsValidUnit(s+"/0"), gc.Equals, expect) c.Assert(names.IsValidUnit(s+"/99"), gc.Equals, expect) c.Assert(names.IsValidUnit(s+"/-1"), gc.Equals, false) c.Assert(names.IsValidUnit(s+"/blah"), gc.Equals, false) c.Assert(names.IsValidUnit(s+"/"), gc.Equals, false) } for i, test := range serviceNameTests { c.Logf("test %d: %q", i, test.pattern) assertService(test.pattern, test.valid) } }
// IsValid checks if the port range is valid. func (p PortRange) IsValid() bool { proto := strings.ToLower(p.Protocol) if proto != "tcp" && proto != "udp" { return false } if !names.IsValidUnit(p.UnitName) { return false } return p.FromPort <= p.ToPort }
func targetToTag(target string) (names.Tag, error) { switch { case names.IsValidMachine(target): return names.NewMachineTag(target), nil case names.IsValidUnit(target): return names.NewUnitTag(target), nil default: return nil, errors.NotValidf("target %q", target) } }
// Unit returns the service's unit with name. func (s *Service) Unit(name string) (*Unit, error) { if !names.IsValidUnit(name) { return nil, fmt.Errorf("%q is not a valid unit name", name) } udoc := &unitDoc{} sel := bson.D{{"_id", name}, {"service", s.doc.Name}} if err := s.st.units.Find(sel).One(udoc); err != nil { return nil, fmt.Errorf("cannot get unit %q from service %q: %v", name, s.doc.Name, err) } return newUnit(s.st, udoc), nil }
// resolveMachine returns the machine id resolving the given unit or machine // placeholder. func (h *bundleHandler) resolveMachine(placeholder string) (string, error) { machineOrUnit := resolve(placeholder, h.results) if !names.IsValidUnit(machineOrUnit) { return machineOrUnit, nil } for h.unitStatus[machineOrUnit] == "" { if err := h.updateUnitStatus(); err != nil { return "", errors.Annotate(err, "cannot resolve machine") } } return h.unitStatus[machineOrUnit], nil }
func (c *RemoveUnitCommand) Init(args []string) error { c.UnitNames = args if len(c.UnitNames) == 0 { return fmt.Errorf("no units specified") } for _, name := range c.UnitNames { if !names.IsValidUnit(name) { return fmt.Errorf("invalid unit name %q", name) } } return nil }
func (c *resolvedCommand) Init(args []string) error { if len(args) > 0 { c.UnitName = args[0] if !names.IsValidUnit(c.UnitName) { return fmt.Errorf("invalid unit name %q", c.UnitName) } args = args[1:] } else { return fmt.Errorf("no unit specified") } return cmd.CheckEmpty(args) }
func (u unitAssigner) Handle(ids []string) error { logger.Tracef("Handling unit assignments: %q", ids) if len(ids) == 0 { return nil } units := make([]names.UnitTag, len(ids)) for i, id := range ids { if !names.IsValidUnit(id) { return errors.Errorf("%q is not a valid unit id", id) } units[i] = names.NewUnitTag(id) } results, err := u.api.AssignUnits(units) if err != nil { return err } failures := map[string]error{} logger.Tracef("Unit assignment results: %q", results) // errors are returned in the same order as the ids given. Any errors from // the assign units call must be reported as error statuses on the // respective units (though the assignments will be retried). Not found // errors indicate that the unit was removed before the assignment was // requested, which can be safely ignored. for i, err := range results { if err != nil && !errors.IsNotFound(err) { failures[units[i].String()] = err } } if len(failures) > 0 { args := params.SetStatus{ Entities: make([]params.EntityStatusArgs, len(failures)), } x := 0 for unit, err := range failures { args.Entities[x] = params.EntityStatusArgs{ Tag: unit, Status: params.StatusError, Info: err.Error(), } x++ } return u.api.SetAgentStatus(args) } return nil }
// IsValid checks if the port range is valid. func (p PortRange) Validate() error { proto := strings.ToLower(p.Protocol) if proto != "tcp" && proto != "udp" { return errors.Errorf("invalid protocol %q", proto) } if !names.IsValidUnit(p.UnitName) { return errors.Errorf("invalid unit %q", p.UnitName) } if p.FromPort > p.ToPort { return errors.Errorf("invalid port range %d-%d", p.FromPort, p.ToPort) } return nil }
// Init initializes the command for running. func (a *UnitAgent) Init(args []string) error { if a.UnitName == "" { return requiredError("unit-name") } if !names.IsValidUnit(a.UnitName) { return fmt.Errorf(`--unit-name option expects "<service>/<n>" argument`) } if err := a.AgentConf.CheckArgs(args); err != nil { return err } a.runner = worker.NewRunner(isFatal, moreImportant) return nil }
// Init implements Command.Init. func (c *addCommand) Init(args []string) (err error) { if len(args) < 2 { return errors.New("storage add requires a unit and a storage directive") } u := args[0] if !names.IsValidUnit(u) { return errors.NotValidf("unit name %q", u) } c.unitTag = names.NewUnitTag(u).String() c.storageCons, err = storage.ParseConstraintsMap(args[1:], false) return }
// Unit returns a unit by name. func (st *State) Unit(name string) (*Unit, error) { if !names.IsValidUnit(name) { return nil, fmt.Errorf("%q is not a valid unit name", name) } doc := unitDoc{} err := st.units.FindId(name).One(&doc) if err == mgo.ErrNotFound { return nil, errors.NotFoundf("unit %q", name) } if err != nil { return nil, fmt.Errorf("cannot get unit %q: %v", name, err) } return newUnit(st, &doc), nil }
// validate returns an error if any fields are invalid or missing. func (c check) validate() error { if !names.IsValidService(c.serviceName) { return errors.Errorf("invalid service name %q", c.serviceName) } if !names.IsValidUnit(c.unitName) { return errors.Errorf("invalid unit name %q", c.unitName) } if c.response == nil { return errors.New("missing response channel") } if c.abort == nil { return errors.New("missing abort channel") } return nil }
// ReadSettings returns a map holding the settings of the unit with the // supplied name within this relation. An error will be returned if the // relation no longer exists, or if the unit's service is not part of the // relation, or the settings are invalid; but mere non-existence of the // unit is not grounds for an error, because the unit settings are // guaranteed to persist for the lifetime of the relation, regardless // of the lifetime of the unit. func (ru *RelationUnit) ReadSettings(uname string) (m map[string]interface{}, err error) { defer errors.Maskf(&err, "cannot read settings for unit %q in relation %q", uname, ru.relation) if !names.IsValidUnit(uname) { return nil, fmt.Errorf("%q is not a valid unit name", uname) } key, err := ru.key(uname) if err != nil { return nil, err } node, err := readSettings(ru.st, key) if err != nil { return nil, err } return node.Map(), nil }
// Init reads and verifies the cli arguments for the collectMetricsCommand func (c *collectMetricsCommand) Init(args []string) error { if len(args) == 0 { return errors.New("you need to specify a unit or service.") } if names.IsValidUnit(args[0]) { c.units = []string{args[0]} } else if names.IsValidService(args[0]) { c.services = []string{args[0]} } else { return errors.Errorf("%q is not a valid unit or service", args[0]) } if err := cmd.CheckEmpty(args[1:]); err != nil { return errors.Errorf("unknown command line arguments: " + strings.Join(args, ",")) } return nil }
func inferRemoteUnit(rctxs map[int]*ContextRelation, info CommandInfo) (int, string, error) { relationId := info.RelationId hasRelation := relationId != -1 remoteUnit := info.RemoteUnitName hasRemoteUnit := remoteUnit != "" // Check baseline sanity of remote unit, if supplied. if hasRemoteUnit { if !names.IsValidUnit(remoteUnit) { return -1, "", errors.Errorf(`invalid remote unit: %s`, remoteUnit) } else if !hasRelation { return -1, "", errors.Errorf("remote unit provided without a relation: %s", remoteUnit) } } // Check sanity of relation, if supplied, otherwise easy early return. if !hasRelation { return relationId, remoteUnit, nil } rctx, found := rctxs[relationId] if !found { return -1, "", errors.Errorf("unknown relation id: %d", relationId) } // Past basic sanity checks; if forced, accept what we're given. if info.ForceRemoteUnit { return relationId, remoteUnit, nil } // Infer an appropriate remote unit if we can. possibles := rctx.UnitNames() if remoteUnit == "" { switch len(possibles) { case 0: return -1, "", errors.Errorf("cannot infer remote unit in empty relation %d", relationId) case 1: return relationId, possibles[0], nil } return -1, "", errors.Errorf("ambiguous remote unit; possibilities are %+v", possibles) } for _, possible := range possibles { if remoteUnit == possible { return relationId, remoteUnit, nil } } return -1, "", errors.Errorf("unknown remote unit %s; possibilities are %+v", remoteUnit, possibles) }
func (ctx *SimpleContext) deployedUnitsUpstartJobs() (map[string]string, error) { fis, err := ioutil.ReadDir(ctx.initDir) if err != nil { return nil, err } installed := make(map[string]string) for _, fi := range fis { if groups := deployedRe.FindStringSubmatch(fi.Name()); len(groups) == 4 { unitName := groups[2] + "/" + groups[3] if !names.IsValidUnit(unitName) { continue } installed[unitName] = groups[1] } } return installed, nil }
// Validate checks if the port range is valid. func (p PortRange) Validate() error { proto := strings.ToLower(p.Protocol) if proto != "tcp" && proto != "udp" { return errors.Errorf("invalid protocol %q", proto) } if !names.IsValidUnit(p.UnitName) { return errors.Errorf("invalid unit %q", p.UnitName) } if p.FromPort > p.ToPort { return errors.Errorf("invalid port range %d-%d", p.FromPort, p.ToPort) } if p.FromPort <= 0 || p.FromPort > 65535 || p.ToPort <= 0 || p.ToPort > 65535 { return errors.Errorf("port range bounds must be between 1 and 65535, got %d-%d", p.FromPort, p.ToPort) } return nil }
func (c *RunCommand) Init(args []string) error { if len(args) == 0 { return fmt.Errorf("no commands specified") } c.commands, args = args[0], args[1:] if c.all { if len(c.machines) != 0 { return fmt.Errorf("You cannot specify --all and individual machines") } if len(c.services) != 0 { return fmt.Errorf("You cannot specify --all and individual services") } if len(c.units) != 0 { return fmt.Errorf("You cannot specify --all and individual units") } } else { if len(c.machines) == 0 && len(c.services) == 0 && len(c.units) == 0 { return fmt.Errorf("You must specify a target, either through --all, --machine, --service or --unit") } } var nameErrors []string for _, machineId := range c.machines { if !names.IsValidMachine(machineId) { nameErrors = append(nameErrors, fmt.Sprintf(" %q is not a valid machine id", machineId)) } } for _, service := range c.services { if !names.IsValidService(service) { nameErrors = append(nameErrors, fmt.Sprintf(" %q is not a valid service name", service)) } } for _, unit := range c.units { if !names.IsValidUnit(unit) { nameErrors = append(nameErrors, fmt.Sprintf(" %q is not a valid unit name", unit)) } } if len(nameErrors) > 0 { return fmt.Errorf("The following run targets are not valid:\n%s", strings.Join(nameErrors, "\n")) } return cmd.CheckEmpty(args) }
// Init reads and verifies the cli arguments for the SetMeterStatusCommand func (c *SetMeterStatusCommand) Init(args []string) error { if len(args) != 2 { return errors.New("you need to specify an entity (service or unit) and a status") } if names.IsValidUnit(args[0]) { c.Tag = names.NewUnitTag(args[0]) } else if names.IsValidService(args[0]) { c.Tag = names.NewServiceTag(args[0]) } else { return errors.Errorf("%q is not a valid unit or service", args[0]) } c.Status = args[1] if err := cmd.CheckEmpty(args[2:]); err != nil { return errors.Errorf("unknown command line arguments: " + strings.Join(args, ",")) } return nil }
func (c *debugHooksCommand) Init(args []string) error { if len(args) < 1 { return fmt.Errorf("no unit name specified") } c.Target = args[0] if !names.IsValidUnit(c.Target) { return fmt.Errorf("%q is not a valid unit name", c.Target) } // If any of the hooks is "*", then debug all hooks. c.hooks = append([]string{}, args[1:]...) for _, h := range c.hooks { if h == "*" { c.hooks = nil break } } return nil }
// NewCommands is part of the Factory interface. func (f *factory) NewCommands(args CommandArgs, sendResponse CommandResponseFunc) (Operation, error) { if args.Commands == "" { return nil, errors.New("commands required") } else if sendResponse == nil { return nil, errors.New("response sender required") } if args.RemoteUnitName != "" { if args.RelationId == -1 { return nil, errors.New("remote unit not valid without relation") } else if !names.IsValidUnit(args.RemoteUnitName) { return nil, errors.Errorf("invalid remote unit name %q", args.RemoteUnitName) } } return &runCommands{ args: args, sendResponse: sendResponse, callbacks: f.config.Callbacks, runnerFactory: f.config.RunnerFactory, }, nil }
func (ctx *SimpleContext) deployedUnitsInitSystemJobs() (map[string]string, error) { fis, err := ctx.listServices() if err != nil { return nil, err } if err != nil { return nil, err } installed := make(map[string]string) for _, fi := range fis { if groups := deployedRe.FindStringSubmatch(fi); len(groups) > 0 { unitName := groups[2] + "/" + groups[3] if !names.IsValidUnit(unitName) { continue } installed[unitName] = groups[1] } } return installed, nil }
// Init gets the unit tag, and checks for other correct args. func (c *doCommand) Init(args []string) error { switch len(args) { case 0: return errors.New("no unit specified") case 1: return errors.New("no action specified") default: // Grab and verify the unit and action names. unitName := args[0] if !names.IsValidUnit(unitName) { return errors.Errorf("invalid unit name %q", unitName) } ActionName := args[1] if valid := ActionNameRule.MatchString(ActionName); !valid { return fmt.Errorf("invalid action name %q", ActionName) } c.unitTag = names.NewUnitTag(unitName) c.actionName = ActionName if len(args) == 2 { return nil } // Parse CLI key-value args if they exist. c.args = make([][]string, 0) for _, arg := range args[2:] { thisArg := strings.SplitN(arg, "=", 2) if len(thisArg) != 2 { return fmt.Errorf("argument %q must be of the form key...=value", arg) } keySlice := strings.Split(thisArg[0], ".") // check each key for validity for _, key := range keySlice { if valid := keyRule.MatchString(key); !valid { return fmt.Errorf("key %q must start and end with lowercase alphanumeric, and contain only lowercase alphanumeric and hyphens", key) } } // c.args={..., [key, key, key, key, value]} c.args = append(c.args, append(keySlice, thisArg[1])) } return nil } }