Skip to content

Commit

Permalink
started adding better error handling and refactored site to workspace…
Browse files Browse the repository at this point in the history
…s partly
  • Loading branch information
sagostin committed Sep 20, 2024
1 parent c13c535 commit d765c12
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 78 deletions.
70 changes: 35 additions & 35 deletions internal/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ package agent
import (
"context"
"crypto/rand"
"errors"
"fmt"
log "github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"io"
"nw-guardian/internal"
"regexp"
"strconv"
"time"
Expand Down Expand Up @@ -63,7 +62,7 @@ func UpdateProbeTarget(db *mongo.Database, probeID primitive.ObjectID, newTarget

_, err := db.Collection("probes").UpdateOne(context.TODO(), filter, update)
if err != nil {
return fmt.Errorf("failed to update probe target: %v", err)
return internal.ErrorFormat{Package: "internal.agent", Function: "UpdateProbeTarget", Level: log.ErrorLevel, ObjectID: probeID, Message: "unable to update probe target", Error: err}.ToError()
}

return nil
Expand Down Expand Up @@ -107,7 +106,7 @@ func (a *Agent) UpdateTimestamp(db *mongo.Database) error {
}
atoi, err := strconv.Atoi(v)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "UpdateTimestamp", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to get version for agent", Error: err}.ToError()
}

splitVer = append(splitVer, atoi)
Expand All @@ -117,7 +116,7 @@ func (a *Agent) UpdateTimestamp(db *mongo.Database) error {
probe := Probe{Agent: a.ID}
pps, err2 := probe.GetAllProbesForAgent(db)
if err2 != nil {
return err2
return internal.ErrorFormat{Package: "internal.agent", Function: "UpdateTimestamp", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to get all probes for agent", Error: err2}.ToError()
}

hasSpeedtestServers := false
Expand All @@ -137,7 +136,13 @@ func (a *Agent) UpdateTimestamp(db *mongo.Database) error {
s2 := Probe{Agent: a.ID, Type: ProbeType_SPEEDTEST_SERVERS}
err = s2.Create(db)
if err != nil {
return err
return internal.ErrorFormat{
Package: "agent",
Function: "UpdateTimestamp",
Level: log.ErrorLevel,
ObjectID: a.ID,
Message: "unable to create speedtest servers probe for agent",
Error: err}.ToError()
}
}

Expand All @@ -147,7 +152,7 @@ func (a *Agent) UpdateTimestamp(db *mongo.Database) error {
s3 := Probe{Agent: a.ID, Type: ProbeType_SPEEDTEST, Config: ProbeConfig{Target: []ProbeTarget{target}}}
err = s3.Create(db)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "UpdateTimestamp", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to create speedtest probe for agent", Error: err}.ToError()
}
}
}
Expand All @@ -164,7 +169,7 @@ func (a *Agent) UpdateAgentVersion(version string, db *mongo.Database) error {

_, err := db.Collection("agents").UpdateOne(context.TODO(), filter, update)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "UpdateAgentVersion", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to update agent version", Error: err}.ToError()
}

return nil
Expand All @@ -177,7 +182,7 @@ func (a *Agent) Initialize(db *mongo.Database) error {

_, err := db.Collection("agents").UpdateOne(context.TODO(), filter, update)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Initialize", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to initialize agent", Error: err}.ToError()
}

return nil
Expand All @@ -190,12 +195,12 @@ func DeleteAgent(db *mongo.Database, agentID primitive.ObjectID) error {

err := DeleteProbesByAgentID(db, agentID)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "DeleteAgent", Level: log.ErrorLevel, ObjectID: agentID, Message: "unable to delete probes by agent id", Error: err}.ToError()
}

_, err = db.Collection("agents").DeleteMany(context.TODO(), filter)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "DeleteAgent", Level: log.ErrorLevel, ObjectID: agentID, Message: "unable to delete agent by id", Error: err}.ToError()
}

return nil
Expand All @@ -212,7 +217,7 @@ func (a *Agent) Deactivate(db *mongo.Database) error {
}
_, err := db.Collection("agents").UpdateOne(context.TODO(), filter, update)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Deactivate", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to deactivate agent", Error: err}.ToError()
}

return nil
Expand All @@ -224,7 +229,7 @@ func (a *Agent) DeInitialize(db *mongo.Database) error {

_, err := db.Collection("agents").UpdateOne(context.TODO(), filter, update)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "DeInitialize", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to de-initialize agent", Error: err}.ToError()
}

