Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dex
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
dex
Commits
820b4605
Commit
820b4605
authored
Aug 02, 2016
by
Eric Chiang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
storage/kubernetes: garbage collect expired objects
parent
45dafb03
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
164 additions
and
13 deletions
+164
-13
client.go
storage/kubernetes/client.go
+12
-1
garbage_collection.go
storage/kubernetes/garbage_collection.go
+37
-8
garbage_collection_test.go
storage/kubernetes/garbage_collection_test.go
+88
-0
storage.go
storage/kubernetes/storage.go
+24
-0
storage_test.go
storage/kubernetes/storage_test.go
+2
-3
storage.go
storage/storage.go
+1
-1
No files found.
storage/kubernetes/client.go
View file @
820b4605
...
@@ -19,6 +19,7 @@ import (
...
@@ -19,6 +19,7 @@ import (
"time"
"time"
"github.com/gtank/cryptopasta"
"github.com/gtank/cryptopasta"
"golang.org/x/net/context"
yaml
"gopkg.in/yaml.v2"
yaml
"gopkg.in/yaml.v2"
"github.com/coreos/poke/storage"
"github.com/coreos/poke/storage"
...
@@ -33,6 +34,9 @@ type client struct {
...
@@ -33,6 +34,9 @@ type client struct {
now
func
()
time
.
Time
now
func
()
time
.
Time
// If not nil, the cancel function for stopping garbage colletion.
cancel
context
.
CancelFunc
// BUG: currently each third party API group can only have one resource in it,
// BUG: currently each third party API group can only have one resource in it,
// so for each resource this storage uses, it need a unique API group.
// so for each resource this storage uses, it need a unique API group.
//
//
...
@@ -251,7 +255,14 @@ func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string) (
...
@@ -251,7 +255,14 @@ func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string) (
}
}
// TODO(ericchiang): make API Group and version configurable.
// TODO(ericchiang): make API Group and version configurable.
return
&
client
{
&
http
.
Client
{
Transport
:
t
},
cluster
.
Server
,
namespace
,
"oidc.coreos.com/v1"
,
time
.
Now
,
true
},
nil
return
&
client
{
client
:
&
http
.
Client
{
Transport
:
t
},
baseURL
:
cluster
.
Server
,
namespace
:
namespace
,
apiVersion
:
"oidc.coreos.com/v1"
,
now
:
time
.
Now
,
prependResourceNameToAPIGroup
:
true
,
},
nil
}
}
type
transport
struct
{
type
transport
struct
{
...
...
storage/kubernetes/garbage_collection.go
View file @
820b4605
...
@@ -3,27 +3,56 @@ package kubernetes
...
@@ -3,27 +3,56 @@ package kubernetes
import
(
import
(
"fmt"
"fmt"
"log"
"log"
"time"
"golang.org/x/net/context"
)
)
// TODO(ericchiang): Complete this.
// 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
())
}
type
multiErr
[]
error
for
{
select
{
case
<-
ctx
.
Done
()
:
return
case
<-
time
.
After
(
every
)
:
}
func
(
m
multiErr
)
Error
()
string
{
// TODO(ericchiang): On failures, run garbage collection more often.
return
fmt
.
Sprintf
(
"errors encountered: %s"
,
m
)
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
(
)
error
{
func
(
cli
*
client
)
gcAuthRequests
(
handleErr
func
(
error
))
{
var
authRequests
AuthRequestList
var
authRequests
AuthRequestList
if
err
:=
cli
.
list
(
resourceAuthRequest
,
&
authRequests
);
err
!=
nil
{
if
err
:=
cli
.
list
(
resourceAuthRequest
,
&
authRequests
);
err
!=
nil
{
return
err
handleErr
(
fmt
.
Errorf
(
"failed to list auth requests: %v"
,
err
))
return
}
}
for
_
,
authRequest
:=
range
authRequests
.
AuthRequests
{
for
_
,
authRequest
:=
range
authRequests
.
AuthRequests
{
if
cli
.
now
()
.
After
(
authRequest
.
Expiry
)
{
if
cli
.
now
()
.
After
(
authRequest
.
Expiry
)
{
if
err
:=
cli
.
delete
(
resourceAuthRequest
,
authRequest
.
ObjectMeta
.
Name
);
err
!=
nil
{
if
err
:=
cli
.
delete
(
resourceAuthRequest
,
authRequest
.
ObjectMeta
.
Name
);
err
!=
nil
{
log
.
Printf
(
"failed to detele auth request: %v"
,
err
)
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
))
}
}
}
}
}
}
return
nil
}
}
storage/kubernetes/garbage_collection_test.go
0 → 100644
View file @
820b4605
package
kubernetes
import
(
"testing"
"time"
"github.com/coreos/poke/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
.
NewNonce
()
goodID
:=
storage
.
NewNonce
()
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
.
NewNonce
()
goodID
:=
storage
.
NewNonce
()
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
)
}
}
storage/kubernetes/storage.go
View file @
820b4605
...
@@ -5,8 +5,10 @@ import (
...
@@ -5,8 +5,10 @@ import (
"fmt"
"fmt"
"os"
"os"
"path/filepath"
"path/filepath"
"time"
homedir
"github.com/mitchellh/go-homedir"
homedir
"github.com/mitchellh/go-homedir"
"golang.org/x/net/context"
"github.com/coreos/poke/storage"
"github.com/coreos/poke/storage"
"github.com/coreos/poke/storage/kubernetes/k8sapi"
"github.com/coreos/poke/storage/kubernetes/k8sapi"
...
@@ -32,10 +34,29 @@ const (
...
@@ -32,10 +34,29 @@ const (
type
Config
struct
{
type
Config
struct
{
InCluster
bool
`yaml:"inCluster"`
InCluster
bool
`yaml:"inCluster"`
KubeConfigPath
string
`yaml:"kubeConfigPath"`
KubeConfigPath
string
`yaml:"kubeConfigPath"`
GCFrequency
int64
`yaml:"gcFrequency"`
// seconds
}
}
// Open returns a storage using Kubernetes third party resource.
// Open returns a storage using Kubernetes third party resource.
func
(
c
*
Config
)
Open
()
(
storage
.
Storage
,
error
)
{
func
(
c
*
Config
)
Open
()
(
storage
.
Storage
,
error
)
{
cli
,
err
:=
c
.
open
()
if
err
!=
nil
{
return
nil
,
err
}
// start up garbage collection
gcFrequency
:=
c
.
GCFrequency
if
gcFrequency
==
0
{
gcFrequency
=
600
}
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
cli
.
cancel
=
cancel
go
cli
.
gc
(
ctx
,
time
.
Duration
(
gcFrequency
)
*
time
.
Second
)
return
cli
,
nil
}
// open returns a client with no garbage collection.
func
(
c
*
Config
)
open
()
(
*
client
,
error
)
{
if
c
.
InCluster
&&
(
c
.
KubeConfigPath
!=
""
)
{
if
c
.
InCluster
&&
(
c
.
KubeConfigPath
!=
""
)
{
return
nil
,
errors
.
New
(
"cannot specify both 'inCluster' and 'kubeConfigPath'"
)
return
nil
,
errors
.
New
(
"cannot specify both 'inCluster' and 'kubeConfigPath'"
)
}
}
...
@@ -70,6 +91,9 @@ func (c *Config) Open() (storage.Storage, error) {
...
@@ -70,6 +91,9 @@ func (c *Config) Open() (storage.Storage, error) {
}
}
func
(
cli
*
client
)
Close
()
error
{
func
(
cli
*
client
)
Close
()
error
{
if
cli
.
cancel
!=
nil
{
cli
.
cancel
()
}
return
nil
return
nil
}
}
...
...
storage/kubernetes/storage_test.go
View file @
820b4605
...
@@ -4,7 +4,6 @@ import (
...
@@ -4,7 +4,6 @@ import (
"os"
"os"
"testing"
"testing"
"github.com/coreos/poke/storage"
"github.com/coreos/poke/storage/storagetest"
"github.com/coreos/poke/storage/storagetest"
)
)
...
@@ -12,12 +11,12 @@ func TestLoadClient(t *testing.T) {
...
@@ -12,12 +11,12 @@ func TestLoadClient(t *testing.T) {
loadClient
(
t
)
loadClient
(
t
)
}
}
func
loadClient
(
t
*
testing
.
T
)
storage
.
Storage
{
func
loadClient
(
t
*
testing
.
T
)
*
client
{
if
os
.
Getenv
(
"KUBECONFIG"
)
==
""
{
if
os
.
Getenv
(
"KUBECONFIG"
)
==
""
{
t
.
Skip
()
t
.
Skip
()
}
}
var
config
Config
var
config
Config
s
,
err
:=
config
.
O
pen
()
s
,
err
:=
config
.
o
pen
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
...
storage/storage.go
View file @
820b4605
...
@@ -73,7 +73,7 @@ func Open(driverName string, config map[string]string) (Storage, error) {
...
@@ -73,7 +73,7 @@ func Open(driverName string, config map[string]string) (Storage, error) {
// require compare-and-swap atomic actions.
// require compare-and-swap atomic actions.
//
//
// Implementations are expected to perform their own garbage collection of
// Implementations are expected to perform their own garbage collection of
// expired objects (expect keys
which are handled by rotation
).
// expired objects (expect keys
, which are handled by the server
).
type
Storage
interface
{
type
Storage
interface
{
Close
()
error
Close
()
error
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment