initial import
Some checks failed
build / test (push) Failing after 5s
build / lint (push) Failing after 6s

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2024-09-26 19:45:39 +03:00
parent c08ab26cf9
commit 973f9ac822
21 changed files with 3074 additions and 0 deletions

55
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,55 @@
name: build
on:
push:
branches:
- master
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v2
with:
go-version: 1.16
- name: cache
uses: actions/cache@v2
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: checkout
uses: actions/checkout@v2
- name: gitconfig
run: git config --global url."https://${{ secrets.TOKEN }}:x-oauth-basic@github.com/".insteadOf https://github.com/
- name: deps
env:
GOINSECURE: github.com/unistack-org/cms*
GONOPROXY: github.com/unistack-org/cms*
GONOSUMDB: github.com/unistack-org/cms*
GOPRIVATE: github.com/unistack-org/cms*
run: go get -v -t -d ./...
- name: test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: gitconfig
run: git config --global url."https://${{ secrets.TOKEN }}:x-oauth-basic@github.com/".insteadOf https://github.com/
- name: lint
uses: golangci/golangci-lint-action@v2
continue-on-error: true
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.30
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

55
.github/workflows/pr.yml vendored Normal file
View File

@ -0,0 +1,55 @@
name: prbuild
on:
pull_request:
branches:
- master
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v2
with:
go-version: 1.16
- name: cache
uses: actions/cache@v2
with:
path: ~/go/pkg
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: checkout
uses: actions/checkout@v2
- name: gitconfig
run: git config --global url."https://${{ secrets.TOKEN }}:x-oauth-basic@github.com/".insteadOf https://github.com/
- name: deps
env:
GOINSECURE: github.com/unistack-org/cms*
GONOPROXY: github.com/unistack-org/cms*
GONOSUMDB: github.com/unistack-org/cms*
GOPRIVATE: github.com/unistack-org/cms*
run: go get -v -t -d ./...
- name: test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v2
- name: gitconfig
run: git config --global url."https://${{ secrets.TOKEN }}:x-oauth-basic@github.com/".insteadOf https://github.com/
- name: lint
uses: golangci/golangci-lint-action@v2
continue-on-error: true
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.30
# Optional: working directory, useful for monorepos
# working-directory: somedir
# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0
# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

44
.golangci.yml Normal file
View File

@ -0,0 +1,44 @@
run:
concurrency: 4
deadline: 5m
issues-exit-code: 1
tests: true
linters-settings:
govet:
check-shadowing: true
enable:
- fieldalignment
linters:
enable:
- govet
- deadcode
- errcheck
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
- bodyclose
- gci
- goconst
- gocritic
- gosimple
- gofmt
- gofumpt
- goimports
- golint
- gosec
- makezero
- misspell
- nakedret
- nestif
- nilerr
- noctx
- prealloc
- unconvert
- unparam
disable-all: false

20
Makefile Normal file
View File

@ -0,0 +1,20 @@
DATE?=$(shell date -u "+%Y-%m-%d %H:%M:%S")
LDFLAGS=-s -w -X 'main.AppVersion=${app_version}' -X 'main.BuildDate=${DATE}'
LDFLAGS=-X 'main.AppVersion=${app_version}' -X 'main.BuildDate=${DATE}'
GOPATH=$(shell go env GOPATH)
.PHONY: build
build:
GOWORK=off CGO_ENABLED=0 go build -ldflags "$(LDFLAGS)" -gcflags=-trimpath=$(GOPATH) -asmflags=-trimpath=$(GOPATH) -trimpath -mod=readonly -o bin/cms-template
.PHONY: test
test:
go test -mod=readonly -race -v ./... -cover
.PHONY: generate
generate:
go generate ./...
.PHONY: docker
docker:
docker build -v $(CURDIR):/build -t cms-template .

51
config/config.go Normal file
View File

