/
serve.go
136 lines (115 loc) · 4.93 KB
/
serve.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package cmd
import (
"log"
"net/http"
"strings"
"github.com/cagedtornado/centralconfig/api"
"github.com/cagedtornado/centralconfig/datastores"
"github.com/gorilla/mux"
"github.com/rs/cors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
serverInterface string
serverPort int
serverUIDirectory string
allowedOrigins string
)
// serveCmd represents the serve command
var serveCmd = &cobra.Command{
Use: "serve",
Short: "Start the config server",
Long: `Centralconfig provides its own webserver which can serve both the
API and the UI for the app.`,
Run: serve,
}
func serve(cmd *cobra.Command, args []string) {
// If we have a config file, report it:
if viper.ConfigFileUsed() != "" {
log.Println("[INFO] Using config file:", viper.ConfigFileUsed())
}
// Log the datastore information we have:
logDatastoreInfo()
// Create a router and setup our REST endpoints...
var Router = mux.NewRouter()
// Setup our routes
Router.HandleFunc("/", api.ShowUI)
Router.HandleFunc("/config/get", api.GetConfig)
Router.HandleFunc("/config/set", api.SetConfig)
Router.HandleFunc("/config/remove", api.RemoveConfig)
Router.HandleFunc("/config/getall", api.GetAllConfig)
Router.HandleFunc("/config/getallforapp", api.GetAllConfigForApp)
Router.HandleFunc("/applications/getall", api.GetAllApplications)
// Websocket connections
Router.Handle("/ws", api.WsHandler{H: api.WsHub})
// If we don't have a UI directory specified...
if viper.GetString("server.ui-dir") == "" {
// Use the static assets file generated with
// https://github.com/elazarl/go-bindata-assetfs using the centralconfig-ui from
// https://github.com/danesparza/centralconfig-ui.
//
// To generate this file, place the 'ui'
// directory under the main centralconfig directory and run the commands:
// go-bindata-assetfs.exe -pkg cmd ./ui/...
// mv bindata_assetfs.go cmd
// go install ./...
Router.PathPrefix("/ui").Handler(http.StripPrefix("/ui", http.FileServer(assetFS())))
} else {
// Use the supplied directory:
log.Printf("[INFO] Using UI directory: %s\n", viper.GetString("server.ui-dir"))
Router.PathPrefix("/ui").Handler(http.StripPrefix("/ui", http.FileServer(http.Dir(viper.GetString("server.ui-dir")))))
}
// Setup the CORS options:
log.Printf("[INFO] Allowed CORS origins: %s\n", viper.GetString("server.allowed-origins"))
c := cors.New(cors.Options{
AllowedOrigins: strings.Split(allowedOrigins, ","),
AllowCredentials: true,
})
corsHandler := c.Handler(Router)
// Format the bound interface:
formattedInterface := viper.GetString("server.bind")
if formattedInterface == "" {
formattedInterface = "127.0.0.1"
}
// If we have an SSL cert specified, use it:
if viper.GetString("server.sslcert") != "" {
log.Printf("[INFO] Using SSL cert: %s\n", viper.GetString("server.sslcert"))
log.Printf("[INFO] Using SSL key: %s\n", viper.GetString("server.sslkey"))
log.Printf("[INFO] Starting HTTPS server: https://%s:%s\n", formattedInterface, viper.GetString("server.port"))
log.Printf("[ERROR] %v\n", http.ListenAndServeTLS(viper.GetString("server.bind")+":"+viper.GetString("server.port"), viper.GetString("server.sslcert"), viper.GetString("server.sslkey"), corsHandler))
} else {
log.Printf("[INFO] Starting HTTP server: http://%s:%s\n", formattedInterface, viper.GetString("server.port"))
log.Printf("[ERROR] %v\n", http.ListenAndServe(viper.GetString("server.bind")+":"+viper.GetString("server.port"), corsHandler))
}
}
func init() {
RootCmd.AddCommand(serveCmd)
// Setup our flags
serveCmd.Flags().IntVarP(&serverPort, "port", "p", 1313, "port on which the server will listen")
serveCmd.Flags().StringVarP(&serverInterface, "bind", "i", "", "interface to which the server will bind")
serveCmd.Flags().StringVarP(&serverUIDirectory, "ui-dir", "u", "", "directory for the UI")
serveCmd.Flags().StringVarP(&allowedOrigins, "allowed-origins", "o", "", "comma seperated list of allowed CORS origins")
// Bind config flags for optional config file override:
viper.BindPFlag("server.port", serveCmd.Flags().Lookup("port"))
viper.BindPFlag("server.bind", serveCmd.Flags().Lookup("bind"))
viper.BindPFlag("server.ui-dir", serveCmd.Flags().Lookup("ui-dir"))
viper.BindPFlag("server.allowed-origins", serveCmd.Flags().Lookup("allowed-origins"))
}
func logDatastoreInfo() {
// Get configuration information
ds := datastores.GetConfigDatastore()
switch t := ds.(type) {
case datastores.MySqlDB:
log.Printf("[INFO] Using MySQL server: %s\n", ds.(datastores.MySqlDB).Address)
log.Printf("[INFO] Using MySQL database: %s\n", ds.(datastores.MySqlDB).Database)
case datastores.MSSqlDB:
log.Printf("[INFO] Using MSSQL server: %s\n", ds.(datastores.MSSqlDB).Address)
log.Printf("[INFO] Using MSSQL database: %s\n", ds.(datastores.MSSqlDB).Database)
case datastores.BoltDB:
log.Printf("[INFO] Using BoltDB database: %s\n", ds.(datastores.BoltDB).Database)
default:
_ = t
log.Println("[ERROR] Can't determine datastore type")
}
}