// Name returns the unit's name. func (u *Unit) Name() string { _, name, err := names.ParseTag(u.tag, names.UnitTagKind) if err != nil { panic(err) } return name }
// Name returns the service name. func (s *Service) Name() string { _, serviceName, err := names.ParseTag(s.tag, names.ServiceTagKind) if err != nil { panic(fmt.Sprintf("%q is not a valid service tag", s.tag)) } return serviceName }
// String returns the relation as a string. func (r *Relation) String() string { _, relId, err := names.ParseTag(r.tag, names.RelationTagKind) if err != nil { panic(fmt.Sprintf("%q is not a valid relation tag", r.tag)) } return relId }
// authenticate parses HTTP basic authentication and authorizes the // request by looking up the provided tag and password against state. func (h *httpHandler) authenticate(r *http.Request) error { parts := strings.Fields(r.Header.Get("Authorization")) if len(parts) != 2 || parts[0] != "Basic" { // Invalid header format or no header provided. return fmt.Errorf("invalid request format") } // Challenge is a base64-encoded "tag:pass" string. // See RFC 2617, Section 2. challenge, err := base64.StdEncoding.DecodeString(parts[1]) if err != nil { return fmt.Errorf("invalid request format") } tagPass := strings.SplitN(string(challenge), ":", 2) if len(tagPass) != 2 { return fmt.Errorf("invalid request format") } // Only allow users, not agents. _, _, err = names.ParseTag(tagPass[0], names.UserTagKind) if err != nil { return common.ErrBadCreds } // Ensure the credentials are correct. _, err = checkCreds(h.state, params.Creds{ AuthTag: tagPass[0], Password: tagPass[1], }) return err }
// Name returns the name of the unit. func (u *Unit) Name() string { _, unitName, err := names.ParseTag(u.tag, names.UnitTagKind) if err != nil { panic(fmt.Sprintf("%q is not a valid unit tag", u.tag)) } return unitName }
// parseTag, given an entity tag, returns the collection name and id // of the entity document. func (st *State) parseTag(tag string) (coll string, id string, err error) { kind, id, err := names.ParseTag(tag, "") if err != nil { return "", "", err } switch kind { case names.MachineTagKind: coll = st.machines.Name case names.ServiceTagKind: coll = st.services.Name case names.UnitTagKind: coll = st.units.Name case names.UserTagKind: coll = st.users.Name case names.RelationTagKind: coll = st.relations.Name case names.EnvironTagKind: coll = st.environments.Name case names.NetworkTagKind: coll = st.networks.Name default: return "", "", fmt.Errorf("%q is not a valid collection tag", tag) } return coll, id, nil }
// Id returns the machine id. func (m *Machine) Id() string { _, machineId, err := names.ParseTag(m.tag, names.MachineTagKind) if err != nil { panic(fmt.Sprintf("%q is not a valid machine tag", m.tag)) } return machineId }
func networkTagsToNames(tags []string) ([]string, error) { netNames := make([]string, len(tags)) for i, tag := range tags { _, name, err := names.ParseTag(tag, names.NetworkTagKind) if err != nil { return nil, err } netNames[i] = name } return netNames, nil }
// reconcileInstances compares the initially started watcher for machines, // units and services with the opened and closed ports of the instances and // opens and closes the appropriate ports for each instance. func (fw *Firewaller) reconcileInstances() error { for _, machined := range fw.machineds { m, err := machined.machine() if params.IsCodeNotFound(err) { if err := fw.forgetMachine(machined); err != nil { return err } continue } else if err != nil { return err } instanceId, err := m.InstanceId() if err != nil { return err } instances, err := fw.environ.Instances([]instance.Id{instanceId}) if err == environs.ErrNoInstances { return nil } else if err != nil { return err } _, machineId, err := names.ParseTag(machined.tag, names.MachineTagKind) if err != nil { return err } initialPorts, err := instances[0].Ports(machineId) if err != nil { return err } // Check which ports to open or to close. toOpen := Diff(machined.ports, initialPorts) toClose := Diff(initialPorts, machined.ports) if len(toOpen) > 0 { logger.Infof("opening instance ports %v for %q", toOpen, machined.tag) if err := instances[0].OpenPorts(machineId, toOpen); err != nil { // TODO(mue) Add local retry logic. return err } instance.SortPorts(toOpen) } if len(toClose) > 0 { logger.Infof("closing instance ports %v for %q", toClose, machined.tag) if err := instances[0].ClosePorts(machineId, toClose); err != nil { // TODO(mue) Add local retry logic. return err } instance.SortPorts(toClose) } } return nil }
// cacheAPIInfo updates the local environment settings (.jenv file) // with the provided apiInfo, assuming we've just successfully // connected to the API server. func cacheAPIInfo(info configstore.EnvironInfo, apiInfo *api.Info) error { info.SetAPIEndpoint(configstore.APIEndpoint{ Addresses: apiInfo.Addrs, CACert: string(apiInfo.CACert), }) _, username, err := names.ParseTag(apiInfo.Tag, names.UserTagKind) if err != nil { return fmt.Errorf("invalid API user tag: %v", err) } info.SetAPICredentials(configstore.APICredentials{ User: username, Password: apiInfo.Password, }) return info.Write() }
func (u *UnitUpgraderAPI) getAssignedMachine(tag string) (*state.Machine, error) { // Check that we really have a unit tag. _, unitName, err := names.ParseTag(tag, names.UnitTagKind) if err != nil { return nil, common.ErrPerm } unit, err := u.st.Unit(unitName) if err != nil { return nil, common.ErrPerm } id, err := unit.AssignedMachineId() if err != nil { return nil, err } return u.st.Machine(id) }
// flushInstancePorts opens and closes ports global on the machine. func (fw *Firewaller) flushInstancePorts(machined *machineData, toOpen, toClose []instance.Port) error { // If there's nothing to do, do nothing. // This is important because when a machine is first created, // it will have no instance id but also no open ports - // InstanceId will fail but we don't care. if len(toOpen) == 0 && len(toClose) == 0 { return nil } m, err := machined.machine() if params.IsCodeNotFound(err) { return nil } if err != nil { return err } _, machineId, err := names.ParseTag(machined.tag, names.MachineTagKind) if err != nil { return err } instanceId, err := m.InstanceId() if err != nil { return err } instances, err := fw.environ.Instances([]instance.Id{instanceId}) if err != nil { return err } // Open and close the ports. if len(toOpen) > 0 { if err := instances[0].OpenPorts(machineId, toOpen); err != nil { // TODO(mue) Add local retry logic. return err } instance.SortPorts(toOpen) logger.Infof("opened ports %v on %q", toOpen, machined.tag) } if len(toClose) > 0 { if err := instances[0].ClosePorts(machineId, toClose); err != nil { // TODO(mue) Add local retry logic. return err } instance.SortPorts(toClose) logger.Infof("closed ports %v on %q", toClose, machined.tag) } return nil }
// FindEntity returns the entity with the given tag. // // The returned value can be of type *Machine, *Unit, // *User, *Service or *Environment, depending // on the tag. func (st *State) FindEntity(tag string) (Entity, error) { kind, id, err := names.ParseTag(tag, "") switch kind { case names.MachineTagKind: return st.Machine(id) case names.UnitTagKind: return st.Unit(id) case names.UserTagKind: return st.User(id) case names.ServiceTagKind: return st.Service(id) case names.EnvironTagKind: env, err := st.Environment() if err != nil { return nil, err } // Return an invalid entity error if the requested environment is not // the current one. if id != env.UUID() { if utils.IsValidUUIDString(id) { return nil, errors.NotFoundf("environment %q", id) } // TODO(axw) 2013-12-04 #1257587 // We should not accept environment tags that do not match the // environment's UUID. We accept anything for now, to cater // both for past usage, and for potentially supporting aliases. logger.Warningf("environment-tag does not match current environment UUID: %q != %q", id, env.UUID()) conf, err := st.EnvironConfig() if err != nil { logger.Warningf("EnvironConfig failed: %v", err) } else if id != conf.Name() { logger.Warningf("environment-tag does not match current environment name: %q != %q", id, conf.Name()) } } return env, nil case names.RelationTagKind: return st.KeyRelation(id) case names.NetworkTagKind: return st.Network(id) } return nil, err }
// Upgrader returns an object that provides access to the Upgrader API facade. // The id argument is reserved for future use and must be empty. func (r *srvRoot) Upgrader(id string) (upgrader.Upgrader, error) { if id != "" { // TODO: There is no direct test for this return nil, common.ErrBadId } // The type of upgrader we return depends on who is asking. // Machines get an UpgraderAPI, units get a UnitUpgraderAPI. // This is tested in the state/api/upgrader package since there // are currently no direct srvRoot tests. tagKind, _, err := names.ParseTag(r.GetAuthTag(), "") if err != nil { return nil, common.ErrPerm } switch tagKind { case names.MachineTagKind: return upgrader.NewUpgraderAPI(r.srv.state, r.resources, r) case names.UnitTagKind: return upgrader.NewUnitUpgraderAPI(r.srv.state, r.resources, r) } // Not a machine or unit. return nil, common.ErrPerm }
// AddService creates a new service, running the supplied charm, with the // supplied name (which must be unique). If the charm defines peer relations, // they will be created automatically. func (st *State) AddService(name, ownerTag string, ch *Charm, includeNetworks, excludeNetworks []string) (service *Service, err error) { defer errors.Maskf(&err, "cannot add service %q", name) kind, ownerId, err := names.ParseTag(ownerTag, names.UserTagKind) if err != nil || kind != names.UserTagKind { return nil, fmt.Errorf("Invalid ownertag %s", ownerTag) } // Sanity checks. if !names.IsService(name) { return nil, fmt.Errorf("invalid name") } if ch == nil { return nil, fmt.Errorf("charm is nil") } if exists, err := isNotDead(st.services, name); err != nil { return nil, err } else if exists { return nil, fmt.Errorf("service already exists") } env, err := st.Environment() if err != nil { return nil, err } else if env.Life() != Alive { return nil, fmt.Errorf("environment is no longer alive") } if userExists, err := st.checkUserExists(ownerId); err != nil { return nil, err } else if !userExists { return nil, fmt.Errorf("user %v doesn't exist", ownerId) } // Create the service addition operations. peers := ch.Meta().Peers svcDoc := &serviceDoc{ Name: name, Series: ch.URL().Series, Subordinate: ch.Meta().Subordinate, CharmURL: ch.URL(), RelationCount: len(peers), Life: Alive, OwnerTag: ownerTag, } svc := newService(st, svcDoc) ops := []txn.Op{ env.assertAliveOp(), createConstraintsOp(st, svc.globalKey(), constraints.Value{}), // TODO(dimitern) 2014-04-04 bug #1302498 // Once we can add networks independently of machine // provisioning, we should check the given networks are valid // and known before setting them. createRequestedNetworksOp(st, svc.globalKey(), includeNetworks, excludeNetworks), createSettingsOp(st, svc.settingsKey(), nil), { C: st.users.Name, Id: ownerId, Assert: txn.DocExists, }, { C: st.settingsrefs.Name, Id: svc.settingsKey(), Assert: txn.DocMissing, Insert: settingsRefsDoc{1}, }, { C: st.services.Name, Id: name, Assert: txn.DocMissing, Insert: svcDoc, }} // Collect peer relation addition operations. peerOps, err := st.addPeerRelationsOps(name, peers) if err != nil { return nil, err } ops = append(ops, peerOps...) if err := st.runTransaction(ops); err == txn.ErrAborted { err := env.Refresh() if (err == nil && env.Life() != Alive) || errors.IsNotFound(err) { return nil, fmt.Errorf("environment is no longer alive") } else if err != nil { return nil, err } if userExists, ueErr := st.checkUserExists(ownerId); ueErr != nil { return nil, ueErr } else if !userExists { return nil, fmt.Errorf("unknown user %q", ownerId) } return nil, fmt.Errorf("service already exists") } else if err != nil { return nil, err } // Refresh to pick the txn-revno. if err = svc.Refresh(); err != nil { return nil, err } return svc, nil }