Example #1
0
File: unit.go Project: jkary/core
// 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
}
Example #2
0
// 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
}
Example #3
0
// 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
}
Example #4
0
// 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
}
Example #5
0
File: unit.go Project: jkary/core
// 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
}
Example #6
0
File: state.go Project: jkary/core
// 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
}
Example #7
0
// 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
}
Example #8
0
File: client.go Project: jkary/core
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
}
Example #9
0
// 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
}
Example #10
0
File: api.go Project: jkary/core
// 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()
}
Example #11
0
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)
}
Example #12
0
// 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
}
Example #13
0
File: state.go Project: jkary/core
// 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
}
Example #14
0
File: root.go Project: jkary/core
// 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
}
Example #15
0
File: state.go Project: jkary/core
// 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
}