Пример #1
0
// fetchData gets all the data from the given path relative to the given base URL.
// It returns the data found and the full URL used.
func fetchData(baseURL, path string, requireSigned bool) (data []byte, dataURL string, err error) {
	dataURL = baseURL
	if !strings.HasSuffix(dataURL, "/") {
		dataURL += "/"
	}
	dataURL += path
	resp, err := http.Get(dataURL)
	if err != nil {
		return nil, dataURL, errors.NotFoundf("invalid URL %q", dataURL)
	}
	defer resp.Body.Close()
	if resp.StatusCode == http.StatusNotFound {
		return nil, dataURL, errors.NotFoundf("cannot find URL %q", dataURL)
	}
	if resp.StatusCode == http.StatusUnauthorized {
		return nil, dataURL, errors.Unauthorizedf("unauthorised access to URL %q", dataURL)
	}
	if resp.StatusCode != http.StatusOK {
		return nil, dataURL, fmt.Errorf("cannot access URL %q, %q", dataURL, resp.Status)
	}

	if requireSigned {
		data, err = DecodeCheckSignature(resp.Body)
	} else {
		data, err = ioutil.ReadAll(resp.Body)
	}
	if err != nil {
		return nil, dataURL, fmt.Errorf("cannot read URL data, %v", err)
	}
	return data, dataURL, nil
}
Пример #2
0
// getImageIdsPath returns the path to the metadata file containing image ids the specified constraint.
func (indexRef *indexReference) getImageIdsPath(ic *ImageConstraint) (string, error) {
	prodIds, err := ic.Ids()
	if err != nil {
		return "", err
	}
	var containsImageIds bool
	for _, metadata := range indexRef.Indexes {
		if metadata.DataType != imageIds {
			continue
		}
		containsImageIds = true
		var cloudSpecMatches bool
		for _, cs := range metadata.Clouds {
			if cs == ic.CloudSpec {
				cloudSpecMatches = true
				break
			}
		}
		var prodSpecMatches bool
		for _, pid := range metadata.ProductIds {
			if containsString(prodIds, pid) {
				prodSpecMatches = true
				break
			}
		}
		if cloudSpecMatches && prodSpecMatches {
			return metadata.ProductsFilePath, nil
		}
	}
	if !containsImageIds {
		return "", errors.NotFoundf("index file missing %q data", imageIds)
	}
	return "", errors.NotFoundf("index file missing data for cloud %v and product name(s) %q", ic.CloudSpec, prodIds)
}
Пример #3
0
// AgentTools returns the tools that the agent is currently running.
// It an error that satisfies IsNotFound if the tools have not yet been set.
func (u *Unit) AgentTools() (*tools.Tools, error) {
	if u.doc.Tools == nil {
		return nil, errors.NotFoundf("agent tools for unit %q", u)
	}
	tools := *u.doc.Tools
	return &tools, nil
}
Пример #4
0
// getUser fetches information about the user with the
// given name into the provided userDoc.
func (st *State) getUser(name string, udoc *userDoc) error {
	err := st.users.Find(D{{"_id", name}}).One(udoc)
	if err == mgo.ErrNotFound {
		err = errors.NotFoundf("user %q", name)
	}
	return err
}
Пример #5
0
// removeSettings removes the Settings for key.
func removeSettings(st *State, key string) error {
	err := st.settings.RemoveId(key)
	if err == mgo.ErrNotFound {
		return errors.NotFoundf("settings")
	}
	return nil
}
Пример #6
0
// 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, "")
	// TODO(fwereade): when lp:1199352 (relation lacks Tag) is fixed, add
	// support for relation entities here.
	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:
		conf, err := st.EnvironConfig()
		if err != nil {
			return nil, err
		}
		// Return an invalid entity error if the requested environment is not
		// the current one.
		if id != conf.Name() {
			return nil, errors.NotFoundf("environment %q", id)
		}
		return st.Environment()
	}
	return nil, err
}
Пример #7
0
// settingsDecRefOps returns a list of operations that decrement the
// ref count of the service settings identified by serviceName and
// curl. If the ref count is set to zero, the appropriate setting and
// ref count documents will both be deleted.
func settingsDecRefOps(st *State, serviceName string, curl *charm.URL) ([]txn.Op, error) {
	key := serviceSettingsKey(serviceName, curl)
	var doc settingsRefsDoc
	if err := st.settingsrefs.FindId(key).One(&doc); err == mgo.ErrNotFound {
		return nil, errors.NotFoundf("service %q settings for charm %q", serviceName, curl)
	} else if err != nil {
		return nil, err
	}
	if doc.RefCount == 1 {
		return []txn.Op{{
			C:      st.settingsrefs.Name,
			Id:     key,
			Assert: D{{"refcount", 1}},
			Remove: true,
		}, {
			C:      st.settings.Name,
			Id:     key,
			Remove: true,
		}}, nil
	}
	return []txn.Op{{
		C:      st.settingsrefs.Name,
		Id:     key,
		Assert: D{{"refcount", D{{"$gt", 1}}}},
		Update: D{{"$inc", D{{"refcount", -1}}}},
	}}, nil
}
Пример #8
0
// AgentTools returns the tools that the agent is currently running.
// It returns an error that satisfies IsNotFound if the tools have not yet been set.
func (m *Machine) AgentTools() (*tools.Tools, error) {
	if m.doc.Tools == nil {
		return nil, errors.NotFoundf("agent tools for machine %v", m)
	}
	tools := *m.doc.Tools
	return &tools, nil
}
Пример #9
0
func (st *fakeLifeState) Lifer(tag string) (state.Lifer, error) {
	if lifer, ok := st.entities[tag]; ok {
		if lifer.err != nil {
			return nil, lifer.err
		}
		return lifer, nil
	}
	return nil, errors.NotFoundf("entity %q", tag)
}
Пример #10
0
func readConstraints(st *State, id string) (constraints.Value, error) {
	doc := constraintsDoc{}
	if err := st.constraints.FindId(id).One(&doc); err == mgo.ErrNotFound {
		return constraints.Value{}, errors.NotFoundf("constraints")
	} else if err != nil {
		return constraints.Value{}, err
	}
	return doc.value(), nil
}
Пример #11
0
func (st *fakeRemoverState) Remover(tag string) (state.Remover, error) {
	if remover, ok := st.entities[tag]; ok {
		if remover.err != nil {
			return nil, remover.err
		}
		return remover, nil
	}
	return nil, errors.NotFoundf("entity %q", tag)
}
Пример #12
0
// Refresh refreshes the contents of the relation from the underlying
// state. It returns an error that satisfies IsNotFound if the relation has been
// removed.
func (r *Relation) Refresh() error {
	doc := relationDoc{}
	err := r.st.relations.FindId(r.doc.Key).One(&doc)
	if err == mgo.ErrNotFound {
		return errors.NotFoundf("relation %v", r)
	}
	if err != nil {
		return fmt.Errorf("cannot refresh relation %v: %v", r, err)
	}
	if r.doc.Id != doc.Id {
		// The relation has been destroyed and recreated. This is *not* the
		// same relation; if we pretend it is, we run the risk of violating
		// the lifecycle-only-advances guarantee.
		return errors.NotFoundf("relation %v", r)
	}
	r.doc = doc
	return nil
}
Пример #13
0
// Refresh refreshes the contents of the Service from the underlying
// state. It returns an error that satisfies IsNotFound if the service has
// been removed.
func (s *Service) Refresh() error {
	err := s.st.services.FindId(s.doc.Name).One(&s.doc)
	if err == mgo.ErrNotFound {
		return errors.NotFoundf("service %q", s)
	}
	if err != nil {
		return fmt.Errorf("cannot refresh service %q: %v", s, err)
	}
	return nil
}
Пример #14
0
func (st *fakeState) FindEntity(tag string) (state.Entity, error) {
	entity, ok := st.entities[tag]
	if !ok {
		return nil, errors.NotFoundf("entity %q", tag)
	}
	if err := entity.error(); err != nil {
		return nil, err
	}
	return entity, nil
}
Пример #15
0
// constraints is a helper function to return a unit's deployment constraints.
func (u *Unit) constraints() (*constraints.Value, error) {
	cons, err := readConstraints(u.st, u.globalKey())
	if errors.IsNotFoundError(err) {
		// Lack of constraints indicates lack of unit.
		return nil, errors.NotFoundf("unit")
	} else if err != nil {
		return nil, err
	}
	return &cons, nil
}
Пример #16
0
// Refresh refreshes the contents of the Unit from the underlying
// state. It an error that satisfies IsNotFound if the unit has been removed.
func (u *Unit) Refresh() error {
	err := u.st.units.FindId(u.doc.Name).One(&u.doc)
	if err == mgo.ErrNotFound {
		return errors.NotFoundf("unit %q", u)
	}
	if err != nil {
		return fmt.Errorf("cannot refresh unit %q: %v", u, err)
	}
	return nil
}
Пример #17
0
// Relation returns the existing relation with the given id.
func (st *State) Relation(id int) (*Relation, error) {
	doc := relationDoc{}
	err := st.relations.Find(D{{"id", id}}).One(&doc)
	if err == mgo.ErrNotFound {
		return nil, errors.NotFoundf("relation %d", id)
	}
	if err != nil {
		return nil, fmt.Errorf("cannot get relation %d: %v", id, err)
	}
	return newRelation(st, &doc), nil
}
Пример #18
0
// KeyRelation returns the existing relation with the given key (which can
// be derived unambiguously from the relation's endpoints).
func (st *State) KeyRelation(key string) (*Relation, error) {
	doc := relationDoc{}
	err := st.relations.Find(D{{"_id", key}}).One(&doc)
	if err == mgo.ErrNotFound {
		return nil, errors.NotFoundf("relation %q", key)
	}
	if err != nil {
		return nil, fmt.Errorf("cannot get relation %q: %v", key, err)
	}
	return newRelation(st, &doc), nil
}
Пример #19
0
// newUnitName returns the next unit name.
func (s *Service) newUnitName() (string, error) {
	change := mgo.Change{Update: D{{"$inc", D{{"unitseq", 1}}}}}
	result := serviceDoc{}
	if _, err := s.st.services.Find(D{{"_id", s.doc.Name}}).Apply(change, &result); err == mgo.ErrNotFound {
		return "", errors.NotFoundf("service %q", s)
	} else if err != nil {
		return "", fmt.Errorf("cannot increment unit sequence: %v", err)
	}
	name := s.doc.Name + "/" + strconv.Itoa(result.UnitSeq)
	return name, nil
}
Пример #20
0
// Get is specified in the StorageReader interface.
func (storage *azureStorage) Get(name string) (io.ReadCloser, error) {
	context, err := storage.getStorageContext()
	if err != nil {
		return nil, err
	}
	reader, err := context.GetBlob(storage.getContainer(), name)
	if gwacl.IsNotFoundError(err) {
		return nil, errors.NotFoundf("file %q not found", name)
	}
	return reader, err
}
Пример #21
0
// Containers returns the container ids belonging to a parent machine.
// TODO(wallyworld): move this method to a service
func (m *Machine) Containers() ([]string, error) {
	var mc machineContainers
	err := m.st.containerRefs.FindId(m.Id()).One(&mc)
	if err == nil {
		return mc.Children, nil
	}
	if err == mgo.ErrNotFound {
		return nil, errors.NotFoundf("container info for machine %v", m.Id())
	}
	return nil, err
}
Пример #22
0
func getInstanceData(st *State, id string) (instanceData, error) {
	var instData instanceData
	err := st.instanceData.FindId(id).One(&instData)
	if err == mgo.ErrNotFound {
		return instanceData{}, errors.NotFoundf("instance data for machine %v", id)
	}
	if err != nil {
		return instanceData{}, fmt.Errorf("cannot get instance data for machine %v: %v", id, err)
	}
	return instData, nil
}
Пример #23
0
// getStatus retrieves the status document associated with the given
// globalKey and copies it to outStatusDoc, which needs to be created
// by the caller before.
func getStatus(st *State, globalKey string) (statusDoc, error) {
	var doc statusDoc
	err := st.statuses.FindId(globalKey).One(&doc)
	if err == mgo.ErrNotFound {
		return statusDoc{}, errors.NotFoundf("status")
	}
	if err != nil {
		return statusDoc{}, fmt.Errorf("cannot get status %q: %v", globalKey, err)
	}
	return doc, nil
}
Пример #24
0
// Machine returns the machine with the given id.
func (st *State) Machine(id string) (*Machine, error) {
	mdoc := &machineDoc{}
	sel := D{{"_id", id}}
	err := st.machines.Find(sel).One(mdoc)
	if err == mgo.ErrNotFound {
		return nil, errors.NotFoundf("machine %s", id)
	}
	if err != nil {
		return nil, fmt.Errorf("cannot get machine %s: %v", id, err)
	}
	return newMachine(st, mdoc), nil
}
Пример #25
0
// Refresh refreshes the contents of the machine from the underlying
// state. It returns an error that satisfies IsNotFound if the machine has
// been removed.
func (m *Machine) Refresh() error {
	doc := machineDoc{}
	err := m.st.machines.FindId(m.doc.Id).One(&doc)
	if err == mgo.ErrNotFound {
		return errors.NotFoundf("machine %v", m)
	}
	if err != nil {
		return fmt.Errorf("cannot refresh machine %v: %v", m, err)
	}
	m.doc = doc
	return nil
}
Пример #26
0
// SetPublicAddress sets the public address of the unit.
func (u *Unit) SetPublicAddress(address string) (err error) {
	ops := []txn.Op{{
		C:      u.st.units.Name,
		Id:     u.doc.Name,
		Assert: txn.DocExists,
		Update: D{{"$set", D{{"publicaddress", address}}}},
	}}
	if err := u.st.runTransaction(ops); err != nil {
		return fmt.Errorf("cannot set public address of unit %q: %v", u, onAbort(err, errors.NotFoundf("unit")))
	}
	u.doc.PublicAddress = address
	return nil
}
Пример #27
0
// retrieveFileObject retrieves the information of the named file, including
// its download URL and its contents, as a MAASObject.
//
// This may return many different errors, but specifically, it returns
// (a pointer to) errors.NotFoundError if the file did not exist.
//
// The function takes out a lock on the storage object.
func (stor *maasStorage) retrieveFileObject(name string) (gomaasapi.MAASObject, error) {
	obj, err := stor.addressFileObject(name).Get()
	if err != nil {
		noObj := gomaasapi.MAASObject{}
		serverErr, ok := err.(gomaasapi.ServerError)
		if ok && serverErr.StatusCode == 404 {
			return noObj, errors.NotFoundf("file '%s' not found", name)
		}
		msg := fmt.Errorf("could not access file '%s': %v", name, err)
		return noObj, msg
	}
	return obj, nil
}
Пример #28
0
// Unit returns a unit by name.
func (st *State) Unit(name string) (*Unit, error) {
	if !names.IsUnit(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
}
Пример #29
0
// Charm returns the charm with the given URL.
func (st *State) Charm(curl *charm.URL) (*Charm, error) {
	cdoc := &charmDoc{}
	err := st.charms.Find(D{{"_id", curl}}).One(cdoc)
	if err == mgo.ErrNotFound {
		return nil, errors.NotFoundf("charm %q", curl)
	}
	if err != nil {
		return nil, fmt.Errorf("cannot get charm %q: %v", curl, err)
	}
	if err := cdoc.Meta.Check(); err != nil {
		return nil, fmt.Errorf("malformed charm metadata found in state: %v", err)
	}
	return newCharm(st, cdoc)
}
Пример #30
0
// Write writes changes made to c back onto its node.  Changes are written
// as a delta applied on top of the latest version of the node, to prevent
// overwriting unrelated changes made to the node since it was last read.
func (c *Settings) Write() ([]ItemChange, error) {
	changes := []ItemChange{}
	updates := map[string]interface{}{}
	deletions := map[string]int{}
	for key := range cacheKeys(c.disk, c.core) {
		old, ondisk := c.disk[key]
		new, incore := c.core[key]
		if new == old {
			continue
		}
		var change ItemChange
		escapedKey := escapeReplacer.Replace(key)
		switch {
		case incore && ondisk:
			change = ItemChange{ItemModified, key, old, new}
			updates[escapedKey] = new
		case incore && !ondisk:
			change = ItemChange{ItemAdded, key, nil, new}
			updates[escapedKey] = new
		case ondisk && !incore:
			change = ItemChange{ItemDeleted, key, old, nil}
			deletions[escapedKey] = 1
		default:
			panic("unreachable")
		}
		changes = append(changes, change)
	}
	if len(changes) == 0 {
		return []ItemChange{}, nil
	}
	sort.Sort(itemChangeSlice(changes))
	ops := []txn.Op{{
		C:      c.st.settings.Name,
		Id:     c.key,
		Assert: txn.DocExists,
		Update: D{
			{"$set", updates},
			{"$unset", deletions},
		},
	}}
	err := c.st.runTransaction(ops)
	if err == txn.ErrAborted {
		return nil, errors.NotFoundf("settings")
	}
	if err != nil {
		return nil, fmt.Errorf("cannot write settings: %v", err)
	}
	c.disk = copyMap(c.core, nil)
	return changes, nil
}