diff --git a/Dockerfile b/Dockerfile index 90de416..95e5088 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,8 +7,9 @@ WORKDIR /pkg RUN go get -d ./... RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o exec -FROM scratch -COPY --from=builder /pkg/exec /main -COPY --from=builder /pkg/api.json /api.json +FROM redis:alpine +COPY --from=builder /pkg/exec /usr/local/bin/docker-exec +COPY --from=builder /pkg/api.json /usr/local/bin/api.json +RUN printf "docker-exec&" >> /usr/local/bin/docker-entrypoint.sh EXPOSE 4242/tcp -ENTRYPOINT ["/main"] \ No newline at end of file +# CMD ["/main"] \ No newline at end of file diff --git a/go.mod b/go.mod index 3e7a231..5f33e27 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,5 @@ go 1.12 require ( git.xdrm.io/go/aicra v0.2.0 - github.com/go-redis/redis v6.15.2+incompatible - github.com/onsi/ginkgo v1.8.0 // indirect - github.com/onsi/gomega v1.5.0 // indirect + github.com/lib/pq v1.1.0 ) diff --git a/go.sum b/go.sum index 947c255..a76a3d9 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/lib/pq v1.1.0 h1:/5u4a+KGJptBRqGzPvYQL9p0d/tPR4S31+Tnzj9lEO4= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= diff --git a/main.go b/main.go index f1c89f6..0282289 100644 --- a/main.go +++ b/main.go @@ -30,15 +30,15 @@ func main() { // 3. storage connect log.Printf("[storage] connecting") - storageClient, err := storage.New() + db, err := storage.New() if err != nil { log.Fatalf("/!\\ cannot connect %v", err) } - defer storageClient.Close() + defer db.Close() // 4. init services - authService := auth.New(storageClient) - shortenerService := shortener.New(storageClient, authService) + authService := auth.New(db) + shortenerService := shortener.New(db, authService) // 5. wire services shortenerService.Wire(server) diff --git a/service/auth/auth.go b/service/auth/auth.go index 7e1a22a..bb36e61 100644 --- a/service/auth/auth.go +++ b/service/auth/auth.go @@ -2,6 +2,7 @@ package auth import ( "crypto/sha512" + "database/sql" "encoding/hex" "log" "strconv" @@ -15,11 +16,11 @@ import ( // Service manages the url shortener type Service struct { - storage *storage.Client + storage *sql.DB } // New returns a bare service -func New(storage *storage.Client) *Service { +func New(storage *sql.DB) *Service { log.Printf("[service.auth] created") return &Service{ storage: storage, diff --git a/service/shortener/model.go b/service/shortener/model.go new file mode 100644 index 0000000..3d27e4a --- /dev/null +++ b/service/shortener/model.go @@ -0,0 +1,31 @@ +package shortener + +import ( + "database/sql" + "context" + "git.xdrm.io/example/aicra/storage" +) + +// tinyModel represents an actual tiny url entry in the database. +type tinyModel BadExpr + +BadDecl + +type repository struct { + db *sql.DB +} + +// newRepo returns an initialized repository. +func newRepo(db *sql.DB) (*model, error) { + log.Printf("[service.shortener] creating repository") + + res, err := db.Exec(ctx, `CREATE TABLE if not exist tiny( + tiny varchar(30) PRIMARY, + target varchar(300) NOT NULL, + )`) + if err != nil { + return nil, err + } + + return &repository{ctx, db} +} diff --git a/service/shortener/shortener.go b/service/shortener/shortener.go index 8b598f0..f15bc0f 100644 --- a/service/shortener/shortener.go +++ b/service/shortener/shortener.go @@ -1,6 +1,7 @@ package shortener import ( + "database/sql" "log" "net/http" @@ -12,17 +13,29 @@ import ( // Service manages the url shortener type Service struct { - storage *storage.Client + storage *sql.DB authService *auth.Service + repo *repository } // New returns a bare service -func New(storage *storage.Client, auth *auth.Service) *Service { - log.Printf("[service.shortener] created") - return &Service{ +func New(storage *sql.DB, auth *auth.Service) *Service { + log.Printf("[service.shortener] creating") + + service := &Service{ storage: storage, authService: auth, } + + // init repo + repo, err := newRepo(db) + if err != nil { + log.Printf("[service.shortener] cannot create repo") + return service + } + + log.Printf("[service.shortener] creating") + return service } // Wire to the aicra server diff --git a/storage/postgres.go b/storage/postgres.go new file mode 100644 index 0000000..81e0203 --- /dev/null +++ b/storage/postgres.go @@ -0,0 +1,34 @@ +package storage + +import ( + "database/sql" + "fmt" +) + +const ( + host = "localhost" + port = 5432 + user = "postgres" + password = "@#postgres-passWoRD#@" + dbname = "aicratest" +) + +var psqlInfo = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname) + +// New returns new postgres connection. +func New() (*sql.DB, error) { + + conn, err := sql.Open("postgres", psqlInfo) + if err != nil { + return nil, err + } + defer conn.Close() + + // actually connect + err = conn.Ping() + if err != nil { + return nil, err + } + + return conn, nil +} diff --git a/storage/redis.go b/storage/redis.go deleted file mode 100644 index f255bbf..0000000 --- a/storage/redis.go +++ /dev/null @@ -1,76 +0,0 @@ -package storage - -import ( - "fmt" - "time" - - "github.com/go-redis/redis" -) - -const nonce = "go-tiny-url" - -const ( - // DATA domain used to store actual data - DATA string = "data" - // TOKEN domain used to store tokens - TOKEN string = "token" -) - -// Client is a wrapper around the redis client -type Client struct { - client *redis.Client -} - -// New returns new client -func New() (*Client, error) { - client := redis.NewClient(&redis.Options{ - Addr: "127.0.0.1:6379", - Password: "", - DB: 0, - }) - - if _, err := client.Ping().Result(); err != nil { - return nil, err - } - - return &Client{ - client: client, - }, nil -} - -// Close closes the connection -func (c *Client) Close() error { - return c.client.Close() -} - -// Get returns a value from key or NIL -func (c *Client) Get(dom, key string) []byte { - - redisKey := fmt.Sprintf("%s:%s:%s", nonce, dom, key) - - val, err := c.client.Get(redisKey).Result() - if err != nil { - return nil - } - - return []byte(val) -} - -// Set stores a value for a key (success state in return) -func (c *Client) Set(dom, key string, value string, exp ...time.Duration) bool { - redisKey := fmt.Sprintf("%s:%s:%s", nonce, dom, key) - - var expiration time.Duration - if len(exp) > 0 { - expiration = exp[0] - } - - return c.client.Set(redisKey, value, expiration).Err() == nil -} - -// Del deletes the value for a key (success state in return) -func (c *Client) Del(dom, key string) bool { - redisKey := fmt.Sprintf("%s:%s:%s", nonce, dom, key) - - return c.client.Del(redisKey).Err() == nil -}