upgrades - plugins

pull/10/head
Hunter Long 2018-06-13 23:38:15 -07:00
parent 077d1a5900
commit 808a2b60f1
14 changed files with 284 additions and 229 deletions

View File

@ -54,7 +54,7 @@ func (s *Service) Check() {
func (s *Service) Record(response *http.Response) {
db.QueryRow("INSERT INTO hits(service,latency,created_at) VALUES($1,$2,NOW()) returning id;", s.Id, s.Latency).Scan()
OnHit(s)
OnSuccess(s)
}
func (s *Service) Failure(issue string) {

15
core.go
View File

@ -6,13 +6,14 @@ import (
)
type Core struct {
Name string
Config string
Key string
Secret string
Version string
Plugins []plugin.Info
Repos []PluginJSON
Name string
Config string
Key string
Secret string
Version string
Plugins []plugin.Info
Repos []PluginJSON
PluginFields []PluginSelect
}
func SelectCore() (*Core, error) {

View File

@ -2,9 +2,9 @@ package main
import "github.com/hunterlong/statup/plugin"
func OnHit(s *Service) {
func OnSuccess(s *Service) {
for _, p := range allPlugins {
p.OnHit(s.ToP())
p.OnSuccess(s.ToP())
}
}

View File

@ -48,26 +48,26 @@
</div>
{{ range .Plugins }}
<div class="tab-pane fade" id="v-pills-{{.Name}}" role="tabpanel" aria-labelledby="v-pills-{{.Name}}-tab">
<h4 class="text-capitalize">{{ .Name }}</h4>
<span class="text-muted">{{ .Description }}</span>
<form class="mt-3" method="POST" action="/plugins/{{.Name}}/save">
{{ range .Form }}
<div class="form-group">
<label for="input_{{ .SQLValue }}" class="text-capitalize">{{ .Name }}</label>
<input type="text" class="form-control" name="{{ .SQLValue }}" value="{{ .Val }}" id="input_{{ .SQLValue }}" placeholder="Example input" aria-describedby="help_{{ .SQLValue }}">
{{ if .Description }}
<small id="help_{{ .SQLValue }}" class="form-text text-muted">
{{ .Description }}
</small>
{{ end }}
</div>
{{ end }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
<form class="mt-3" method="POST" action="/plugins/{{.Name}}/save">
{{ range .Form }}
<div class="form-group">
<label for="input_{{ .InputName }}" class="text-capitalize">{{ .Name }}</label>
<input type="text" class="form-control" name="{{ .InputName }}" value="{{ .Value }}" id="input_{{ .InputName }}" placeholder="Example input" aria-describedby="help_{{ .InputName }}">
{{ if .Description }}
<small id="help_{{ .InputName }}" class="form-text text-muted">
{{ .Description }}
</small>
{{ end }}
</div>
{{ end }}
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
{{end}}

138
main.go
View File

@ -10,6 +10,7 @@ import (
"github.com/hunterlong/statup/plugin"
_ "github.com/lib/pq"
"golang.org/x/crypto/bcrypt"
"io"
"io/ioutil"
"net/http"
"os"
@ -70,6 +71,135 @@ func (c *Core) FetchPluginRepo() []PluginJSON {
return pk
}
func DownloadFile(filepath string, url string) error {
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}
func SelectSettings(p plugin.Info) map[string]string {
data := make(map[string]string)
var tableInput []string
for _, v := range p.Form {
val := fmt.Sprintf("%v", v.InputName)
tableInput = append(tableInput, val)
}
ins := strings.Join(tableInput, ", ")
sql := fmt.Sprintf("SELECT %v FROM settings_%v LIMIT 1", ins, p.Name)
rows, err := db.Query(sql)
if err != nil {
fmt.Println("SQL ERROR: ", err)
return map[string]string{}
}
count := len(p.Form)
valuePtrs := make([]interface{}, count)
values := make([]interface{}, count)
for rows.Next() {
for i, _ := range p.Form {
valuePtrs[i] = &values[i]
}
err = rows.Scan(valuePtrs...)
if err != nil {
panic(err)
}
for i, col := range p.Form {
val := values[i]
b, _ := val.([]byte)
realVal := string(b)
//col.ChangeVal(realVal)
fmt.Println(col.Value, realVal)
data[col.InputName] = realVal
}
}
return data
}
func CreateSettingsTable(p plugin.Info) string {
var tableValues []string
tableValues = append(tableValues, "plugin text")
tableValues = append(tableValues, "enabled bool")
for _, v := range p.Form {
tb := fmt.Sprintf("%v %v", v.InputName, v.InputType)
tableValues = append(tableValues, tb)
}
vals := strings.Join(tableValues, ", ")
out := fmt.Sprintf("CREATE TABLE settings_%v (%v);", p.Name, vals)
smtp, _ := db.Prepare(out)
_, _ = smtp.Exec()
InitalSettings(p)
return out
}
func InitalSettings(p plugin.Info) {
var tableValues []string
var tableInput []string
tableValues = append(tableValues, "plugin")
tableInput = append(tableInput, fmt.Sprintf("'%v'", p.Name))
tableValues = append(tableValues, "enabled")
tableInput = append(tableInput, "false")
for _, v := range p.Form {
val := fmt.Sprintf("'%v'", v.Value)
tableValues = append(tableValues, v.InputName)
tableInput = append(tableInput, val)
}
vals := strings.Join(tableValues, ",")
ins := strings.Join(tableInput, ",")
sql := fmt.Sprintf("INSERT INTO settings_%v(%v) VALUES(%v);", p.Name, vals, ins)
smtp, _ := db.Prepare(sql)
_, _ = smtp.Exec()
}
func UpdateSettings(p plugin.Info, data map[string]string) {
var tableInput []string
for _, v := range p.Form {
newValue := data[v.InputName]
val := fmt.Sprintf("%v='%v'", v.InputName, newValue)
tableInput = append(tableInput, val)
}
ins := strings.Join(tableInput, ", ")
sql := fmt.Sprintf("UPDATE settings_%v SET %v WHERE plugin='%v';", p.Name, ins, p.Name)
smtp, _ := db.Prepare(sql)
_, _ = smtp.Exec()
}
//func DownloadPlugin(name string) {
// plugin := SelectPlugin(name)
// var _, err = os.Stat("plugins/" + plugin.Namespace)
@ -119,7 +249,7 @@ func mainProcess() {
DbConnection()
core, err = SelectCore()
if err != nil {
panic(err)
throw(err)
}
go CheckServices()
if !setupMode {
@ -128,6 +258,11 @@ func mainProcess() {
}
}
func throw(err error) {
fmt.Println(err)
os.Exit(1)
}
func ForEachPlugin() {
if len(core.Plugins) > 0 {
//for _, p := range core.Plugins {
@ -162,6 +297,7 @@ func LoadPlugins() {
continue
}
symPlugin, err := plug.Lookup("Plugin")
var plugActions plugin.PluginActions
plugActions, ok := symPlugin.(plugin.PluginActions)
if !ok {

View File

@ -2,16 +2,25 @@ package main
import (
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
)
func TestInit(t *testing.T) {
VERSION = "1.1.1"
RenderBoxes()
}
func TestMakeConfig(t *testing.T) {
config := &DbConfig{
"postgres",
"localhost",
"travis",
"",
"postgres",
os.Getenv("DB_HOST"),
os.Getenv("DB_USER"),
os.Getenv("DB_PASS"),
os.Getenv("DB_DATABASE"),
5432,
"Testing",
"admin",
@ -21,8 +30,30 @@ func TestMakeConfig(t *testing.T) {
assert.Nil(t, err)
}
func Test(t *testing.T) {
assert.Equal(t, "", "")
func TestSetConfig(t *testing.T) {
configs = LoadConfig()
}
func TestRun(t *testing.T) {
configs = LoadConfig()
go mainProcess()
time.Sleep(15 * time.Second)
}
func TestServiceUrl(t *testing.T) {
req, err := http.NewRequest("GET", "/service/1", nil)
assert.Nil(t, err)
rr := httptest.NewRecorder()
Router().ServeHTTP(rr, req)
assert.Equal(t, 3305, len(rr.Body.Bytes()), "should be balance")
}
func Test(t *testing.T) {
req, err := http.NewRequest("GET", "/dashboard", nil)
assert.Nil(t, err)
rr := httptest.NewRecorder()
Router().ServeHTTP(rr, req)
assert.Equal(t, 2048, len(rr.Body.Bytes()), "should be balance")
}

View File

@ -1,27 +1,64 @@
package plugin
import (
"database/sql"
"fmt"
"net/http"
"time"
)
//
// STATUP PLUGIN INTERFACE
//
// v0.1
//
// https://statup.io
//
var (
DB *sql.DB
)
func SetDatabase(database *sql.DB) {
DB = database
}
func Throw(err error) {
fmt.Println(err)
}
type PluginInfo struct {
Info Info
PluginActions
}
type PluginActions interface {
GetInfo() Info
SetInfo(map[string]string) Info
Routes() []Routing
OnSave(map[string]string)
OnFailure(*Service)
OnSuccess(*Service)
OnSettingsSaved(map[string]string)
OnNewUser(*User)
OnNewService(*Service)
OnUpdatedService(*Service)
OnDeletedService(*Service)
OnInstall()
OnUninstall()
OnFailure(*Service)
OnHit(*Service)
OnSettingsSaved()
OnNewUser()
OnNewService()
OnShutdown()
OnLoad()
OnBeforeRequest()
OnAfterRequest()
}
type User struct {
Id int64
Username string
Password string
Email string
}
type Service struct {
Id int64
Name string
@ -49,11 +86,6 @@ type Failure struct {
Ago string
}
type PluginInfo struct {
Info Info
PluginActions
}
type Routing struct {
URL string
Method string
@ -63,13 +95,13 @@ type Routing struct {
type Info struct {
Name string
Description string
Form []FormElement
Form []*FormElement
}
type FormElement struct {
Name string
Description string
SQLValue string
SQLType string
Value interface{}
InputName string
InputType string
Value string
}

7
plugin/main_test.go Normal file
View File

@ -0,0 +1,7 @@
package plugin
import "testing"
func TestInit(t *testing.T) {
}

View File

@ -1,169 +0,0 @@
package plugin
import (
"database/sql"
"fmt"
"html/template"
"io"
"net/http"
"os"
"strings"
)
var (
db *sql.DB
AllPlugins []Info
)
func CreateSettingsTable(p Info) string {
var tableValues []string
for _, v := range p.Form {
tb := fmt.Sprintf("%v %v", v.SQLValue, v.SQLType)
tableValues = append(tableValues, tb)
}
vals := strings.Join(tableValues, ", ")
out := fmt.Sprintf("CREATE TABLE settings_%v (%v);", p.Name, vals)
smtp, _ := db.Prepare(out)
_, _ = smtp.Exec()
InitalSettings(p)
return out
}
func InitalSettings(p Info) {
var tableValues []string
var tableInput []string
for _, v := range p.Form {
val := fmt.Sprintf("'%v'", "example data")
tableValues = append(tableValues, v.SQLValue)
tableInput = append(tableInput, val)
}
vals := strings.Join(tableValues, ",")
ins := strings.Join(tableInput, ",")
sql := fmt.Sprintf("INSERT INTO settings_%v(%v) VALUES(%v);", p.Name, vals, ins)
smtp, _ := db.Prepare(sql)
_, _ = smtp.Exec()
SelectSettings(p)
}
func (f FormElement) Val() string {
var v string
fmt.Println(f.Value)
b, ok := f.Value.([]byte)
if ok {
v = string(b)
}
return v
}
func SelectSettings(p Info) []*FormElement {
var newForm []*FormElement
sql := fmt.Sprintf("SELECT * FROM settings_%v LIMIT 1", p.Name)
rows, err := db.Query(sql)
if err != nil {
panic(err)
}
count := len(p.Form)
valuePtrs := make([]interface{}, count)
values := make([]interface{}, count)
for rows.Next() {
for i, _ := range p.Form {
valuePtrs[i] = &values[i]
}
err = rows.Scan(valuePtrs...)
if err != nil {
panic(err)
}
for i, col := range p.Form {
var v interface{}
val := values[i]
b, ok := val.([]byte)
if ok {
v = string(b)
} else {
v = val
}
ll := &FormElement{
Name: col.Name,
Description: col.Description,
SQLValue: col.SQLValue,
SQLType: col.SQLType,
Value: v,
}
newForm = append(newForm, ll)
fmt.Println(col.SQLValue, v)
col.Value = v
}
}
return newForm
}
func RunSQL(query string, args ...interface{}) (*sql.Rows, error) {
rows, err := db.Query(query, args)
return rows, err
}
func (i Info) Template() *template.Template {
t := template.New("form")
temp, _ := t.Parse("hello nworld")
return temp
}
func DownloadFile(filepath string, url string) error {
out, err := os.Create(filepath)
if err != nil {
return err
}
defer out.Close()
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
return err
}
return nil
}
func SetDatabase(database *sql.DB) {
db = database
}
func (p *PluginInfo) InstallPlugin(w http.ResponseWriter, r *http.Request) {
//sql := "CREATE TABLE " + p.Name + " (enabled BOOLEAN, api_key text, api_secret text, channel text);"
//db.QueryRow(p.InstallSQL()).Scan()
http.Redirect(w, r, "/plugins", http.StatusSeeOther)
}
func (p *PluginInfo) UninstallPlugin(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/plugins", http.StatusSeeOther)
}
func (p *PluginInfo) SavePlugin(w http.ResponseWriter, r *http.Request) {
//values := r.PostForm
//p.SaveFunc(values)
http.Redirect(w, r, "/plugins", http.StatusSeeOther)
}

Binary file not shown.

Binary file not shown.

View File

@ -4,6 +4,7 @@ import (
"crypto/sha1"
"encoding/json"
"fmt"
"github.com/hunterlong/statup/plugin"
"math/rand"
"strconv"
"time"
@ -30,6 +31,7 @@ type Service struct {
AvgResponse string
TotalUptime string
Failures []*Failure
plugin.Service
}
func SelectService(id string) *Service {

View File

@ -3,7 +3,8 @@ CREATE TABLE core (
config text,
api_key text,
api_secret text,
version text
version text,
plugins_enabled text,
);
CREATE TABLE users (

36
web.go
View File

@ -15,15 +15,11 @@ var (
session *sessions.CookieStore
)
func RunHTTPServer() {
func Router() *mux.Router {
r := mux.NewRouter()
fmt.Println("Statup HTTP Server running on http://localhost:8080")
r.Handle("/", http.HandlerFunc(IndexHandler))
r.PathPrefix("/css/").Handler(http.StripPrefix("/css/", http.FileServer(cssBox.HTTPBox())))
r.PathPrefix("/js/").Handler(http.StripPrefix("/js/", http.FileServer(jsBox.HTTPBox())))
r.Handle("/setup", http.HandlerFunc(SetupHandler))
r.Handle("/setup/save", http.HandlerFunc(ProcessSetupHandler))
r.Handle("/dashboard", http.HandlerFunc(DashboardHandler))
@ -41,7 +37,12 @@ func RunHTTPServer() {
r.Handle("/plugins/download/{name}", http.HandlerFunc(PluginsDownloadHandler))
r.Handle("/plugins/{name}/save", http.HandlerFunc(PluginSavedHandler)).Methods("POST")
r.Handle("/help", http.HandlerFunc(HelpHandler))
return r
}
func RunHTTPServer() {
fmt.Println("Statup HTTP Server running on http://localhost:8080")
r := Router()
for _, p := range allPlugins {
info := p.GetInfo()
for _, route := range p.Routes() {
@ -214,6 +215,9 @@ func ServicesDeleteHandler(w http.ResponseWriter, r *http.Request) {
func IsAuthenticated(r *http.Request) bool {
session, _ := store.Get(r, "apizer_auth")
if session.Values["authenticated"] == nil {
return false
}
return session.Values["authenticated"].(bool)
}
@ -226,17 +230,26 @@ func PluginsHandler(w http.ResponseWriter, r *http.Request) {
tmpl := ParsePlugins("plugins.html")
core.FetchPluginRepo()
var pluginFields []PluginSelect
for _, p := range allPlugins {
for _, f := range p.GetInfo().Form {
fields := SelectSettings(p.GetInfo())
f.Val()
}
pluginFields = append(pluginFields, PluginSelect{p.GetInfo().Name, fields})
}
core.PluginFields = pluginFields
fmt.Println(&core.PluginFields)
tmpl.Execute(w, core)
}
type PluginSelect struct {
Plugin string
Params map[string]string
}
func PluginSavedHandler(w http.ResponseWriter, r *http.Request) {
auth := IsAuthenticated(r)
if !auth {
@ -245,12 +258,13 @@ func PluginSavedHandler(w http.ResponseWriter, r *http.Request) {
}
r.ParseForm()
vars := mux.Vars(r)
plugin := SelectPlugin(vars["name"])
plug := SelectPlugin(vars["name"])
data := make(map[string]string)
for k, v := range r.PostForm {
data[k] = strings.Join(v, "")
}
plugin.OnSave(data)
UpdateSettings(plug.GetInfo(), data)
plug.OnSave(data)
http.Redirect(w, r, "/settings", http.StatusSeeOther)
}