func (cmd *GroupStack) Run(ctx context.Context) error { modelhelper.Initialize(envMongoURL()) defer modelhelper.Close() var mu sync.Mutex var wg sync.WaitGroup merr := new(multierror.Error) jobs := make(chan string) go func() { for _, username := range cmd.groupValues.values { jobs <- username } close(jobs) }() DefaultUi.Info(fmt.Sprintf("processing %d users...", len(cmd.groupValues.values))) for range make([]struct{}, cmd.jobs) { wg.Add(1) go func() { defer wg.Done() for username := range jobs { sd, err := cmd.details(username) if err != nil { merr = multierror.Append(merr, err) continue } if cmd.rm { err = modelhelper.RemoveFromStack(sd) } else { err = modelhelper.AddToStack(sd) } if err != nil { DefaultUi.Warn(fmt.Sprintf("processing %q user stack failed: %s", username, err)) mu.Lock() merr = multierror.Append(merr, err) mu.Unlock() } else { DefaultUi.Warn(fmt.Sprintf("processed %q user stack", username)) } } }() } wg.Wait() return merr.ErrorOrNil() }
func TestAddAndRemoveFromStack(t *testing.T) { db := modeltesthelper.NewMongoDB(t) defer db.Close() user, group, machine, account, clean := testFixture(t) defer clean() sd := &modelhelper.StackDetails{ UserID: user.ObjectId, GroupID: group.Id, MachineID: machine.ObjectId, UserName: user.Name, GroupSlug: group.Slug, AccountID: account.Id, BaseID: bson.ObjectIdHex("53fe557af052f8e9435a04fa"), } // Add for a first time. err := modelhelper.AddToStack(sd) if err != nil { t.Fatalf("error adding machine %q to stack: %s", machine.ObjectId.Hex(), err) } s, err := modelhelper.GetComputeStackByGroup(group.Slug, account.Id) if err != nil { t.Fatalf("error getting stack for koding, %q: %s", account.Id.Hex(), err) } if len(s.Machines) != 1 { t.Fatalf("want 1 machine, got %d", len(s.Machines)) } if s.Machines[0] != machine.ObjectId { t.Fatalf("want machine %q to be added to stack, got %q instead", machine.ObjectId.Hex(), s.Machines[0].Hex()) } m, err := modelhelper.GetMachine(machine.ObjectId.Hex()) if err != nil { t.Fatalf("error getting machine %q: %s", machine.ObjectId.Hex(), err) } if len(m.Groups) != 1 { t.Fatalf("want 1 group, got %d", len(m.Groups)) } if m.Groups[0].Id != group.Id { t.Fatalf("want group %q, got %q", group.Id.Hex(), m.Groups[0].Id.Hex()) } // Adding for a second time must be idempotent. err = modelhelper.AddToStack(sd) if err != nil { t.Fatalf("error adding machine %q to stack: %s", machine.ObjectId.Hex(), err) } s2, err := modelhelper.GetComputeStackByGroup(group.Slug, account.Id) if err != nil { t.Fatalf("error getting stack for koding, %q: %s", account.Id.Hex(), err) } if s.Id != s2.Id { t.Errorf("want jComputeStack.ObjetId %q; got %q", s.Id.Hex(), s2.Id.Hex()) } if len(s.Machines) != 1 { t.Fatalf("want 1 machine, got %d", len(s.Machines)) } if s.Machines[0] != machine.ObjectId { t.Fatalf("want machine %q to be added to stack, got %q instead", machine.ObjectId.Hex(), s.Machines[0].Hex()) } m, err = modelhelper.GetMachine(machine.ObjectId.Hex()) if err != nil { t.Fatalf("error getting machine %q: %s", machine.ObjectId.Hex(), err) } if len(m.Groups) != 1 { t.Fatalf("want 1 group, got %d", len(m.Groups)) } if m.Groups[0].Id != group.Id { t.Fatalf("want group %q, got %q", group.Id.Hex(), m.Groups[0].Id.Hex()) } // Remove from stack. err = modelhelper.RemoveFromStack(sd) if err != nil { t.Fatalf("error removing %q from stack: %s", machine.ObjectId.Hex(), err) } s3, err := modelhelper.GetComputeStackByGroup(group.Slug, account.Id) if err != nil { t.Fatalf("error getting stack for koding, %q: %s", account.Id.Hex(), err) } if len(s3.Machines) != 0 { t.Fatalf("want 0 machine, got %d", len(s.Machines)) } m, err = modelhelper.GetMachine(machine.ObjectId.Hex()) if err != nil { t.Fatalf("error getting machine %q: %s", machine.ObjectId.Hex(), err) } if len(m.Groups) != 0 { t.Fatalf("want 0 group, got %d", len(m.Groups)) } }