multinode/console: embed web assets
Embed web static files in multinode binary to be able to release multinode as single binary. Add make commands to build multinode binary with embeded web assets. Change-Id: I348aff7a7d847fae5c021cbf59abc7f892c0df80
This commit is contained in:
parent
30cd7d3da3
commit
6db6b76b27
25
Makefile
25
Makefile
@ -157,6 +157,24 @@ storagenode-console:
|
|||||||
/usr/bin/env echo -e '\nfunc init() { FileSystem = AssetFile() }' >> storagenode/console/consoleassets/bindata.resource.go
|
/usr/bin/env echo -e '\nfunc init() { FileSystem = AssetFile() }' >> storagenode/console/consoleassets/bindata.resource.go
|
||||||
gofmt -w -s storagenode/console/consoleassets/bindata.resource.go
|
gofmt -w -s storagenode/console/consoleassets/bindata.resource.go
|
||||||
|
|
||||||
|
.PHONY: multinode-console
|
||||||
|
multinode-console:
|
||||||
|
# build web assets
|
||||||
|
rm -rf web/multinode/dist
|
||||||
|
# install npm dependencies and build the binaries
|
||||||
|
docker run --rm -i \
|
||||||
|
--mount type=bind,src="${PWD}",dst=/go/src/storj.io/storj \
|
||||||
|
-w /go/src/storj.io/storj/web/multinode \
|
||||||
|
-e HOME=/tmp \
|
||||||
|
-u $(shell id -u):$(shell id -g) \
|
||||||
|
node:14.15.3 \
|
||||||
|
/bin/bash -c "npm ci && npm run build"
|
||||||
|
# embed web assets into go
|
||||||
|
go-bindata -prefix web/multinode/ -fs -o multinode/console/consoleassets/bindata.resource.go -pkg consoleassets web/multinode/dist/... web/multinode/static/...
|
||||||
|
# configure existing go code to know about the new assets
|
||||||
|
/usr/bin/env echo -e '\nfunc init() { FileSystem = AssetFile() }' >> multinode/console/consoleassets/bindata.resource.go
|
||||||
|
gofmt -w -s multinode/console/consoleassets/bindata.resource.go
|
||||||
|
|
||||||
.PHONY: satellite-wasm
|
.PHONY: satellite-wasm
|
||||||
satellite-wasm:
|
satellite-wasm:
|
||||||
docker run --rm -i -v "${PWD}":/go/src/storj.io/storj -e GO111MODULE=on \
|
docker run --rm -i -v "${PWD}":/go/src/storj.io/storj -e GO111MODULE=on \
|
||||||
@ -283,13 +301,16 @@ uplink_%:
|
|||||||
.PHONY: versioncontrol_%
|
.PHONY: versioncontrol_%
|
||||||
versioncontrol_%:
|
versioncontrol_%:
|
||||||
$(MAKE) binary-check COMPONENT=versioncontrol GOARCH=$(word 3, $(subst _, ,$@)) GOOS=$(word 2, $(subst _, ,$@))
|
$(MAKE) binary-check COMPONENT=versioncontrol GOARCH=$(word 3, $(subst _, ,$@)) GOOS=$(word 2, $(subst _, ,$@))
|
||||||
|
.PHONY: multinode_%
|
||||||
|
multinode_%: multinode-console
|
||||||
|
$(MAKE) binary-check COMPONENT=multinode GOARCH=$(word 3, $(subst _, ,$@)) GOOS=$(word 2, $(subst _, ,$@))
|
||||||
|
|
||||||
|
|
||||||
COMPONENTLIST := certificates identity inspector satellite storagenode storagenode-updater uplink versioncontrol
|
COMPONENTLIST := certificates identity inspector satellite storagenode storagenode-updater uplink versioncontrol multinode
|
||||||
OSARCHLIST := darwin_amd64 linux_amd64 linux_arm linux_arm64 windows_amd64 freebsd_amd64
|
OSARCHLIST := darwin_amd64 linux_amd64 linux_arm linux_arm64 windows_amd64 freebsd_amd64
|
||||||
BINARIES := $(foreach C,$(COMPONENTLIST),$(foreach O,$(OSARCHLIST),$C_$O))
|
BINARIES := $(foreach C,$(COMPONENTLIST),$(foreach O,$(OSARCHLIST),$C_$O))
|
||||||
.PHONY: binaries
|
.PHONY: binaries
|
||||||
binaries: ${BINARIES} ## Build certificates, identity, inspector, satellite, storagenode, uplink, and versioncontrol binaries (jenkins)
|
binaries: ${BINARIES} ## Build certificates, identity, inspector, satellite, storagenode, uplink, versioncontrol and multinode binaries (jenkins)
|
||||||
|
|
||||||
.PHONY: sign-windows-installer
|
.PHONY: sign-windows-installer
|
||||||
sign-windows-installer:
|
sign-windows-installer:
|
||||||
|
13
multinode/console/consoleassets/assets.go
Normal file
13
multinode/console/consoleassets/assets.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
package consoleassets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileSystem is nil by default, but when our Makefile generates
|
||||||
|
// embedded resources via go-bindata, it will also drop an init method
|
||||||
|
// that sets this to not nil.
|
||||||
|
var FileSystem http.FileSystem
|
@ -6,9 +6,9 @@ package server
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/zeebo/errs"
|
"github.com/zeebo/errs"
|
||||||
@ -52,7 +52,7 @@ type Server struct {
|
|||||||
log *zap.Logger
|
log *zap.Logger
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
http http.Server
|
http http.Server
|
||||||
config Config
|
assets http.FileSystem
|
||||||
|
|
||||||
nodes *nodes.Service
|
nodes *nodes.Service
|
||||||
payouts *payouts.Service
|
payouts *payouts.Service
|
||||||
@ -65,11 +65,11 @@ type Server struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewServer returns new instance of Multinode Dashboard http server.
|
// NewServer returns new instance of Multinode Dashboard http server.
|
||||||
func NewServer(log *zap.Logger, listener net.Listener, config Config, services Services) (*Server, error) {
|
func NewServer(log *zap.Logger, listener net.Listener, assets http.FileSystem, services Services) (*Server, error) {
|
||||||
server := Server{
|
server := Server{
|
||||||
log: log,
|
log: log,
|
||||||
listener: listener,
|
listener: listener,
|
||||||
config: config,
|
assets: assets,
|
||||||
nodes: services.Nodes,
|
nodes: services.Nodes,
|
||||||
operators: services.Operators,
|
operators: services.Operators,
|
||||||
payouts: services.Payouts,
|
payouts: services.Payouts,
|
||||||
@ -79,7 +79,6 @@ func NewServer(log *zap.Logger, listener net.Listener, config Config, services S
|
|||||||
}
|
}
|
||||||
|
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
fs := http.FileServer(http.Dir(server.config.StaticDir))
|
|
||||||
|
|
||||||
apiRouter := router.PathPrefix("/api/v0").Subrouter()
|
apiRouter := router.PathPrefix("/api/v0").Subrouter()
|
||||||
apiRouter.NotFoundHandler = controllers.NewNotFound(server.log)
|
apiRouter.NotFoundHandler = controllers.NewNotFound(server.log)
|
||||||
@ -133,7 +132,8 @@ func NewServer(log *zap.Logger, listener net.Listener, config Config, services S
|
|||||||
reputationRouter := apiRouter.PathPrefix("/reputation").Subrouter()
|
reputationRouter := apiRouter.PathPrefix("/reputation").Subrouter()
|
||||||
reputationRouter.HandleFunc("/satellites/{satelliteID}", reputationController.Stats)
|
reputationRouter.HandleFunc("/satellites/{satelliteID}", reputationController.Stats)
|
||||||
|
|
||||||
if server.config.StaticDir != "" {
|
if server.assets != nil {
|
||||||
|
fs := http.FileServer(server.assets)
|
||||||
router.PathPrefix("/static/").Handler(http.StripPrefix("/static", fs))
|
router.PathPrefix("/static/").Handler(http.StripPrefix("/static", fs))
|
||||||
router.PathPrefix("/").HandlerFunc(server.appHandler)
|
router.PathPrefix("/").HandlerFunc(server.appHandler)
|
||||||
}
|
}
|
||||||
@ -193,9 +193,19 @@ func (server *Server) Close() error {
|
|||||||
|
|
||||||
// initializeTemplates is used to initialize all templates.
|
// initializeTemplates is used to initialize all templates.
|
||||||
func (server *Server) initializeTemplates() (err error) {
|
func (server *Server) initializeTemplates() (err error) {
|
||||||
server.index, err = template.ParseFiles(filepath.Join(server.config.StaticDir, "dist", "index.html"))
|
f, err := server.assets.Open("/dist/index.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
server.log.Error("dist folder is not generated. use 'npm run build' command", zap.Error(err))
|
server.log.Error("dist folder is not generated. use 'npm run build' command", zap.Error(err))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b, err := ioutil.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
return Error.Wrap(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
server.index, err = template.New("index.html").Parse(string(b))
|
||||||
|
if err != nil {
|
||||||
|
return Error.Wrap(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -6,6 +6,7 @@ package multinode
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/spacemonkeygo/monkit/v3"
|
"github.com/spacemonkeygo/monkit/v3"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@ -16,6 +17,7 @@ import (
|
|||||||
"storj.io/common/rpc"
|
"storj.io/common/rpc"
|
||||||
"storj.io/private/debug"
|
"storj.io/private/debug"
|
||||||
"storj.io/storj/multinode/bandwidth"
|
"storj.io/storj/multinode/bandwidth"
|
||||||
|
"storj.io/storj/multinode/console/consoleassets"
|
||||||
"storj.io/storj/multinode/console/server"
|
"storj.io/storj/multinode/console/server"
|
||||||
"storj.io/storj/multinode/nodes"
|
"storj.io/storj/multinode/nodes"
|
||||||
"storj.io/storj/multinode/operators"
|
"storj.io/storj/multinode/operators"
|
||||||
@ -173,10 +175,16 @@ func New(log *zap.Logger, full *identity.FullIdentity, config Config, db DB) (_
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assets := consoleassets.FileSystem
|
||||||
|
if config.Console.StaticDir != "" {
|
||||||
|
// a specific directory has been configured. use it
|
||||||
|
assets = http.Dir(config.Console.StaticDir)
|
||||||
|
}
|
||||||
|
|
||||||
peer.Console.Endpoint, err = server.NewServer(
|
peer.Console.Endpoint, err = server.NewServer(
|
||||||
peer.Log.Named("console:endpoint"),
|
peer.Log.Named("console:endpoint"),
|
||||||
peer.Console.Listener,
|
peer.Console.Listener,
|
||||||
config.Console,
|
assets,
|
||||||
server.Services{
|
server.Services{
|
||||||
Nodes: peer.Nodes.Service,
|
Nodes: peer.Nodes.Service,
|
||||||
Payouts: peer.Payouts.Service,
|
Payouts: peer.Payouts.Service,
|
||||||
|
Loading…
Reference in New Issue
Block a user