Skip to content

Commit

Permalink
Merge pull request #10 from aerogear/db-implementation
Browse files Browse the repository at this point in the history
Database Integration
  • Loading branch information
david-martin committed Feb 23, 2018
2 parents f8c2d66 + 0565639 commit bc1ee5d
Show file tree
Hide file tree
Showing 23 changed files with 878 additions and 104 deletions.
12 changes: 10 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ jobs:
docker:
# specify the version
- image: circleci/golang:1.9

- image: postgres:9.5
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
POSTGRES_DB: aerogear_mobile_metrics

# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
Expand All @@ -23,5 +31,5 @@ jobs:
- run: go get github.com/mattn/goveralls
- run: go get -u github.com/golang/dep/cmd/dep
- run: dep ensure
- run: go test -v -coverpkg=./... ./...
- run: /go/bin/goveralls -service=circle-ci -repotoken=$COVERALLS_TOKEN
- run: make test-integration-cover
- run: /go/bin/goveralls -coverprofile=coverage-all.out -service=circle-ci -repotoken=$COVERALLS_TOKEN
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
vendor/
.idea/
metrics
dist/
dist/
coverage*.out
38 changes: 37 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 8 additions & 27 deletions Gopkg.toml
Original file line number Diff line number Diff line change
@@ -1,30 +1,3 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true


[[constraint]]
name = "github.com/darahayes/go-boom"
version = "1.0.1"
Expand All @@ -36,3 +9,11 @@
[prune]
go-tests = true
unused-packages = true

[[constraint]]
branch = "master"
name = "github.com/lib/pq"

