c-go: Use http Etag cache

Add a new command-line cachedir flag to specify where to store the http
cache responses. This cache will only be used for OpenAPI Swagger spec
for now (as this is the only end-point that returns an ETag).
This commit is contained in:
Antoine Pelisse 2017-06-09 10:30:47 -07:00
parent a1d0384e82
commit d7bba25d4a
8 changed files with 43 additions and 0 deletions

View File

@ -71,6 +71,10 @@ type Config struct {
// TODO: demonstrate an OAuth2 compatible client.
BearerToken string
// CacheDir is the directory where we'll store HTTP cached responses.
// If set to empty string, no caching mechanism will be used.
CacheDir string
// Impersonate is the configuration that RESTClient will use for impersonation.
Impersonate ImpersonationConfig

View File

@ -249,6 +249,7 @@ func TestAnonymousConfig(t *testing.T) {
expected.BearerToken = ""
expected.Username = ""
expected.Password = ""
expected.CacheDir = ""
expected.AuthProvider = nil
expected.AuthConfigPersister = nil
expected.TLSClientConfig.CertData = nil

View File

@ -89,6 +89,7 @@ func (c *Config) TransportConfig() (*transport.Config, error) {
},
Username: c.Username,
Password: c.Password,
CacheDir: c.CacheDir,
BearerToken: c.BearerToken,
Impersonate: transport.ImpersonationConfig{
UserName: c.Impersonate.UserName,

View File

@ -22,6 +22,7 @@ import (
"io/ioutil"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/golang/glog"
@ -31,16 +32,19 @@ import (
restclient "k8s.io/client-go/rest"
clientauth "k8s.io/client-go/tools/auth"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/util/homedir"
)
var (
// ClusterDefaults has the same behavior as the old EnvVar and DefaultCluster fields
// DEPRECATED will be replaced
ClusterDefaults = clientcmdapi.Cluster{Server: getDefaultServer()}
cacheDirDefault = filepath.Join(homedir.HomeDir(), ".kube", "http-cache")
// DefaultClientConfig represents the legacy behavior of this package for defaulting
// DEPRECATED will be replace
DefaultClientConfig = DirectClientConfig{*clientcmdapi.NewConfig(), "", &ConfigOverrides{
ClusterDefaults: ClusterDefaults,
CacheDir: cacheDirDefault,
}, nil, NewDefaultClientConfigLoadingRules(), promptedCredentials{}}
)
@ -131,6 +135,7 @@ func (config *DirectClientConfig) ClientConfig() (*restclient.Config, error) {
clientConfig := &restclient.Config{}
clientConfig.Host = configClusterInfo.Server
clientConfig.CacheDir = config.overrides.CacheDir
if len(config.overrides.Timeout) > 0 {
timeout, err := ParseTimeout(config.overrides.Timeout)

View File

@ -17,11 +17,13 @@ limitations under the License.
package clientcmd
import (
"path/filepath"
"strconv"
"github.com/spf13/pflag"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/client-go/util/homedir"
)
// ConfigOverrides holds values that should override whatever information is pulled from the actual Config object. You can't
@ -34,6 +36,7 @@ type ConfigOverrides struct {
Context clientcmdapi.Context
CurrentContext string
Timeout string
CacheDir string
}
// ConfigOverrideFlags holds the flag names to be used for binding command line flags. Notice that this structure tightly
@ -44,6 +47,7 @@ type ConfigOverrideFlags struct {
ContextOverrideFlags ContextOverrideFlags
CurrentContext FlagInfo
Timeout FlagInfo
CacheDir FlagInfo
}
// AuthOverrideFlags holds the flag names to be used for binding command line flags for AuthInfo objects
@ -146,10 +150,12 @@ const (
FlagUsername = "username"
FlagPassword = "password"
FlagTimeout = "request-timeout"
FlagCacheDir = "cachedir"
)
// RecommendedConfigOverrideFlags is a convenience method to return recommended flag names prefixed with a string of your choosing
func RecommendedConfigOverrideFlags(prefix string) ConfigOverrideFlags {
defaultCacheDir := filepath.Join(homedir.HomeDir(), ".kube", "http-cache")
return ConfigOverrideFlags{
AuthOverrideFlags: RecommendedAuthOverrideFlags(prefix),
ClusterOverrideFlags: RecommendedClusterOverrideFlags(prefix),
@ -157,6 +163,7 @@ func RecommendedConfigOverrideFlags(prefix string) ConfigOverrideFlags {
CurrentContext: FlagInfo{prefix + FlagContext, "", "", "The name of the kubeconfig context to use"},
Timeout: FlagInfo{prefix + FlagTimeout, "", "0", "The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests."},
CacheDir: FlagInfo{prefix + FlagCacheDir, "", defaultCacheDir, "Path to http-cache directory"},
}
}
@ -198,6 +205,7 @@ func BindOverrideFlags(overrides *ConfigOverrides, flags *pflag.FlagSet, flagNam
BindContextFlags(&overrides.Context, flags, flagNames.ContextOverrideFlags)
flagNames.CurrentContext.BindStringFlag(flags, &overrides.CurrentContext)
flagNames.Timeout.BindStringFlag(flags, &overrides.Timeout)
flagNames.CacheDir.BindStringFlag(flags, &overrides.CacheDir)
}
// BindAuthInfoFlags is a convenience method to bind the specified flags to their associated variables

View File

@ -30,6 +30,9 @@ go_library(
tags = ["automanaged"],
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/gregjones/httpcache:go_default_library",
"//vendor/github.com/gregjones/httpcache/diskcache:go_default_library",
"//vendor/github.com/peterbourgon/diskv:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
],
)

View File

@ -34,6 +34,10 @@ type Config struct {
// Bearer token for authentication
BearerToken string
// CacheDir is the directory where we'll store HTTP cached responses.
// If set to empty string, no caching mechanism will be used.
CacheDir string
// Impersonate is the config that this Config will impersonate using
Impersonate ImpersonationConfig

View File

@ -23,6 +23,9 @@ import (
"time"
"github.com/golang/glog"
"github.com/gregjones/httpcache"
"github.com/gregjones/httpcache/diskcache"
"github.com/peterbourgon/diskv"
utilnet "k8s.io/apimachinery/pkg/util/net"
)
@ -56,6 +59,9 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip
len(config.Impersonate.Extra) > 0 {
rt = NewImpersonatingRoundTripper(config.Impersonate, rt)
}
if len(config.CacheDir) > 0 {
rt = NewCacheRoundTripper(config.CacheDir, rt)
}
return rt, nil
}
@ -87,6 +93,17 @@ type authProxyRoundTripper struct {
rt http.RoundTripper
}
// NewCacheRoundTripper creates a roundtripper that reads the ETag on
// response headers and send the If-None-Match header on subsequent
// corresponding requests.
func NewCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripper {
d := diskv.New(diskv.Options{BasePath: cacheDir})
t := httpcache.NewTransport(diskcache.NewWithDiskv(d))
t.Transport = rt
return t
}
// NewAuthProxyRoundTripper provides a roundtripper which will add auth proxy fields to requests for
// authentication terminating proxy cases
// assuming you pull the user from the context: