123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- /*
- Copyright 2015 The Kubernetes Authors.
- 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 serves ComponentConfig objects from running components.
- //
- // Each component that wants to serve its ComponentConfig creates a Config
- // object, and the program should call InstallHandler once. e.g.,
- // func main() {
- // boatConfig := getBoatConfig()
- // planeConfig := getPlaneConfig()
- //
- // bcz, err := configz.New("boat")
- // if err != nil {
- // panic(err)
- // }
- // bcz.Set(boatConfig)
- //
- // pcz, err := configz.New("plane")
- // if err != nil {
- // panic(err)
- // }
- // pcz.Set(planeConfig)
- //
- // configz.InstallHandler(http.DefaultServeMux)
- // http.ListenAndServe(":8080", http.DefaultServeMux)
- // }
- package configz
- import (
- "encoding/json"
- "fmt"
- "net/http"
- "sync"
- )
- var (
- configsGuard sync.RWMutex
- configs = map[string]*Config{}
- )
- // Config is a handle to a ComponentConfig object. Don't create these directly;
- // use New() instead.
- type Config struct {
- val interface{}
- }
- // InstallHandler adds an HTTP handler on the given mux for the "/configz"
- // endpoint which serves all registered ComponentConfigs in JSON format.
- func InstallHandler(m mux) {
- m.Handle("/configz", http.HandlerFunc(handle))
- }
- type mux interface {
- Handle(string, http.Handler)
- }
- // New creates a Config object with the given name. Each Config is registered
- // with this package's "/configz" 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
- }
- // Delete removes the named ComponentConfig from this package's "/configz"
- // handler.
- func Delete(name string) {
- configsGuard.Lock()
- defer configsGuard.Unlock()
- delete(configs, name)
- }
- // Set sets the ComponentConfig for this Config.
- func (v *Config) Set(val interface{}) {
- configsGuard.Lock()
- defer configsGuard.Unlock()
- v.val = val
- }
- // MarshalJSON marshals the ComponentConfig as JSON data.
- 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 http.ResponseWriter) error {
- var b []byte
- var err error
- func() {
- configsGuard.RLock()
- defer configsGuard.RUnlock()
- b, err = json.Marshal(configs)
- }()
- if err != nil {
- return fmt.Errorf("error marshaling json: %v", err)
- }
- w.Header().Set("Content-Type", "application/json")
- _, err = w.Write(b)
- return err
- }
|