Skip to content
Merged

Hw #1

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ lint:
.PHONY: test
test:
echo 'Running tests...'

export POSTGRES_DB=godb && \
export POSTGRES_USER=nikongo && \
export POSTGRES_PASSWORD=go && \
export POSTGRES_PORT=5432 && \
export POSTGRES_HOST=localhost && \
export GRPC_PORT=8080 && \
export GRPC_GATEWAY_PORT=8081 && \
export POSTGRES_MAX_CONN=10 && \
${GO_TEST} ${GO_TEST_ARGS}

.PHONY: update
Expand Down Expand Up @@ -88,7 +97,8 @@ bin-deps: .bin-deps
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1 && \
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2.0 && \
go install golang.org/x/tools/cmd/goimports@v0.19.0 && \
go install github.com/envoyproxy/protoc-gen-validate@v1.2.1
go install github.com/envoyproxy/protoc-gen-validate@v1.2.1 && \
go install go.uber.org/mock/mockgen@latest

.create-bin:
rm -rf ./bin
Expand All @@ -106,11 +116,15 @@ fast-generate: .generate
rm -rf ./docs/spec
mkdir -p ./docs/spec

rm -rf ./mocks-generated
mkdir ./mocks-generated

rm -rf ~/.easyp/

(PATH="$(PATH):$(LOCAL_BIN)" && $(EASYP_BIN) mod download && $(EASYP_BIN) generate)

$(GOIMPORTS_BIN) -w .
go generate ./...

build:
go mod tidy
Expand Down
170 changes: 170 additions & 0 deletions api/library/library.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
syntax = "proto3";

import "google/api/annotations.proto";
import "validate/validate.proto";
import "google/protobuf/timestamp.proto";

package library;

option go_package = "github.com/project/library/pkg/api/library;library";

service Library {
rpc AddBook(AddBookRequest) returns (AddBookResponse) {
option (google.api.http) = {
post: "/v1/library/book"
body: "*"
};
}

rpc UpdateBook(UpdateBookRequest) returns (UpdateBookResponse) {
option (google.api.http) = {
put: "/v1/library/book"
body: "*"
};
}

rpc GetBookInfo(GetBookInfoRequest) returns (GetBookInfoResponse) {
option (google.api.http) = {
get: "/v1/library/book/{id}"
};
}

rpc RegisterAuthor(RegisterAuthorRequest) returns (RegisterAuthorResponse) {
option (google.api.http) = {
post: "/v1/library/author"
body: "*"
};
}

rpc ChangeAuthorInfo(ChangeAuthorInfoRequest) returns (ChangeAuthorInfoResponse) {
option (google.api.http) = {
put: "/v1/library/author"
body: "*"
};
}

rpc GetAuthorInfo(GetAuthorInfoRequest) returns (GetAuthorInfoResponse) {
option (google.api.http) = {
get: "/v1/library/author/{id}"
};
}

rpc GetAuthorBooks(GetAuthorBooksRequest) returns (stream Book) {
option (google.api.http) = {
get: "/v1/library/author_books/{author_id}"
};
}
}

message Book {
string id = 1 [
(validate.rules).string.uuid = true
];

string name = 2;

repeated string author_id = 3 [
(validate.rules).repeated = {
min_items: 0,
items: {
string: {uuid: true}
}
}
];

google.protobuf.Timestamp created_at = 4;
google.protobuf.Timestamp updated_at = 5;
}

message AddBookRequest {
string name = 1;

repeated string author_ids = 2 [
(validate.rules).repeated = {
min_items: 0,
items: {
string: {uuid: true}
}
}
];
}

message AddBookResponse {
Book book = 1;
}

message UpdateBookRequest {
string id = 1 [
(validate.rules).string.uuid = true
];

string name = 2;

repeated string author_ids = 3 [
(validate.rules).repeated = {
min_items: 0,
items: {
string: {uuid: true}
}
}
];
}

message UpdateBookResponse {}

message GetBookInfoRequest {
string id = 1 [
(validate.rules).string.uuid = true
];
}

message GetBookInfoResponse {
Book book = 1;
}

message RegisterAuthorRequest {
string name = 1 [
(validate.rules).string = {
pattern: "^[A-Za-z0-9]+( [A-Za-z0-9]+)*$",
min_len: 1,
max_len: 512
}
];
}

message RegisterAuthorResponse {
string id = 1;
}

message ChangeAuthorInfoRequest {
string id = 1 [
(validate.rules).string.uuid = true
];
string name = 2 [
(validate.rules).string = {
pattern: "^[A-Za-z0-9]+( [A-Za-z0-9]+)*$",
min_len: 1,
max_len: 512
}
];
}

message ChangeAuthorInfoResponse {}


message GetAuthorInfoRequest {
string id = 1 [
(validate.rules).string.uuid = true
];
}

