mirror of https://github.com/dexidp/dex.git
20 changed files with 265 additions and 357 deletions
@ -1,58 +0,0 @@
|
||||
package kubernetes |
||||
|
||||
import ( |
||||
"fmt" |
||||
"log" |
||||
"time" |
||||
|
||||
"golang.org/x/net/context" |
||||
) |
||||
|
||||
// gc begins the gc process for Kubernetes.
|
||||
func (cli *client) gc(ctx context.Context, every time.Duration) { |
||||
handleErr := func(err error) { log.Println(err.Error()) } |
||||
|
||||
for { |
||||
select { |
||||
case <-ctx.Done(): |
||||
return |
||||
case <-time.After(every): |
||||
} |
||||
|
||||
// TODO(ericchiang): On failures, run garbage collection more often.
|
||||
log.Println("kubernetes: running garbage collection") |
||||
cli.gcAuthRequests(handleErr) |
||||
cli.gcAuthCodes(handleErr) |
||||
log.Printf("kubernetes: garbage collection finished, next run at %s", cli.now().Add(every)) |
||||
} |
||||
} |
||||
|
||||
func (cli *client) gcAuthRequests(handleErr func(error)) { |
||||
var authRequests AuthRequestList |
||||
if err := cli.list(resourceAuthRequest, &authRequests); err != nil { |
||||
handleErr(fmt.Errorf("failed to list auth requests: %v", err)) |
||||
return |
||||
} |
||||
for _, authRequest := range authRequests.AuthRequests { |
||||
if cli.now().After(authRequest.Expiry) { |
||||
if err := cli.delete(resourceAuthRequest, authRequest.ObjectMeta.Name); err != nil { |
||||
handleErr(fmt.Errorf("failed to detele auth request: %v", err)) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
func (cli *client) gcAuthCodes(handleErr func(error)) { |
||||
var authCodes AuthCodeList |
||||
if err := cli.list(resourceAuthCode, &authCodes); err != nil { |
||||
handleErr(fmt.Errorf("failed to list auth codes: %v", err)) |
||||
return |
||||
} |
||||
for _, authCode := range authCodes.AuthCodes { |
||||
if cli.now().After(authCode.Expiry) { |
||||
if err := cli.delete(resourceAuthCode, authCode.ObjectMeta.Name); err != nil { |
||||
handleErr(fmt.Errorf("failed to delete auth code: %v", err)) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,88 +0,0 @@
|
||||
package kubernetes |
||||
|
||||
import ( |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/coreos/dex/storage" |
||||
) |
||||
|
||||
func muster(t *testing.T) func(err error) { |
||||
return func(err error) { |
||||
if err != nil { |
||||
t.Fatal(err) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestGCAuthRequests(t *testing.T) { |
||||
cli := loadClient(t) |
||||
must := muster(t) |
||||
|
||||
now := time.Now() |
||||
cli.now = func() time.Time { return now } |
||||
|
||||
expiredID := storage.NewID() |
||||
goodID := storage.NewID() |
||||
|
||||
must(cli.CreateAuthRequest(storage.AuthRequest{ |
||||
ID: expiredID, |
||||
Expiry: now.Add(-time.Second), |
||||
})) |
||||
|
||||
must(cli.CreateAuthRequest(storage.AuthRequest{ |
||||
ID: goodID, |
||||
Expiry: now.Add(time.Second), |
||||
})) |
||||
|
||||
handleErr := func(err error) { t.Error(err.Error()) } |
||||
cli.gcAuthRequests(handleErr) |
||||
|
||||
if _, err := cli.GetAuthRequest(goodID); err != nil { |
||||
t.Errorf("failed to get good auth ID: %v", err) |
||||
} |
||||
_, err := cli.GetAuthRequest(expiredID) |
||||
switch { |
||||
case err == nil: |
||||
t.Errorf("gc did not remove expired auth request") |
||||
case err == storage.ErrNotFound: |
||||
default: |
||||
t.Errorf("expected storage.ErrNotFound, got %v", err) |
||||
} |
||||
} |
||||
|
||||
func TestGCAuthCodes(t *testing.T) { |
||||
cli := loadClient(t) |
||||
must := muster(t) |
||||
|
||||
now := time.Now() |
||||
cli.now = func() time.Time { return now } |
||||
|
||||
expiredID := storage.NewID() |
||||
goodID := storage.NewID() |
||||
|
||||
must(cli.CreateAuthCode(storage.AuthCode{ |
||||
ID: expiredID, |
||||
Expiry: now.Add(-time.Second), |
||||
})) |
||||
|
||||
must(cli.CreateAuthCode(storage.AuthCode{ |
||||
ID: goodID, |
||||
Expiry: now.Add(time.Second), |
||||
})) |
||||
|
||||
handleErr := func(err error) { t.Error(err.Error()) } |
||||
cli.gcAuthCodes(handleErr) |
||||
|
||||
if _, err := cli.GetAuthCode(goodID); err != nil { |
||||
t.Errorf("failed to get good auth ID: %v", err) |
||||
} |
||||
_, err := cli.GetAuthCode(expiredID) |
||||
switch { |
||||
case err == nil: |
||||
t.Errorf("gc did not remove expired auth request") |
||||
case err == storage.ErrNotFound: |
||||
default: |
||||
t.Errorf("expected storage.ErrNotFound, got %v", err) |
||||
} |
||||
} |
||||
@ -1,53 +0,0 @@
|
||||
package sql |
||||
|
||||
import ( |
||||
"context" |
||||
"fmt" |
||||
"log" |
||||
"time" |
||||
|
||||
"github.com/coreos/dex/storage" |
||||
) |
||||
|
||||
type gc struct { |
||||
now func() time.Time |
||||
conn *conn |
||||
} |
||||
|
||||
func (gc gc) run() error { |
||||
for _, table := range []string{"auth_request", "auth_code"} { |
||||
_, err := gc.conn.Exec(`delete from `+table+` where expiry < $1`, gc.now()) |
||||
if err != nil { |
||||
return fmt.Errorf("gc %s: %v", table, err) |
||||
} |
||||
// TODO(ericchiang): when we have levelled logging print how many rows were gc'd
|
||||
} |
||||
return nil |
||||
} |
||||
|
||||
type withCancel struct { |
||||
storage.Storage |
||||
cancel context.CancelFunc |
||||
} |
||||
|
||||
func (w withCancel) Close() error { |
||||
w.cancel() |
||||
return w.Storage.Close() |
||||
} |
||||
|
||||
func withGC(conn *conn, now func() time.Time) storage.Storage { |
||||
ctx, cancel := context.WithCancel(context.Background()) |
||||
run := (gc{now, conn}).run |
||||
go func() { |
||||
for { |
||||
select { |
||||
case <-time.After(time.Second * 30): |
||||
if err := run(); err != nil { |
||||
log.Printf("gc failed: %v", err) |
||||
} |
||||
case <-ctx.Done(): |
||||
} |
||||
} |
||||
}() |
||||
return withCancel{conn, cancel} |
||||
} |
||||
@ -1,53 +0,0 @@
|
||||
package sql |
||||
|
||||
import ( |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/coreos/dex/storage" |
||||
) |
||||
|
||||
func TestGC(t *testing.T) { |
||||
// TODO(ericchiang): Add a GarbageCollect method to the storage interface so
|
||||
// we can write conformance tests instead of directly testing each implementation.
|
||||
s := &SQLite3{":memory:"} |
||||
conn, err := s.open() |
||||
if err != nil { |
||||
t.Fatal(err) |
||||
} |
||||
defer conn.Close() |
||||
|
||||
clock := time.Now() |
||||
now := func() time.Time { return clock } |
||||
|
||||
runGC := (gc{now, conn}).run |
||||
|
||||
a := storage.AuthRequest{ |
||||
ID: storage.NewID(), |
||||
Expiry: now().Add(time.Second), |
||||
} |
||||
|
||||
if err := conn.CreateAuthRequest(a); err != nil { |
||||
t.Fatal(err) |
||||
} |
||||
|
||||
if err := runGC(); err != nil { |
||||
t.Errorf("gc failed: %v", err) |
||||
} |
||||
|
||||
if _, err := conn.GetAuthRequest(a.ID); err != nil { |
||||
t.Errorf("failed to get auth request after gc: %v", err) |
||||
} |
||||
|
||||
clock = clock.Add(time.Minute) |
||||
|
||||
if err := runGC(); err != nil { |
||||
t.Errorf("gc failed: %v", err) |
||||
} |
||||
|
||||
if _, err := conn.GetAuthRequest(a.ID); err == nil { |
||||
t.Errorf("expected error after gc'ing auth request: %v", err) |
||||
} else if err != storage.ErrNotFound { |
||||
t.Errorf("expected error storage.NotFound got: %v", err) |
||||
} |
||||
} |
||||
Loading…
Reference in new issue