package service import ( "context" "go.infratographer.com/x/events" "go.infratographer.com/x/gidx" "go.equinixmetal.net/infra9-metal-bridge/internal/metal/models" ) const projectEvent = "metalproject" // buildProjectRelationships compiles all relations into a relationships object to be processed by the processors. func (s *service) buildProjectRelationships(project *models.ProjectDetails) (Relationships, error) { relations := Relationships{ Resource: project, // Relate project to organization. Parent: Relation{ Resource: project.Organization, Relation: RelateParent, }, } for _, member := range project.Memberships { for _, role := range member.Roles { if _, ok := s.roles[role]; !ok { s.logger.Warnf("unrecognized project role '%s' for %s on %s", role, member.User.PrefixedID(), project.PrefixedID()) continue } relations.Memberships = append(relations.Memberships, ResourceMemberships{ Role: role, Member: member.User, }) } } return relations, nil } // IsProjectID checks if the provided id has the metal project prefix. func (s *service) IsProjectID(id gidx.PrefixedID) bool { if idType, ok := s.idPrefixMap[id.Prefix()]; ok { return idType == TypeProject } return false } // TouchProject initializes a sync for the provided project id for relationships and memberships. func (s *service) TouchProject(ctx context.Context, id gidx.PrefixedID) error { logger := s.logger.With("project.id", id.String()) project, err := s.metal.GetProjectDetails(ctx, id) if err != nil { logger.Errorw("failed to get project", "error", err) return err } relationships, err := s.buildProjectRelationships(project) if err != nil { logger.Errorw("failed to build project relationships", "error", err) return err } relationshipChanges := s.processRelationships(ctx, projectEvent, relationships) rolesChanged, assignmentsChanged := s.syncMemberships(ctx, relationships, false) s.logger.Infow("project sync complete", "resource.id", project.PrefixedID(), "relationships.changed", relationshipChanges, "membership.roles_changed", rolesChanged, "membership.assignments_changed", assignmentsChanged, ) return nil } // DeleteProject deletes the provided project id. func (s *service) DeleteProject(ctx context.Context, id gidx.PrefixedID) error { err := s.publisher.PublishChange(ctx, projectEvent, events.ChangeMessage{ SubjectID: id, EventType: string(events.DeleteChangeType), }) if err != nil { s.logger.Errorw("error publishing project delete", "subject_type", projectEvent, "resource.id", id, "error", err, ) } return nil }