Split to server and CLI binaries
- introduce CLI binary - move server binary to subdirectory to have a uniformed directory structure - update goreleaser to build all binaries and create dist packages - update ignore files accordingly
This commit is contained in:
parent
13a38298ec
commit
d89ab3a576
11 changed files with 287 additions and 21 deletions
|
@ -3,8 +3,10 @@
|
|||
###############
|
||||
|
||||
.git/
|
||||
.github/
|
||||
.idea/
|
||||
.vscode/
|
||||
api/
|
||||
deploy/
|
||||
dist/
|
||||
doc/
|
||||
|
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -7,8 +7,9 @@
|
|||
**/*.so
|
||||
*.key
|
||||
*.pem
|
||||
inetmock
|
||||
main
|
||||
/inetmock
|
||||
/imctl
|
||||
./main
|
||||
|
||||
###############
|
||||
# directories #
|
||||
|
|
|
@ -5,24 +5,49 @@ before:
|
|||
# You may remove this if you don't use go modules.
|
||||
- make plugins
|
||||
builds:
|
||||
- id: "default"
|
||||
- id: "inetmock"
|
||||
binary: inetmock
|
||||
main: ./cmd/inetmock/main.go
|
||||
ldflags:
|
||||
- -w -s
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
- id: "imctl"
|
||||
binary: imctl
|
||||
main: ./cmd/imctl/main.go
|
||||
ldflags:
|
||||
- -w -s
|
||||
goos:
|
||||
- linux
|
||||
- freebsd
|
||||
- darwin
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
archives:
|
||||
- id: default
|
||||
- id: inetmock
|
||||
builds:
|
||||
- default
|
||||
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
- inetmock
|
||||
name_template: "{{ .ProjectName }}_server_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
replacements:
|
||||
amd64: x86_64
|
||||
wrap_in_directory: true
|
||||
files:
|
||||
- config.yaml
|
||||
- "*.so"
|
||||
- id: imctl
|
||||
builds:
|
||||
- imctl
|
||||
name_template: "{{ .ProjectName }}_cli_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
||||
replacements:
|
||||
amd64: x86_64
|
||||
wrap_in_directory: true
|
||||
files: []
|
||||
checksum:
|
||||
name_template: 'checksums.txt'
|
||||
snapshot:
|
||||
|
|
29
Makefile
29
Makefile
|
@ -1,50 +1,57 @@
|
|||
VERSION = $(shell git describe --dirty --tags --always)
|
||||
DIR = $(dir $(realpath $(firstword $(MAKEFILE_LIST))))
|
||||
BUILD_PATH = $(DIR)/main.go
|
||||
SERVER_BUILD_PATH = github.com/baez90/inetmock/cmd/inetmock
|
||||
CLI_BUILD_PATH = github.com/baez90/inetmock/cmd/imctl
|
||||
PKGS = $(shell go list ./...)
|
||||
TEST_PKGS = $(shell go list ./...)
|
||||
PROTO_FILES = $(shell find $(DIR)api/ -type f -name "*.proto")
|
||||
GOARGS = GOOS=linux GOARCH=amd64
|
||||
GO_BUILD_ARGS = -ldflags="-w -s"
|
||||
GO_CONTAINER_BUILD_ARGS = -ldflags="-w -s" -a -installsuffix cgo
|
||||
GO_BUILD_ARGS = -ldflags='-w -s'
|
||||
GO_CONTAINER_BUILD_ARGS = -ldflags='-w -s' -a -installsuffix cgo
|
||||
GO_DEBUG_BUILD_ARGS = -gcflags "all=-N -l"
|
||||
BINARY_NAME = inetmock
|
||||
SERVER_BINARY_NAME = inetmock
|
||||
CLI_BINARY_NAME = imctl
|
||||
PLUGINS = $(wildcard $(DIR)plugins/*/.)
|
||||
DEBUG_PORT = 2345
|
||||
DEBUG_ARGS?= --development-logs=true
|
||||
CONTAINER_BUILDER ?= podman
|
||||
DOCKER_IMAGE ?= inetmock
|
||||
|
||||
.PHONY: clean all format deps update-deps compile debug generate protoc snapshot-release test cli-cover-report html-cover-report plugins $(PLUGINS) $(GO_GEN_FILES)
|
||||
.PHONY: clean all format deps update-deps compile compile-server compile-cli debug generate protoc snapshot-release test cli-cover-report html-cover-report plugins $(PLUGINS) $(GO_GEN_FILES)
|
||||
all: clean format compile test plugins
|
||||
|
||||
clean:
|
||||
@find $(DIR) -type f \( -name "*.out" -or -name "*.so" \) -exec rm -f {} \;
|
||||
@rm -rf $(DIR)*.so
|
||||
@rm -f $(DIR)$(BINARY_NAME) $(DIR)main
|
||||
@rm -f $(DIR)$(SERVER_BINARY_NAME) $(DIR)$(CLI_BINARY_NAME) $(DIR)main
|
||||
|
||||
format:
|
||||
@go fmt $(PKGS)
|
||||
|
||||
deps:
|
||||
@go build -v $(BUILD_PATH)
|
||||
@go build -v $(SERVER_BUILD_PATH)
|
||||
|
||||
update-deps:
|
||||
@go mod tidy
|
||||
@go get -u
|
||||
|
||||
compile: deps
|
||||
compile-server: deps
|
||||
ifdef DEBUG
|
||||
@echo 'Compiling for debugging...'
|
||||
@$(GOARGS) go build $(GO_DEBUG_BUILD_ARGS) -o $(DIR)$(BINARY_NAME) $(BUILD_PATH)
|
||||
@$(GOARGS) go build $(GO_DEBUG_BUILD_ARGS) -o $(DIR)$(SERVER_BINARY_NAME) $(SERVER_BUILD_PATH)
|
||||
else ifdef CONTAINER
|
||||
@echo 'Compiling for container usage...'
|
||||
@$(GOARGS) go build $(GO_CONTAINER_BUILD_ARGS) -o $(DIR)$(BINARY_NAME) $(BUILD_PATH)
|
||||
@$(GOARGS) go build $(GO_CONTAINER_BUILD_ARGS) -o $(DIR)$(SERVER_BINARY_NAME) $(SERVER_BUILD_PATH)
|
||||
else
|
||||
@echo 'Compiling for normal Linux env...'
|
||||
@$(GOARGS) go build $(GO_BUILD_ARGS) -o $(DIR)$(BINARY_NAME) $(BUILD_PATH)
|
||||
@$(GOARGS) go build $(GO_BUILD_ARGS) -o $(DIR)$(SERVER_BINARY_NAME) $(SERVER_BUILD_PATH)
|
||||
endif
|
||||
|
||||
compile-cli: deps
|
||||
@$(GOARGS) go build $(GO_BUILD_ARGS) -o $(CLI_BINARY_NAME) $(CLI_BUILD_PATH)
|
||||
|
||||
compile: compile-server compile-cli
|
||||
|
||||
debug: export INETMOCK_PLUGINS_DIRECTORY = $(DIR)
|
||||
debug:
|
||||
dlv debug $(DIR) \
|
||||
|
|
9
cmd/imctl/main.go
Normal file
9
cmd/imctl/main.go
Normal file
|
@ -0,0 +1,9 @@
|
|||
package main
|
||||
|
||||
import "github.com/baez90/inetmock/internal/cmd"
|
||||
|
||||
func main() {
|
||||
if err := cmd.ExecuteClientCommand(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ func main() {
|
|||
logger, _ := zap.NewProduction()
|
||||
defer logger.Sync()
|
||||
|
||||
if err := cmd.ExecuteRootCommand(); err != nil {
|
||||
if err := cmd.ExecuteServerCommand(); err != nil {
|
||||
logger.Error("Failed to run inetmock",
|
||||
zap.Error(err),
|
||||
)
|
|
@ -53,7 +53,7 @@ func init() {
|
|||
generateCaCmd.Flags().Duration(generateCANotAfterRelative, 17520*time.Hour, "Relative time value until when in the future the CA certificate should be valid. The value has a time unit, the greatest time unit is h for hour.")
|
||||
}
|
||||
|
||||
func runGenerateCA(cmd *cobra.Command, args []string) {
|
||||
func runGenerateCA(_ *cobra.Command, _ []string) {
|
||||
var certOutPath, curveName string
|
||||
var notBefore, notAfter time.Duration
|
||||
var err error
|
||||
|
|
27
internal/cmd/cli.go
Normal file
27
internal/cmd/cli.go
Normal file
|
@ -0,0 +1,27 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
cliCmd = &cobra.Command{
|
||||
Use: "",
|
||||
Short: "IMCTL is the CLI app to interact with an INetMock server",
|
||||
}
|
||||
|
||||
inetMockSocketPath string
|
||||
outputFormat string
|
||||
grpcTimeout time.Duration
|
||||
)
|
||||
|
||||
func init() {
|
||||
cliCmd.PersistentFlags().StringVar(&inetMockSocketPath, "socket-path", "./inetmock.sock", "Path to the INetMock socket file")
|
||||
cliCmd.PersistentFlags().StringVarP(&outputFormat, "format", "f", "table", "Output format to use. Possible values: table, json, yaml")
|
||||
cliCmd.PersistentFlags().DurationVar(&grpcTimeout, "grpc-timeout", 5*time.Second, "Timeout to connect to the gRPC API")
|
||||
|
||||
cliCmd.AddCommand(endpointsCmd, handlerCmd)
|
||||
endpointsCmd.AddCommand(getEndpoints)
|
||||
handlerCmd.AddCommand(getHandlersCmd)
|
||||
}
|
72
internal/cmd/endpoints.go
Normal file
72
internal/cmd/endpoints.go
Normal file
|
@ -0,0 +1,72 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/baez90/inetmock/internal/format"
|
||||
"github.com/baez90/inetmock/internal/rpc"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
getEndpoints = &cobra.Command{
|
||||
Use: "get",
|
||||
Short: "Get all running endpoints",
|
||||
Run: runGetEndpoints,
|
||||
}
|
||||
|
||||
endpointsCmd = &cobra.Command{
|
||||
Use: "endpoints",
|
||||
Short: "endpoints is the entrypoint to all kind of commands to interact with endpoints",
|
||||
Aliases: []string{"ep", "endpoint"},
|
||||
}
|
||||
)
|
||||
|
||||
type printableEndpoint struct {
|
||||
Id string
|
||||
Name string
|
||||
Handler string
|
||||
ListenAddress string
|
||||
Port int
|
||||
}
|
||||
|
||||
func fromEndpoint(ep *rpc.Endpoint) *printableEndpoint {
|
||||
return &printableEndpoint{
|
||||
Id: ep.Id,
|
||||
Name: ep.Name,
|
||||
Handler: ep.Handler,
|
||||
ListenAddress: ep.ListenAddress,
|
||||
Port: int(ep.Port),
|
||||
}
|
||||
}
|
||||
|
||||
func fromEndpoints(eps []*rpc.Endpoint) (out []*printableEndpoint) {
|
||||
for idx := range eps {
|
||||
out = append(out, fromEndpoint(eps[idx]))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func runGetEndpoints(_ *cobra.Command, _ []string) {
|
||||
var err error
|
||||
var conn *grpc.ClientConn
|
||||
|
||||
if conn, err = grpc.Dial(inetMockSocketPath, grpc.WithInsecure()); err != nil {
|
||||
fmt.Printf("Failed to connecto INetMock socket: %v\n", err)
|
||||
os.Exit(10)
|
||||
}
|
||||
endpointsClient := rpc.NewEndpointsClient(conn)
|
||||
ctx, _ := context.WithTimeout(context.Background(), grpcTimeout)
|
||||
var endpointsResp *rpc.GetEndpointsResponse
|
||||
if endpointsResp, err = endpointsClient.GetEndpoints(ctx, &rpc.GetEndpointsRequest{}); err != nil {
|
||||
fmt.Printf("Failed to get the endpoints: %v", err)
|
||||
os.Exit(11)
|
||||
}
|
||||
|
||||
writer := format.Writer(outputFormat, os.Stdout)
|
||||
if err = writer.Write(fromEndpoints(endpointsResp.Endpoints)); err != nil {
|
||||
fmt.Printf("Error occurred during writing response values: %v\n", err)
|
||||
}
|
||||
}
|
61
internal/cmd/handlers.go
Normal file
61
internal/cmd/handlers.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/baez90/inetmock/internal/format"
|
||||
"github.com/baez90/inetmock/internal/rpc"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/grpc"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
getHandlersCmd = &cobra.Command{
|
||||
Use: "get",
|
||||
Short: "Get all registered handlers",
|
||||
Run: runGetHandlers,
|
||||
}
|
||||
|
||||
handlerCmd = &cobra.Command{
|
||||
Use: "handlers",
|
||||
Short: "handlers is the entrypoint to all kind of commands to interact with handlers",
|
||||
Aliases: []string{"handler"},
|
||||
}
|
||||
)
|
||||
|
||||
type printableHandler struct {
|
||||
Handler string
|
||||
}
|
||||
|
||||
func fromHandlers(hs []string) (handlers []*printableHandler) {
|
||||
for idx := range hs {
|
||||
handlers = append(handlers, &printableHandler{
|
||||
Handler: hs[idx],
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func runGetHandlers(_ *cobra.Command, _ []string) {
|
||||
var err error
|
||||
var conn *grpc.ClientConn
|
||||
|
||||
if conn, err = grpc.Dial(inetMockSocketPath, grpc.WithInsecure()); err != nil {
|
||||
fmt.Printf("Failed to connecto INetMock socket: %v\n", err)
|
||||
os.Exit(10)
|
||||
}
|
||||
handlersClient := rpc.NewHandlersClient(conn)
|
||||
ctx, _ := context.WithTimeout(context.Background(), grpcTimeout)
|
||||
var handlersResp *rpc.GetHandlersResponse
|
||||
|
||||
if handlersResp, err = handlersClient.GetHandlers(ctx, &rpc.GetHandlersRequest{}); err != nil {
|
||||
fmt.Printf("Failed to get the endpoints: %v", err)
|
||||
os.Exit(11)
|
||||
}
|
||||
|
||||
writer := format.Writer(outputFormat, os.Stdout)
|
||||
if err = writer.Write(fromHandlers(handlersResp.Handlers)); err != nil {
|
||||
fmt.Printf("Error occurred during writing response values: %v\n", err)
|
||||
}
|
||||
}
|
|
@ -2,13 +2,19 @@ package cmd
|
|||
|
||||
import (
|
||||
"github.com/baez90/inetmock/internal/endpoints"
|
||||
"github.com/baez90/inetmock/internal/plugins"
|
||||
"github.com/baez90/inetmock/internal/rpc"
|
||||
"github.com/baez90/inetmock/pkg/api"
|
||||
"github.com/baez90/inetmock/pkg/config"
|
||||
"github.com/baez90/inetmock/pkg/logging"
|
||||
"github.com/baez90/inetmock/pkg/path"
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -21,9 +27,58 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func onServerInit() {
|
||||
logging.ConfigureLogging(
|
||||
logging.ParseLevel(logLevel),
|
||||
developmentLogs,
|
||||
map[string]interface{}{"cwd": path.WorkingDirectory()},
|
||||
)
|
||||
|
||||
logger, _ = logging.CreateLogger()
|
||||
config.CreateConfig(serverCmd.Flags())
|
||||
appConfig := config.Instance()
|
||||
|
||||
if err := appConfig.ReadConfig(configFilePath); err != nil {
|
||||
logger.Error(
|
||||
"failed to read config file",
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
|
||||
if err := api.InitServices(appConfig, logger); err != nil {
|
||||
logger.Error(
|
||||
"failed to initialize app services",
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
|
||||
registry := plugins.Registry()
|
||||
cfg := config.Instance()
|
||||
|
||||
pluginLoadStartTime := time.Now()
|
||||
if err := registry.LoadPlugins(cfg.PluginsDir()); err != nil {
|
||||
logger.Error("Failed to load plugins",
|
||||
zap.String("pluginsDirectory", cfg.PluginsDir()),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
pluginLoadDuration := time.Since(pluginLoadStartTime)
|
||||
logger.Info(
|
||||
"loading plugins completed",
|
||||
zap.Duration("pluginLoadDuration", pluginLoadDuration),
|
||||
)
|
||||
}
|
||||
|
||||
func startINetMock(_ *cobra.Command, _ []string) {
|
||||
onServerInit()
|
||||
endpointManager = endpoints.NewEndpointManager(logger)
|
||||
cfg := config.Instance()
|
||||
rpcAPI := rpc.NewINetMockAPI(
|
||||
cfg,
|
||||
endpointManager,
|
||||
plugins.Registry(),
|
||||
)
|
||||
|
||||
for endpointName, endpointHandler := range cfg.EndpointConfigs() {
|
||||
handlerSubConfig := cfg.Viper().Sub(strings.Join([]string{config.EndpointsKey, endpointName, config.OptionsKey}, "."))
|
||||
endpointHandler.Options = handlerSubConfig
|
||||
|
@ -38,6 +93,12 @@ func startINetMock(_ *cobra.Command, _ []string) {
|
|||
}
|
||||
|
||||
endpointManager.StartEndpoints()
|
||||
if err := rpcAPI.StartServer(); err != nil {
|
||||
logger.Error(
|
||||
"failed to start gRPC API",
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
|
||||
signalChannel := make(chan os.Signal, 1)
|
||||
signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||
|
@ -50,5 +111,6 @@ func startINetMock(_ *cobra.Command, _ []string) {
|
|||
zap.String("signal", s.String()),
|
||||
)
|
||||
|
||||
rpcAPI.StopServer()
|
||||
endpointManager.ShutdownEndpoints()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue