// suspendRevokedRelationsOps suspends any relations the given user has against
// the specified offer.
967111
func (st *State) suspendRevokedRelationsOps(offerUUID, userId string) ([]txn.Op, error) {
	conns, err := st.OfferConnections(offerUUID)
	if err != nil {
		return nil, errors.Trace(err)
	}

	var ops []txn.Op
	relIdsToSuspend := make(set.Ints)
	for _, oc := range conns {
		if oc.UserName() == userId {
			rel, err := st.Relation(oc.RelationId())
			if err != nil {
				return nil, errors.Trace(err)
			}
			if rel.Suspended() {
				continue
			}
			relIdsToSuspend.Add(rel.Id())
			suspendOp := txn.Op{
				C:      relationsC,
				Id:     rel.doc.DocID,
				Assert: txn.DocExists,
				Update: bson.D{{"$set", bson.D{{"suspended", true}}}},
			}
			ops = append(ops, suspendOp)
		}
	}

	// Add asserts that the relations against the offered application don't change.
	// This is broader than what we need but it's all that's possible.
	ao := NewApplicationOffers(st)
	offer, err := ao.ApplicationOfferForUUID(offerUUID)
	if err != nil {
		return nil, errors.Trace(err)
	}
	app, err := st.Application(offer.ApplicationName)
	if err != nil {
		return nil, errors.Trace(err)
	}
	relations, err := app.Relations()
	if err != nil {
		return nil, errors.Trace(err)
	}
	sameRelCount := bson.D{{"relationcount", len(relations)}}
	ops = append(ops, txn.Op{
		C:      applicationsC,
		Id:     app.doc.DocID,
		Assert: sameRelCount,
	})
	// Ensure any relations not being updated still exist.
	for _, r := range relations {
		if relIdsToSuspend.Contains(r.Id()) {
			continue
		}
		ops = append(ops, txn.Op{
			C:      relationsC,
			Id:     r.doc.DocID,
			Assert: txn.DocExists,
		})
	}

	return ops, nil
}
569286
func CorrectRelationUnitCounts(pool *StatePool) error {
	st := pool.SystemState()
	applicationsColl, aCloser := st.db().GetRawCollection(applicationsC)
	defer aCloser()

	relationsColl, rCloser := st.db().GetRawCollection(relationsC)
	defer rCloser()

	scopesColl, sCloser := st.db().GetRawCollection(relationScopesC)
	defer sCloser()

	applications, err := collectApplicationInfo(applicationsColl)
	if err != nil {
		return errors.Trace(err)
	}
	relations, err := collectRelationInfo(relationsColl)
	if err != nil {
		return errors.Trace(err)
	}

	var ops []txn.Op
	var scope struct {
		DocId     string `bson:"_id"`
		Key       string `bson:"key"`
		ModelUUID string `bson:"model-uuid"`
	}
	relationsToUpdate := set.NewStrings()
	iter := scopesColl.Find(nil).Iter()
	defer iter.Close()

	for iter.Next(&scope) {
		// Scope key looks like: r#<relation id>#[<principal unit for container scope>#]<role>#<unit>
		keyParts := strings.Split(scope.Key, "#")
		if len(keyParts) < 4 {
			upgradesLogger.Errorf("malformed scope key %q", scope.Key)
			continue
		}

		principalApp, found := extractPrincipalUnitApp(keyParts)
		if !found {
			// No change needed - this isn't a container scope.
			continue
		}
		relationKey := scope.ModelUUID + ":" + keyParts[1]
		relation, ok := relations[relationKey]
		if !ok {
			upgradesLogger.Errorf("orphaned relation scope %q", scope.DocId)
			continue
		}

		if relation.endpoints.Contains(principalApp) {
			// This scope record is fine - it's for an app that's in the relation.
			continue
		}

		unit := keyParts[len(keyParts)-1]
		subordinate, err := otherEndIsSubordinate(relation, unit, scope.ModelUUID, applications)
		if err != nil {
			return errors.Trace(err)
		}
		if subordinate {
			// The other end for this unit is for a subordinate
			// application, allow those.
			continue
		}

		// This scope record needs to be removed and the unit count updated.
		relation.unitCount--
		relationsToUpdate.Add(relationKey)
		ops = append(ops, txn.Op{
			C:      relationScopesC,
			Id:     scope.DocId,
			Assert: txn.DocExists,
			Remove: true,
		})
	}
	if err := iter.Close(); err != nil {
		return errors.Trace(err)
	}

	// Add in the updated unit counts.
	for _, key := range relationsToUpdate.Values() {
		relation := relations[key]
		ops = append(ops, txn.Op{
			C:      relationsC,
			Id:     relation.docId,
			Assert: txn.DocExists,
			Update: bson.M{"$set": bson.M{"unitcount": relation.unitCount}},
		})
	}
	if len(ops) > 0 {
		return errors.Trace(st.runRawTransaction(ops))
	}
	return nil
}
308460
func (c *Client) DestroyRelation(force *bool, maxWait *time.Duration, endpoints ...string) error {
	args := params.DestroyRelation{
		Endpoints: endpoints,
		Force:     force,
		MaxWait:   maxWait,
	}
	return c.facade.FacadeCall("DestroyRelation", args, nil)
}
646098
func (s *Session) RelationshipFriendRequestSend(userID string) (err error) {
	err = s.relationshipCreate(userID, 4)
	return
}
249675
func (s *UpdateStackSetInput) SetOperationPreferences(v *StackSetOperationPreferences) *UpdateStackSetInput {
	s.OperationPreferences = v
	return s
}
1248195
func (p ResourcePersistence) NewRemovePendingAppResourcesOps(applicationID string, pendingIDs map[string]string) ([]txn.Op, error) {
	docs, err := p.resources(applicationID)
	if err != nil {
		return nil, errors.Trace(err)
	}
	pending := make([]resourceDoc, 0, len(docs))
	for _, doc := range docs {
		if doc.UnitID != "" || doc.PendingID == "" {
			continue
		}
		if pendingIDs[doc.Name] != doc.PendingID {
			// This is a pending resource for a different deployment
			// of an application with the same name.
			continue
		}
		pending = append(pending, doc)
	}
	return removeResourcesAndStorageCleanupOps(pending), nil
}
107415
func (p *remoteRelationPoller) pollLoop() error {
	logger.Debugf("polling for relation %v on %v to be ready", p.relationTag, p.applicationTag)
	for {
		select {
		case <-p.catacomb.Dying():
			return p.catacomb.ErrDying()
		case <-p.fw.pollClock.After(3 * time.Second):
			// Relation is exported with the consuming model UUID.
			relToken, err := p.fw.remoteRelationsApi.GetToken(p.relationTag)
			if err != nil {
				continue
			}
			logger.Debugf("token %v for relation id: %v in model %v", relToken, p.relationTag.Id(), p.fw.modelUUID)

			// Application is exported with the offering model UUID.
			appToken, err := p.fw.remoteRelationsApi.GetToken(p.applicationTag)
			if err != nil {
				continue
			}
			logger.Debugf("token %v for application id: %v", appToken, p.applicationTag.Id())

			// relation and application are ready.
			relationInfo := remoteRelationInfo{
				relationToken:    relToken,
				applicationToken: appToken,
			}
			select {
			case <-p.catacomb.Dying():
				return p.catacomb.ErrDying()
			case p.relationReady <- relationInfo:
			}
			return nil
		}
	}
}
1097810
func (r *multiModelRunner) updateOps(ops []txn.Op) ([]txn.Op, error) {
	var outOps []txn.Op
	for _, op := range ops {
		collInfo, found := r.schema[op.C]
		if !found {
			return nil, errors.Errorf("forbidden transaction: references unknown collection %q", op.C)
		}
		if collInfo.rawAccess {
			return nil, errors.Errorf("forbidden transaction: references raw-access collection %q", op.C)
		}
		outOp := op
		if !collInfo.global {
			outOp.Id = ensureModelUUIDIfString(r.modelUUID, op.Id)
			if op.Insert != nil {
				newInsert, err := mungeDocForMultiModel(op.Insert, r.modelUUID, modelUUIDRequired)
				if err != nil {
					return nil, errors.Annotatef(err, "cannot insert into %q", op.C)
				}
				outOp.Insert = newInsert
			}
			if op.Update != nil {
				newUpdate, err := r.mungeUpdate(op.Update)
				if err != nil {
					return nil, errors.Annotatef(err, "cannot update %q", op.C)
				}
				outOp.Update = newUpdate
			}
		}
		outOps = append(outOps, outOp)
	}
	return outOps, nil
}
1063996
func (c *Client) RegisterRemoteRelations(relations ...params.RegisterRemoteRelationArg) ([]params.RegisterRemoteRelationResult, error) {
	var (
		args         params.RegisterRemoteRelationArgs
		retryIndices []int
	)

	args = params.RegisterRemoteRelationArgs{Relations: relations}
	// Use any previously cached discharge macaroons.
	for i, arg := range relations {
		if ms, ok := c.getCachedMacaroon("register remote relation", arg.RelationToken); ok {
			newArg := arg
			newArg.Macaroons = ms
			args.Relations[i] = newArg
		}
	}

	var results params.RegisterRemoteRelationResults
	apiCall := func() error {
		// Reset the results struct before each api call.
		results = params.RegisterRemoteRelationResults{}
		err := c.facade.FacadeCall("RegisterRemoteRelations", args, &results)
		if err != nil {
			return errors.Trace(err)
		}
		if len(results.Results) != len(args.Relations) {
			return errors.Errorf("expected %d result(s), got %d", len(args.Relations), len(results.Results))
		}
		return nil
	}

	// Make the api call the first time.
	if err := apiCall(); err != nil {
		return nil, errors.Trace(err)
	}
	// On error, possibly discharge the macaroon and retry.
	result := results.Results
	args = params.RegisterRemoteRelationArgs{}
	// Separate the successful calls from those needing a retry.
	for i, res := range results.Results {
		if res.Error == nil {
			continue
		}
		mac, err := c.handleError(res.Error)
		if err != nil {
			resCopy := res
			resCopy.Error.Message = err.Error()
			result[i] = resCopy
			continue
		}
		retryArg := relations[i]
		retryArg.Macaroons = mac
		args.Relations = append(args.Relations, retryArg)
		retryIndices = append(retryIndices, i)
		c.cache.Upsert(retryArg.RelationToken, mac)
	}
	// Nothing to retry so return the original result.
	if len(args.Relations) == 0 {
		return result, nil
	}

	if err := apiCall(); err != nil {
		return nil, errors.Trace(err)
	}
	// After a retry, insert the results into the original result slice.
	for j, res := range results.Results {
		resCopy := res
		result[retryIndices[j]] = resCopy
	}
	return result, nil
}
1309389
func (s *Block) SetRelationships(v []*Relationship) *Block {
	s.Relationships = v
	return s
}
395439
func (vm *VM) Suspend() error {
	if vm.MockSuspend != nil {
		return vm.MockSuspend()
	}
	return lvm.ErrNotImplemented
}
1204418
func (s *ProjectService) NewSuspendProjectParams(id string) *SuspendProjectParams {
	p := &SuspendProjectParams{}
	p.p = make(map[string]interface{})
	p.p["id"] = id
	return p
}
711466
func (s *RemoteApplication) removeOps(asserts bson.D) ([]txn.Op, error) {
	r := s.st.RemoteEntities()
	ops := []txn.Op{
		{
			C:      remoteApplicationsC,
			Id:     s.doc.DocID,
			Assert: asserts,
			Remove: true,
		},
		removeStatusOp(s.st, s.globalKey()),
	}
	tokenOps := r.removeRemoteEntityOps(s.Tag())
	ops = append(ops, tokenOps...)
	return ops, nil
}
290641
func (r *Relation) removeLocalEndpointOps(ep Endpoint, departingUnitName string, op *ForcedOperation) ([]txn.Op, error) {
	var asserts bson.D
	hasRelation := bson.D{{"relationcount", bson.D{{"$gt", 0}}}}
	departingUnitApplicationMatchesEndpoint := func() bool {
		s, err := names.UnitApplication(departingUnitName)
		return err == nil && s == ep.ApplicationName
	}
	var cleanupOps []txn.Op
	if departingUnitName == "" {
		// We're constructing a destroy operation, either of the relation
		// or one of its applications, and can therefore be assured that both
		// applications are Alive.
		asserts = append(hasRelation, isAliveDoc...)
	} else if departingUnitApplicationMatchesEndpoint() {
		// This application must have at least one unit -- the one that's
		// departing the relation -- so it cannot be ready for removal.
		cannotDieYet := bson.D{{"unitcount", bson.D{{"$gt", 0}}}}
		asserts = append(hasRelation, cannotDieYet...)
	} else {
		// This application may require immediate removal.
		// Check if the application is Dying, and if so, queue up a potential
		// cleanup in case this was the last reference.
		applications, closer := r.st.db().GetCollection(applicationsC)
		defer closer()

		asserts = append(hasRelation)
		var appDoc applicationDoc
		if err := applications.FindId(ep.ApplicationName).One(&appDoc); err == nil {
			if appDoc.Life != Alive {
				cleanupOps = append(cleanupOps, newCleanupOp(
					cleanupApplication,
					ep.ApplicationName,
					false, // destroyStorage
					op.Force,
				))
			}
		} else if !op.Force {
			return nil, errors.Trace(err)
		}
	}
	return append([]txn.Op{{
		C:      applicationsC,
		Id:     r.st.docID(ep.ApplicationName),
		Assert: asserts,
		Update: bson.D{{"$inc", bson.D{{"relationcount", -1}}}},
	}}, cleanupOps...), nil
}
774426
func (o *oracleInstance) disassociatePublicIps(remove bool) error {
	associations, err := o.publicAddressesAssociations()
	if err != nil {
		return err
	}

	for _, ipAssoc := range associations {
		reservation := ipAssoc.Reservation
		name := ipAssoc.Name
		if err := o.env.client.DeleteIpAssociation(name); err != nil {
			if oci.IsNotFound(err) {
				continue
			}

			return err
		}

		if remove {
			if err := o.env.client.DeleteIpReservation(reservation); err != nil {
				if oci.IsNotFound(err) {
					return nil
				}
				return err
			}
		}
	}

	return nil
}
362337
func (c *Client) CharmRelations(application string) ([]string, error) {
	var results params.ApplicationCharmRelationsResults
	args := params.ApplicationCharmRelations{ApplicationName: application}
	err := c.facade.FacadeCall("CharmRelations", args, &results)
	return results.CharmRelations, err
}
1079574
func (a *authenticator) CheckRelationMacaroons(relationTag names.Tag, mac macaroon.Slice) error {
	requiredValues := map[string]string{
		sourcemodelKey: a.sourceModelUUID,
		relationKey:    relationTag.Id(),
	}
	_, err := a.checkMacaroons(mac, requiredValues)
	return err
}