Skip to content
This repository has been archived by the owner on Jun 1, 2021. It is now read-only.

Commit

Permalink
implemented token/credentials cache
Browse files Browse the repository at this point in the history
  • Loading branch information
ernado committed Oct 11, 2014
1 parent 6c03a86 commit 20b47de
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 8 deletions.
41 changes: 33 additions & 8 deletions storage/selctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import (
)

const (
envKey = storage.EnvKey
envUser = storage.EnvUser
envContainer = "SELECTEL_CONTAINER"
envKey = storage.EnvKey
envUser = storage.EnvUser
cacheFilename = ".~selct.cache"
envCache = "SELCTL_CACHE"
envContainer = "SELECTEL_CONTAINER"
)

var (
Expand All @@ -23,11 +25,13 @@ var (
container string
api storage.API
debug bool
cache bool
errorNotEnough = errors.New("Not enought arguments")
)

func init() {
client.DefineBoolFlagVar(&debug, "debug", false, "debug mode")
client.DefineBoolFlagVar(&cache, "cache", false, "cache credentials")
client.DefineStringFlag("key", "", fmt.Sprintf("selectel storage key (%s)", envKey))
client.AliasFlag('k', "key")
client.DefineStringFlag("user", "", fmt.Sprintf("selectel storage user (%s)", envUser))
Expand Down Expand Up @@ -70,27 +74,48 @@ func blank(s string) bool {

// connect reads credentials and performs auth
func connect(c cli.Command) {
var err error

key = readFlag(c, "key", envKey)
user = readFlag(c, "user", envUser)
container = readFlag(c, "container", envContainer)

if cache {
api, err = storage.NewFromCache(cacheFilename)
if err != nil && err != os.ErrNotExist {
log.Println("unable to load from cache:", err)
} else {
return
}
} else {
os.Remove(cacheFilename)
}

// checking for blank credentials
if blank(key) || blank(user) {
if blank(key) || blank(user) && api != nil {
log.Fatal(storage.ErrorBadCredentials)
}

// connencting to api
var err error
api, err = storage.New(user, key)
if err != nil {
api = storage.NewAsync(user, key)
api.Debug(debug)
if err = api.Auth(user, key); err != nil {
log.Fatal(err)
}
api.Debug(debug)
}

func wrap(callback func(cli.Command)) func(cli.Command) {
return func(c cli.Command) {
connect(c.Parent())
defer func() {
if cache {
if err := api.SaveToCache(cacheFilename); err != nil {
log.Println("unable to save to cache:", err)
} else {
log.Println("saved to cache")
}
}
}()
callback(c)
}
}
Expand Down
62 changes: 62 additions & 0 deletions storage/storage.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package storage

import (
"encoding/gob"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -61,6 +62,65 @@ type Client struct {
debug bool
}

type ClientCredentials struct {
Token string
Key string
User string
Debug bool
Expire int
ExpireFrom *time.Time
URL string
}

func NewFromCache(filename string) (API, error) {
var cache = new(ClientCredentials)
f, err := os.Open(filename)
if err != nil {
return nil, err
}
decorer := gob.NewDecoder(f)
if err := decorer.Decode(cache); err != nil {
return nil, err
}
c := newClient(new(http.Client))
if blank(cache.User) || blank(cache.Key) {
return nil, ErrorBadCredentials
}
c.user = cache.User
c.key = cache.Key
c.token = cache.Token
c.tokenExpire = cache.Expire
c.debug = cache.Debug
c.expireFrom = cache.ExpireFrom
c.storageURL, err = url.Parse(cache.URL)
if err != nil {
return nil, ErrorBadCredentials
}
return c, nil
}

func (c *Client) Credentials() (cache ClientCredentials) {
cache.User = c.user
cache.Key = c.key
cache.URL = c.storageURL.String()
cache.Expire = c.tokenExpire
cache.ExpireFrom = c.expireFrom
cache.Token = c.token
cache.Debug = c.debug

return cache
}

func (c *Client) SaveToCache(filename string) error {
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
encoder := gob.NewEncoder(f)
return encoder.Encode(c.Credentials())
}

// StorageInformation contains some usefull metrics about storage for current user
type StorageInformation struct {
ObjectCount uint64
Expand Down Expand Up @@ -91,6 +151,8 @@ type API interface {
ContainerInfo(name string) (info ContainerInfo, err error)
ContainersInfo() ([]ContainerInfo, error)
Containers() ([]ContainerAPI, error)
Credentials() (cache ClientCredentials)
SaveToCache(filename string) error
}

// DoClient is mock of http.Client
Expand Down

0 comments on commit 20b47de

Please sign in to comment.