From e1b3836c6002f8aecc08b0345418bbfd5671e46e Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Sun, 1 Feb 2015 02:35:00 -0800 Subject: [PATCH] Service a new WebUI server at port 8081. It is provided to avoid the router clutter on the Object API end. This is just a first cut sample we are going to build on top of this the new management console UI. General interest comes from subsequently writing a small UI to generate `AccessKey` and `SecretKey` to build authorization layer. --- main.go | 95 +++++++++++------- pkg/{webapi => api}/minioapi/definitions.go | 0 pkg/{webapi => api}/minioapi/minioapi.go | 0 pkg/{webapi => api}/minioapi/minioapi_test.go | 0 pkg/api/webuiapi/webuiapi.go | 46 +++++++++ pkg/httpserver/httpserver.go | 12 ++- pkg/server/server.go | 97 +++++++++++++------ 7 files changed, 181 insertions(+), 69 deletions(-) rename pkg/{webapi => api}/minioapi/definitions.go (100%) rename pkg/{webapi => api}/minioapi/minioapi.go (100%) rename pkg/{webapi => api}/minioapi/minioapi_test.go (100%) create mode 100644 pkg/api/webuiapi/webuiapi.go diff --git a/main.go b/main.go index 108b2697e..0f1b0309c 100644 --- a/main.go +++ b/main.go @@ -8,15 +8,70 @@ import ( "github.com/minio-io/minio/pkg/server" ) +func getStorageType(input string) server.StorageType { + switch { + case input == "file": + return server.FileStorage + case input == "inmemory": + return server.InMemoryStorage + default: + { + log.Println("Unknown storage type:", input) + log.Println("Choosing default storage type as 'file'..") + return server.FileStorage + } + } +} + +func runCmd(c *cli.Context) { + storageTypeStr := c.String("storage-type") + apiaddress := c.String("api-address") + webaddress := c.String("web-address") + certFile := c.String("cert") + keyFile := c.String("key") + if (certFile != "" && keyFile == "") || (certFile == "" && keyFile != "") { + log.Fatal("Both certificate and key must be provided to enable https") + } + tls := (certFile != "" && keyFile != "") + storageType := getStorageType(storageTypeStr) + var serverConfigs []server.ServerConfig + apiServerConfig := server.ServerConfig{ + Address: apiaddress, + Tls: tls, + CertFile: certFile, + KeyFile: keyFile, + ApiType: server.MinioApi{ + StorageType: storageType, + }, + } + webUiServerConfig := server.ServerConfig{ + Address: webaddress, + Tls: false, + CertFile: "", + KeyFile: "", + ApiType: server.WebUIApi{ + Websocket: false, + }, + } + serverConfigs = append(serverConfigs, apiServerConfig) + serverConfigs = append(serverConfigs, webUiServerConfig) + server.Start(serverConfigs) +} + func main() { app := cli.NewApp() app.Name = "minio" app.Usage = "" app.Flags = []cli.Flag{ cli.StringFlag{ - Name: "http-address,a", + Name: "api-address,a", Value: ":8080", - Usage: "http address to listen on", + Usage: "address for incoming API requests", + }, + cli.StringFlag{ + Name: "web-address,w", + Value: ":8081", + Usage: "address for incoming Management UI requests", }, cli.StringFlag{ Name: "cert,c", @@ -34,40 +89,6 @@ func main() { Usage: "valid entries: file,inmemory", }, } - app.Action = func(c *cli.Context) { - storageTypeStr := c.String("storage-type") - address := c.String("http-address") - log.Println(address) - certFile := c.String("cert") - keyFile := c.String("key") - if (certFile != "" && keyFile == "") || (certFile == "" && keyFile != "") { - log.Fatal("Both certificate and key must be provided to enable https") - } - tls := (certFile != "" && keyFile != "") - storageType := getStorageType(storageTypeStr) - serverConfig := server.ServerConfig{ - Address: address, - Tls: tls, - CertFile: certFile, - KeyFile: keyFile, - StorageType: storageType, - } - server.Start(serverConfig) - } + app.Action = runCmd app.Run(os.Args) } - -func getStorageType(input string) server.StorageType { - switch { - case input == "file": - return server.FileStorage - case input == "inmemory": - return server.InMemoryStorage - default: - { - log.Println("Unknown storage type:", input) - log.Println("Choosing default storage type as 'file'..") - return server.FileStorage - } - } -} diff --git a/pkg/webapi/minioapi/definitions.go b/pkg/api/minioapi/definitions.go similarity index 100% rename from pkg/webapi/minioapi/definitions.go rename to pkg/api/minioapi/definitions.go diff --git a/pkg/webapi/minioapi/minioapi.go b/pkg/api/minioapi/minioapi.go similarity index 100% rename from pkg/webapi/minioapi/minioapi.go rename to pkg/api/minioapi/minioapi.go diff --git a/pkg/webapi/minioapi/minioapi_test.go b/pkg/api/minioapi/minioapi_test.go similarity index 100% rename from pkg/webapi/minioapi/minioapi_test.go rename to pkg/api/minioapi/minioapi_test.go diff --git a/pkg/api/webuiapi/webuiapi.go b/pkg/api/webuiapi/webuiapi.go new file mode 100644 index 000000000..91e19c371 --- /dev/null +++ b/pkg/api/webuiapi/webuiapi.go @@ -0,0 +1,46 @@ +/* + * Mini Object Storage, (C) 2014 Minio, Inc. + * + * 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 webuiapi + +import ( + "fmt" + "net/http" + + "github.com/gorilla/mux" +) + +type webUiApi struct { +} + +func HttpHandler() http.Handler { + mux := mux.NewRouter() + var api = webUiApi{} + mux.HandleFunc("/", api.homeHandler).Methods("GET") + /* + mux.HandleFunc("/{bucket}/", api.listObjectsHandler).Methods("GET") + mux.HandleFunc("/{bucket}/", api.putBucketHandler).Methods("PUT") + mux.HandleFunc("/{bucket}/{object:.*}", api.getObjectHandler).Methods("GET") + mux.HandleFunc("/{bucket}/{object:.*}", api.headObjectHandler).Methods("HEAD") + mux.HandleFunc("/{bucket}/{object:.*}", api.putObjectHandler).Methods("PUT") + */ + return mux +} + +func (web *webUiApi) homeHandler(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Server", "Minio Management Console") + fmt.Fprintln(w, "Welcome!") +} diff --git a/pkg/httpserver/httpserver.go b/pkg/httpserver/httpserver.go index 01eacc57f..c1b4253b8 100644 --- a/pkg/httpserver/httpserver.go +++ b/pkg/httpserver/httpserver.go @@ -23,10 +23,11 @@ import ( ) type HttpServerConfig struct { - Address string - TLS bool - CertFile string - KeyFile string + Address string + TLS bool + CertFile string + KeyFile string + Websocket bool } type HttpServer struct{} @@ -39,7 +40,8 @@ func Start(handler http.Handler, config HttpServerConfig) (chan<- string, <-chan return ctrlChannel, errorChannel, &server } -func start(ctrlChannel <-chan string, errorChannel chan<- error, router http.Handler, config HttpServerConfig, server *HttpServer) { +func start(ctrlChannel <-chan string, errorChannel chan<- error, + router http.Handler, config HttpServerConfig, server *HttpServer) { var err error // Minio server config diff --git a/pkg/server/server.go b/pkg/server/server.go index 48ceaefb7..736a0d70e 100644 --- a/pkg/server/server.go +++ b/pkg/server/server.go @@ -23,21 +23,30 @@ import ( "path" "reflect" + "github.com/minio-io/minio/pkg/api/minioapi" + "github.com/minio-io/minio/pkg/api/webuiapi" "github.com/minio-io/minio/pkg/httpserver" mstorage "github.com/minio-io/minio/pkg/storage" "github.com/minio-io/minio/pkg/storage/fs" "github.com/minio-io/minio/pkg/storage/inmemory" - "github.com/minio-io/minio/pkg/webapi/minioapi" ) type ServerConfig struct { - Address string - Tls bool - CertFile string - KeyFile string + Address string + Tls bool + CertFile string + KeyFile string + ApiType interface{} +} + +type MinioApi struct { StorageType StorageType } +type WebUIApi struct { + Websocket bool +} + type StorageType int const ( @@ -45,27 +54,62 @@ const ( FileStorage ) -func Start(config ServerConfig) { - // maintain a list of input and output channels for communicating with services - var ctrlChans []chan<- string - var statusChans []<-chan error - +func getHttpChannels(configs []ServerConfig) (ctrlChans []chan<- string, statusChans []<-chan error) { // a pair of control channels, we use these primarily to add to the lists above var ctrlChan chan<- string var statusChan <-chan error - // configure web server - var storage mstorage.Storage - var httpConfig = httpserver.HttpServerConfig{} - httpConfig.Address = config.Address - httpConfig.TLS = config.Tls + for _, config := range configs { + switch k := config.ApiType.(type) { + case MinioApi: + { + // configure web server + var storage mstorage.Storage + var httpConfig = httpserver.HttpServerConfig{} + httpConfig.Address = config.Address + httpConfig.Websocket = false + httpConfig.TLS = config.Tls - if config.CertFile != "" { - httpConfig.CertFile = config.CertFile - } - if config.KeyFile != "" { - httpConfig.KeyFile = config.KeyFile + if config.CertFile != "" { + httpConfig.CertFile = config.CertFile + } + if config.KeyFile != "" { + httpConfig.KeyFile = config.KeyFile + } + + ctrlChans, statusChans, storage = getStorageChannels(k.StorageType) + // start minio api in a web server, pass storage driver into it + ctrlChan, statusChan, _ = httpserver.Start(minioapi.HttpHandler(storage), httpConfig) + + ctrlChans = append(ctrlChans, ctrlChan) + statusChans = append(statusChans, statusChan) + + } + case WebUIApi: + { + var httpConfig = httpserver.HttpServerConfig{} + httpConfig.Address = config.Address + httpConfig.TLS = config.Tls + httpConfig.CertFile = config.CertFile + httpConfig.KeyFile = config.KeyFile + + httpConfig.Websocket = k.Websocket + ctrlChan, statusChan, _ = httpserver.Start(webuiapi.HttpHandler(), httpConfig) + + ctrlChans = append(ctrlChans, ctrlChan) + statusChans = append(statusChans, statusChan) + } + default: + log.Fatal("Invalid api type") + } } + return +} + +func getStorageChannels(storageType StorageType) (ctrlChans []chan<- string, statusChans []<-chan error, storage mstorage.Storage) { + // a pair of control channels, we use these primarily to add to the lists above + var ctrlChan chan<- string + var statusChan <-chan error // instantiate storage // preconditions: @@ -76,13 +120,13 @@ func Start(config ServerConfig) { // - ctrlChans has channel to communicate to storage // - statusChans has channel for messages coming from storage switch { - case config.StorageType == InMemoryStorage: + case storageType == InMemoryStorage: { ctrlChan, statusChan, storage = inmemory.Start() ctrlChans = append(ctrlChans, ctrlChan) statusChans = append(statusChans, statusChan) } - case config.StorageType == FileStorage: + case storageType == FileStorage: { // TODO Replace this with a more configurable and robust version currentUser, err := user.Current() @@ -103,15 +147,14 @@ func Start(config ServerConfig) { default: // should never happen log.Fatal("No storage driver found") } + return +} - // start minio api in a web server, pass storage driver into it - ctrlChan, statusChan, _ = httpserver.Start(minioapi.HttpHandler(storage), httpConfig) - ctrlChans = append(ctrlChans, ctrlChan) - statusChans = append(statusChans, statusChan) - +func Start(configs []ServerConfig) { // listen for critical errors // TODO Handle critical errors appropriately when they arise // reflected looping is necessary to remove dead channels from loop and not flood switch + _, statusChans := getHttpChannels(configs) cases := createSelectCases(statusChans) for len(cases) > 0 { chosen, value, recvOk := reflect.Select(cases)