restructure and process additions and deleteions of relationships, roles and memberships
This commit is contained in:
@@ -5,27 +5,207 @@ import (
|
||||
|
||||
"go.infratographer.com/x/events"
|
||||
"go.infratographer.com/x/gidx"
|
||||
|
||||
"go.equinixmetal.net/infra9-metal-bridge/internal/permissions"
|
||||
)
|
||||
|
||||
func (s *service) processRelationships(ctx context.Context, subjectType string, relationships []Relationship) {
|
||||
var err error
|
||||
type relationshipStats struct {
|
||||
parentCreated bool
|
||||
parentsDeleted int
|
||||
subjectRelationshipsCreated int
|
||||
subjectRelationshipsDeleted int
|
||||
}
|
||||
|
||||
for _, rel := range relationships {
|
||||
err = s.publisher.PublishChange(ctx, subjectType, events.ChangeMessage{
|
||||
SubjectID: rel.Resource.PrefixedID(),
|
||||
func (s *service) processRelationships(ctx context.Context, eventType string, relationships Relationships) int {
|
||||
rlogger := s.logger.With("resource.id", relationships.Resource.PrefixedID())
|
||||
|
||||
wantParentRelationship, wantSubjectRelationships := s.mapRelationWants(relationships)
|
||||
|
||||
liveParentRelationships, liveSubjectRelationships, err := s.getRelationshipMap(ctx, relationships.Resource, relationships.SubjectType)
|
||||
if err != nil {
|
||||
rlogger.Errorw("failed to get relationship map",
|
||||
"relationships.subject_type", relationships.SubjectType,
|
||||
"error", err,
|
||||
)
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
var (
|
||||
createParentRelationship *Relation
|
||||
deleteParentRelationships []gidx.PrefixedID
|
||||
|
||||
foundParent bool
|
||||
|
||||
createSubjectRelationships []Relation
|
||||
deleteSubjectRelationships []Relation
|
||||
)
|
||||
|
||||
if wantParentRelationship != nil {
|
||||
for subjID := range liveParentRelationships {
|
||||
if subjID == wantParentRelationship.Resource.PrefixedID() {
|
||||
foundParent = true
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
deleteParentRelationships = append(deleteParentRelationships, subjID)
|
||||
}
|
||||
|
||||
if !foundParent {
|
||||
createParentRelationship = wantParentRelationship
|
||||
}
|
||||
} else {
|
||||
for subjID := range liveParentRelationships {
|
||||
deleteParentRelationships = append(deleteParentRelationships, subjID)
|
||||
}
|
||||
}
|
||||
|
||||
for resID, relation := range wantSubjectRelationships {
|
||||
if _, ok := liveSubjectRelationships[resID]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
createSubjectRelationships = append(createSubjectRelationships, Relation{
|
||||
Resource: prefixedID{resID},
|
||||
Relation: relation,
|
||||
})
|
||||
}
|
||||
|
||||
for resID, relation := range liveSubjectRelationships {
|
||||
if _, ok := wantSubjectRelationships[resID]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
deleteSubjectRelationships = append(deleteSubjectRelationships, Relation{
|
||||
Resource: prefixedID{resID},
|
||||
Relation: relation,
|
||||
})
|
||||
}
|
||||
|
||||
var processEvents []events.ChangeMessage
|
||||
|
||||
rlogger.Debugw("processing relationships",
|
||||
"parent.create", createParentRelationship != nil,
|
||||
"parent.delete", len(deleteParentRelationships),
|
||||
"subject.create", len(createSubjectRelationships),
|
||||
"subject.delete", len(deleteSubjectRelationships),
|
||||
)
|
||||
|
||||
if createParentRelationship != nil {
|
||||
processEvents = append(processEvents, events.ChangeMessage{
|
||||
SubjectID: relationships.Resource.PrefixedID(),
|
||||
EventType: string(events.CreateChangeType),
|
||||
AdditionalSubjectIDs: []gidx.PrefixedID{
|
||||
rel.RelatedResource.PrefixedID(),
|
||||
createParentRelationship.Resource.PrefixedID(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for _, relatedResourceID := range deleteParentRelationships {
|
||||
processEvents = append(processEvents, events.ChangeMessage{
|
||||
SubjectID: relationships.Resource.PrefixedID(),
|
||||
EventType: string(events.DeleteChangeType),
|
||||
AdditionalSubjectIDs: []gidx.PrefixedID{
|
||||
relatedResourceID,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for _, relation := range createSubjectRelationships {
|
||||
processEvents = append(processEvents, events.ChangeMessage{
|
||||
SubjectID: relation.Resource.PrefixedID(),
|
||||
EventType: string(events.CreateChangeType),
|
||||
AdditionalSubjectIDs: []gidx.PrefixedID{
|
||||
relationships.Resource.PrefixedID(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for _, relation := range deleteSubjectRelationships {
|
||||
processEvents = append(processEvents, events.ChangeMessage{
|
||||
SubjectID: relation.Resource.PrefixedID(),
|
||||
EventType: string(events.DeleteChangeType),
|
||||
AdditionalSubjectIDs: []gidx.PrefixedID{
|
||||
relationships.Resource.PrefixedID(),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
for _, event := range processEvents {
|
||||
err = s.publisher.PublishChange(ctx, eventType, event)
|
||||
|
||||
if err != nil {
|
||||
s.logger.Errorw("error publishing change",
|
||||
"subject_type", subjectType,
|
||||
"resource.id", rel.Resource.PrefixedID(),
|
||||
"related_resource.id", rel.RelatedResource.PrefixedID(),
|
||||
rlogger.Errorw("error publishing change",
|
||||
"subject_type", eventType,
|
||||
"subject.id", event.SubjectID,
|
||||
"event.type", event.EventType,
|
||||
"additional_subject_ids", event.AdditionalSubjectIDs,
|
||||
"error", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
rlogger.Debugw("relationships processed",
|
||||
"parent.create", createParentRelationship != nil,
|
||||
"parent.delete", len(deleteParentRelationships),
|
||||
"subject.create", len(createSubjectRelationships),
|
||||
"subject.delete", len(deleteSubjectRelationships),
|
||||
)
|
||||
|
||||
changes := len(deleteParentRelationships) + len(createSubjectRelationships) + len(deleteSubjectRelationships)
|
||||
|
||||
if createParentRelationship != nil {
|
||||
changes++
|
||||
}
|
||||
|
||||
return changes
|
||||
}
|
||||
|
||||
func (s *service) mapRelationWants(relationships Relationships) (*Relation, map[gidx.PrefixedID]RelationshipType) {
|
||||
var wantParent *Relation
|
||||
|
||||
wantSubject := make(map[gidx.PrefixedID]RelationshipType)
|
||||
|
||||
if relationships.Parent.Resource != nil {
|
||||
wantParent = &relationships.Parent
|
||||
}
|
||||
|
||||
for _, relationship := range relationships.SubjectRelationships {
|
||||
wantSubject[relationship.Resource.PrefixedID()] = relationship.Relation
|
||||
}
|
||||
|
||||
return wantParent, wantSubject
|
||||
}
|
||||
|
||||
func (s *service) getRelationshipMap(ctx context.Context, resource IDPrefixableResource, relatedObjectType ObjectType) (map[gidx.PrefixedID]RelationshipType, map[gidx.PrefixedID]RelationshipType, error) {
|
||||
liveResource, err := s.perms.ListResourceRelationships(ctx, resource.PrefixedID(), "")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var liveSubject []permissions.ResourceRelationship
|
||||
|
||||
if relatedObjectType != "" {
|
||||
liveSubject, err = s.perms.ListResourceRelationships(ctx, resource.PrefixedID(), relatedObjectType.Prefix())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
parents := make(map[gidx.PrefixedID]RelationshipType, len(liveResource))
|
||||
for _, relationship := range liveResource {
|
||||
if relationship.Relation != string(RelateParent) {
|
||||
continue
|
||||
}
|
||||
|
||||
parents[relationship.SubjectID] = RelationshipType(relationship.Relation)
|
||||
}
|
||||
|
||||
subject := make(map[gidx.PrefixedID]RelationshipType, len(liveSubject))
|
||||
for _, relationship := range liveSubject {
|
||||
subject[relationship.ResourceID] = RelationshipType(relationship.Relation)
|
||||
}
|
||||
|
||||
return parents, subject, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user