mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-04-12 21:52:57 +00:00
Purge restarts app, and first attempt at integration testing
* Restart app when purging * Use log.Fatal to exit with status 1 * Quotes in entry.sh * Use JSON for request body * Handle errors for parseJsonBody * Better error printing in main * First attempt at testing nodesuper from Go * Cleaner build * Use ARCH to differentiate concurrent tests/builds * Use --rm to autoremove containers
This commit is contained in:
parent
dd53bbd1db
commit
513cc24d1c
7
Makefile
7
Makefile
@ -55,9 +55,12 @@ go-builder:
|
||||
|
||||
gosuper: go-builder
|
||||
-mkdir -p gosuper/bin
|
||||
docker run -v $(shell pwd)/gosuper/bin:/usr/src/app/bin -e USER_ID=$(shell id -u) -e GROUP_ID=$(shell id -g) -e GOARCH=$(GOARCH) resin/go-supervisor-builder:$(SUPERVISOR_VERSION)
|
||||
docker run --rm -v $(shell pwd)/gosuper/bin:/usr/src/app/bin -e USER_ID=$(shell id -u) -e GROUP_ID=$(shell id -g) -e GOARCH=$(GOARCH) resin/go-supervisor-builder:$(SUPERVISOR_VERSION)
|
||||
|
||||
test-gosuper: go-builder
|
||||
docker run -v $(shell pwd)/gosuper/bin:/usr/src/app/bin resin/go-supervisor-builder:$(SUPERVISOR_VERSION) bash -c "cd src/resin-supervisor && go test -v ./..."
|
||||
docker run --rm -v $(shell pwd)/gosuper/bin:/usr/src/app/bin resin/go-supervisor-builder:$(SUPERVISOR_VERSION) bash -c "cd src/resin-supervisor && go test -v ./gosuper"
|
||||
|
||||
test-integration: run-supervisor go-builder
|
||||
docker run --rm --net=host -e SUPERVISOR_IP="$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' resin_supervisor_1)" -v $(shell pwd)/gosuper/bin:/usr/src/app/bin resin/go-supervisor-builder:$(SUPERVISOR_VERSION) bash -c "cd src/resin-supervisor && go test -v ./supertest"
|
||||
|
||||
.PHONY: supervisor deploy supervisor-dind run-supervisor
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
go install -a -v ./...
|
||||
go install -a -v ./gosuper
|
||||
RETURN_VALUE=$?
|
||||
|
||||
# For consistency, always keep the binary within a linux_$GOARCH folder
|
||||
|
2
entry.sh
2
entry.sh
@ -2,7 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z $GOSUPER_SOCKET ]; then
|
||||
if [ -z "$GOSUPER_SOCKET" ]; then
|
||||
GOSUPER_SOCKET=/var/run/gosuper.sock
|
||||
fi
|
||||
|
||||
|
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -22,12 +23,12 @@ func main() {
|
||||
var err error
|
||||
Config, err = ReadConfig("/boot/config.json")
|
||||
if err != nil {
|
||||
return
|
||||
log.Fatalf("Could not read configuration file: %v", err)
|
||||
}
|
||||
*/
|
||||
|
||||
ResinDataPath = "/resin-data/"
|
||||
laddr := os.Getenv("GOSUPER_SOCKET")
|
||||
listenAddress := os.Getenv("GOSUPER_SOCKET")
|
||||
|
||||
r := mux.NewRouter()
|
||||
r.HandleFunc("/ping", pingHandler)
|
||||
@ -35,14 +36,12 @@ func main() {
|
||||
|
||||
apiv1.HandleFunc("/purge", PurgeHandler).Methods("POST")
|
||||
|
||||
listener, err := net.Listen("unix", laddr)
|
||||
listener, err := net.Listen("unix", listenAddress)
|
||||
if err != nil {
|
||||
fmt.Println("Could not listen on " + laddr)
|
||||
return
|
||||
log.Fatalf("Could not listen on "+listenAddress+": %v", err)
|
||||
}
|
||||
err = http.Serve(listener, r)
|
||||
if err != nil {
|
||||
fmt.Println("Could not start HTTP server")
|
||||
return
|
||||
log.Fatalf("Could not start HTTP server: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
|
||||
func TestPurge(t *testing.T) {
|
||||
appId := "1"
|
||||
req, _ := http.NewRequest("POST", "/api/v1/purge", strings.NewReader("applicationId="+appId))
|
||||
req, _ := http.NewRequest("POST", "/api/v1/purge", strings.NewReader(`{"applicationId": "`+appId+`"}`))
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value")
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
|
@ -13,6 +13,10 @@ type ApiResponse struct {
|
||||
Error string
|
||||
}
|
||||
|
||||
type PurgeBody struct {
|
||||
ApplicationId string
|
||||
}
|
||||
|
||||
func jsonResponse(w http.ResponseWriter, response interface{}, status int) {
|
||||
j, _ := json.Marshal(response)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
@ -20,17 +24,29 @@ func jsonResponse(w http.ResponseWriter, response interface{}, status int) {
|
||||
w.Write(j)
|
||||
}
|
||||
|
||||
func parseJsonBody(r *http.Request, dest interface{}) error {
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
err := decoder.Decode(&dest)
|
||||
return err
|
||||
}
|
||||
|
||||
func PurgeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("Purging /data")
|
||||
var body PurgeBody
|
||||
err := parseJsonBody(r, &body)
|
||||
if err != nil {
|
||||
jsonResponse(w, ApiResponse{"Error", "Invalid request"}, 422)
|
||||
return
|
||||
}
|
||||
|
||||
appId := r.FormValue("applicationId")
|
||||
appId := body.ApplicationId
|
||||
if appId == "" {
|
||||
jsonResponse(w, ApiResponse{"Error", "applicationId is required"}, 422)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate that the appId is an integer
|
||||
_, err := strconv.ParseInt(appId, 10, 0)
|
||||
_, err = strconv.ParseInt(appId, 10, 0)
|
||||
if err != nil {
|
||||
jsonResponse(w, ApiResponse{"Error", "Invalid applicationId"}, 422)
|
||||
return
|
||||
|
@ -18,6 +18,9 @@ module.exports = (secret) ->
|
||||
else
|
||||
res.sendStatus(401)
|
||||
|
||||
api.get '/ping', (req, res) ->
|
||||
res.send('OK')
|
||||
|
||||
api.post '/v1/blink', (req, res) ->
|
||||
utils.mixpanelTrack('Device blink')
|
||||
utils.blink.pattern.start()
|
||||
@ -60,6 +63,18 @@ module.exports = (secret) ->
|
||||
res.status(503).send(err?.message or err or 'Unknown error')
|
||||
|
||||
api.post '/v1/purge', (req, res) ->
|
||||
request.post(config.gosuperAddress + '/v1/purge', req.body).pipe(res)
|
||||
appId = req.body.appId
|
||||
utils.mixpanelTrack('Purge /data', appId)
|
||||
if !appId?
|
||||
return res.status(400).send('Missing app id')
|
||||
knex('app').select().where({appId})
|
||||
.then ([ app ]) ->
|
||||
if !app?
|
||||
throw new Error('App not found')
|
||||
application.kill(app)
|
||||
.then ->
|
||||
request.post(config.gosuperAddress + '/v1/purge', {json: true, body: applicationId: appId}).on 'response', ->
|
||||
application.start(app)
|
||||
.pipe(res)
|
||||
|
||||
return api
|
||||
|
@ -35,7 +35,9 @@ knex.init.then ->
|
||||
randomstring = require 'randomstring'
|
||||
|
||||
console.log('Starting API server..')
|
||||
|
||||
secret = randomstring.generate()
|
||||
secret = config.forceApiSecret if config.forceApiSecret?
|
||||
api(secret).listen(config.listenPort)
|
||||
|
||||
# Let API know what version we are, and our api connection info.
|
||||
|
@ -82,7 +82,7 @@ logSystemEvent = (logType, app, error) ->
|
||||
utils.mixpanelTrack(logType.eventName, {app, error})
|
||||
return
|
||||
|
||||
kill = (app) ->
|
||||
exports.kill = kill = (app) ->
|
||||
logSystemEvent(logTypes.stopApp, app)
|
||||
device.updateState(status: 'Stopping')
|
||||
container = docker.getContainer(app.containerId)
|
||||
|
@ -24,6 +24,7 @@ module.exports = config =
|
||||
restartSuccessTimeout: checkInt(process.env.RESTART_SUCCESS_TIMEOUT) ? 60000
|
||||
appUpdatePollInterval: checkInt(process.env.APPLICATION_UPDATE_POLL_INTERVAL) ? 60000
|
||||
successMessage: 'SUPERVISOR OK'
|
||||
forceApiSecret: process.env.RESIN_SUPERVISOR_SECRET ? null
|
||||
|
||||
config.supervisorContainer =
|
||||
Volumes:
|
||||
|
32
supertest/supertest.go
Normal file
32
supertest/supertest.go
Normal file
@ -0,0 +1,32 @@
|
||||
package supertest
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPing(t *testing.T) {
|
||||
supervisorIP := os.getEnv("SUPERVISOR_IP")
|
||||
if supervisorIP == "" {
|
||||
t.Error("Supervisor IP not set")
|
||||
}
|
||||
|
||||
address := "http://"+ supervisorIP +":48484"
|
||||
|
||||
request, err := http.NewRequest("GET", address+"/ping?apikey=bananas", nil)
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
res, err := http.DefaultClient.Do(request)
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
t.Errorf("Expected 200, got %d", res.StatusCode)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user