[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.1"
29 changes: 22 additions & 7 deletions cmd/metrics-api/metrics-api.go
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
package main

import (
"log"
"net/http"

"github.com/aerogear/aerogear-metrics-api/pkg/config"
"github.com/aerogear/aerogear-metrics-api/pkg/dao"
"github.com/aerogear/aerogear-metrics-api/pkg/mobile"
"github.com/aerogear/aerogear-metrics-api/pkg/web"
)

func main() {
router := web.NewRouter()
db, err := dao.Connect()

config := config.GetConfig()

dbHandler := dao.DatabaseHandler{}

err := dbHandler.Connect(config["DBHost"], config["DBUser"], config["DBPassword"], config["DBName"], config["SSLMode"])

if err != nil {
panic("failed to connect to sql database : " + err.Error())
}
defer db.Close()
metricDao := dao.NewMetricsDAO(db)
defer dbHandler.DB.Close()

if err := dbHandler.DoInitialSetup(); err != nil {
panic("failed to perform database setup : " + err.Error())
}

metricsDao := dao.NewMetricsDAO(dbHandler.DB)
router := web.NewRouter()

//metrics route
{
metricsService := mobile.NewMetricsService(metricDao)
metricsService := mobile.NewMetricsService(metricsDao)
metricsHandler := web.NewMetricsHandler(metricsService)
web.MetricsRoute(router, metricsHandler)
}
//health route
{
healthHandler := web.NewHealthHandler()
healthHandler := web.NewHealthHandler(metricsDao)
web.HealthzRoute(router, healthHandler)
}

log.Printf("Starting application... going to listen on %v", config["ListenAddress"])

//start
if err := http.ListenAndServe(":3000", router); err != nil {
if err := http.ListenAndServe(config["ListenAddress"], router); err != nil {
panic("failed to start " + err.Error())
}
}
6 changes: 2 additions & 4 deletions deployments/docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
postgres:
image: timescale/timescaledb
image: postgres:9.5
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: postgres
POSTGRES_USER: postgres
PGDATA : /var/lib/postgresql/data/pgdata
volumes:
- psqlvolumes:/var/lib/postgresql/data/pgdata
POSTGRES_DB: aerogear_mobile_metrics
17 changes: 15 additions & 2 deletions makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PKG = github.com/aerogear/aerogear-metrics-api
TOP_SRC_DIRS = pkg
TEST_DIRS ?= $(shell sh -c "find $(TOP_SRC_DIRS) -name \\*_test.go \
PACKAGES ?= $(shell sh -c "find $(TOP_SRC_DIRS) -name \\*_test.go \
-exec dirname {} \\; | sort | uniq")
BIN_DIR := $(GOPATH)/bin
SHELL = /bin/bash
Expand All @@ -27,7 +27,20 @@ build_binary:
test-unit:
@echo Running tests:
go test -v -race -cover $(UNIT_TEST_FLAGS) \
$(addprefix $(PKG)/,$(TEST_DIRS))
$(addprefix $(PKG)/,$(PACKAGES))

.PHONY: test-integration
test-integration:
@echo Running tests:
go test -v -race -cover $(UNIT_TEST_FLAGS) -tags=integration \
$(addprefix $(PKG)/,$(PACKAGES))

.PHONY: test-integration-cover
test-integration-cover:
echo "mode: count" > coverage-all.out
$(foreach pkg,$(PACKAGES),\
go test -tags=integration -coverprofile=coverage.out -covermode=count $(addprefix $(PKG)/,$(pkg));\
tail -n +2 coverage.out >> coverage-all.out;)

.PHONY: errcheck
errcheck:
Expand Down
25 changes: 25 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package config

import (
"fmt"
"os"
)

// Simple helper function to read an environment or return a default value
func getEnv(key string, defaultVal string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultVal
}

func GetConfig() map[string]string {
return map[string]string{
"DBHost": getEnv("PGHOST", "localhost"),
"DBUser": getEnv("PGUSER", "postgres"),
"DBPassword": getEnv("PGPASSWORD", "postgres"),
"DBName": getEnv("PGDATABASE", "aerogear_mobile_metrics"),
"SSLMode": getEnv("PGSSLMODE", "disable"),
"ListenAddress": fmt.Sprintf(":%s", getEnv("PORT", "3000")),
}
}
72 changes: 72 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package config

import (
"os"
"reflect"
"testing"
)

func TestGetConfig(t *testing.T) {
expected := map[string]string{
"DBHost": "localhost",
"DBUser": "postgres",
"DBPassword": "postgres",
"DBName": "aerogear_mobile_metrics",
"SSLMode": "disable",
"ListenAddress": ":3000",
}

config := GetConfig()

if !reflect.DeepEqual(config, expected) {
t.Error("GetConfig() did not return expected result")
}
}

func TestGetConfigCustomEnvVariables(t *testing.T) {
expected := map[string]string{
"DBHost": "testing",
"DBUser": "testing",
"DBPassword": "testing",
"DBName": "testing",
"SSLMode": "testing",
"ListenAddress": ":testing",
}

os.Setenv("PGHOST", "testing")
os.Setenv("PGUSER", "testing")
os.Setenv("PGPASSWORD", "testing")
os.Setenv("PGDATABASE", "testing")
os.Setenv("PGSSLMODE", "testing")
os.Setenv("PORT", "testing")

config := GetConfig()

if !reflect.DeepEqual(config, expected) {
t.Error("GetConfig() did not return expected result")
}
}

func TestGetConfigEmptyEnvVariables(t *testing.T) {
expected := map[string]string{
"DBHost": "localhost",
"DBUser": "postgres",
"DBPassword": "postgres",
"DBName": "aerogear_mobile_metrics",
"SSLMode": "disable",
"ListenAddress": ":3000",
}

os.Setenv("PGHOST", "")
os.Setenv("PGUSER", "")
os.Setenv("PGPASSWORD", "")
os.Setenv("PGDATABASE", "")
os.Setenv("PGSSLMODE", "")
os.Setenv("PORT", "")

config := GetConfig()

if !reflect.DeepEqual(config, expected) {
t.Error("GetConfig() did not return expected result")
}
}
27 changes: 7 additions & 20 deletions pkg/dao/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,23 @@ package dao

import (
"database/sql"
"errors"

"github.com/aerogear/aerogear-metrics-api/pkg/mobile"
)

type MetricsDAO struct {
db *sql.DB
}

// Create a metrics record
func (m *MetricsDAO) Create(metric mobile.Metric) (mobile.Metric, error) {
return metric, errors.New("Not Implemented yet")
}

// Update an existing job
// Not sure if we need this
func (m *MetricsDAO) Update() {

func (m *MetricsDAO) Create(clientId string, metricsData []byte) error {
_, err := m.db.Exec("INSERT INTO mobileappmetrics(clientId, data) VALUES($1, $2)", clientId, metricsData)
return err
}

// Delete an existing job
// Not sure if we need this
func (m *MetricsDAO) Delete() {

}

// CheckConnection checks that we are connected to the database
// IsHealthy checks that we are connected to the database
// This will be used by the healthcheck
func (m *MetricsDAO) CheckConnection() {

func (m *MetricsDAO) IsHealthy() (bool, error) {
err := m.db.Ping()
return err == nil, err
}

func NewMetricsDAO(db *sql.DB) *MetricsDAO {
Expand Down
Loading

0 comments on commit bc1ee5d

Please sign in to comment.