func forEachList(vm *VM, obj []interface{}, workerNum int, f func(item interface{}) error) error { if obj == nil { return nil } size := len(obj) if size == 0 { return nil } if workerNum == 0 { for _, value := range obj { select { case f := <-vm.StopChan: f() return nil default: err := f(value) if err != nil { return err } } } return nil } queue := job.NewQueue(uint(workerNum)) for _, item := range obj { localItem := item queue.Add(job.NewJob(func() { f(localItem) })) } queue.Wait() return nil }
//MakeQueue makes new worker queue with specfied workers func MakeQueue(workers int) *job.Queue { return job.NewQueue(uint(workers)) }
//NewServer returns new GohanAPIServer func NewServer(configFile string) (*Server, error) { manager := schema.GetManager() config := util.GetConfig() err := config.ReadConfig(configFile) err = os.Chdir(path.Dir(configFile)) if err != nil { return nil, fmt.Errorf("Config load error: %s", err) } err = l.SetUpLogging(config) if err != nil { return nil, fmt.Errorf("Logging setup error: %s", err) } log.Info("logging initialized") server := &Server{} m := martini.Classic() m.Handlers() m.Use(middleware.Logging()) m.Use(martini.Recovery()) m.Use(middleware.JSONURLs()) m.Use(middleware.WithContext()) server.martini = m port := os.Getenv("PORT") if port == "" { port = "9091" } setupEditor(server) server.timelimit = config.GetInt("extension/timelimit", 30) server.extensions = config.GetStringList("extension/use", []string{ "javascript", "gohanscript", "go", }) schema.DefaultExtension = config.GetString("extension/default", "javascript") server.address = config.GetString("address", ":"+port) if config.GetBool("tls/enabled", false) { log.Info("TLS enabled") server.tls = &tlsConfig{ KeyFile: config.GetString("tls/key_file", "./etc/key.pem"), CertFile: config.GetString("tls/cert_file", "./etc/cert.pem"), } } etcdServers := config.GetStringList("etcd", nil) if etcdServers != nil { log.Info("etcd servers: %s", etcdServers) server.sync = etcd.NewSync(etcdServers) } server.connectDB() schemaFiles := config.GetStringList("schemas", nil) if schemaFiles == nil { log.Fatal("No schema specified in configuraion") } else { err = manager.LoadSchemasFromFiles(schemaFiles...) if err != nil { return nil, fmt.Errorf("invalid schema: %s", err) } } if !config.GetBool("database/no_init", false) { server.initDB() } if config.GetList("database/initial_data", nil) != nil { initialDataList := config.GetList("database/initial_data", nil) for _, initialData := range initialDataList { initialDataConfig := initialData.(map[string]interface{}) inType := initialDataConfig["type"].(string) inConnection := initialDataConfig["connection"].(string) log.Info("Importing data from %s ...", inConnection) inDB, err := db.ConnectDB(inType, inConnection, db.DefaultMaxOpenConn) if err != nil { log.Fatal(err) } db.CopyDBResources(inDB, server.db, false) } } if config.GetBool("keystone/use_keystone", false) { //TODO remove this if config.GetBool("keystone/fake", false) { server.keystoneIdentity = &middleware.FakeIdentity{} //TODO(marcin) requests to fake server also get authenticated // we need a separate routing Group log.Info("Debug Mode with Fake Keystone Server") } else { log.Info("Keystone backend server configured") server.keystoneIdentity, err = cloud.NewKeystoneIdentity( config.GetString("keystone/auth_url", "http://localhost:35357/v3"), config.GetString("keystone/user_name", "admin"), config.GetString("keystone/password", "password"), config.GetString("keystone/domain_name", "Default"), config.GetString("keystone/tenant_name", "admin"), config.GetString("keystone/version", ""), ) if err != nil { log.Fatal(err) } } m.MapTo(server.keystoneIdentity, (*middleware.IdentityService)(nil)) m.Use(middleware.Authentication()) //m.Use(Authorization()) } else { m.MapTo(&middleware.NoIdentityService{}, (*middleware.IdentityService)(nil)) m.Map(schema.NewAuthorization("admin", "admin", "admin_token", []string{"admin"}, nil)) } if err != nil { return nil, fmt.Errorf("invalid base dir: %s", err) } server.addOptionsRoute() cors := config.GetString("cors", "") if cors != "" { log.Info("Enabling CORS for %s", cors) if cors == "*" { log.Warning("cors for * have security issue") } server.martini.Use(func(rw http.ResponseWriter, r *http.Request) { rw.Header().Add("Access-Control-Allow-Origin", cors) rw.Header().Add("Access-Control-Allow-Headers", "X-Auth-Token, Content-Type") rw.Header().Add("Access-Control-Expose-Headers", "X-Total-Count") rw.Header().Add("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE") }) } documentRoot := config.GetString("document_root", "embed") if config.GetBool("webui_config/enabled", false) { m.Use(func(res http.ResponseWriter, req *http.Request, c martini.Context) { if req.URL.Path != "/webui/config.json" { c.Next() return } address := config.GetString("webui_config/address", server.address) if address[0] == ':' { address = "__HOST__" + address } baseURL := "http://" + address authURL := "http://" + address + "/v2.0" if config.GetBool("webui_config/tls", config.GetBool("tls/enabled", false)) { baseURL = "https://" + address authURL = "https://" + address + "/v2.0" } authURL = config.GetString("webui_config/auth_url", authURL) webUIConfig := map[string]interface{}{ "authUrl": authURL, "gohan": map[string]interface{}{ "schema": "/gohan/v0.1/schemas", "url": baseURL, }, } routes.ServeJson(res, webUIConfig) }) } if documentRoot == "embed" { m.Use(staticbin.Static("public", util.Asset, staticbin.Options{ SkipLogging: true, })) } else { log.Info("Static file serving from %s", documentRoot) documentRootABS, err := filepath.Abs(documentRoot) if err != nil { return nil, err } server.martini.Use(martini.Static(documentRootABS, martini.StaticOptions{ SkipLogging: true, })) } server.mapRoutes() maxWorkerCount := config.GetInt("workers", 100) server.queue = job.NewQueue(uint(maxWorkerCount)) return server, nil }