Skip to content

Commit 7c7c69f

Browse files
committed
chore: sync with go-monolith-example
1 parent dd92f14 commit 7c7c69f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+674
-404
lines changed

cmd/address-book/main.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020

2121
//nolint:gochecknoglobals // Main.
2222
var (
23-
svc = &service{}
23+
svc = &Service{}
2424

2525
log = structlog.New(structlog.KeyUnit, "main")
2626

@@ -45,12 +45,13 @@ var (
4545
)
4646

4747
func main() {
48+
_ = os.Unsetenv("GO_TEST_DISABLE_SENSITIVE")
4849
err := def.Init()
4950
if err != nil {
5051
log.Fatalf("failed to get defaults: %s", err)
5152
}
5253

53-
err = initService(rootCmd, serveCmd)
54+
err = svc.Init(rootCmd, serveCmd)
5455
if err != nil {
5556
log.Fatalf("failed to init service: %s", err)
5657
}
@@ -77,15 +78,13 @@ func runServeWithGracefulShutdown(_ *cobra.Command, _ []string) error {
7778
defer cancel()
7879

7980
ctxShutdown, shutdown := context.WithCancel(context.Background())
80-
sigc := make(chan os.Signal, 1)
81-
signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGABRT, syscall.SIGTERM)
82-
go func() { <-sigc; shutdown() }()
81+
ctxShutdown, _ = signal.NotifyContext(ctxShutdown, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGABRT, syscall.SIGTERM)
8382
go func() {
8483
<-ctxShutdown.Done()
8584
time.Sleep(serveShutdownTimeout.Value(nil))
8685
log.PrintErr("failed to graceful shutdown", "version", def.Version())
8786
os.Exit(1)
8887
}()
8988

90-
return svc.runServe(ctxStartup, ctxShutdown, shutdown)
89+
return svc.RunServe(ctxStartup, ctxShutdown, shutdown)
9190
}

cmd/address-book/service.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ type Ctx = context.Context
2525

2626
var reg = prometheus.NewPedanticRegistry() //nolint:gochecknoglobals // Metrics are global anyway.
2727

28-
type service struct {
28+
type Service struct {
2929
cfg *config.ServeConfig
3030
repo *dal.Repo
3131
appl *app.App
3232
srv *restapi.Server
3333
}
3434

35-
func initService(cmd, serveCmd *cobra.Command) error {
35+
func (s *Service) Init(cmd, serveCmd *cobra.Command) error {
3636
namespace := regexp.MustCompile(`[^a-zA-Z0-9]+`).ReplaceAllString(def.ProgName, "_")
3737
initMetrics(reg, namespace)
3838
dal.InitMetrics(reg, namespace)
@@ -48,7 +48,7 @@ func initService(cmd, serveCmd *cobra.Command) error {
4848
})
4949
}
5050

51-
func (s *service) runServe(ctxStartup, ctxShutdown Ctx, shutdown func()) (err error) {
51+
func (s *Service) RunServe(ctxStartup, ctxShutdown Ctx, shutdown func()) (err error) {
5252
log := structlog.FromContext(ctxShutdown, nil)
5353
if s.cfg == nil {
5454
s.cfg, err = config.GetServe()
@@ -69,7 +69,7 @@ func (s *service) runServe(ctxStartup, ctxShutdown Ctx, shutdown func()) (err er
6969
}
7070
s.srv, err = openapi.NewServer(s.appl, openapi.Config{
7171
APIKeyAdmin: s.cfg.APIKeyAdmin,
72-
Addr: s.cfg.Addr,
72+
Addr: s.cfg.BindAddr,
7373
})
7474
if err != nil {
7575
return log.Err("failed to openapi.NewServer", "err", err)
@@ -85,14 +85,14 @@ func (s *service) runServe(ctxStartup, ctxShutdown Ctx, shutdown func()) (err er
8585
return nil
8686
}
8787

88-
func (s *service) connectRepo(ctx Ctx) (interface{}, error) {
89-
return dal.New(ctx, s.cfg.MySQLGooseDir, s.cfg.MySQL)
88+
func (s *Service) connectRepo(ctx Ctx) (interface{}, error) {
89+
return dal.New(ctx, s.cfg.GooseMySQLDir, s.cfg.MySQL)
9090
}
9191

92-
func (s *service) serveMetrics(ctx Ctx) error {
93-
return serve.Metrics(ctx, s.cfg.MetricsAddr, reg)
92+
func (s *Service) serveMetrics(ctx Ctx) error {
93+
return serve.Metrics(ctx, s.cfg.BindMetricsAddr, reg)
9494
}
9595

96-
func (s *service) serveOpenAPI(ctx Ctx) error {
96+
func (s *Service) serveOpenAPI(ctx Ctx) error {
9797
return serve.OpenAPI(ctx, s.srv, "OpenAPI")
9898
}

cmd/address-book/service_integration_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
func TestSmoke(tt *testing.T) {
2222
t := check.T(tt)
2323

24-
s := &service{cfg: cfg}
24+
s := &Service{cfg: cfg}
2525

2626
tempDBCfg, cleanup, err := mysqlx.EnsureTempDB(tLogger(*t), "", cfg.MySQL)
2727
cfg.MySQL = tempDBCfg // Assign to cfg and not s.cfg as a reminder: they are the same.
@@ -32,19 +32,19 @@ func TestSmoke(tt *testing.T) {
3232
defer cancel()
3333
ctxShutdown, shutdown := context.WithCancel(ctx)
3434
errc := make(chan error)
35-
go func() { errc <- s.runServe(ctxStartup, ctxShutdown, shutdown) }()
35+
go func() { errc <- s.RunServe(ctxStartup, ctxShutdown, shutdown) }()
3636
defer func() {
3737
shutdown()
3838
t.Nil(<-errc, "RunServe")
3939
if s.repo != nil {
4040
s.repo.Close()
4141
}
4242
}()
43-
t.Must(t.Nil(netx.WaitTCPPort(ctxStartup, cfg.Addr), "connect to service"))
43+
t.Must(t.Nil(netx.WaitTCPPort(ctxStartup, cfg.BindAddr), "connect to service"))
4444

4545
openapiClient := client.NewHTTPClientWithConfig(nil, &client.TransportConfig{
4646
Schemes: []string{"http"},
47-
Host: cfg.Addr.String(),
47+
Host: cfg.BindAddr.String(),
4848
BasePath: client.DefaultBasePath,
4949
})
5050

go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ require (
1818
github.com/golangci/golangci-lint v1.40.1
1919
github.com/jessevdk/go-flags v1.4.0
2020
github.com/jmoiron/sqlx v1.3.4
21+
github.com/lib/pq v1.9.0
2122
github.com/mattn/goveralls v0.0.9
2223
github.com/powerman/appcfg v0.6.0
2324
github.com/powerman/check v1.3.1
@@ -27,6 +28,7 @@ require (
2728
github.com/powerman/must v0.1.0
2829
github.com/powerman/mysqlx v0.3.3
2930
github.com/powerman/narada4d v1.7.1
31+
github.com/powerman/sensitive v0.0.6
3032
github.com/powerman/sqlxx v0.2.0
3133
github.com/powerman/structlog v0.7.1
3234
github.com/prometheus/client_golang v1.10.0

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,8 @@ github.com/powerman/mysqlx v0.3.3/go.mod h1:ZSl17PWU2DgwM2KjN8OrdAq9tYC5p4Xm3lTN
838838
github.com/powerman/narada4d v1.7.1 h1:G6hkEQxfCBWIsrUtB4MyWq4c84qcS/3XsBQLWUuUyik=
839839
github.com/powerman/narada4d v1.7.1/go.mod h1:LUOXFkHgtSwPqtrZx+F/Ab1PqOiL96O3GfYnoKfg6T0=
840840
github.com/powerman/pqx v0.6.1/go.mod h1:EJGFN0+vvTWFqwT1bTrnVWrJ8hO7RAW6rp2JVhYwrVE=
841+
github.com/powerman/sensitive v0.0.6 h1:cLE/om0/J2mpiI/Z6o1r9AUbs8Q7G1vhISEbdGeIGQc=
842+
github.com/powerman/sensitive v0.0.6/go.mod h1:BT3bBXUqTDKM13MXlYvN4Csg9WXSZblJ12mGgHAY/wU=
841843
github.com/powerman/sqlxx v0.2.0 h1:NA2Z+o7Q6Lu9UqwGFqqPePKWoPYZ5doOsBnfstCU1uU=
842844
github.com/powerman/sqlxx v0.2.0/go.mod h1:dsfudBeSTo0U61OEAC/WS0Ea7qityww7jvFvWt3U1Fw=
843845
github.com/powerman/structlog v0.7.1 h1:68xN/GdxU7SYbXu/7P4RWyK7lKaN7FXjncarf7wO+Wk=

internal/apix/ctx.go

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package apix
2+
3+
import "context"
4+
5+
type Ctx = context.Context
6+
7+
type contextKey int
8+
9+
const (
10+
_ contextKey = iota
11+
contextKeyRemoteIP
12+
)
13+
14+
// NewContextWithRemoteIP creates and returns new context containing given
15+
// remoteIP.
16+
func NewContextWithRemoteIP(ctx Ctx, remoteIP string) Ctx {
17+
return context.WithValue(ctx, contextKeyRemoteIP, remoteIP)
18+
}
19+
20+
// FromContext returns values describing request stored in ctx, if any.
21+
func FromContext(ctx Ctx) (remoteIP string) {
22+
remoteIP, _ = ctx.Value(contextKeyRemoteIP).(string)
23+
return
24+
}

internal/apix/doc.go

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// Package apix provide API-related helpers.
2+
package apix

internal/app/contact_test.go

+2-4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ import (
1111

1212
func TestContacts(tt *testing.T) {
1313
t := check.T(tt)
14-
cleanup, a, mockRepo := testNew(t)
15-
defer cleanup()
14+
a, mockRepo := testNew(t)
1615

1716
var (
1817
c1 = app.Contact{ID: 1, Name: "A"}
@@ -35,8 +34,7 @@ func TestContacts(tt *testing.T) {
3534

3635
func TestAddContact(tt *testing.T) {
3736
t := check.T(tt)
38-
cleanup, a, mockRepo := testNew(t)
39-
defer cleanup()
37+
a, mockRepo := testNew(t)
4038

4139
c1 := app.Contact{Name: "A"}
4240

internal/app/init_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ var (
2828
auth1 = app.Auth{UserID: "1"}
2929
)
3030

31-
func testNew(t *check.C) (func(), *app.App, *app.MockRepo) {
31+
func testNew(t *check.C) (*app.App, *app.MockRepo) {
3232
ctrl := gomock.NewController(t)
3333

3434
mockRepo := app.NewMockRepo(ctrl)
3535
a := app.New(mockRepo, app.Config{})
36-
return ctrl.Finish, a, mockRepo
36+
return a, mockRepo
3737
}

internal/config/config.go

+30-30
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ var all = &struct { //nolint:gochecknoglobals // Config is global anyway.
3434
MySQLAuthLogin appcfg.NotEmptyString `env:"MYSQL_AUTH_LOGIN"`
3535
MySQLAuthPass appcfg.String `env:"MYSQL_AUTH_PASS"`
3636
MySQLDBName appcfg.NotEmptyString `env:"MYSQL_DB"`
37-
MySQLGooseDir appcfg.NotEmptyString
37+
GooseMySQLDir appcfg.NotEmptyString
3838
}{ // Defaults, if any:
3939
AddrHost: appcfg.MustNotEmptyString(def.Hostname),
4040
AddrPort: appcfg.MustPort("8000"),
4141
MetricsAddrPort: appcfg.MustPort("9000"),
4242
MySQLAddrPort: appcfg.MustPort("3306"),
4343
MySQLAuthLogin: appcfg.MustNotEmptyString(def.ProgName),
4444
MySQLDBName: appcfg.MustNotEmptyString(def.ProgName),
45-
MySQLGooseDir: appcfg.MustNotEmptyString("internal/migrations/mysql"),
45+
GooseMySQLDir: appcfg.MustNotEmptyString("internal/migrations/mysql"),
4646
}
4747

4848
// FlagSets for all CLI subcommands which use flags to set config values.
@@ -65,31 +65,31 @@ func Init(flagsets FlagSets) error {
6565
return err
6666
}
6767

68-
appcfg.AddPFlag(fs.Serve, &all.AddrHost, "host", "host to serve OpenAPI")
69-
appcfg.AddPFlag(fs.Serve, &all.AddrPort, "port", "port to serve OpenAPI")
70-
appcfg.AddPFlag(fs.Serve, &all.MetricsAddrPort, "metrics.port", "port to serve Prometheus metrics")
71-
appcfg.AddPFlag(fs.Serve, &all.MySQLAddrHost, "mysql.host", "host to connect to MySQL")
72-
appcfg.AddPFlag(fs.Serve, &all.MySQLAddrPort, "mysql.port", "port to connect to MySQL")
73-
appcfg.AddPFlag(fs.Serve, &all.MySQLAuthLogin, "mysql.user", "MySQL username")
74-
appcfg.AddPFlag(fs.Serve, &all.MySQLAuthPass, "mysql.pass", "MySQL password")
75-
appcfg.AddPFlag(fs.Serve, &all.MySQLDBName, "mysql.dbname", "MySQL database name")
76-
7768
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLAddrHost, "mysql.host", "host to connect to MySQL")
7869
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLAddrPort, "mysql.port", "port to connect to MySQL")
70+
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLDBName, "mysql.dbname", "MySQL database name")
7971
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLAuthLogin, "mysql.user", "MySQL username")
8072
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLAuthPass, "mysql.pass", "MySQL password")
81-
appcfg.AddPFlag(fs.GooseMySQL, &all.MySQLDBName, "mysql.dbname", "MySQL database name")
73+
74+
appcfg.AddPFlag(fs.Serve, &all.MySQLAddrHost, "mysql.host", "host to connect to MySQL")
75+
appcfg.AddPFlag(fs.Serve, &all.MySQLAddrPort, "mysql.port", "port to connect to MySQL")
76+
appcfg.AddPFlag(fs.Serve, &all.MySQLDBName, "mysql.dbname", "MySQL database name")
77+
appcfg.AddPFlag(fs.Serve, &all.MySQLAuthLogin, "mysql.user", "MySQL username")
78+
appcfg.AddPFlag(fs.Serve, &all.MySQLAuthPass, "mysql.pass", "MySQL password")
79+
appcfg.AddPFlag(fs.Serve, &all.AddrHost, "host", "host to serve OpenAPI")
80+
appcfg.AddPFlag(fs.Serve, &all.AddrPort, "port", "port to serve OpenAPI")
81+
appcfg.AddPFlag(fs.Serve, &all.MetricsAddrPort, "metrics.port", "port to serve Prometheus metrics")
8282

8383
return nil
8484
}
8585

8686
// ServeConfig contains configuration for subcommand.
8787
type ServeConfig struct {
88-
MySQL *mysql.Config
89-
MySQLGooseDir string
90-
Addr netx.Addr
91-
MetricsAddr netx.Addr
92-
APIKeyAdmin string
88+
MySQL *mysql.Config
89+
GooseMySQLDir string
90+
BindAddr netx.Addr
91+
BindMetricsAddr netx.Addr
92+
APIKeyAdmin string
9393
}
9494

9595
// GetServe validates and returns configuration for subcommand.
@@ -98,15 +98,15 @@ func GetServe() (c *ServeConfig, err error) {
9898

9999
c = &ServeConfig{
100100
MySQL: def.NewMySQLConfig(def.MySQLConfig{
101-
Addr: netx.NewAddr(all.MySQLAddrHost.Value(&err), all.MySQLAddrPort.Value(&err)),
102-
User: all.MySQLAuthLogin.Value(&err),
103-
Pass: all.MySQLAuthPass.Value(&err),
104-
DB: all.MySQLDBName.Value(&err),
101+
Addr: netx.NewAddr(all.MySQLAddrHost.Value(&err), all.MySQLAddrPort.Value(&err)),
102+
DBName: all.MySQLDBName.Value(&err),
103+
User: all.MySQLAuthLogin.Value(&err),
104+
Pass: all.MySQLAuthPass.Value(&err),
105105
}),
106-
MySQLGooseDir: all.MySQLGooseDir.Value(&err),
107-
Addr: netx.NewAddr(all.AddrHost.Value(&err), all.AddrPort.Value(&err)),
108-
MetricsAddr: netx.NewAddr(all.AddrHost.Value(&err), all.MetricsAddrPort.Value(&err)),
109-
APIKeyAdmin: all.APIKeyAdmin.Value(&err),
106+
GooseMySQLDir: all.GooseMySQLDir.Value(&err),
107+
BindAddr: netx.NewAddr(all.AddrHost.Value(&err), all.AddrPort.Value(&err)),
108+
BindMetricsAddr: netx.NewAddr(all.AddrHost.Value(&err), all.MetricsAddrPort.Value(&err)),
109+
APIKeyAdmin: all.APIKeyAdmin.Value(&err),
110110
}
111111
if err != nil {
112112
return nil, appcfg.WrapPErr(err, fs.Serve, all)
@@ -119,12 +119,12 @@ func GetGooseMySQL() (c *cobrax.GooseMySQLConfig, err error) {
119119

120120
c = &cobrax.GooseMySQLConfig{
121121
MySQL: def.NewMySQLConfig(def.MySQLConfig{
122-
Addr: netx.NewAddr(all.MySQLAddrHost.Value(&err), all.MySQLAddrPort.Value(&err)),
123-
User: all.MySQLAuthLogin.Value(&err),
124-
Pass: all.MySQLAuthPass.Value(&err),
125-
DB: all.MySQLDBName.Value(&err),
122+
Addr: netx.NewAddr(all.MySQLAddrHost.Value(&err), all.MySQLAddrPort.Value(&err)),
123+
DBName: all.MySQLDBName.Value(&err),
124+
User: all.MySQLAuthLogin.Value(&err),
125+
Pass: all.MySQLAuthPass.Value(&err),
126126
}),
127-
MySQLGooseDir: all.MySQLGooseDir.Value(&err),
127+
GooseMySQLDir: all.GooseMySQLDir.Value(&err),
128128
}
129129
if err != nil {
130130
return nil, appcfg.WrapPErr(err, fs.GooseMySQL, all)

internal/config/config_test.go

+20-20
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import (
1313
func Test(t *testing.T) {
1414
want := &ServeConfig{
1515
MySQL: def.NewMySQLConfig(def.MySQLConfig{
16-
Addr: netx.NewAddr("localhost", 3306),
17-
User: "config",
18-
Pass: "",
19-
DB: "config",
16+
Addr: netx.NewAddr("localhost", 3306),
17+
DBName: "config",
18+
User: "config",
19+
Pass: "",
2020
}),
21-
MySQLGooseDir: "internal/migrations/mysql",
22-
Addr: netx.NewAddr(def.Hostname, 8000),
23-
MetricsAddr: netx.NewAddr(def.Hostname, 9000),
24-
APIKeyAdmin: "admin",
21+
GooseMySQLDir: "internal/migrations/mysql",
22+
BindAddr: netx.NewAddr(def.Hostname, 8000),
23+
BindMetricsAddr: netx.NewAddr(def.Hostname, 9000),
24+
APIKeyAdmin: "admin",
2525
}
2626

2727
t.Run("required", func(tt *testing.T) {
@@ -62,13 +62,13 @@ func Test(t *testing.T) {
6262
c, err := testGetServe()
6363
t.Nil(err)
6464
want.MySQL = def.NewMySQLConfig(def.MySQLConfig{
65-
Addr: netx.NewAddr("mysql3", 33306),
66-
User: "user3",
67-
Pass: "pass3",
68-
DB: "db3",
65+
Addr: netx.NewAddr("mysql3", 33306),
66+
DBName: "db3",
67+
User: "user3",
68+
Pass: "pass3",
6969
})
70-
want.Addr = netx.NewAddr("localhost3", 8003)
71-
want.MetricsAddr = netx.NewAddr("localhost3", 9003)
70+
want.BindAddr = netx.NewAddr("localhost3", 8003)
71+
want.BindMetricsAddr = netx.NewAddr("localhost3", 9003)
7272
want.APIKeyAdmin = "admin3"
7373
t.DeepEqual(c, want)
7474
})
@@ -86,13 +86,13 @@ func Test(t *testing.T) {
8686
)
8787
t.Nil(err)
8888
want.MySQL = def.NewMySQLConfig(def.MySQLConfig{
89-
Addr: netx.NewAddr("mysql4", 43306),
90-
User: "user4",
91-
Pass: "pass4",
92-
DB: "db4",
89+
Addr: netx.NewAddr("mysql4", 43306),
90+
DBName: "db4",
91+
User: "user4",
92+
Pass: "pass4",
9393
})
94-
want.Addr = netx.NewAddr("localhost4", 8004)
95-
want.MetricsAddr = netx.NewAddr("localhost4", 9004)
94+
want.BindAddr = netx.NewAddr("localhost4", 8004)
95+
want.BindMetricsAddr = netx.NewAddr("localhost4", 9004)
9696
t.DeepEqual(c, want)
9797
})
9898
t.Run("cleanup", func(tt *testing.T) {

0 commit comments

Comments
 (0)