@ -0,0 +1,51 @@
package config
import (
"fmt"
"net"
"strconv"
service "go.unistack.org/cms-service"
)
type App struct {
TLSCrt string `flag:"name=account.tls_crt,desc='tls crt file'"`
TLSKey string `flag:"name=account.tls_key,desc='tls key file'"`
Address string `flag:"name=account.address,desc='listen address',default=':0'"`
}
type Config struct {
App *App
Storage *service.ConfigStorage
Logger *service.ConfigLogger
Service *service.ConfigService
Core *service.ConfigCore
}
func NewConfig() *Config {
return &Config{
Service: &service.ConfigService{
Name: ServiceName,
Version: ServiceVersion,
},
}
}
func (c *App) Validate() error {
_, port, err := net.SplitHostPort(c.Address)
if err != nil {
return fmt.Errorf("invalid address: %s, err: %w", c.Address, err)
}
if port == "443" && (c.TLSCrt == "" || c.TLSKey == "") {
return fmt.Errorf("use secured connection without tls crt/key")
}
if v, err := strconv.Atoi(port); err != nil {
return fmt.Errorf("invalid address/port: %v", c.Address)
} else if v < 0 || v > 65535 {
return fmt.Errorf("invalid address/port: %v", c.Address)
}
return nil
}

6
config/variables.go Normal file
View File

@ -0,0 +1,6 @@
package config
var (
ServiceName = "account"
ServiceVersion = "0.0.1"
)

60
go.mod Normal file
View File

@ -0,0 +1,60 @@
module go.unistack.org/cms-template
go 1.20
require (
github.com/golang-migrate/migrate/v4 v4.15.2
go.unistack.org/cms-account-proto v0.0.1
go.unistack.org/cms-service v0.0.1
go.unistack.org/micro-server-grpc/v3 v3.10.3
go.unistack.org/micro/v3 v3.10.18
)
require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/envoyproxy/protoc-gen-validate v0.9.1 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgx/v5 v5.3.1 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sijms/go-ora/v2 v2.6.7 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.unistack.org/cms-api-proto v0.0.4 // indirect
go.unistack.org/micro-broker-service/v3 v3.8.2 // indirect
go.unistack.org/micro-codec-yaml/v3 v3.10.0 // indirect
go.unistack.org/micro-config-env/v3 v3.8.5 // indirect
go.unistack.org/micro-config-file/v3 v3.8.3 // indirect
go.unistack.org/micro-config-flag/v3 v3.8.9 // indirect
go.unistack.org/micro-config-service/v3 v3.8.1 // indirect
go.unistack.org/micro-proto/v3 v3.3.1 // indirect
go.unistack.org/micro-server-http/v3 v3.10.13 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/genproto v0.0.0-20230323212658-478b75c54725 // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
lukechampine.com/uint128 v1.3.0 // indirect
modernc.org/cc/v3 v3.40.0 // indirect
modernc.org/ccgo/v3 v3.16.13 // indirect
modernc.org/libc v1.22.3 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/sqlite v1.21.0 // indirect
modernc.org/strutil v1.1.3 // indirect
modernc.org/token v1.1.0 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

2365
go.sum Normal file

File diff suppressed because it is too large Load Diff

42
handler/handler.go Normal file
View File

@ -0,0 +1,42 @@
package handler
import (
"context"
cmsstorage "go.unistack.org/cms-service/storage"
mpb "go.unistack.org/cms-template-proto"
templatepb "go.unistack.org/cms-template-proto/micro"
"go.unistack.org/cms-template/storage"
"go.unistack.org/micro/v3"
)
var _ templatepb.AccountServiceServer = (*Handler)(nil)
type Handler struct {
svc micro.Service
store storage.Storage
}
func NewHandler(svc micro.Service) *Handler {
return &Handler{svc: svc}
}
func (h *Handler) Init(ctx context.Context) error {
store := cmsstorage.InterfaceFromContext(h.svc.Options().Context)
if store == nil {
return cmsstorage.ErrMissingStorage
}
st, ok := store.(storage.Storage)
if !ok {
return cmsstorage.ErrInvalidStorage
}
h.store = st
return nil
}
func (h *Handler) Call(ctx context.Context, req *mpb.CallReq, rsp *mpb.CallRsp) error {
return nil
}

0
local.yaml Normal file
View File

24
main.go Normal file
View File

@ -0,0 +1,24 @@
//go:build !single
package main
import (
"context"
"go.unistack.org/cms-template/service"
"go.unistack.org/micro/v3/logger"
)
func main() {
ctx := context.Background()
svc, err := service.NewService(ctx)
if err != nil {
logger.Fatalf(ctx, "failed to create service: %v", err)
}
// start server
if err := svc.Run(); err != nil {
logger.Fatal(ctx, err)
}
}

11
service/embed.go Normal file
View File

