add http handler to export configuration state

pull/6/head
Mike Danese 2016-02-01 18:09:02 -08:00
parent 0b9451cb73
commit 5ec02bd021
7 changed files with 193 additions and 0 deletions

View File

@ -62,6 +62,7 @@ import (
"k8s.io/kubernetes/pkg/healthz"
"k8s.io/kubernetes/pkg/serviceaccount"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/configz"
"k8s.io/kubernetes/pkg/util/wait"
"github.com/golang/glog"
@ -100,6 +101,11 @@ func ResyncPeriod(s *options.CMServer) func() time.Duration {
// Run runs the CMServer. This should never exit.
func Run(s *options.CMServer) error {
if c, err := configz.New("componentconfig"); err == nil {
c.Set(s.KubeControllerManagerConfiguration)
} else {
glog.Errorf("unable to register configz: %s", err)
}
kubeconfig, err := clientcmd.BuildConfigFromFlags(s.Master, s.Kubeconfig)
if err != nil {
return err

View File

@ -39,6 +39,7 @@ import (
"k8s.io/kubernetes/pkg/proxy/userspace"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/configz"
utildbus "k8s.io/kubernetes/pkg/util/dbus"
"k8s.io/kubernetes/pkg/util/exec"
utiliptables "k8s.io/kubernetes/pkg/util/iptables"
@ -122,6 +123,11 @@ with the apiserver API to configure the proxy.`,
// NewProxyServerDefault creates a new ProxyServer object with default parameters.
func NewProxyServerDefault(config *options.ProxyServerConfig) (*ProxyServer, error) {
if c, err := configz.New("componentconfig"); err == nil {
c.Set(config.KubeProxyConfiguration)
} else {
glog.Errorf("unable to register configz: %s", err)
}
protocol := utiliptables.ProtocolIpv4
if net.ParseIP(config.BindAddress).To4() == nil {
protocol = utiliptables.ProtocolIpv6
@ -280,6 +286,7 @@ func (s *ProxyServer) Run() error {
http.HandleFunc("/proxyMode", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "%s", s.ProxyMode)
})
configz.InstallHandler(http.DefaultServeMux)
go wait.Until(func() {
err := http.ListenAndServe(s.Config.HealthzBindAddress+":"+strconv.Itoa(s.Config.HealthzPort), nil)
if err != nil {

View File

@ -58,6 +58,7 @@ import (
"k8s.io/kubernetes/pkg/kubelet/server"
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/configz"
"k8s.io/kubernetes/pkg/util/flock"
"k8s.io/kubernetes/pkg/util/io"
"k8s.io/kubernetes/pkg/util/mount"
@ -277,6 +278,11 @@ func run(s *options.KubeletServer, kcfg *KubeletConfig) (err error) {
return fmt.Errorf("unable to aquire file lock on %q: %v", s.LockFilePath, err)
}
}
if c, err := configz.New("componentconfig"); err == nil {
c.Set(s.KubeletConfiguration)
} else {
glog.Errorf("unable to register configz: %s", err)
}
if kcfg == nil {
cfg, err := UnsecuredKubeletConfig(s)
if err != nil {

View File

@ -52,6 +52,7 @@ import (
"k8s.io/kubernetes/pkg/kubelet/server/stats"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/types"
"k8s.io/kubernetes/pkg/util/configz"
"k8s.io/kubernetes/pkg/util/flushwriter"
"k8s.io/kubernetes/pkg/util/httpstream"
"k8s.io/kubernetes/pkg/util/httpstream/spdy"
@ -328,6 +329,8 @@ func (s *Server) InstallDebuggingHandlers() {
Operation("getContainerLogs"))
s.restfulCont.Add(ws)
configz.InstallHandler(s.restfulCont)
handlePprofEndpoint := func(req *restful.Request, resp *restful.Response) {
name := strings.TrimPrefix(req.Request.URL.Path, pprofBasePath)
switch name {

View File

@ -0,0 +1,86 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configz
import (
"encoding/json"
"fmt"
"io"
"net/http"
"sync"
)
var (
configsGuard sync.RWMutex
configs = map[string]*Config{}
)
type Config struct {
val interface{}
}
func InstallHandler(m mux) {
m.Handle("/configz", http.HandlerFunc(handle))
}
type mux interface {
Handle(string, http.Handler)
}
func New(name string) (*Config, error) {
configsGuard.Lock()
defer configsGuard.Unlock()
if _, found := configs[name]; found {
return nil, fmt.Errorf("register config %q twice", name)
}
newConfig := Config{}
configs[name] = &newConfig
return &newConfig, nil
}
func Delete(name string) {
configsGuard.Lock()
defer configsGuard.Unlock()
delete(configs, name)
}
func (v *Config) Set(val interface{}) {
configsGuard.Lock()
defer configsGuard.Unlock()
v.val = val
}
func (v *Config) MarshalJSON() ([]byte, error) {
return json.Marshal(v.val)
}
func handle(w http.ResponseWriter, r *http.Request) {
if err := write(w); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
func write(w io.Writer) error {
configsGuard.Lock()
defer configsGuard.Unlock()
b, err := json.Marshal(configs)
if err != nil {
return fmt.Errorf("error marshaling json: %v", err)
}
_, err = w.Write(b)
return err
}

View File

@ -0,0 +1,78 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package configz
import (
"io/ioutil"
"net/http"
"net/http/httptest"
"testing"
)
func TestConfigz(t *testing.T) {
v, err := New("testing")
if err != nil {
t.Fatalf("err: %v", err)
}
v.Set("blah")
s := httptest.NewServer(http.HandlerFunc(handle))
// TODO: Uncomment when fix #19254
// defer s.Close()
resp, err := http.Get(s.URL + "/configz")
if err != nil {
t.Fatalf("err: %v", err)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf("err: %v", err)
}
if string(body) != `{"testing":"blah"}` {
t.Fatalf("unexpected output: %v", err)
}
v.Set("bing")
resp, err = http.Get(s.URL + "/configz")
if err != nil {
t.Fatalf("err: %v", err)
}
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf("err: %v", err)
}
if string(body) != `{"testing":"bing"}` {
t.Fatalf("unexpected output: %v", err)
}
Delete("testing")
resp, err = http.Get(s.URL + "/configz")
if err != nil {
t.Fatalf("err: %v", err)
}
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatalf("err: %v", err)
}
if string(body) != `{}` {
t.Fatalf("unexpected output: %v", err)
}
}

View File

@ -33,6 +33,7 @@ import (
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
"k8s.io/kubernetes/pkg/healthz"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/configz"
"k8s.io/kubernetes/plugin/cmd/kube-scheduler/app/options"
"k8s.io/kubernetes/plugin/pkg/scheduler"
_ "k8s.io/kubernetes/plugin/pkg/scheduler/algorithmprovider"
@ -68,6 +69,11 @@ through the API as necessary.`,
// Run runs the specified SchedulerServer. This should never exit.
func Run(s *options.SchedulerServer) error {
if c, err := configz.New("componentconfig"); err == nil {
c.Set(s.KubeSchedulerConfiguration)
} else {
glog.Errorf("unable to register configz: %s", err)
}
kubeconfig, err := clientcmd.BuildConfigFromFlags(s.Master, s.Kubeconfig)
if err != nil {
return err
@ -90,6 +96,7 @@ func Run(s *options.SchedulerServer) error {
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
}
configz.InstallHandler(mux)
mux.Handle("/metrics", prometheus.Handler())
server := &http.Server{