From d0f63ca0e0db5bf3f436a2507dde1a6031cdade9 Mon Sep 17 00:00:00 2001 From: Michael Desa Date: Wed, 13 Dec 2017 09:04:44 -0800 Subject: [PATCH] Add /config/:section endpoint --- server/config.go | 44 ++++++++++++++++++ server/config_test.go | 101 ++++++++++++++++++++++++++++++++++++++++++ server/mux.go | 1 + 3 files changed, 146 insertions(+) diff --git a/server/config.go b/server/config.go index b6141fa62b..3adef69dfe 100644 --- a/server/config.go +++ b/server/config.go @@ -1,8 +1,10 @@ package server import ( + "fmt" "net/http" + "github.com/bouk/httprouter" "github.com/influxdata/chronograf" ) @@ -20,6 +22,20 @@ func newConfigResponse(config chronograf.Config) *configResponse { } } +type authConfigResponse struct { + Links selfLinks `json:"links"` + chronograf.AuthConfig +} + +func newAuthConfigResponse(config chronograf.Config) *authConfigResponse { + return &authConfigResponse{ + Links: selfLinks{ + Self: "/chronograf/v1/config/auth", + }, + AuthConfig: config.Auth, + } +} + // Config retrieves the global application configuration func (s *Service) Config(w http.ResponseWriter, r *http.Request) { ctx := r.Context() @@ -37,3 +53,31 @@ func (s *Service) Config(w http.ResponseWriter, r *http.Request) { res := newConfigResponse(*config) encodeJSON(w, http.StatusOK, res, s.Logger) } + +// Config retrieves the global application configuration +func (s *Service) ConfigSection(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + config, err := s.Store.Config(ctx).Get(ctx) + if err != nil { + Error(w, http.StatusBadRequest, err.Error(), s.Logger) + return + } + + if config == nil { + Error(w, http.StatusBadRequest, "Configuration object was nil", s.Logger) + return + } + + section := httprouter.GetParamFromContext(ctx, "section") + var res interface{} + switch section { + case "auth": + res = newAuthConfigResponse(*config) + default: + Error(w, http.StatusBadRequest, fmt.Sprintf("received unknown section %q", section), s.Logger) + return + } + + encodeJSON(w, http.StatusOK, res, s.Logger) +} diff --git a/server/config_test.go b/server/config_test.go index f1cdc541af..ea058ace35 100644 --- a/server/config_test.go +++ b/server/config_test.go @@ -5,6 +5,7 @@ import ( "net/http/httptest" "testing" + "github.com/bouk/httprouter" "github.com/influxdata/chronograf" "github.com/influxdata/chronograf/log" "github.com/influxdata/chronograf/mocks" @@ -74,3 +75,103 @@ func TestConfig(t *testing.T) { }) } } + +func TestConfigSection(t *testing.T) { + type fields struct { + ConfigStore chronograf.ConfigStore + } + type args struct { + section string + } + type wants struct { + statusCode int + contentType string + body string + } + + tests := []struct { + name string + fields fields + args args + wants wants + }{ + { + name: "Get auth configuration", + fields: fields{ + ConfigStore: &mocks.ConfigStore{ + Config: &chronograf.Config{ + Auth: chronograf.AuthConfig{ + SuperAdminFirstUserOnly: true, + }, + }, + }, + }, + args: args{ + section: "auth", + }, + wants: wants{ + statusCode: 200, + contentType: "application/json", + body: `{"superAdminFirstUserOnly": true, "links": {"self": "/chronograf/v1/config/auth"}}`, + }, + }, + { + name: "Get unknown configuration", + fields: fields{ + ConfigStore: &mocks.ConfigStore{ + Config: &chronograf.Config{ + Auth: chronograf.AuthConfig{ + SuperAdminFirstUserOnly: true, + }, + }, + }, + }, + args: args{ + section: "unknown", + }, + wants: wants{ + statusCode: 400, + contentType: "application/json", + body: `{"code":400,"message":"received unknown section \"unknown\""}`, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + s := &Service{ + Store: &mocks.Store{ + ConfigStore: tt.fields.ConfigStore, + }, + Logger: log.New(log.DebugLevel), + } + + w := httptest.NewRecorder() + r := httptest.NewRequest("GET", "http://any.url", nil) + r = r.WithContext(httprouter.WithParams( + r.Context(), + httprouter.Params{ + { + Key: "section", + Value: tt.args.section, + }, + })) + + s.ConfigSection(w, r) + + resp := w.Result() + content := resp.Header.Get("Content-Type") + body, _ := ioutil.ReadAll(resp.Body) + + if resp.StatusCode != tt.wants.statusCode { + t.Errorf("%q. Config() = %v, want %v", tt.name, resp.StatusCode, tt.wants.statusCode) + } + if tt.wants.contentType != "" && content != tt.wants.contentType { + t.Errorf("%q. Config() = %v, want %v", tt.name, content, tt.wants.contentType) + } + if eq, _ := jsonEqual(string(body), tt.wants.body); tt.wants.body != "" && !eq { + t.Errorf("%q. Config() = \n***%v***\n,\nwant\n***%v***", tt.name, string(body), tt.wants.body) + } + }) + } +} diff --git a/server/mux.go b/server/mux.go index 5cdd25902e..716409fb1a 100644 --- a/server/mux.go +++ b/server/mux.go @@ -239,6 +239,7 @@ func NewMux(opts MuxOpts, service Service) http.Handler { // Global application config for Chronograf router.GET("/chronograf/v1/config", EnsureSuperAdmin(service.Config)) + router.GET("/chronograf/v1/config/:section", EnsureSuperAdmin(service.ConfigSection)) allRoutes := &AllRoutes{ Logger: opts.Logger,