@ -0,0 +1,11 @@
//go:build single
package service
import (
service "go.unistack.org/cms-service"
)
func init() {
service.RegisterService("template", NewService)
}

149
service/service.go Normal file
View File

@ -0,0 +1,149 @@
package service
import (
"context"
"fmt"
cmsservice "go.unistack.org/cms-service"
cmsstorage "go.unistack.org/cms-service/storage"
mpb "go.unistack.org/cms-template-proto/micro"
serviceConfig "go.unistack.org/cms-template/config"
"go.unistack.org/cms-template/handler"
storage "go.unistack.org/cms-template/storage"
grpcsrv "go.unistack.org/micro-server-grpc/v3"
"go.unistack.org/micro/v3"
"go.unistack.org/micro/v3/broker"
"go.unistack.org/micro/v3/config"
"go.unistack.org/micro/v3/logger"
"go.unistack.org/micro/v3/register"
"go.unistack.org/micro/v3/router"
"go.unistack.org/micro/v3/server"
)
func NewService(ctx context.Context) (micro.Service, error) {
var err error
var svc micro.Service
var reg register.Register
var brk broker.Broker
var rtr router.Router
if ctx == nil {
ctx = context.Background()
}
cfg := serviceConfig.NewConfig()
cs := cmsservice.NewConfigLocal(cfg) // service.NewConfigRemote(cfg)...)
if r, ok := register.FromContext(ctx); ok && r != nil {
reg = r
} else {
reg = register.NewRegister()
}
if b, ok := broker.FromContext(ctx); ok && b != nil {
brk = b
} else {
brk = broker.NewBroker()
}
if r, ok := router.FromContext(ctx); ok && r != nil {
rtr = r
} else {
rtr = router.NewRouter()
}
// create grpc server
mgsrv := grpcsrv.NewServer(
server.Register(reg),
)
// create service
svc = micro.NewService(
micro.Server(mgsrv),
micro.Register(reg),
micro.Broker(brk),
micro.Router(rtr),
micro.Config(cs...),
)
h := handler.NewHandler(svc)
// init service
if err := svc.Init(
micro.AfterStart(func(_ context.Context) error {
return h.Init(svc.Options().Context)
}),
micro.BeforeStart(func(ctx context.Context) error {
if err = config.Load(ctx, cs, config.LoadOverride(true)); err != nil {
return err
}
if err = config.Validate(ctx, cfg); err != nil {
return err
}
if err = svc.Init(
micro.Name(cfg.Service.Name),
micro.Version(cfg.Service.Version),
); err != nil {
return err
}
if err = svc.Server("grpc").Init(
server.Address(cfg.App.Address),
server.Name(cfg.Service.Name),
server.Version(cfg.Service.Version),
); err != nil {
return err
}
return nil
}),
micro.BeforeStart(func(_ context.Context) error {
level := logger.InfoLevel
if v, ok := cfg.Logger.Level[cfg.Service.Name]; ok {
level = logger.ParseLevel(v)
} else if v, ok := cfg.Logger.Level["all"]; ok {
level = logger.ParseLevel(v)
}
log := logger.NewLogger(
logger.WithLevel(level),
logger.WithCallerSkipCount(3),
)
return svc.Init(micro.Logger(log))
}),
micro.BeforeStart(func(_ context.Context) error {
var scheme string
var connstr string
var dsn string
if v, ok := cfg.Storage.DSN[cfg.Service.Name]; ok {
connstr = v
} else if v, ok := cfg.Storage.DSN["all"]; ok {
connstr = v
}
fmt.Printf("SSSS %s\n", connstr)
scheme, dsn, err = cmsstorage.StorageOptions(connstr)
if err != nil {
return err
}
db, dbok := cmsstorage.FromContext(svc.Options().Context)
if !dbok {
var err error
db, err = cmsstorage.NewStorage(scheme, dsn)
if err != nil {
return err
}
}
store, err := storage.NewStorage(scheme, db)
if err != nil {
return err
}
return svc.Init(micro.Context(cmsstorage.InterfaceNewContext(svc.Options().Context, store)))
}),
); err != nil {
return nil, err
}
if err = mpb.RegisterAccountServiceServer(mgsrv, h); err != nil {
logger.Fatalf(ctx, "failed to register handler: %v", err)
}
return svc, nil
}

View File

View File

3
storage/models.go Normal file
View File