message GetAuthorInfoResponse {
string id = 1;
string name = 2;
}

message GetAuthorBooksRequest {
string author_id = 1 [
(validate.rules).string.uuid = true
];
}
2 changes: 1 addition & 1 deletion cmd/library/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

func main() {
cfg, err := config.NewConfig()
cfg, err := config.New()

if err != nil {
log.Fatalf("can not get application config: %s", err)
Expand Down
136 changes: 135 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,152 @@
package config

import (
"errors"
"fmt"
"net"
"net/url"
"os"
)

type (
Config struct {
GRPC
PG
}

GRPC struct {
Port string `env:"GRPC_PORT"`
GatewayPort string `env:"GRPC_GATEWAY_PORT"`
}

PG struct {
URL string
Host string `env:"POSTGRES_HOST"`
Port string `env:"POSTGRES_PORT"`
DB string `env:"POSTGRES_DB"`
User string `env:"POSTGRES_USER"`
Password string `env:"POSTGRES_PASSWORD"`
MaxConn string `env:"POSTGRES_MAX_CONN"`
}
)

var (
ErrGRPCPortNotSet = errors.New("GRPC_PORT environment variable not set")
ErrGRPCGatewayPortNotSet = errors.New("GRPC_GATEWAY_PORT environment variable not set")
ErrPostgresHostNotSet = errors.New("POSTGRES_HOST environment variable not set")
ErrPostgresPortNotSet = errors.New("POSTGRES_PORT environment variable not set")
ErrPostgresDBNotSet = errors.New("POSTGRES_DB environment variable not set")
ErrPostgresUserNotSet = errors.New("POSTGRES_USER environment variable not set")
ErrPostgresPasswordNotSet = errors.New("POSTGRES_PASSWORD environment variable not set")
ErrPostgresMaxConnNotSet = errors.New("POSTGRES_MAX_CONN environment variable not set")
)

func NewConfig() (*Config, error) {
func New() (*Config, error) {
cfg := &Config{}

if err := cfg.readGrpcPort(); err != nil {
return nil, err
}
if err := cfg.readGrpcGatewayPort(); err != nil {
return nil, err
}
if err := cfg.readPGHost(); err != nil {
return nil, err
}
if err := cfg.readPGUser(); err != nil {
return nil, err
}
if err := cfg.readPGPort(); err != nil {
return nil, err
}
if err := cfg.readPGPassword(); err != nil {
return nil, err
}
if err := cfg.readPGDB(); err != nil {
return nil, err
}
if err := cfg.readPGMaxConn(); err != nil {
return nil, err
}

cfg.PG.URL = fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable",
url.PathEscape(cfg.PG.User),
url.PathEscape(cfg.PG.Password),
net.JoinHostPort(cfg.PG.Host, cfg.PG.Port),
cfg.PG.DB,
)

return cfg, nil
}

func (config *Config) readGrpcPort() error {
var ok bool
config.GRPC.Port, ok = os.LookupEnv("GRPC_PORT")
if !ok || config.GRPC.Port == "" {
return ErrGRPCPortNotSet
}
return nil
}

func (config *Config) readGrpcGatewayPort() error {
var ok bool
config.GRPC.GatewayPort, ok = os.LookupEnv("GRPC_GATEWAY_PORT")
if !ok || config.GRPC.GatewayPort == "" {
return ErrGRPCGatewayPortNotSet
}
return nil
}

func (config *Config) readPGHost() error {
var ok bool
config.PG.Host, ok = os.LookupEnv("POSTGRES_HOST")
if !ok || config.PG.Host == "" {
return ErrPostgresHostNotSet
}
return nil
}

func (config *Config) readPGPort() error {
var ok bool
config.PG.Port, ok = os.LookupEnv("POSTGRES_PORT")
if !ok || config.PG.Port == "" {
return ErrPostgresPortNotSet
}
return nil
}

func (config *Config) readPGUser() error {
var ok bool
config.PG.User, ok = os.LookupEnv("POSTGRES_USER")
if !ok || config.PG.User == "" {
return ErrPostgresUserNotSet
}
return nil
}

func (config *Config) readPGDB() error {
var ok bool
config.PG.DB, ok = os.LookupEnv("POSTGRES_DB")
if !ok || config.PG.DB == "" {
return ErrPostgresDBNotSet
}
return nil
}

func (config *Config) readPGPassword() error {
var ok bool
config.PG.Password, ok = os.LookupEnv("POSTGRES_PASSWORD")
if !ok || config.PG.Password == "" {
return ErrPostgresPasswordNotSet
}
return nil
}

func (config *Config) readPGMaxConn() error {
var ok bool
config.PG.MaxConn, ok = os.LookupEnv("POSTGRES_MAX_CONN")
if !ok || config.PG.MaxConn == "" {
return ErrPostgresMaxConnNotSet
}
return nil
}
Loading
Loading