Merge pull request #1746 from hmrm/refactor-kubelet-access

Refactor kubelet access and add SSL
This commit is contained in:
Clayton Coleman
2014-10-22 19:44:43 -04:00
10 changed files with 120 additions and 60 deletions

View File

@@ -21,6 +21,7 @@ package client
type FlagSet interface {
StringVar(p *string, name, value, usage string)
BoolVar(p *bool, name string, value bool, usage string)
UintVar(p *uint, name string, value uint, usage string)
}
// BindClientConfigFlags registers a standard set of CLI flags for connecting to a Kubernetes API server.
@@ -30,5 +31,13 @@ func BindClientConfigFlags(flags FlagSet, config *Config) {
flags.BoolVar(&config.Insecure, "insecure_skip_tls_verify", config.Insecure, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure.")
flags.StringVar(&config.CertFile, "client_certificate", config.CertFile, "Path to a client key file for TLS.")
flags.StringVar(&config.KeyFile, "client_key", config.KeyFile, "Path to a client key file for TLS.")
flags.StringVar(&config.CAFile, "certificate_authority", config.CAFile, "Path to a cert. file for the certificate authority")
flags.StringVar(&config.CAFile, "certificate_authority", config.CAFile, "Path to a cert. file for the certificate authority.")
}
func BindKubeletClientConfigFlags(flags FlagSet, config *KubeletConfig) {
flags.BoolVar(&config.EnableHttps, "kubelet_https", config.EnableHttps, "Use https for kubelet connections")
flags.UintVar(&config.Port, "kubelet_port", config.Port, "Kubelet port")
flags.StringVar(&config.CertFile, "kubelet_client_certificate", config.CertFile, "Path to a client key file for TLS.")
flags.StringVar(&config.KeyFile, "kubelet_client_key", config.KeyFile, "Path to a client key file for TLS.")
flags.StringVar(&config.CAFile, "kubelet_certificate_authority", config.CAFile, "Path to a cert. file for the certificate authority.")
}

View File

@@ -61,6 +61,19 @@ type Config struct {
Transport http.RoundTripper
}
type KubeletConfig struct {
// ToDo: Add support for different kubelet instances exposing different ports
Port uint
EnableHttps bool
// TLS Configuration, only applies if EnableHttps is true.
CertFile string
// TLS Configuration, only applies if EnableHttps is true.
KeyFile string
// TLS Configuration, only applies if EnableHttps is true.
CAFile string
}
// New creates a Kubernetes client for the given config. This client works with pods,
// replication controllers and services. It allows operations such as list, get, update
// and delete on these objects. An error is returned if the provided configuration

View File

@@ -26,11 +26,23 @@ import (
"strconv"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/health"
)
// ErrPodInfoNotAvailable may be returned when the requested pod info is not available.
var ErrPodInfoNotAvailable = errors.New("no pod info available")
// KubeletClient is an interface for all kubelet functionality
type KubeletClient interface {
KubeletHealthChecker
PodInfoGetter
}
// KubeletHealthchecker is an interface for healthchecking kubelets
type KubeletHealthChecker interface {
HealthCheck(host string) (health.Status, error)
}
// PodInfoGetter is an interface for things that can get information about a pod's containers.
// Injectable for easy testing.
type PodInfoGetter interface {
@@ -39,19 +51,50 @@ type PodInfoGetter interface {
GetPodInfo(host, podNamespace, podID string) (api.PodInfo, error)
}
// HTTPPodInfoGetter is the default implementation of PodInfoGetter, accesses the kubelet over HTTP.
type HTTPPodInfoGetter struct {
Client *http.Client
Port uint
// HTTPKubeletClient is the default implementation of PodInfoGetter and KubeletHealthchecker, accesses the kubelet over HTTP.
type HTTPKubeletClient struct {
Client *http.Client
Port uint
EnableHttps bool
}
func NewKubeletClient(config *KubeletConfig) (KubeletClient, error) {
transport := http.DefaultTransport
if config.CAFile != "" {
t, err := NewClientCertTLSTransport(config.CertFile, config.KeyFile, config.CAFile)
if err != nil {
return nil, err
}
transport = t
}
c := &http.Client{Transport: transport}
return &HTTPKubeletClient{
Client: c,
Port: config.Port,
EnableHttps: config.EnableHttps,
}, nil
}
func (c *HTTPKubeletClient) url(host string) string {
scheme := "http://"
if c.EnableHttps {
scheme = "https://"
}
return fmt.Sprintf(
"%s%s",
scheme,
net.JoinHostPort(host, strconv.FormatUint(uint64(c.Port), 10)))
}
// GetPodInfo gets information about the specified pod.
func (c *HTTPPodInfoGetter) GetPodInfo(host, podNamespace, podID string) (api.PodInfo, error) {
func (c *HTTPKubeletClient) GetPodInfo(host, podNamespace, podID string) (api.PodInfo, error) {
request, err := http.NewRequest(
"GET",
fmt.Sprintf(
"http://%s/podInfo?podID=%s&podNamespace=%s",
net.JoinHostPort(host, strconv.FormatUint(uint64(c.Port), 10)),
"%s/podInfo?podID=%s&podNamespace=%s",
c.url(host),
podID,
podNamespace),
nil)
@@ -79,7 +122,11 @@ func (c *HTTPPodInfoGetter) GetPodInfo(host, podNamespace, podID string) (api.Po
return info, nil
}
// FakePodInfoGetter is a fake implementation of PodInfoGetter. It is useful for testing.
func (c *HTTPKubeletClient) HealthCheck(host string) (health.Status, error) {
return health.DoHTTPCheck(fmt.Sprintf("%s/healthz", c.url(host)), c.Client)
}
// FakeKubeletClient is a fake implementation of PodInfoGetter. It is useful for testing.
type FakePodInfoGetter struct {
data api.PodInfo
err error

View File

@@ -29,7 +29,7 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
)
func TestHTTPPodInfoGetter(t *testing.T) {
func TestHTTPKubeletClient(t *testing.T) {
expectObj := api.PodInfo{
"myID": api.ContainerStatus{},
}
@@ -56,7 +56,7 @@ func TestHTTPPodInfoGetter(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
podInfoGetter := &HTTPPodInfoGetter{
podInfoGetter := &HTTPKubeletClient{
Client: http.DefaultClient,
Port: uint(port),
}
@@ -71,7 +71,7 @@ func TestHTTPPodInfoGetter(t *testing.T) {
}
}
func TestHTTPPodInfoGetterNotFound(t *testing.T) {
func TestHTTPKubeletClientNotFound(t *testing.T) {
expectObj := api.PodInfo{
"myID": api.ContainerStatus{},
}
@@ -98,7 +98,7 @@ func TestHTTPPodInfoGetterNotFound(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
podInfoGetter := &HTTPPodInfoGetter{
podInfoGetter := &HTTPKubeletClient{
Client: http.DefaultClient,
Port: uint(port),
}