From 6db6b76b27d3b44fb9f0b74c17b46b0b0400d05e Mon Sep 17 00:00:00 2001 From: Yaroslav Vorobiov Date: Mon, 12 Jul 2021 18:11:37 +0300 Subject: [PATCH] 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 --- Makefile | 25 +++++++++++++++++++++-- multinode/console/consoleassets/assets.go | 13 ++++++++++++ multinode/console/server/server.go | 24 +++++++++++++++------- multinode/peer.go | 10 ++++++++- 4 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 multinode/console/consoleassets/assets.go diff --git a/Makefile b/Makefile index a07082ac5..1f8505119 100644 --- a/Makefile +++ b/Makefile @@ -157,6 +157,24 @@ storagenode-console: /usr/bin/env echo -e '\nfunc init() { FileSystem = AssetFile() }' >> 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 satellite-wasm: docker run --rm -i -v "${PWD}":/go/src/storj.io/storj -e GO111MODULE=on \ @@ -283,13 +301,16 @@ uplink_%: .PHONY: versioncontrol_% versioncontrol_%: $(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 BINARIES := $(foreach C,$(COMPONENTLIST),$(foreach O,$(OSARCHLIST),$C_$O)) .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 sign-windows-installer: diff --git a/multinode/console/consoleassets/assets.go b/multinode/console/consoleassets/assets.go new file mode 100644 index 000000000..db6fd5da9 --- /dev/null +++ b/multinode/console/consoleassets/assets.go @@ -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 diff --git a/multinode/console/server/server.go b/multinode/console/server/server.go index 3e1c19c5c..bdcfdf0b6 100644 --- a/multinode/console/server/server.go +++ b/multinode/console/server/server.go @@ -6,9 +6,9 @@ package server import ( "context" "html/template" + "io/ioutil" "net" "net/http" - "path/filepath" "github.com/gorilla/mux" "github.com/zeebo/errs" @@ -52,7 +52,7 @@ type Server struct { log *zap.Logger listener net.Listener http http.Server - config Config + assets http.FileSystem nodes *nodes.Service payouts *payouts.Service @@ -65,11 +65,11 @@ type Server struct { } // 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{ log: log, listener: listener, - config: config, + assets: assets, nodes: services.Nodes, operators: services.Operators, payouts: services.Payouts, @@ -79,7 +79,6 @@ func NewServer(log *zap.Logger, listener net.Listener, config Config, services S } router := mux.NewRouter() - fs := http.FileServer(http.Dir(server.config.StaticDir)) apiRouter := router.PathPrefix("/api/v0").Subrouter() 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.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("/").HandlerFunc(server.appHandler) } @@ -193,9 +193,19 @@ func (server *Server) Close() error { // initializeTemplates is used to initialize all templates. 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 { 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 diff --git a/multinode/peer.go b/multinode/peer.go index ea1e39229..f97153514 100644 --- a/multinode/peer.go +++ b/multinode/peer.go @@ -6,6 +6,7 @@ package multinode import ( "context" "net" + "net/http" "github.com/spacemonkeygo/monkit/v3" "go.uber.org/zap" @@ -16,6 +17,7 @@ import ( "storj.io/common/rpc" "storj.io/private/debug" "storj.io/storj/multinode/bandwidth" + "storj.io/storj/multinode/console/consoleassets" "storj.io/storj/multinode/console/server" "storj.io/storj/multinode/nodes" "storj.io/storj/multinode/operators" @@ -173,10 +175,16 @@ func New(log *zap.Logger, full *identity.FullIdentity, config Config, db DB) (_ 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.Log.Named("console:endpoint"), peer.Console.Listener, - config.Console, + assets, server.Services{ Nodes: peer.Nodes.Service, Payouts: peer.Payouts.Service,