@ -0,0 +1,3 @@
package storage
// TODO: create models

View File

@ -0,0 +1,75 @@
// go:build postgres
package postgres
import (
"database/sql"
"embed"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/golang-migrate/migrate/v4/source/iofs"
)
type PostgresStorage struct {
db *sql.DB
fs embed.FS
}
func NewStoragePostgres(fs embed.FS) func(*sql.DB) (interface{}, error) {
return func(db *sql.DB) (interface{}, error) {
return &PostgresStorage{db: db, fs: fs}, nil
}
}
func (s *PostgresStorage) MigrateUp() error {
driver, err := postgres.WithInstance(s.db, &postgres.Config{
MigrationsTable: postgres.DefaultMigrationsTable,
DatabaseName: "template",
})
if err != nil {
return err
}
source, err := iofs.New(s.fs, "migrations/postgres")
if err != nil {
return err
}
// TODO: pass own logger
m, err := migrate.NewWithInstance("fs", source, "template", driver)
if err != nil {
return err
}
if err = m.Up(); err != nil && err != migrate.ErrNoChange {
return err
}
return nil
}
func (s *PostgresStorage) MigrateDown() error {
driver, err := postgres.WithInstance(s.db, &postgres.Config{
MigrationsTable: postgres.DefaultMigrationsTable,
DatabaseName: "template",
})
if err != nil {
return err
}
source, err := iofs.New(s.fs, "migrations/postgres")
if err != nil {
return err
}
// TODO: pass own logger
m, err := migrate.NewWithInstance("fs", source, "template", driver)
if err != nil {
return err
}
if err = m.Down(); err != nil && err != migrate.ErrNoChange {
return err
}
return nil
}

View File

@ -0,0 +1,5 @@
package postgres
const (
// TODO: fill queries
)

5
storage/sqlite/query.go Normal file
View File

@ -0,0 +1,5 @@
package sqlite
const (
// TODO: fill queries
)

75
storage/sqlite/sqlite.go Normal file
View File

@ -0,0 +1,75 @@
// go:build sqlite
package sqlite
import (
"database/sql"
"embed"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/sqlite"
"github.com/golang-migrate/migrate/v4/source/iofs"
)
type SqliteStorage struct {
db *sql.DB
fs embed.FS
}
func NewStorageSqlite(fs embed.FS) func(*sql.DB) (interface{}, error) {
return func(db *sql.DB) (interface{}, error) {
return &SqliteStorage{db: db, fs: fs}, nil
}
}
func (s *SqliteStorage) MigrateUp() error {
driver, err := sqlite.WithInstance(s.db, &sqlite.Config{
MigrationsTable: sqlite.DefaultMigrationsTable,
DatabaseName: "template",
})
if err != nil {
return err
}
source, err := iofs.New(s.fs, "migrations/sqlite")
if err != nil {
return err
}
// TODO: pass own logger
m, err := migrate.NewWithInstance("fs", source, "template", driver)
if err != nil {
return err
}
if err = m.Up(); err != nil && err != migrate.ErrNoChange {
return err
}
return nil
}
func (s *SqliteStorage) MigrateDown() error {
driver, err := sqlite.WithInstance(s.db, &sqlite.Config{
MigrationsTable: sqlite.DefaultMigrationsTable,
DatabaseName: "template",
})
if err != nil {
return err
}
source, err := iofs.New(s.fs, "migrations/sqlite")
if err != nil {
return err
}
// TODO: pass own logger
m, err := migrate.NewWithInstance("fs", source, "template", driver)
if err != nil {
return err
}
if err = m.Down(); err != nil && err != migrate.ErrNoChange {
return err
}
return nil
}

29
storage/storage.go Normal file
View File

@ -0,0 +1,29 @@
package storage
import (
"context"
"database/sql"
"embed"
store "go.unistack.org/cms-service/storage"
"go.unistack.org/cms-template/storage/sqlite"
)
//go:embed all:migrations
var fs embed.FS
var storages = store.NewStorageInterface()
func init() {
storages.RegisterStorage("sqlite", sqlite.NewStorageSqlite(fs))
}
type Storage interface {
Auth(ctx context.Context, login, passw string) error
Delete(ctx context.Context, uuid string) error
store.Migrator
}
func NewStorage(name string, db *sql.DB) (interface{}, error) {
return storages.NewStorage(name, db)
}