Skip to content

Commit

Permalink
WIP: fix unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
simo5 committed Dec 8, 2017
1 parent eda1084 commit b2c879e
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 62 deletions.
33 changes: 24 additions & 9 deletions pkg/auth/oauth/registry/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authentication/user"
clienttesting "k8s.io/client-go/testing"
Expand Down Expand Up @@ -428,14 +429,30 @@ func TestAuthenticateTokenValidated(t *testing.T) {
}
}

type oauthClientGetterFunc func(name string, options metav1.GetOptions) (*oapi.OAuthClient, error)
type fakeOAuthClientLister struct {
client oapi.OAuthClient
}

func (f fakeOAuthClientLister) Get(name string) (*oapi.OAuthClient, error) {
if name == f.client.Name {
return &f.client, nil
}
panic("shouldn't happen")
}

func (f oauthClientGetterFunc) Get(name string) (*oapi.OAuthClient, error) {
return f(name, metav1.GetOptions{})
func (f fakeOAuthClientLister) List(selector labels.Selector) ([]*oapi.OAuthClient, error) {
return []*oapi.OAuthClient{&f.client}, nil
}

func TestAuthenticateTokenTimeout(t *testing.T) {
stopCh := make(chan struct{})
defer close(stopCh)

var timeout int32 = 4 // 4 seconds
oauthClient := oapi.OAuthClient{
ObjectMeta: metav1.ObjectMeta{Name: "testClient"},
AccessTokenTimeoutSeconds: &timeout,
}
fakeOAuthClient := oauthfake.NewSimpleClientset(
&oapi.OAuthAccessToken{
ObjectMeta: metav1.ObjectMeta{Name: "token", CreationTimestamp: metav1.Time{Time: time.Now()}},
Expand All @@ -445,16 +462,14 @@ func TestAuthenticateTokenTimeout(t *testing.T) {
UserUID: string("bar"),
TimeoutsIn: timeout,
},
&oapi.OAuthClient{
ObjectMeta: metav1.ObjectMeta{Name: "testClient"},
AccessTokenTimeoutSeconds: &timeout,
},
&oauthClient,
)
userRegistry := usertest.NewUserRegistry()
userRegistry.GetUsers["foo"] = &userapi.User{ObjectMeta: metav1.ObjectMeta{UID: "bar"}}
accessTokenGetter := fakeOAuthClient.Oauth().OAuthAccessTokens()
getter := oauthClientGetterFunc(fakeOAuthClient.Oauth().OAuthClients().Get)
timeouts := NewTimeoutValidator(accessTokenGetter, getter, timeout)
lister := &fakeOAuthClientLister{oauthClient}
timeouts := NewTimeoutValidator(accessTokenGetter, lister, timeout, timeout, timeout)
go timeouts.Run(stopCh)
tokenAuthenticator := NewTokenAuthenticator(accessTokenGetter, userRegistry, identitymapper.NoopGroupMapper{}, timeouts)

// first time should succeed
Expand Down
107 changes: 55 additions & 52 deletions pkg/auth/oauth/registry/timeoutvalidator.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"k8s.io/apimachinery/pkg/util/runtime"

"github.com/openshift/origin/pkg/oauth/apis/oauth"
"github.com/openshift/origin/pkg/oauth/apis/oauth/validation"
oauthclient "github.com/openshift/origin/pkg/oauth/generated/internalclientset/typed/oauth/internalversion"
oauthclientlister "github.com/openshift/origin/pkg/oauth/generated/listers/oauth/internalversion"
"github.com/openshift/origin/pkg/user/apis/user"
Expand Down Expand Up @@ -43,53 +42,38 @@ func (a *tokenDataRef) Less(than btree.Item) bool {
return a.timeout.Before(than.(*tokenDataRef).timeout)
}

type TimeoutValidator struct {
oauthClients oauthclientlister.OAuthClientLister
tokens oauthclient.OAuthAccessTokenInterface
tokenChannel chan tokenData
data map[string]tokenData
tree *btree.BTree
defaultTimeout time.Duration
flushTimeout time.Duration
safetyMargin time.Duration
func timeoutAsDuration(timeout int32) time.Duration {
return time.Duration(timeout) * time.Second
}

func computeTimeouts(configuredTimeout int32) (actualTimeout int32, flushTimeout int32, safetyMargin int32) {
actualTimeout = configuredTimeout
if actualTimeout < validation.ReferenceTimeoutInterval {
actualTimeout = validation.ReferenceTimeoutInterval
}
// flushTimeout is set to one third of defaultTimeout or
// ReferenceTimeoutInterval, whichever is lower
flushTimeout = actualTimeout / 3
if flushTimeout > validation.ReferenceTimeoutInterval {
flushTimeout = validation.ReferenceTimeoutInterval
}
// safetyMargin is set to one tenth of flushTimeout
safetyMargin = flushTimeout / 10

return actualTimeout, flushTimeout, safetyMargin
type TimeoutValidator struct {
oauthClients oauthclientlister.OAuthClientLister
tokens oauthclient.OAuthAccessTokenInterface
tokenChannel chan tokenData
data map[string]tokenData
tree *btree.BTree
minValidTimeout int32
maxFlushTimeout int32
defaultTimeout time.Duration
flushTimeout time.Duration
safetyMargin time.Duration
}

func NewTimeoutValidator(tokens oauthclient.OAuthAccessTokenInterface, oauthClients oauthclientlister.OAuthClientLister, configuredTimeout int32) *TimeoutValidator {
defaultTimeout, flushTimeout, safetyMargin := computeTimeouts(configuredTimeout)
ttu := &TimeoutValidator{
oauthClients,
tokens,
make(chan tokenData),
make(map[string]tokenData),
func NewTimeoutValidator(tokens oauthclient.OAuthAccessTokenInterface, oauthClients oauthclientlister.OAuthClientLister, defaultTimeout int32, minValidTimeout int32, maxFlushTimeout int32) *TimeoutValidator {
a := &TimeoutValidator{
oauthClients: oauthClients,
tokens: tokens,
tokenChannel: make(chan tokenData),
data: make(map[string]tokenData),
// FIXME: what is the right degree for the btree
btree.New(32),
timeoutAsDuration(defaultTimeout),
timeoutAsDuration(flushTimeout),
timeoutAsDuration(safetyMargin),
tree: btree.New(32),
minValidTimeout: minValidTimeout,
maxFlushTimeout: maxFlushTimeout,
}
glog.V(5).Infof("Token Timeout Validator primed with defaultTimeout=%d flushTimeout=%d safetyMargin=%d", defaultTimeout, flushTimeout, safetyMargin)
return ttu
}

func timeoutAsDuration(timeout int32) time.Duration {
return time.Duration(timeout) * time.Second
a.defaultTimeout, a.flushTimeout, a.safetyMargin = a.computeTimeouts(defaultTimeout)
glog.V(5).Infof("Token Timeout Validator primed with defaultTimeout=%d flushTimeout=%d safetyMargin=%d",
int(a.defaultTimeout.Seconds()), int(a.flushTimeout.Seconds()), int(a.safetyMargin.Seconds()))
return a
}

// CheckTimeout is called with a token when it is seen by an authenticator
Expand Down Expand Up @@ -120,6 +104,23 @@ func (a *TimeoutValidator) updateToken(td tokenData) {
a.tokenChannel <- td
}

func (a *TimeoutValidator) computeTimeouts(newTimeout int32) (actualTimeout, flushTimeout, safetyMargin time.Duration) {
actual := newTimeout
if actual < a.minValidTimeout {
actual = a.minValidTimeout
}
// flushTimeout is set to one third of defaultTimeout or
// maxFlushTimeout, whichever is lower
flush := actual / 3
if flush > a.maxFlushTimeout {
flush = a.maxFlushTimeout
}
// safetyMargin is set to one tenth of flushTimeout
safety := flush / 10

return timeoutAsDuration(actual), timeoutAsDuration(flush), timeoutAsDuration(safety)
}

func (a *TimeoutValidator) clientTimeout(name string) time.Duration {
oauthClient, err := a.oauthClients.Get(name)
if err != nil {
Expand All @@ -133,8 +134,9 @@ func (a *TimeoutValidator) clientTimeout(name string) time.Duration {
}

func (a *TimeoutValidator) updateTimeouts() {
smallerTimeout := int32(a.defaultTimeout / time.Second)
smallerClientName := "<default>"
timeout := int32(a.defaultTimeout / time.Second)
clientType := "<internal "
clientName := "default>"
clients, err := a.oauthClients.List(labels.Everything())
if err != nil {
glog.V(5).Infof("Failed to list OauthClients to update timeout values: %v", err)
Expand All @@ -147,16 +149,17 @@ func (a *TimeoutValidator) updateTimeouts() {
if *client.AccessTokenTimeoutSeconds == 0 {
continue
}
if *client.AccessTokenTimeoutSeconds < smallerTimeout {
smallerTimeout = *client.AccessTokenTimeoutSeconds
smallerClientName = client.Name
if *client.AccessTokenTimeoutSeconds < timeout {
timeout = *client.AccessTokenTimeoutSeconds
clientType = "OAuthClient"
clientName = client.Name
}
}
_, flushTimeout, safetyMargin := computeTimeouts(smallerTimeout)
if flushTimeout < int32(a.flushTimeout/time.Second) {
a.flushTimeout = timeoutAsDuration(flushTimeout)
a.safetyMargin = timeoutAsDuration(safetyMargin)
glog.V(5).Infof("OauthClient %q updates timeouts to flushTimeout=%s safetyMargin=%s", smallerClientName, a.flushTimeout, a.safetyMargin)
previousFlushTimeout := a.flushTimeout
_, a.flushTimeout, a.safetyMargin = a.computeTimeouts(timeout)
if a.flushTimeout != previousFlushTimeout {
glog.V(5).Infof("%s %s updates timeouts to flushTimeout=%d safetyMargin=%d",
clientType, clientName, int(a.flushTimeout.Seconds()), int(a.safetyMargin.Seconds()))
}
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/server/origin/authenticator.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/openshift/origin/pkg/auth/userregistry/identitymapper"
configapi "github.com/openshift/origin/pkg/cmd/server/api"
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
oauthvalidation "github.com/openshift/origin/pkg/oauth/apis/oauth/validation"
oauthclient "github.com/openshift/origin/pkg/oauth/generated/internalclientset/typed/oauth/internalversion"
oauthclientlister "github.com/openshift/origin/pkg/oauth/generated/listers/oauth/internalversion"
usercache "github.com/openshift/origin/pkg/user/cache"
Expand Down Expand Up @@ -95,7 +96,7 @@ func newAuthenticator(config configapi.MasterConfig, accessTokenGetter oauthclie
if config.OAuthConfig != nil {
validators := []openshiftauthenticator.OAuthTokenValidator{authnregistry.NewExpirationValidator(), authnregistry.NewUIDValidator()}
if config.OAuthConfig.TokenConfig.AccessTokenTimeoutSeconds != nil {
timeoutValidator := authnregistry.NewTimeoutValidator(accessTokenGetter, oauthClientLister, *config.OAuthConfig.TokenConfig.AccessTokenTimeoutSeconds)
timeoutValidator := authnregistry.NewTimeoutValidator(accessTokenGetter, oauthClientLister, *config.OAuthConfig.TokenConfig.AccessTokenTimeoutSeconds, oauthvalidation.ReferenceTimeoutInterval, oauthvalidation.ReferenceTimeoutInterval)
validators = append(validators, timeoutValidator)
postStartHooks["openshift.io-TokenTimeoutUpdater"] = func(context genericapiserver.PostStartHookContext) error {
go timeoutValidator.Run(context.StopCh)
Expand Down

0 comments on commit b2c879e

Please sign in to comment.