Client build scripts fixes and server stub with local devzone.
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Linting and tests / Linting (push) Successful in 6s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Linting and tests / Linting (push) Successful in 6s
				
			This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | ||||
| *DS_Store* | ||||
| fyne-cross | ||||
| .build | ||||
| _build | ||||
| *.apk | ||||
| *.app | ||||
| dist | ||||
| .task | ||||
|   | ||||
							
								
								
									
										10
									
								
								Taskfile.yml
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Taskfile.yml
									
									
									
									
									
								
							| @@ -14,19 +14,25 @@ vars: | ||||
|     sh: git rev-list --count HEAD | ||||
|   BUILD_DATE: | ||||
|     sh: TZ=UTC date +'%Y-%m-%d %H:%M:%S %Z' | ||||
|   BASIC_LDFLAGS: "-X 'bunker/commons/constants.Version={{.VERSION}}' -X 'bunker/commons/constants.Branch={{.BRANCH}}' -X 'bunker/commons/constants.Commit={{.COMMIT}}' -X 'bunker/commons/constants.Build={{.BUILD}}' -X 'bunker/commons/constants.BuildDate={{.BUILD_DATE}}'" | ||||
|   BASIC_LDFLAGS: "-X 'bunker/commons.Version={{.VERSION}}' -X 'bunker/commons.Branch={{.BRANCH}}' -X 'bunker/commons.Commit={{.COMMIT}}' -X 'bunker/commons.Build={{.BUILD}}' -X 'bunker/commons.BuildDate={{.BUILD_DATE}}'" | ||||
|  | ||||
| env: | ||||
|   GOFLAGS: "-trimpath" | ||||
|  | ||||
| includes: | ||||
|   client: ./client | ||||
|   server: ./server | ||||
|  | ||||
| tasks: | ||||
|   cleanup: | ||||
|     desc: "Cleanup _build directory." | ||||
|     cmds: | ||||
|       - task: server:cmd:bunkerd:cleanup | ||||
|  | ||||
|   ensure-builddir: | ||||
|     internal: true | ||||
|     cmds: | ||||
|       - mkdir -p .build | ||||
|       - mkdir -p _build | ||||
|  | ||||
|   lint: | ||||
|     desc: "Lints whole workspace." | ||||
|   | ||||
| @@ -16,7 +16,7 @@ tasks: | ||||
|     cmds: | ||||
|       - task: ::ensure-builddir | ||||
|       - task: cleanup | ||||
|       - fyne build --release -o ../../../.build/{{ .ClientBinary }} --pprof --pprof-port 6060 {{ .MetadataParams }} | ||||
|       - fyne build --release -o ../../../_build/{{ .ClientBinary }} --pprof --pprof-port 6060 {{ .MetadataParams }} | ||||
|  | ||||
|   build-debug: | ||||
|     desc: "Build client in debug mode." | ||||
| @@ -25,7 +25,7 @@ tasks: | ||||
|     cmds: | ||||
|       - task: ::ensure-builddir | ||||
|       - task: cleanup | ||||
|       - fyne build -o ../../../.build/{{ .ClientBinary }} --tags debug {{ .MetadataParams }} | ||||
|       - fyne build -o ../../../_build/{{ .ClientBinary }} --tags debug {{ .MetadataParams }} | ||||
|  | ||||
|   # build-production: | ||||
|   #   desc: "Build production package for current OS." | ||||
| @@ -92,7 +92,7 @@ tasks: | ||||
|   cleanup: | ||||
|     desc: "Cleanup build environment." | ||||
|     cmds: | ||||
|       - rm .build/{{ .ClientBinary }} | ||||
|       - rm _build/{{ .ClientBinary }} | ||||
|     ignore_error: true | ||||
|  | ||||
|   ensure-dist-dir: | ||||
| @@ -105,10 +105,10 @@ tasks: | ||||
|     desc: "Launch client." | ||||
|     cmds: | ||||
|       - task: build | ||||
|       - .build/{{ .ClientBinary }} | ||||
|       - _build/{{ .ClientBinary }} | ||||
|  | ||||
|   run-debug: | ||||
|     desc: "Launch client in debug mode." | ||||
|     cmds: | ||||
|       - task: build-debug | ||||
|       - .build/{{ .ClientBinary }} | ||||
|       - _build/{{ .ClientBinary }} | ||||
|   | ||||
| @@ -23,7 +23,7 @@ func main() { | ||||
|  | ||||
| 	lgr := app.NewLogger("module", "main") | ||||
| 	lgr.Info( | ||||
| 		"Starting Bunker...", | ||||
| 		"Starting Bunker client...", | ||||
| 		"version", app.Fyne().Metadata().Custom["Version"], | ||||
| 		"build_no", app.Fyne().Metadata().Custom["Build"], | ||||
| 		"commit", app.Fyne().Metadata().Custom["Commit"], | ||||
|   | ||||
| @@ -9,7 +9,10 @@ import ( | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	"bunker/commons" | ||||
|  | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/app" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -19,6 +22,8 @@ var ( | ||||
|  | ||||
| // Application is a lifecycle controlling structure for application. | ||||
| type Application struct { | ||||
| 	ctx        context.Context | ||||
| 	cancelFunc context.CancelFunc | ||||
| 	fyneApp    fyne.App | ||||
| 	baseLogger *slog.Logger | ||||
| 	appLogger  *slog.Logger | ||||
| @@ -96,7 +101,7 @@ func (a *Application) connectDependencies() error { | ||||
|  | ||||
| // ContextWithTimeout returns context.Context with requested timeout. | ||||
| func (a *Application) ContextWithTimeout(timeout time.Duration) context.Context { | ||||
| 	ctx, cancelFunc := context.WithTimeout(context.Background(), timeout) | ||||
| 	ctx, cancelFunc := context.WithTimeout(a.ctx, timeout) | ||||
|  | ||||
| 	// As we do not need to call cancelFunc - make linter happy. | ||||
| 	// This probably will lead to context leak, so it should be investigated. | ||||
| @@ -106,11 +111,13 @@ func (a *Application) ContextWithTimeout(timeout time.Duration) context.Context | ||||
| } | ||||
|  | ||||
| func (a *Application) initialize() { | ||||
| 	a.ctx, a.cancelFunc = context.WithCancel(context.Background()) | ||||
|  | ||||
| 	a.initializeLogger() | ||||
|  | ||||
| 	a.services = make([]Service, 0) | ||||
| 	a.fyneApp = app.NewWithID(commons.ClientAppID) | ||||
|  | ||||
| 	a.initializeFyne() | ||||
| 	a.services = make([]Service, 0) | ||||
| } | ||||
|  | ||||
| func (a *Application) launchStartupTasks() error { | ||||
| @@ -167,7 +174,6 @@ func (a *Application) launchStartupTasks() error { | ||||
| func (a *Application) Shutdown() error { | ||||
| 	a.appLogger.Info("Stopping pztrn's Bunker...") | ||||
|  | ||||
| 	// Сначала тушим фичи. | ||||
| 	for _, service := range a.services { | ||||
| 		if !strings.Contains(service.Name(), "features/") { | ||||
| 			continue | ||||
| @@ -180,7 +186,6 @@ func (a *Application) Shutdown() error { | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Потом тушим ядро. | ||||
| 	for _, service := range a.services { | ||||
| 		if !strings.Contains(service.Name(), "core/") { | ||||
| 			continue | ||||
| @@ -198,7 +203,7 @@ func (a *Application) Shutdown() error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Start запускает приложение. | ||||
| // Start starts application. | ||||
| func (a *Application) Start() error { | ||||
| 	if err := a.connectDependencies(); err != nil { | ||||
| 		return fmt.Errorf("%w: %w", errApplication, err) | ||||
|   | ||||
| @@ -1,17 +1,10 @@ | ||||
| package application | ||||
|  | ||||
| import ( | ||||
| 	"bunker/commons" | ||||
|  | ||||
| 	"fyne.io/fyne/v2" | ||||
| 	"fyne.io/fyne/v2/app" | ||||
| ) | ||||
|  | ||||
| // Fyne возвращает экземпляр Fyne для взаимодействия с ним. | ||||
| // Fyne returns Fyne instance. | ||||
| func (a *Application) Fyne() fyne.App { | ||||
| 	return a.fyneApp | ||||
| } | ||||
|  | ||||
| func (a *Application) initializeFyne() { | ||||
| 	a.fyneApp = app.NewWithID(commons.ClientAppID) | ||||
| } | ||||
|   | ||||
							
								
								
									
										18
									
								
								server/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								server/Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| FROM code.pztrn.name/containers/go-toolbox:v8 AS build | ||||
|  | ||||
| WORKDIR /bunkerd | ||||
| COPY . /bunkerd | ||||
| RUN --mount=type=cache,target="/home/container/go" task server:cmd:bunkerd:build --force | ||||
|  | ||||
| FROM debian:13-slim | ||||
|  | ||||
| RUN apt-get update && \ | ||||
|     apt-get install -y ca-certificates iputils-ping coreutils && \ | ||||
|     rm -rf /var/lib/apt/* /var/cache/apt/* | ||||
|  | ||||
| COPY --from=build /bunkerd/_build/bunkerd /bunkerd | ||||
| COPY --from=build /usr/local/bin/dlv /dlv | ||||
|  | ||||
| COPY server/entrypoint.sh /entrypoint.sh | ||||
|  | ||||
| ENTRYPOINT ["/entrypoint.sh"] | ||||
							
								
								
									
										6
									
								
								server/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								server/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| --- | ||||
| version: "3" | ||||
|  | ||||
| includes: | ||||
|   localdev: ./localdevzone | ||||
|   cmd: ./cmd | ||||
							
								
								
									
										5
									
								
								server/cmd/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								server/cmd/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| --- | ||||
| version: "3" | ||||
|  | ||||
| includes: | ||||
|   bunkerd: ./bunkerd | ||||
							
								
								
									
										26
									
								
								server/cmd/bunkerd/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								server/cmd/bunkerd/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| --- | ||||
| version: "3" | ||||
|  | ||||
| tasks: | ||||
|   build: | ||||
|     desc: "Builds bunkerd binary." | ||||
|     cmds: | ||||
|       - task: :::ensure-builddir | ||||
|       - task: cleanup | ||||
|       - go build -ldflags="{{ .BASIC_LDFLAGS }}" -o _build/bunkerd{{exeExt}} ./server/cmd/bunkerd/main.go | ||||
|     sources: | ||||
|       - ./Taskfile.yml | ||||
|       - ./go.mod | ||||
|       - ./commons/* | ||||
|       - ./server/**/*.go | ||||
|       - ./server/Taskfile.yml | ||||
|       - ./server/**/Taskfile.yml | ||||
|       - ./server/entrypoint.sh | ||||
|     generates: | ||||
|       - ./_build/bunkerd{{exeExt}} | ||||
|     method: timestamp | ||||
|  | ||||
|   cleanup: | ||||
|     desc: "Deletes bunkerd binary from local build cache." | ||||
|     cmds: | ||||
|       - rm -f _build/bunkerd{{exeExt}} | ||||
							
								
								
									
										39
									
								
								server/cmd/bunkerd/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								server/cmd/bunkerd/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| package main | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
|  | ||||
| 	"bunker/commons" | ||||
| 	"bunker/server/internal/application" | ||||
| ) | ||||
|  | ||||
| func main() { | ||||
| 	app := application.New() | ||||
|  | ||||
| 	lgr := app.NewLogger("module", "main") | ||||
| 	lgr.Info( | ||||
| 		"Starting bunkerd...", | ||||
| 		"version", commons.Version, | ||||
| 		"build_no", commons.Build, | ||||
| 		"buint_on", commons.BuildDate, | ||||
| 		"commit", commons.Commit, | ||||
| 		"branch", commons.Branch, | ||||
| 	) | ||||
|  | ||||
| 	if err := app.Start(); err != nil { | ||||
| 		lgr.Error("Failed to start bunkerd!", "error", err.Error()) | ||||
|  | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
|  | ||||
| 	lgr.Info("bunkerd started.") | ||||
|  | ||||
| 	<-app.ShutdownChan() | ||||
| 	lgr.Info("Shutting down bunkerd...") | ||||
|  | ||||
| 	if err := app.Shutdown(); err != nil { | ||||
| 		lgr.Error("Failed to shutdown bunkerd!", "error", err.Error()) | ||||
|  | ||||
| 		os.Exit(1) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										8
									
								
								server/entrypoint.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								server/entrypoint.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| echo "* Starting bunkerd..." | ||||
| if [ -n "${BUNKERD_DEBUG}" ]; then | ||||
|     exec /dlv --listen=:4000 --headless=true --log=true --accept-multiclient --api-version=2 exec /bunkerd --continue | ||||
| else | ||||
|     exec /bunkerd | ||||
| fi | ||||
							
								
								
									
										199
									
								
								server/internal/application/application.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								server/internal/application/application.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | ||||
| package application | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"log/slog" | ||||
| 	"os" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	errApplication  = errors.New("application") | ||||
| 	errNoMainWindow = errors.New("no main window service registered") | ||||
| ) | ||||
|  | ||||
| // Application is a lifecycle controlling structure for application. | ||||
| type Application struct { | ||||
| 	shutdownChan chan struct{} | ||||
| 	ctx          context.Context | ||||
| 	cancelFunc   context.CancelFunc | ||||
| 	baseLogger   *slog.Logger | ||||
| 	appLogger    *slog.Logger | ||||
| 	services     []Service | ||||
| } | ||||
|  | ||||
| // New creates new instance of lifecycle controlling structure. | ||||
| func New() *Application { | ||||
| 	appl := &Application{} | ||||
|  | ||||
| 	appl.initialize() | ||||
|  | ||||
| 	return appl | ||||
| } | ||||
|  | ||||
| func (a *Application) configure() error { | ||||
| 	// First iteration - core services. | ||||
| 	for _, service := range a.services { | ||||
| 		if !strings.Contains(service.Name(), "core/") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		a.appLogger.Debug("Launching configuration procedure for service", "service", service.Name()) | ||||
|  | ||||
| 		if err := service.Configure(); err != nil { | ||||
| 			return fmt.Errorf("configure service '%s': %w", service.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Second iteration - rest of the services. | ||||
| 	for _, service := range a.services { | ||||
| 		if strings.Contains(service.Name(), "core/") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		a.appLogger.Debug("Launching configuration procedure for service", "service", service.Name()) | ||||
|  | ||||
| 		if err := service.Configure(); err != nil { | ||||
| 			return fmt.Errorf("configure service '%s': %w", service.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (a *Application) connectDependencies() error { | ||||
| 	// First iteration - core services. | ||||
| 	for _, service := range a.services { | ||||
| 		if !strings.Contains(service.Name(), "core/") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		a.appLogger.Debug("Connecting dependencies for service.", "service", service.Name()) | ||||
|  | ||||
| 		if err := service.ConnectDependencies(); err != nil { | ||||
| 			return fmt.Errorf("connect dependencies for service '%s': %w", service.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Second iteration - rest of the services. | ||||
| 	for _, service := range a.services { | ||||
| 		if strings.Contains(service.Name(), "core/") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		a.appLogger.Debug("Connecting dependencies for service.", "service", service.Name()) | ||||
|  | ||||
| 		if err := service.ConnectDependencies(); err != nil { | ||||
| 			return fmt.Errorf("connect dependencies for service '%s': %w", service.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ContextWithTimeout returns context.Context with requested timeout. | ||||
| func (a *Application) ContextWithTimeout(timeout time.Duration) context.Context { | ||||
| 	ctx, cancelFunc := context.WithTimeout(a.ctx, timeout) | ||||
|  | ||||
| 	// As we do not need to call cancelFunc - make linter happy. | ||||
| 	// This probably will lead to context leak, so it should be investigated. | ||||
| 	go func(_ context.CancelFunc) {}(cancelFunc) | ||||
|  | ||||
| 	return ctx | ||||
| } | ||||
|  | ||||
| func (a *Application) initialize() { | ||||
| 	a.ctx, a.cancelFunc = context.WithCancel(context.Background()) | ||||
|  | ||||
| 	a.initializeLogger() | ||||
|  | ||||
| 	a.services = make([]Service, 0) | ||||
| } | ||||
|  | ||||
| func (a *Application) launchStartupTasks() error { | ||||
| 	for _, service := range a.services { | ||||
| 		if strings.Contains(service.Name(), "mainwindow") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if !strings.Contains(service.Name(), "core/") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		a.appLogger.Debug("Launching startup tasks for service.", "service", service.Name()) | ||||
|  | ||||
| 		if err := service.LaunchStartupTasks(); err != nil { | ||||
| 			return fmt.Errorf("launch startup tasks for core/%s: %w", service.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for _, service := range a.services { | ||||
| 		if strings.Contains(service.Name(), "core/") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		a.appLogger.Debug("Launching startup tasks for service.", "service", service.Name()) | ||||
|  | ||||
| 		if err := service.LaunchStartupTasks(); err != nil { | ||||
| 			return fmt.Errorf("launch startup tasks for core/%s: %w", service.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Shutdown stops application. | ||||
| func (a *Application) Shutdown() error { | ||||
| 	a.appLogger.Info("Stopping pztrn's Bunker...") | ||||
|  | ||||
| 	for _, service := range a.services { | ||||
| 		if !strings.Contains(service.Name(), "features/") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		a.appLogger.Debug("Shutting down service.", "service", service.Name()) | ||||
|  | ||||
| 		if err := service.Shutdown(); err != nil { | ||||
| 			return fmt.Errorf("shutting down service '%s': %w", service.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for _, service := range a.services { | ||||
| 		if !strings.Contains(service.Name(), "core/") { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		a.appLogger.Debug("Shutting down service.", "service", service.Name()) | ||||
|  | ||||
| 		if err := service.Shutdown(); err != nil { | ||||
| 			return fmt.Errorf("shutting down service '%s': %w", service.Name(), err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	os.Exit(0) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Start starts application. | ||||
| // Server application will start a goroutine that monitors SIGTERM and sends empty struct to channel. | ||||
| func (a *Application) Start() error { | ||||
| 	if err := a.connectDependencies(); err != nil { | ||||
| 		return fmt.Errorf("%w: %w", errApplication, err) | ||||
| 	} | ||||
|  | ||||
| 	if err := a.configure(); err != nil { | ||||
| 		return fmt.Errorf("%w: %w", errApplication, err) | ||||
| 	} | ||||
|  | ||||
| 	if err := a.launchStartupTasks(); err != nil { | ||||
| 		return fmt.Errorf("%w: %w", errApplication, err) | ||||
| 	} | ||||
|  | ||||
| 	a.startServer() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
							
								
								
									
										20
									
								
								server/internal/application/logger.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								server/internal/application/logger.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| package application | ||||
|  | ||||
| import ( | ||||
| 	"log/slog" | ||||
| 	"os" | ||||
| ) | ||||
|  | ||||
| func (a *Application) initializeLogger() { | ||||
| 	a.baseLogger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ | ||||
| 		AddSource: true, | ||||
| 		Level:     slog.LevelDebug, | ||||
| 	})) | ||||
|  | ||||
| 	a.appLogger = a.baseLogger.With("module", "application") | ||||
| } | ||||
|  | ||||
| // NewLogger creates new sub-instance of base logger and adds some additional data to it for persistent output. | ||||
| func (a *Application) NewLogger(withs ...interface{}) *slog.Logger { | ||||
| 	return a.baseLogger.With(withs...) | ||||
| } | ||||
							
								
								
									
										26
									
								
								server/internal/application/server.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								server/internal/application/server.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| package application | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"syscall" | ||||
| ) | ||||
|  | ||||
| // ShutdownChan returns shutdown channel for main function. | ||||
| func (a *Application) ShutdownChan() chan struct{} { | ||||
| 	return a.shutdownChan | ||||
| } | ||||
|  | ||||
| func (a *Application) startServer() { | ||||
| 	a.shutdownChan = make(chan struct{}) | ||||
|  | ||||
| 	go func() { | ||||
| 		listener := make(chan os.Signal, 1) | ||||
|  | ||||
| 		signal.Notify(listener, syscall.SIGTERM, os.Interrupt) | ||||
|  | ||||
| 		<-listener | ||||
|  | ||||
| 		a.shutdownChan <- struct{}{} | ||||
| 	}() | ||||
| } | ||||
							
								
								
									
										80
									
								
								server/internal/application/service.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								server/internal/application/service.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| package application | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	// ErrServiceAlreadyRegistered returns if trying to register a service with name already taken by other service. | ||||
| 	ErrServiceAlreadyRegistered = errors.New("service with such name already registered") | ||||
| 	// ErrServiceNotFound returns if trying to gather service with unknown name. | ||||
| 	ErrServiceNotFound = errors.New("service with such name wasn't found") | ||||
| ) | ||||
|  | ||||
| // Service is an interface every service should conform to. Specific services will have own interface for | ||||
| // cross-service interation. | ||||
| type Service interface { | ||||
| 	// Configure configures service. Called after ConnectDependencies and before LaunchStartupTasks. | ||||
| 	Configure() error | ||||
| 	// ConnectDependencies gets necessary dependencies. | ||||
| 	ConnectDependencies() error | ||||
| 	// Initialize initializes service's internal state. Called while registering service with Application | ||||
| 	// lifecycle controller. | ||||
| 	Initialize() error | ||||
| 	// Name returns service name. | ||||
| 	Name() string | ||||
| 	// LaunchStartupTasks launches tasks on application start. Called after ConnectDependencies and Configure. | ||||
| 	LaunchStartupTasks() error | ||||
| 	// Shutdown stops service. | ||||
| 	Shutdown() error | ||||
| } | ||||
|  | ||||
| // RegisterService registering service with lifecycle controller for later use in any other service. | ||||
| func (a *Application) RegisterService(srv Service) error { | ||||
| 	var found bool | ||||
|  | ||||
| 	for _, knownService := range a.services { | ||||
| 		if srv.Name() == knownService.Name() { | ||||
| 			found = true | ||||
|  | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if found { | ||||
| 		return fmt.Errorf( | ||||
| 			"%w: RegisterService: check for service '%s' registration: %w", | ||||
| 			errApplication, | ||||
| 			srv.Name(), | ||||
| 			ErrServiceAlreadyRegistered, | ||||
| 		) | ||||
| 	} | ||||
|  | ||||
| 	if err := srv.Initialize(); err != nil { | ||||
| 		return fmt.Errorf("%w: RegisterService: initialize service '%s': %w", errApplication, srv.Name(), err) | ||||
| 	} | ||||
|  | ||||
| 	a.services = append(a.services, srv) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Service returns requested service. | ||||
| func (a *Application) Service(name string) Service { | ||||
| 	var srv Service | ||||
|  | ||||
| 	for _, knownService := range a.services { | ||||
| 		if knownService.Name() == name { | ||||
| 			srv = knownService | ||||
|  | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if srv == nil { | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	return srv | ||||
| } | ||||
							
								
								
									
										19
									
								
								server/localdevzone/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								server/localdevzone/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| --- | ||||
| version: "3" | ||||
|  | ||||
| includes: | ||||
|   bunkerd: ./bunkerd | ||||
|   common: ./common | ||||
|  | ||||
| tasks: | ||||
|   down: | ||||
|     desc: "Removes development environment." | ||||
|     cmds: | ||||
|       - task: bunkerd:down | ||||
|       - task: common:network-down | ||||
|  | ||||
|   up: | ||||
|     desc: "Creates development environment." | ||||
|     cmds: | ||||
|       - task: common:network-up | ||||
|       - task: bunkerd:up | ||||
							
								
								
									
										47
									
								
								server/localdevzone/bunkerd/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								server/localdevzone/bunkerd/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| --- | ||||
| version: "3" | ||||
|  | ||||
| tasks: | ||||
|   build: | ||||
|     desc: "Builds bunkerd's container." | ||||
|     dir: "./server/localdevzone/bunkerd" | ||||
|     cmds: | ||||
|       - docker compose -p bunkerd -f docker-compose.yaml build | ||||
|  | ||||
|   down: | ||||
|     desc: "Deletes all bunkerd's data (down)." | ||||
|     dir: "./server/localdevzone/bunkerd" | ||||
|     cmds: | ||||
|       - docker compose -p bunkerd -f docker-compose.yaml down --volumes | ||||
|  | ||||
|   logs: | ||||
|     desc: "Show bunkerd logs." | ||||
|     dir: "./server/localdevzone/bunkerd" | ||||
|     cmds: | ||||
|       - docker compose -p bunkerd -f docker-compose.yaml logs -f | ||||
|  | ||||
|   restart: | ||||
|     desc: "Restart bunkerd." | ||||
|     dir: "./server/localdevzone/bunkerd" | ||||
|     cmds: | ||||
|       - docker compose -p bunkerd -f docker-compose.yaml restart | ||||
|  | ||||
|   start: | ||||
|     desc: "Start bunkerd." | ||||
|     dir: "./server/localdevzone/bunkerd" | ||||
|     cmds: | ||||
|       - docker compose -p bunkerd -f docker-compose.yaml start | ||||
|  | ||||
|   stop: | ||||
|     desc: "Stop bunkerd without deleting it's data." | ||||
|     dir: "./server/localdevzone/bunkerd" | ||||
|     cmds: | ||||
|       - docker compose -p bunkerd -f docker-compose.yaml stop | ||||
|  | ||||
|   up: | ||||
|     desc: "Start bunkerd (up -d)." | ||||
|     dir: "./server/localdevzone/bunkerd" | ||||
|     cmds: | ||||
|       - task: :common:network-up | ||||
|       - task: build | ||||
|       - docker compose -p bunkerd -f docker-compose.yaml up -d | ||||
							
								
								
									
										24
									
								
								server/localdevzone/bunkerd/docker-compose.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								server/localdevzone/bunkerd/docker-compose.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| --- | ||||
| services: | ||||
|   bunkerd: | ||||
|     container_name: "bunkerd" | ||||
|     build: | ||||
|       context: ../../../ | ||||
|       dockerfile: server/Dockerfile | ||||
|     ports: | ||||
|       - "53400:53400" | ||||
|       - "54000:4000" | ||||
|     volumes: | ||||
|       - "./data:/data" | ||||
|     networks: | ||||
|       bunkerd: | ||||
|         ipv4_address: 247.247.0.2 | ||||
|     environment: | ||||
|       BUNKERD_DEBUG: "true" | ||||
|       BUNKERD_DATABASE_DSN: " " | ||||
|     cap_add: | ||||
|       - SYS_PTRACE | ||||
|  | ||||
| networks: | ||||
|   bunkerd: | ||||
|     external: true | ||||
							
								
								
									
										15
									
								
								server/localdevzone/common/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								server/localdevzone/common/Taskfile.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| --- | ||||
| version: "3" | ||||
|  | ||||
| tasks: | ||||
|   network-down: | ||||
|     desc: "Deletes Docker network for development." | ||||
|     dir: "./server/localdevzone/common" | ||||
|     cmds: | ||||
|       - docker compose -p bunkerd-network -f network.yaml down | ||||
|  | ||||
|   network-up: | ||||
|     desc: "Creates Docker network for development" | ||||
|     dir: "./server/localdevzone/common" | ||||
|     cmds: | ||||
|       - docker compose -p bunkerd-network  -f network.yaml up -d | ||||
							
								
								
									
										18
									
								
								server/localdevzone/common/network.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								server/localdevzone/common/network.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| --- | ||||
| services: | ||||
|   dummy: | ||||
|     image: busybox | ||||
|     container_name: bunkerd-dummy | ||||
|     hostname: dummy | ||||
|     networks: | ||||
|       bunkerd: | ||||
|         ipv4_address: 247.247.0.254 | ||||
|  | ||||
| networks: | ||||
|   bunkerd: | ||||
|     driver: bridge | ||||
|     name: "bunkerd" | ||||
|     ipam: | ||||
|       config: | ||||
|         - subnet: 247.247.0.0/24 | ||||
|           gateway: 247.247.0.1 | ||||
		Reference in New Issue
	
	Block a user