Final touches
* Possibility to pass token in query param * More appropriate names for gathering and resource updating functions * Shorter measuring delay * Container status available immediatelly when needed
This commit is contained in:
parent
60f99d52b0
commit
9348504f9e
2
api.http
2
api.http
@ -63,7 +63,7 @@ Content-type: application/json
|
|||||||
|
|
||||||
# Get
|
# Get
|
||||||
|
|
||||||
GET http://localhost:1323/v1/apps/test_1235
|
GET http://localhost:1323/v1/apps/test_1234
|
||||||
Content-type: application/json
|
Content-type: application/json
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,8 +111,8 @@ func Update(name string, SSHPort int, HTTPPort int, image string, CPU int, memor
|
|||||||
return &app, err
|
return &app, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateState sets state
|
// UpdateResources updates various metrics saved in the database
|
||||||
func UpdateState(name string, state string, CPUUsage float64, memory int, diskUsageBytes int, diskUsageInodes int) error {
|
func UpdateResources(name string, state string, CPUUsage float64, memory int, diskUsageBytes int, diskUsageInodes int) error {
|
||||||
db := common.GetDBConnection()
|
db := common.GetDBConnection()
|
||||||
|
|
||||||
err := db.Model(&App{}).Where("name = ?", name).Updates(App{
|
err := db.Model(&App{}).Where("name = ?", name).Updates(App{
|
||||||
@ -125,8 +125,8 @@ func UpdateState(name string, state string, CPUUsage float64, memory int, diskUs
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateContainerState sets container's state
|
// UpdateState sets container's state
|
||||||
func UpdateContainerState(name string, state string) error {
|
func UpdateState(name string, state string) error {
|
||||||
db := common.GetDBConnection()
|
db := common.GetDBConnection()
|
||||||
|
|
||||||
err := db.Model(&App{}).Where("name = ?", name).Updates(App{
|
err := db.Model(&App{}).Where("name = ?", name).Updates(App{
|
||||||
|
4
auth.go
4
auth.go
@ -20,6 +20,10 @@ func TokenMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
|
|||||||
tokenHeader := c.Request().Header.Get("Authorization")
|
tokenHeader := c.Request().Header.Get("Authorization")
|
||||||
token := strings.Replace(tokenHeader, "Token ", "", -1)
|
token := strings.Replace(tokenHeader, "Token ", "", -1)
|
||||||
|
|
||||||
|
if token == "" {
|
||||||
|
token = c.QueryParam("token")
|
||||||
|
}
|
||||||
|
|
||||||
if token != configuredToken || configuredToken == "" {
|
if token != configuredToken || configuredToken == "" {
|
||||||
return c.JSONPretty(403, map[string]string{"message": "access denied"}, " ")
|
return c.JSONPretty(403, map[string]string{"message": "access denied"}, " ")
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Stats delay in seconds
|
// Stats delay in seconds
|
||||||
const statsDelay = 5
|
const statsDelay = 1
|
||||||
|
|
||||||
// Docker timeout
|
// Docker timeout
|
||||||
const dockerTimeout = 10
|
const dockerTimeout = 10
|
||||||
@ -104,6 +104,39 @@ func (d *Driver) Status(name string) (string, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RawStats returns snapshot of current cpu and memory usage, CPU cannot be used
|
||||||
|
// for % usage because it's number of used tics. Call this twice to get the % usage.
|
||||||
|
// One second is 10 000 000 ticks.
|
||||||
|
func (d *Driver) RawStats(name string) (int64, int, error) {
|
||||||
|
cli, err := d.getClient()
|
||||||
|
if err != nil {
|
||||||
|
return 0.0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
containerID, err := d.nameToID(name)
|
||||||
|
if err != nil {
|
||||||
|
return 0.0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stats, err := cli.ContainerStats(context.TODO(), containerID, false)
|
||||||
|
if err != nil {
|
||||||
|
return 0.0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
row := ContainerStats{}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadAll(stats.Body)
|
||||||
|
if err != nil {
|
||||||
|
return 0.0, 0, err
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(data, &row)
|
||||||
|
if err != nil {
|
||||||
|
return 0.0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return row.CPU.Usage.Total, row.Memory.Usage, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Stats returns current CPU and memory usage
|
// Stats returns current CPU and memory usage
|
||||||
func (d *Driver) Stats(name string) (float64, int, error) {
|
func (d *Driver) Stats(name string) (float64, int, error) {
|
||||||
cli, err := d.getClient()
|
cli, err := d.getClient()
|
||||||
|
@ -7,7 +7,7 @@ type ContainerStats struct {
|
|||||||
} `json:"pids_stats"`
|
} `json:"pids_stats"`
|
||||||
CPU struct {
|
CPU struct {
|
||||||
Usage struct {
|
Usage struct {
|
||||||
Total int `json:"total_usage"`
|
Total int64 `json:"total_usage"`
|
||||||
} `json:"cpu_usage"`
|
} `json:"cpu_usage"`
|
||||||
} `json:"cpu_stats"`
|
} `json:"cpu_stats"`
|
||||||
Memory struct {
|
Memory struct {
|
||||||
|
@ -8,6 +8,9 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/rosti-cz/node-api/apps"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Return bytes, inodes occupied by a directory and/or error if there is any
|
// Return bytes, inodes occupied by a directory and/or error if there is any
|
||||||
@ -78,3 +81,51 @@ func removeDirectory(dir string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CPUMemoryStats returns list of applications with updated CPU and memory usage effectively.
|
||||||
|
// Sample is number of seconds between two measurements of the CPU usage. More means more precise.
|
||||||
|
func CPUMemoryStats(applist *[]apps.App, sample int) (*[]apps.App, error) {
|
||||||
|
if sample <= 0 {
|
||||||
|
sample = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
containers := []Container{}
|
||||||
|
for _, app := range *applist {
|
||||||
|
containers = append(containers, Container{App: &app})
|
||||||
|
}
|
||||||
|
|
||||||
|
startMap := make(map[string]int64)
|
||||||
|
endMap := make(map[string]int64)
|
||||||
|
|
||||||
|
start := time.Now().UnixNano()
|
||||||
|
for _, container := range containers {
|
||||||
|
cpu, _, err := container.GetRawResourceStats()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
startMap[container.App.Name] = cpu
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Duration(sample) * time.Second)
|
||||||
|
|
||||||
|
for idx, container := range containers {
|
||||||
|
cpu, memory, err := container.GetRawResourceStats()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
endMap[container.App.Name] = cpu
|
||||||
|
containers[idx].App.MemoryUsage = memory
|
||||||
|
}
|
||||||
|
|
||||||
|
end := time.Now().UnixNano()
|
||||||
|
difference := (float64(end) - float64(start)) / float64(1000000000)
|
||||||
|
|
||||||
|
updatedApps := []apps.App{}
|
||||||
|
for _, container := range containers {
|
||||||
|
app := *container.App
|
||||||
|
app.CPUUsage = (float64(endMap[app.Name]) - float64(startMap[app.Name])) / difference / 10000000.0
|
||||||
|
updatedApps = append(updatedApps, app)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &updatedApps, nil
|
||||||
|
}
|
||||||
|
@ -22,7 +22,14 @@ func (c *Container) volumeHostPath() string {
|
|||||||
return path.Join("/srv", c.App.Name)
|
return path.Join("/srv", c.App.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetState app object with populated state fields
|
// GetRawResourceStats returns RAW CPU and memory usage directly from Docker API
|
||||||
|
func (c *Container) GetRawResourceStats() (int64, int, error) {
|
||||||
|
driver := c.getDriver()
|
||||||
|
cpu, memory, err := driver.RawStats(c.App.Name)
|
||||||
|
return cpu, memory, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetState returns app state object with populated state fields
|
||||||
func (c *Container) GetState() (*apps.AppState, error) {
|
func (c *Container) GetState() (*apps.AppState, error) {
|
||||||
status, err := c.Status()
|
status, err := c.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -73,7 +80,7 @@ func (c *Container) Status() (string, error) {
|
|||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiskUsage returns number of MB and inodes used by the container in it's mounted volume
|
// DiskUsage returns number of bytes and inodes used by the container in it's mounted volume
|
||||||
func (c *Container) DiskUsage() (int, int, error) {
|
func (c *Container) DiskUsage() (int, int, error) {
|
||||||
return du(c.volumeHostPath())
|
return du(c.volumeHostPath())
|
||||||
}
|
}
|
||||||
|
27
main.go
27
main.go
@ -26,7 +26,7 @@ func main() {
|
|||||||
// Stats loop
|
// Stats loop
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
err := gatherContainersStats()
|
err := gatherStats()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("LOOP ERROR:", err.Error())
|
log.Println("LOOP ERROR:", err.Error())
|
||||||
}
|
}
|
||||||
@ -49,14 +49,16 @@ func main() {
|
|||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.Renderer = t
|
e.Renderer = t
|
||||||
|
|
||||||
// e.Use(TokenMiddleware)
|
e.Use(TokenMiddleware)
|
||||||
|
|
||||||
// Returns list of apps
|
// Returns list of apps
|
||||||
e.GET("/", func(c echo.Context) error {
|
e.GET("/", func(c echo.Context) error {
|
||||||
return c.Render(http.StatusOK, "index.html", "")
|
return c.Render(http.StatusOK, "index.html", templateData{
|
||||||
|
Token: configuredToken,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
e.GET("/v1/apps", func(c echo.Context) error {
|
e.GET("/v1/apps", func(c echo.Context) error {
|
||||||
err := gatherContainersStates()
|
err := gatherStates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
}
|
}
|
||||||
@ -74,12 +76,12 @@ func main() {
|
|||||||
e.GET("/v1/apps/:name", func(c echo.Context) error {
|
e.GET("/v1/apps/:name", func(c echo.Context) error {
|
||||||
name := c.Param("name")
|
name := c.Param("name")
|
||||||
|
|
||||||
app, err := apps.Get(name)
|
err := updateState(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = updateContainerState(app)
|
app, err := apps.Get(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
}
|
}
|
||||||
@ -163,8 +165,6 @@ func main() {
|
|||||||
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
go updateContainerStats(&app)
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -186,8 +186,6 @@ func main() {
|
|||||||
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
go updateContainerStats(app)
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -209,8 +207,6 @@ func main() {
|
|||||||
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
go updateContainerStats(app)
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -232,8 +228,6 @@ func main() {
|
|||||||
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
go updateContainerStats(app)
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -286,7 +280,10 @@ func main() {
|
|||||||
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
}
|
}
|
||||||
|
|
||||||
go updateContainerStats(app)
|
err = container.Start()
|
||||||
|
if err != nil {
|
||||||
|
return c.JSONPretty(http.StatusInternalServerError, Message{Message: err.Error()}, JSONIndent)
|
||||||
|
}
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
return c.JSON(http.StatusOK, Message{Message: "ok"})
|
||||||
})
|
})
|
||||||
|
70
stats.go
70
stats.go
@ -7,8 +7,41 @@ import (
|
|||||||
"github.com/rosti-cz/node-api/docker"
|
"github.com/rosti-cz/node-api/docker"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// updateUsage updates various resource usage of the container/app in the database
|
||||||
|
func updateUsage(name string) error {
|
||||||
|
app, err := apps.Get(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
container := docker.Container{
|
||||||
|
App: app,
|
||||||
|
}
|
||||||
|
|
||||||
|
state, err := container.GetState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = apps.UpdateResources(
|
||||||
|
name,
|
||||||
|
state.State,
|
||||||
|
state.CPUUsage,
|
||||||
|
state.MemoryUsage,
|
||||||
|
state.DiskUsageBytes,
|
||||||
|
state.DiskUsageInodes,
|
||||||
|
)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Updates only container's state
|
// Updates only container's state
|
||||||
func updateContainerState(app *apps.App) error {
|
func updateState(name string) error {
|
||||||
|
app, err := apps.Get(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
container := docker.Container{
|
container := docker.Container{
|
||||||
App: app,
|
App: app,
|
||||||
}
|
}
|
||||||
@ -17,43 +50,22 @@ func updateContainerState(app *apps.App) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = apps.UpdateContainerState(
|
err = apps.UpdateState(
|
||||||
app.Name,
|
app.Name,
|
||||||
state,
|
state,
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates info about all containers
|
// gatherStats loops over all applications and calls updateUsage to write various metric into the database.
|
||||||
func updateContainerStats(app *apps.App) error {
|
func gatherStats() error {
|
||||||
container := docker.Container{
|
|
||||||
App: app,
|
|
||||||
}
|
|
||||||
state, err := container.GetState()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = apps.UpdateState(
|
|
||||||
app.Name,
|
|
||||||
state.State,
|
|
||||||
state.CPUUsage,
|
|
||||||
state.MemoryUsage,
|
|
||||||
state.DiskUsageBytes,
|
|
||||||
state.DiskUsageInodes,
|
|
||||||
)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// gatherContainersStats gathers information about containers and saves it into the database
|
|
||||||
func gatherContainersStats() error {
|
|
||||||
appList, err := apps.List()
|
appList, err := apps.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, app := range *appList {
|
for _, app := range *appList {
|
||||||
err := updateContainerStats(&app)
|
err := updateUsage(app.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("STATS ERROR:", err.Error())
|
log.Println("STATS ERROR:", err.Error())
|
||||||
}
|
}
|
||||||
@ -62,15 +74,15 @@ func gatherContainersStats() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// gatherContainersStates refreshes all container's state
|
// gatherStates loops over all apps and updates their container state
|
||||||
func gatherContainersStates() error {
|
func gatherStates() error {
|
||||||
appList, err := apps.List()
|
appList, err := apps.List()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, app := range *appList {
|
for _, app := range *appList {
|
||||||
err := updateContainerState(&app)
|
err := updateState(app.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("STATE ERROR:", err.Error())
|
log.Println("STATE ERROR:", err.Error())
|
||||||
}
|
}
|
||||||
|
5
types.go
5
types.go
@ -5,3 +5,8 @@ type Message struct {
|
|||||||
Message string `json:"message,omitempty"`
|
Message string `json:"message,omitempty"`
|
||||||
Errors []string `json:"errors,omitempty"`
|
Errors []string `json:"errors,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// data passed into the template
|
||||||
|
type templateData struct {
|
||||||
|
Token string
|
||||||
|
}
|
||||||
|
@ -110,9 +110,9 @@
|
|||||||
node: {},
|
node: {},
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
fetch('/v1/apps').then(response => response.json())
|
fetch('/v1/apps?token={{ .Token }}').then(response => response.json())
|
||||||
.then(data => this.apps = data);
|
.then(data => this.apps = data);
|
||||||
fetch('/v1/node').then(response => response.json())
|
fetch('/v1/node?token={{ .Token }}').then(response => response.json())
|
||||||
.then(data => this.node = data);
|
.then(data => this.node = data);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -123,14 +123,14 @@
|
|||||||
return this.api_status_code >= 400 && this.api_status_code < 505
|
return this.api_status_code >= 400 && this.api_status_code < 505
|
||||||
},
|
},
|
||||||
refresh: () => {
|
refresh: () => {
|
||||||
fetch('/v1/apps').then(response => response.json())
|
fetch('/v1/apps?token={{ .Token }}').then(response => response.json())
|
||||||
.then(data => this.apps = data);
|
.then(data => this.apps = data);
|
||||||
fetch('/v1/node').then(response => response.json())
|
fetch('/v1/node?token={{ .Token }}').then(response => response.json())
|
||||||
.then(data => this.node = data);
|
.then(data => this.node = data);
|
||||||
},
|
},
|
||||||
start: (id) => {
|
start: (id) => {
|
||||||
app.api_response = "working"
|
app.api_response = "working"
|
||||||
fetch('/v1/apps/'+id+'/start', {method: 'PUT'})
|
fetch('/v1/apps/'+id+'/start?token={{ .Token }}', {method: 'PUT'})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
app.api_status_code = response.status
|
app.api_status_code = response.status
|
||||||
return response.json()
|
return response.json()
|
||||||
@ -139,7 +139,7 @@
|
|||||||
},
|
},
|
||||||
stop: (id) => {
|
stop: (id) => {
|
||||||
app.api_response = "working"
|
app.api_response = "working"
|
||||||
fetch('/v1/apps/'+id+'/stop', {method: 'PUT'})
|
fetch('/v1/apps/'+id+'/stop?token={{ .Token }}', {method: 'PUT'})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
app.api_status_code = response.status
|
app.api_status_code = response.status
|
||||||
return response.json()
|
return response.json()
|
||||||
@ -148,7 +148,7 @@
|
|||||||
},
|
},
|
||||||
restart: (id) => {
|
restart: (id) => {
|
||||||
app.api_response = "working"
|
app.api_response = "working"
|
||||||
fetch('/v1/apps/'+id+'/restart', {method: 'PUT'})
|
fetch('/v1/apps/'+id+'/restart?token={{ .Token }}', {method: 'PUT'})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
app.api_status_code = response.status
|
app.api_status_code = response.status
|
||||||
return response.json()
|
return response.json()
|
||||||
@ -157,7 +157,7 @@
|
|||||||
},
|
},
|
||||||
rebuild: (id) => {
|
rebuild: (id) => {
|
||||||
app.api_response = "working"
|
app.api_response = "working"
|
||||||
fetch('/v1/apps/'+id+'/rebuild', {method: 'PUT'})
|
fetch('/v1/apps/'+id+'/rebuild?token={{ .Token }}', {method: 'PUT'})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
app.api_status_code = response.status
|
app.api_status_code = response.status
|
||||||
return response.json()
|
return response.json()
|
||||||
@ -168,7 +168,7 @@
|
|||||||
},
|
},
|
||||||
remove: (id) => {
|
remove: (id) => {
|
||||||
app.api_response = "working"
|
app.api_response = "working"
|
||||||
fetch('/v1/apps/'+id, {method: 'DELETE'})
|
fetch('/v1/apps/'+id+"?token={{ .Token }}", {method: 'DELETE'})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
response.json()
|
response.json()
|
||||||
app.api_status_code = response.status
|
app.api_status_code = response.status
|
||||||
|
Loading…
Reference in New Issue
Block a user