return nil
Expand All @@ -235,7 +240,8 @@ func GeneratePin(max int) string {
b := make([]byte, max)
n, err := io.ReadAtLeast(rand.Reader, b, max)
if n != max {
panic(err)
log.Error(err)
return "6969420" // the gamer numbers (XD rawr)
}
for i := 0; i < len(b); i++ {
b[i] = table[int(b[i])%len(table)]
Expand All @@ -248,33 +254,29 @@ func (a *Agent) Get(db *mongo.Database) error {

cursor, err := db.Collection("agents").Find(context.TODO(), filter)
if err != nil {
log.Errorf("error searching database for agent: %s", err)
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Get", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to search for agent by id", Error: err}.ToError()
}
var results []bson.D
if err = cursor.All(context.TODO(), &results); err != nil {
log.Errorf("error cursoring through agents: %s", err)
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Get", Level: log.ErrorLevel, ObjectID: a.ID, Message: "error cursoring through agents", Error: err}.ToError()
}

if len(results) > 1 {
return errors.New("multiple agents match when getting using id") // edge case??
return internal.ErrorFormat{Package: "internal.agent", Function: "Get", Level: log.ErrorLevel, ObjectID: a.ID, Message: "multiple agents match when getting using id", Error: err}.ToError() // edge case??
}

if len(results) == 0 {
return errors.New("no agents match when getting using id")
return internal.ErrorFormat{Package: "internal.agent", Function: "Get", Level: log.ErrorLevel, ObjectID: a.ID, Message: "no agents match", Error: err}.ToError()
}

doc, err := bson.Marshal(&results[0])
if err != nil {
log.Errorf("1 %s", err)
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Get", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to marshal get agents results[0]", Error: err}.ToError()
}

err = bson.Unmarshal(doc, &a)
if err != nil {
log.Errorf("2 %s", err)
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Get", Level: log.ErrorLevel, ObjectID: a.ID, Message: "unable to marshal get agents result", Error: err}.ToError()
}

return nil
Expand All @@ -290,48 +292,46 @@ func (a *Agent) Create(db *mongo.Database) error {

mar, err := bson.Marshal(a)
if err != nil {
log.Errorf("error marshalling agent data when creating: %s", err)
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Create", Level: log.ErrorLevel, ObjectID: a.ID, Message: "error marshalling agent data when creating agent", Error: err}.ToError()
}
var b *bson.D
err = bson.Unmarshal(mar, &b)
if err != nil {
log.Errorf("error unmarhsalling agent data when creating: %s", err)
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Create", Level: log.ErrorLevel, ObjectID: a.ID, Message: "error unmarshalling agent when creating agent", Error: err}.ToError()
}
result, err := db.Collection("agents").InsertOne(context.TODO(), b)
if err != nil {
log.Errorf("error inserting to database: %s", err)
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Create", Level: log.ErrorLevel, ObjectID: a.ID, Message: "error creating agent", Error: err}.ToError()
}

// also create netinfo probe
probe := Probe{Agent: a.ID, Type: ProbeType_NETWORKINFO}
err = probe.Create(db)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Create", Level: log.ErrorLevel, ObjectID: a.ID, Message: "error creating network info probe", Error: err}.ToError()
}

// also create system info probe
ss := Probe{Agent: a.ID, Type: ProbeType_SYSTEMINFO}
err = ss.Create(db)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Create", Level: log.ErrorLevel, ObjectID: a.ID, Message: "error creating system info probe", Error: err}.ToError()
}

s2 := Probe{Agent: a.ID, Type: ProbeType_SPEEDTEST_SERVERS}
err = s2.Create(db)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Create", Level: log.ErrorLevel, ObjectID: a.ID, Message: "error creating speedtest servers probe", Error: err}.ToError()
}
target := ProbeTarget{Target: "ok"}

s3 := Probe{Agent: a.ID, Type: ProbeType_SPEEDTEST, Config: ProbeConfig{Target: []ProbeTarget{target}}}
err = s3.Create(db)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "Create", Level: log.ErrorLevel, ObjectID: a.ID, Message: "error creating speedtest probe", Error: err}.ToError()
}

fmt.Printf("created agent with id: %v\n", result.InsertedID)
// todo output to loki??
log.Info("created agent with id: %v\n", result.InsertedID)

Check failure on line 335 in internal/agent/agent.go

View workflow job for this annotation

GitHub Actions / build

github.com/sirupsen/logrus.Info call has possible Printf formatting directive %v
return nil
}
2 changes: 2 additions & 0 deletions internal/agent/groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"go.mongodb.org/mongo-driver/mongo"
)

// todo add better error handling??!??

type Group struct {
ID primitive.ObjectID `json:"id" bson:"_id"`
SiteID primitive.ObjectID `json:"site,omitempty" bson:"site"`
Expand Down
7 changes: 4 additions & 3 deletions internal/agent/probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"nw-guardian/internal"
"strings"
"time"
)
Expand Down Expand Up @@ -63,13 +64,13 @@ func DeleteProbesByAgentID(db *mongo.Database, agentID primitive.ObjectID) error
p := Probe{Agent: agentID}
get, err := p.Get(db)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "DeleteProbesByAgentID", ObjectID: agentID, Message: "unable to get probes by agent id", Error: err}.ToError()
}

for _, probe := range get {
err := DeleteProbeDataByProbeID(db, probe.ID)
if err != nil {
log.Error(err)
return internal.ErrorFormat{Package: "internal.agent", Function: "DeleteProbesByAgentID", ObjectID: agentID, Message: "error deleting probes by id", Error: err}.ToError()
}
}

Expand All @@ -80,7 +81,7 @@ func DeleteProbesByAgentID(db *mongo.Database, agentID primitive.ObjectID) error
// Perform the deletion
_, err = db.Collection("probes").DeleteMany(context.TODO(), filter)
if err != nil {
return err
return internal.ErrorFormat{Package: "internal.agent", Function: "DeleteProbesByAgentID", ObjectID: agentID, Message: "failed to delete probes for agent", Error: err}.ToError()
}

return nil
Expand Down
31 changes: 31 additions & 0 deletions internal/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package internal

import (
"encoding/json"
"fmt"
"github.com/sirupsen/logrus"
"go.mongodb.org/mongo-driver/bson/primitive"
)

type ErrorFormat struct {
ObjectID primitive.ObjectID `json:"objectID,omitempty"`
Message string `json:"message,omitempty"`
Error error `json:"error,omitempty"`
Function string `json:"function,omitempty"`
Level logrus.Level `json:"level,omitempty"`
Package string `json:"package,omitempty"`
}

func (e ErrorFormat) string() (string, error) {
marshal, err := json.Marshal(e)
if err != nil {
return "", err
}

return string(marshal), nil
}

func (e ErrorFormat) ToError() error {
logrus.Info(e.string())
return fmt.Errorf(e.string())
}
36 changes: 18 additions & 18 deletions internal/site/members.go → internal/workspace/members.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package site
package workspace

import (
"context"
Expand All @@ -11,28 +11,28 @@ import (
"go.mongodb.org/mongo-driver/mongo"
)

type SiteMemberRole string
type Role string

const (
SiteMemberRole_READONLY SiteMemberRole = "READ_ONLY" // view site only, no editing
SiteMemberRole_READWRITE SiteMemberRole = "READ_WRITE" // view, add agents, probes, etc.
SiteMemberRole_ADMIN SiteMemberRole = "ADMIN" // general admin, can add members, cannot remove owner or members
SiteMemberRole_OWNER SiteMemberRole = "OWNER" // super admin
MemberRole_READONLY Role = "READ_ONLY" // view site only, no editing
MemberRole_READWRITE Role = "READ_WRITE" // view, add agents, probes, etc.
MemberRole_ADMIN Role = "ADMIN" // general admin, can add members, cannot remove owner or members
MemberRole_OWNER Role = "OWNER" // super admin
)

type SiteMember struct {
User primitive.ObjectID `bson:"user"json:"user"`
Role SiteMemberRole `bson:"role"json:"role"`
type Member struct {
User primitive.ObjectID `bson:"user" json:"user"`
Role Role `bson:"role" json:"role"`
// roles: 0=READ ONLY, 1=READ-WRITE (Create only), 2=ADMIN (Delete Agents), 3=OWNER (Delete Sites)
// ADMINS can regenerate agent pins
}

type NewSiteMember struct {
Email string `json:"email"form:"email"`
Role SiteMemberRole `json:"role"form:"role"`
type NewWorkspaceMember struct {
Email string `json:"email" form:"email"`
Role Role `json:"role" form:"role"`
}

func (s *Site) GetMemberRole(memberID primitive.ObjectID) (SiteMemberRole, error) {
func (s *Site) GetMemberRole(memberID primitive.ObjectID) (Role, error) {
for _, member := range s.Members {
if member.User == memberID {
return member.Role, nil
Expand All @@ -45,12 +45,12 @@ type MemberInfo struct {
Email string `bson:"email"json:"email"` // email, will be used as username
FirstName string `bson:"firstName"json:"firstName"`
LastName string `bson:"lastName"json:"lastName"`
Role SiteMemberRole `bson:"role"json:"role"`
Role Role `bson:"role"json:"role"`
ID primitive.ObjectID `json:"id"bson:"_id"`
}

// UpdateMemberRole updates the role of a member in the site and the database
func (s *Site) UpdateMemberRole(memberID primitive.ObjectID, newRole SiteMemberRole, db *mongo.Database) error {
func (s *Site) UpdateMemberRole(memberID primitive.ObjectID, newRole Role, db *mongo.Database) error {
// Find and update the member's role
found := false
for i, member := range s.Members {
Expand Down Expand Up @@ -116,13 +116,13 @@ func (s *Site) IsMember(id primitive.ObjectID) bool {
}

// AddMember Add a member to the site then update document
func (s *Site) AddMember(id primitive.ObjectID, role SiteMemberRole, db *mongo.Database) error {
func (s *Site) AddMember(id primitive.ObjectID, role Role, db *mongo.Database) error {
// add member with the provided role
if s.IsMember(id) {
return errors.New("already a member")
}

newMember := SiteMember{
newMember := Member{
User: id,
Role: role,
}
Expand Down Expand Up @@ -154,7 +154,7 @@ func (s *Site) RemoveMember(id primitive.ObjectID, db *mongo.Database) error {
}

// Remove the member with the provided ID
var updatedMembers []SiteMember
var updatedMembers []Member
for _, member := range s.Members {
if member.User != id {
updatedMembers = append(updatedMembers, member)
Expand Down
Loading

0 comments on commit d765c12

Please sign in to comment.