fix(pkg/daemon): save measured values into postgres database if defined

This commit is contained in:
volker.raschek committed 2019-12-08 12:49:19 +01:00
1 parent 6223f4e79b
commit 04bc3baffe
60 files changed
+670 -368

No files matched your search

+2 -2
View File
@@ -7,11 +7,11 @@ jobs:
include:
- stage: build
name: go-build
script: make container/all
script: make container-run/all
deploy:
- provider: script
script: make container/release
script: make container-run/release/all
# skip_cleanup: true
on:
tags: true
+3
View File
@@ -0,0 +1,3 @@
FROM busybox:latest
COPY bin/linux/amd64/flucky /usr/bin/flucky
ENTRYPOINT [ "/usr/bin/flucky" ]
+215 -89
View File
@@ -5,90 +5,185 @@
UID?=$(shell id --user)
GID?=$(shell id --group)
# VERSION
IMAGE_VERSION:=$(or ${VERSION}, latest)
# VERSION/RELEASE
# If no version is specified as a parameter of make, the last git hash
# value is taken.
VERSION:=$(or ${TRAVIS_TAG}, $(shell git rev-parse --short HEAD)-git)
VERSION?=$(shell git describe --abbrev=0)+hash.$(shell git rev-parse --short HEAD)
RELEASE?=1
# CONTAINER_RUNTIME
CONTAINER_RUNTIME?=$(shell which docker)
# BUILD_IMAGE
BUILD_IMAGE:=volkerraschek/build-image:latest
# GH_USER/GITHUB_TOKEN
# It's the user name from github.com and his token. This token and the username
# can be set over encrypted environment variables in the ci/cd pipeline
GITHUB_USER=volker-raschek
GITHUB_TOKEN?=""
# BUILD_IMAGE
BUILD_IMAGE:=volkerraschek/build-image:latest
# EXECUTABLE
# Executable binary which should be compiled for different architecures
EXECUTABLE:=flucky
# UNIX_EXECUTABLES
# DARWIN_EXECUTABLES AND TARGETS
DARWIN_EXECUTABLES:=\
darwin/386/${EXECUTABLE} \
darwin/amd64/${EXECUTABLE}
DARWIN_EXECUTABLE_TARGETS:=${DARWIN_EXECUTABLES:%=bin/%}
# FREEBSD_EXECUTABLES AND TARGETS
FREEBSD_EXECUTABLES:= \
freebsd/amd64/${EXECUTABLE}
FREEBSD_EXECUTABLE_TARGETS:=${FREEBSD_EXECUTABLES:%=bin/%}
# LINUX_EXECUTABLES AND TARGETS
LINUX_EXECUTABLES:= \
linux/amd64/${EXECUTABLE} \
linux/386/${EXECUTABLE} \
linux/arm/5/${EXECUTABLE} \
linux/arm/7/${EXECUTABLE}
LINUX_EXECUTABLE_TARGETS:=${LINUX_EXECUTABLES:%=bin/%}
# UNIX_EXECUTABLES AND TARGETS
# Define all executables for different architectures and operation systems
UNIX_EXECUTABLES:= \
darwin/386/$(EXECUTABLE) \
darwin/amd64/$(EXECUTABLE) \
freebsd/amd64/$(EXECUTABLE) \
linux/386/$(EXECUTABLE) \
linux/amd64/$(EXECUTABLE) \
linux/arm/5/$(EXECUTABLE) \
linux/arm/7/$(EXECUTABLE) \
${DARWIN_EXECUTABLES} \
${FREEBSD_EXECUTABLES} \
${LINUX_EXECUTABLES}
UNIX_EXECUTABLE_TARGETS:= \
${DARWIN_EXECUTABLE_TARGETS} \
${FREEBSD_EXECUTABLE_TARGETS} \
${LINUX_EXECUTABLE_TARGETS}
# EXECUTABLE_TARGETS
# Include the relative paths to all executables
EXECUTABLE_TARGETS=$(UNIX_EXECUTABLES:%=bin/%)
# Include all UNIX and Windows targets.
EXECUTABLE_TARGETS:= \
${UNIX_EXECUTABLE_TARGETS}
# COMPRSSED_EXECUTABLES
# Append to all defined executables the compression extentions to detect the
# different make steps which compress the binary
COMPRESSED_EXECUTABLES=$(UNIX_EXECUTABLES:%=%.tar.bz2) $(UNIX_EXECUTABLES:%=%.tar.gz) $(UNIX_EXECUTABLES:%=%.tar.xz)
COMPRESSED_EXECUTABLE_TARGETS=$(COMPRESSED_EXECUTABLES:%=bin/%)
COMPRESSED_EXECUTABLES:= \
${UNIX_EXECUTABLES:%=%.tar.bz2} \
${UNIX_EXECUTABLES:%=%.tar.gz} \
${UNIX_EXECUTABLES:%=%.tar.xz} \
${UNIX_EXECUTABLES:%=%.zip}
COMPRESSED_EXECUTABLE_TARGETS:=${COMPRESSED_EXECUTABLES:%=bin/%}
# PHONY
# To avoid a conflict with an existing file and a defined make step
.PHONY: clean container/${EXECUTABLE_TARGETS} container/test release remote test
# RPM_TARGETS
RPM_EXECUTABLES:=${LINUX_EXECUTABLES:%=%.rpm}
RPM_EXECUTABLE_TARGETS:=${RPM_EXECUTABLES:%=bin/%}
$(EXECUTABLE): bindata
go build -ldflags "-X main.version=${VERSION}" -o "$@"
# RELEASE_TARGETS
RELEASE_EXECUTABLES:= \
${COMPRESSED_EXECUTABLE_TARGETS} \
${RPM_EXECUTABLE_TARGETS}
RELEASE_EXECUTABLE_TARGETS:= \
${COMPRESSED_EXECUTABLE_TARGETS:%=release/%} \
${RPM_EXECUTABLE_TARGETS:%=release/%}
# BINARIES
# ==============================================================================
# current os
${EXECUTABLE}: bindata
CGO_ENABLED=0 go build -ldflags "-X main.version=${VERSION}" -o "$@"
# build all binaries
PHONY:=all
all: ${EXECUTABLE_TARGETS}
container/bin/tmp/${EXECUTABLE}:
$(MAKE) container-run COMMAND=$(subst container/,,$@)
# darwin os
bin/darwin/386/${EXECUTABLE}: bindata
CGO_ENABLED=0 GOARCH=386 GOOS=darwin go build -ldflags "-X main.version=${VERSION}" -o "$@"
# 386
bin/darwin/386/$(EXECUTABLE): bindata
GOARCH=386 GOOS=darwin go build -ldflags "-X main.version=${VERSION}" -o "$@"
bin/darwin/amd64/${EXECUTABLE}: bindata
CGO_ENABLED=0 GOARCH=amd64 GOOS=darwin go build -ldflags "-X main.version=${VERSION}" -o "$@"
bin/linux/386/$(EXECUTABLE): bindata
GOARCH=386 GOOS=linux go build -ldflags "-X main.version=${VERSION}" -o "$@"
# freebsd os
bin/freebsd/amd64/${EXECUTABLE}: bindata
CGO_ENABLED=0 GOARCH=amd64 GOOS=freebsd go build -ldflags "-X main.version=${VERSION}" -o "$@"
# amd64
bin/freebsd/amd64/$(EXECUTABLE): bindata
GOARCH=amd64 GOOS=freebsd go build -ldflags "-X main.version=${VERSION}" -o "$@"
# linux os
bin/linux/386/${EXECUTABLE}: bindata
CGO_ENABLED=0 GOARCH=386 GOOS=linux go build -ldflags "-X main.version=${VERSION}" -o "$@"
bin/darwin/amd64/$(EXECUTABLE): bindata
GOARCH=amd64 GOOS=darwin go build -ldflags "-X main.version=${VERSION}" -o "$@"
bin/linux/amd64/${EXECUTABLE}: bindata
CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -ldflags "-X main.version=${VERSION}" -o "$@"
bin/linux/amd64/$(EXECUTABLE): bindata
GOARCH=amd64 GOOS=linux go build -ldflags "-X main.version=${VERSION}" -o "$@"
# arm
bin/linux/arm/5/${EXECUTABLE}: bindata
GOARM=5 GOARCH=arm go build -ldflags "-X main.version=${VERSION}" -o "$@"
CGO_ENABLED=0 GOARM=5 GOARCH=arm GOOS=linux go build -ldflags "-X main.version=${VERSION}" -o "$@"
bin/linux/arm/7/${EXECUTABLE}: bindata
GOARM=7 GOARCH=arm go build -ldflags "-X main.version=${VERSION}" -o "$@"
CGO_ENABLED=0 GOARM=7 GOARCH=arm GOOS=linux go build -ldflags "-X main.version=${VERSION}" -o "$@"
# GO-BINDATA
# ==============================================================================
bindata:
go-bindata -pkg db -o ./pkg/db/bindataSQL.go ./pkg/db/sql/***
go-bindata -pkg goldenfiles -o ./test/goldenfiles/bindata.go ./test/goldenfiles/json/***
go-bindata -pkg db -o ./pkg/storage/db/bindataSQL.go ./pkg/storage/db/sql/*** ./pkg/storage/db/sql/psql/schema/***
go-bindata -pkg goldenfiles -o ./test/goldenfiles/bindata.go ./test/goldenfiles/json
# TEST
# ==============================================================================
PHONY+=test test-update-all
test: ${EXECUTABLE}
go test -v ./...
test-update-all: ${EXECUTABLE}
go test -v ./pkg/... -update all
# PACKAGES
# ==============================================================================
%.rpm: %
rpm-builder \
--exec-file "$<:/usr/bin/${EXECUTABLE}" \
--dir "systemd:/usr/lib/systemd/system" \
--license AGFA_PROPERTERY \
--version ${VERSION} \
--release ${RELEASE} \
--out $@ \
${EXECUTABLE}
# RELEASE
# ==============================================================================
PHONY+=release/all
release/all: clean ${RELEASE_EXECUTABLES}
github-release release \
--user ${GITHUB_USER} \
--repo ${EXECUTABLE} \
--tag ${VERSION}
$(foreach FILE,${RELEASE_EXECUTABLES},github-release upload --user ${GITHUB_USER} --repo ${EXECUTABLE} --tag ${VERSION} --name $(subst /,-,${FILE}) --file bin/${FILE} --replace;)
PHONY+=${RELEASE_EXECUTABLE_TARGETS}
${RELEASE_EXECUTABLE_TARGETS}: clean
$(MAKE) $(subst release/,,$@)
github-release release \
--user ${GITHUB_USER} \
--repo ${EXECUTABLE} \
--tag ${VERSION}
github-release upload \
--user ${GITHUB_USER} \
--repo ${EXECUTABLE} \
--tag ${VERSION} \
--name $(subst /,-,$(subst release/bin/,,$@)) \
--file $(subst release/,,$@) \
--replace
# COMPRESSION
# ==============================================================================
%.tar.bz2: %
tar --create --bzip2 --file "$@" "$<"
@@ -98,66 +193,88 @@ bindata:
%.tar.xz: %
tar --create --xz --file "$@" "$<"
%.zip: %
zip "$@" "$<"
test: ${EXECUTABLE}
go test -v ./pkg/...
release: clean
$(MAKE) $(COMPRESSED_EXECUTABLE_TARGETS)
github-release release \
--user ${GITHUB_USER} \
--repo ${EXECUTABLE} \
--tag ${VERSION}
$(foreach FILE,$(COMPRESSED_EXECUTABLES),github-release upload --user ${GITHUB_USER} --repo ${EXECUTABLE} --tag ${VERSION} --name $(subst /,-,$(FILE)) --file bin/$(FILE) --replace;)
# OTHER STUFF
# ==============================================================================
PHONY+=clean
clean:
rm ${EXECUTABLE} || true
rm ${EXECUTABLE}.* || true
rm --recursive --force bin/ || true
# CONTAINER IMAGE STEPS
# ==============================================================================
PHONY+=container-image/build/amd64
container-image/build/amd64: bin/linux/amd64/${EXECUTABLE}
${CONTAINER_RUNTIME} build \
--tag volkerraschek/${EXECUTABLE}:${IMAGE_VERSION} \
.
PHONY+=container-image/push/amd64
container-image/push/amd64: container-image/build/amd64
${CONTAINER_RUNTIME} push volkerraschek/${EXECUTABLE}:${IMAGE_VERSION}
# container
container/${EXECUTABLE}:
$(MAKE) container-run COMMAND=$(subst container/,,$@)
# CONTAINER STEPS - BINARY
# ==============================================================================
# current os
PHONY+=container-run/${EXECUTABLE}
container-run/${EXECUTABLE}:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
container/all:
$(MAKE) container-run COMMAND=$(subst container/,,$@)
# build all binaries for any operating system
PHONY+=container-run/all
container-run/all:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
container/test:
$(MAKE) container-run COMMAND=$(subst container/,,$@)
PHONY+=${UNIX_EXECUTABLE_TARGETS:%=container-run/%}
${UNIX_EXECUTABLE_TARGETS:%=container-run/%}:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
container/release:
$(MAKE) container-run COMMAND=$(subst container/,,$@)
# CONTAINER STEPS - GO-BINDATA
# ==============================================================================
PHONY+=container-run/bindata
container-run/bindata:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
# container - 386
container/bin/darwin/386/$(EXECUTABLE):
$(MAKE) container-run COMMAND=$(subst container/,,$@)
# CONTAINER STEPS - TEST
# ==============================================================================
PHONY+=container-run/test
container-run/test:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
container/bin/linux/386/$(EXECUTABLE):
$(MAKE) container-run COMMAND=$(subst container/,,$@)
PHONY+=container-run/test-update-all
container-run/test-update-all:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
# container - amd
container/bin/freebsd/amd64/$(EXECUTABLE):
$(MAKE) container-run COMMAND=$(subst container/,,$@)
# CONTAINER STEPS - COMPRESSED BINARIES AND PACKAGES
# ==============================================================================
PHONY+=${COMPRESSED_EXECUTABLE_TARGETS:%=container-run/%}
${COMPRESSED_EXECUTABLE_TARGETS:%=container-run/%}:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
container/bin/darwin/amd64/$(EXECUTABLE):
$(MAKE) container-run COMMAND=$(subst container/,,$@)
PHONY+=${RPM_EXECUTABLE_TARGETS:%=container-run/%}
${RPM_EXECUTABLE_TARGETS:%=container-run/%}:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
container/bin/linux/amd64/$(EXECUTABLE):
$(MAKE) container-run COMMAND=$(subst container/,,$@)
# CONTAINER STEPS - RELEASE COMPRESSED BINARIES AND PACKAGES
# ==============================================================================
PHONY+=${RELEASE_EXECUTABLE_TARGETS%=container-run/%}
${RELEASE_EXECUTABLE_TARGETS:%=container-run/%}:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
# container - arm
container/bin/linux/arm/7/${EXECUTABLE}:
$(MAKE) container-run COMMAND=$(subst container/,,$@)
# CONTAINER STEPS - OTHER STUF
# ==============================================================================
PHONY+=container-run/clean
container-run/clean:
$(MAKE) container-run/ COMMAND=$(subst container-run/,,$@)
container/bin/linux/arm/5/${EXECUTABLE}:
$(MAKE) container-run COMMAND=$(subst container/,,$@)
container-run:
# GENERAL CONTAINER COMMAND
# ==============================================================================
PHONY+=container-run/
container-run/:
${CONTAINER_RUNTIME} run \
--rm \
--volume ${PWD}:/workspace \
@@ -166,8 +283,17 @@ container-run:
UID=${UID} \
GID=${GID} \
VERSION=${VERSION} \
GITHUB_TOKEN=${GITHUB_TOKEN}
RELEASE=${RELEASE}
remote: bin/linux/arm/7/${EXECUTABLE}
scp bin/linux/arm/7/${EXECUTABLE} ${FLUCKY_REMOTE}:/usr/local/bin
ssh ${FLUCKY_REMOTE} "chmod +x /usr/local/bin/flucky"
# REMOTE
# ==============================================================================
PHONY+=${FLUCKY_REMOTE:%=remote/%}
remote/${FLUCKY_REMOTE}: bin/linux/arm/7/${EXECUTABLE}
scp bin/linux/arm/7/${EXECUTABLE} root@${FLUCKY_REMOTE}:/usr/local/bin/${EXECUTABLE}
ssh root@${FLUCKY_REMOTE} 'chmod +x /usr/local/bin/${EXECUTABLE}'
# PHONY
# ==============================================================================
# Declare the contents of the PHONY variable as phony. We keep that information
# in a variable so we can use it in if_changed.
.PHONY: ${PHONY}
+10 -10
View File
@@ -47,9 +47,9 @@ var rootCmd = &cobra.Command{
Device: &types.Device{
DeviceID: uuid.NewV4().String(),
DeviceName: hostname,
Logfile: "/var/log/flucky/logfile.csv",
CreationDate: t,
},
Logfile: "/var/log/flucky/logfile.csv",
}
err = config.Write(&cnf, configFile)
@@ -68,14 +68,14 @@ func Execute(version *semver.Version) {
rootCmd.PersistentFlags().StringVar(&configFile, "config", "/etc/flucky/config.json", "Config file")
compression.InitCmd(rootCmd, &configFile)
convert.InitCmd(rootCmd, &configFile)
daemon.InitCmd(rootCmd, &configFile)
// db.InitCmd(rootCmd, &configFile)
humidity.InitCmd(rootCmd, &configFile)
pressure.InitCmd(rootCmd, &configFile)
rgbled.InitCmd(rootCmd, &configFile)
sensor.InitCmd(rootCmd, &configFile)
temperature.InitCmd(rootCmd, &configFile)
compression.InitCmd(rootCmd, &configFile, version)
convert.InitCmd(rootCmd, &configFile, version)
daemon.InitCmd(rootCmd, &configFile, version)
// db.InitCmd(rootCmd, &configFile, version)
humidity.InitCmd(rootCmd, &configFile, version)
pressure.InitCmd(rootCmd, &configFile, version)
rgbled.InitCmd(rootCmd, &configFile, version)
sensor.InitCmd(rootCmd, &configFile, version)
temperature.InitCmd(rootCmd, &configFile, version)
rootCmd.Execute()
}
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"log"
"github.com/Masterminds/semver"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/spf13/cobra"
)
+1 -1
View File
@@ -4,7 +4,7 @@ import (
"log"
"github.com/Masterminds/semver"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/spf13/cobra"
)
+3 -3
View File
@@ -37,13 +37,13 @@ var daemonCmd = &cobra.Command{
}
logger := logger.NewDefaultLogger(logger.LogLevelDebug)
daemon.Start(cnf, duration, compression, round, logger)
daemon.SetLogger(logger)
daemon.Start(cnf, duration, compression, round, version)
},
}
func InitCmd(cmd *cobra.Command, cnfFile *string, sverion *semver.Version) {
func InitCmd(cmd *cobra.Command, cnfFile *string, sversion *semver.Version) {
configFile = cnfFile
version = sversion
+9 -2
View File
@@ -5,7 +5,8 @@ import (
"log"
"github.com/Masterminds/semver"
database "github.com/go-flucky/flucky/pkg/db"
"github.com/go-flucky/flucky/pkg/config"
database "github.com/go-flucky/flucky/pkg/storage/db"
"github.com/go-flucky/flucky/pkg/types"
"github.com/spf13/cobra"
)
@@ -21,7 +22,13 @@ var dbCmd = &cobra.Command{
Short: "Operates with the configured database",
Run: func(cmd *cobra.Command, args []string) {
postgresDB, err := database.New(database.DBOTypePostgres, "localhost", "5432", "postgres", "postgres", "postgres")
// read configuration
cnf, err := config.Read(*configFile)
if err != nil {
log.Fatalln(err)
}
postgresDB, err := database.New(cnf.DatabaseSettings)
if err != nil {
log.Fatalf("%v", err)
}
+2 -2
View File
@@ -5,11 +5,11 @@ import (
"log"
"os"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/go-flucky/flucky/pkg/types"
"github.com/go-flucky/flucky/pkg/cli"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/rgbled"
"github.com/spf13/cobra"
)
@@ -26,7 +26,7 @@ var listTemperatureCmd = &cobra.Command{
log.Fatalln(err)
}
logfile := logfile.New(cnf.Device.Logfile)
logfile := logfile.New(cnf.Logfile)
rgbLEDs := cnf.GetRGBLEDs(config.ENABLED)
if err := rgbled.Logfile(rgbLEDs); err != nil {
+2 -2
View File
@@ -5,11 +5,11 @@ import (
"log"
"os"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/go-flucky/flucky/pkg/types"
"github.com/go-flucky/flucky/pkg/cli"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/rgbled"
"github.com/go-flucky/flucky/pkg/sensor"
"github.com/spf13/cobra"
@@ -56,7 +56,7 @@ var readHumidityCmd = &cobra.Command{
cli.PrintMeasuredValues(measuredValues, cnf, os.Stdout)
if logs {
measuredValuesLogfile := logfile.New(cnf.Device.Logfile)
measuredValuesLogfile := logfile.New(cnf.Logfile)
err := logfile.Append(measuredValuesLogfile, compression, round, measuredValues)
if err != nil {
log.Fatalln(err)
+3 -4
View File
@@ -5,12 +5,11 @@ import (
"log"
"os"
"github.com/go-flucky/flucky/pkg/types"
"github.com/go-flucky/flucky/pkg/cli"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/go-flucky/flucky/pkg/rgbled"
"github.com/go-flucky/flucky/pkg/types"
"github.com/spf13/cobra"
)
@@ -26,7 +25,7 @@ var listTemperatureCmd = &cobra.Command{
log.Fatalln(err)
}
logfile := logfile.New(cnf.Device.Logfile)
logfile := logfile.New(cnf.Logfile)
rgbLEDs := cnf.GetRGBLEDs(config.ENABLED)
if err := rgbled.Logfile(rgbLEDs); err != nil {
+2 -2
View File
@@ -5,11 +5,11 @@ import (
"log"
"os"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/go-flucky/flucky/pkg/types"
"github.com/go-flucky/flucky/pkg/cli"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/rgbled"
"github.com/go-flucky/flucky/pkg/sensor"
"github.com/spf13/cobra"
@@ -56,7 +56,7 @@ var readPressureCmd = &cobra.Command{
cli.PrintMeasuredValues(measuredValues, cnf, os.Stdout)
if logs {
measuredValuesLogfile := logfile.New(cnf.Device.Logfile)
measuredValuesLogfile := logfile.New(cnf.Logfile)
err := logfile.Append(measuredValuesLogfile, compression, round, measuredValues)
if err != nil {
log.Fatalln(err)
+2 -2
View File
@@ -5,11 +5,11 @@ import (
"log"
"os"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/go-flucky/flucky/pkg/types"
"github.com/go-flucky/flucky/pkg/cli"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/rgbled"
"github.com/spf13/cobra"
)
@@ -26,7 +26,7 @@ var listTemperatureCmd = &cobra.Command{
log.Fatalln(err)
}
logfile := logfile.New(cnf.Device.Logfile)
logfile := logfile.New(cnf.Logfile)
rgbLEDs := cnf.GetRGBLEDs(config.ENABLED)
if err := rgbled.Logfile(rgbLEDs); err != nil {
+2 -2
View File
@@ -7,11 +7,11 @@ import (
"os"
"github.com/go-flucky/flucky/pkg/rgbled"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/go-flucky/flucky/pkg/types"
"github.com/go-flucky/flucky/pkg/cli"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/sensor"
"github.com/spf13/cobra"
)
@@ -60,7 +60,7 @@ var readTemperatureCmd = &cobra.Command{
cli.PrintMeasuredValues(measuredValues, cnf, os.Stdout)
if logs {
measuredValuesLogfile := logfile.New(cnf.Device.Logfile)
measuredValuesLogfile := logfile.New(cnf.Logfile)
err := logfile.Append(measuredValuesLogfile, compression, round, measuredValues)
if err != nil {
rgbled.Error(rgbLEDs)
+6
View File
@@ -7,10 +7,16 @@ require (
github.com/d2r2/go-bsbmp v0.0.0-20190515110334-3b4b3aea8375
github.com/d2r2/go-i2c v0.0.0-20181113114621-14f8dd4e89ce
github.com/d2r2/go-logger v0.0.0-20181221090742-9998a510495e
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/docker v1.13.1 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/go-flucky/go-dht v0.1.1
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/lib/pq v1.2.0
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/pkg/errors v0.8.1 // indirect
github.com/satori/go.uuid v1.2.0
github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.3 // indirect
+13
View File
@@ -8,6 +8,14 @@ github.com/d2r2/go-logger v0.0.0-20181221090742-9998a510495e h1:ZG3JBA6rPRl0xxQ+
github.com/d2r2/go-logger v0.0.0-20181221090742-9998a510495e/go.mod h1:oA+9PUt8F1aKJ6o4YU1T120i7sgo1T6/1LWEEBy0BSs=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo=
github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/go-flucky/go-dht v0.1.1 h1:dPz9F5D7oUaTd0GUGTvT4lBH2R043h1bkmhTlpQax1Y=
github.com/go-flucky/go-dht v0.1.1/go.mod h1:Yk/cct+/u+eCS7pB/kc0tc7MrVXdFI4W15MJCj5FRUc=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
@@ -19,6 +27,10 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
@@ -33,6 +45,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+2 -2
View File
@@ -29,9 +29,9 @@ func main() {
sversion, err := semver.NewVersion(version)
if err != nil {
log.Println("The sematic versioning is invalid: %v", version)
log.Printf("The sematic versioning is invalid: %v", version)
os.Exit(1)
}
cmd.Execute(version)
cmd.Execute(sversion)
}
+21
View File
@@ -0,0 +1,21 @@
package config
type DatabaseSettings struct {
Vendor DatabaseVendor `json:"vendor"`
Host string `json:"host"`
Port string `json:"port"`
Database string `json:"database"`
User string `json:"user"`
Password string `json:"password"`
}
type DatabaseVendor string
func (dv DatabaseVendor) String() string {
return string(dv)
}
const (
VendorPostgreSQL DatabaseVendor = "postgres"
VendorOracle = "oracle"
)
+12
View File
@@ -32,7 +32,9 @@ var temperatureSensorModels = map[types.SensorModel]types.SensorModel{
// Configuration of flucky
type Configuration struct {
DatabaseSettings *DatabaseSettings `json:"database_settings"`
Device *types.Device `json:"device"`
Logfile string `json:"logfile" xml:"logfile"`
RGBLEDs []*types.RGBLED `json:"rgb_leds"`
Sensors []*types.Sensor `json:"sensors"`
}
@@ -451,6 +453,11 @@ func (c *Configuration) GetTemperatureSensorsByName(names []string) []sensor.Sen
return c.convertSensors(temperatureSensors)
}
// RemoveDatabaseSettings remove data base setting informations
func (c *Configuration) RemoveDatabaseSettings() {
c.DatabaseSettings = nil
}
// RemoveRGBLED deletes a LED by its name or its unique UUID
func (c *Configuration) RemoveRGBLED(name string) error {
for i, rgbLED := range c.RGBLEDs {
@@ -513,6 +520,11 @@ func (c *Configuration) RenameSensor(oldName, newName string) error {
return fmt.Errorf("Could not find remote %v to replace into with %v", oldName, newName)
}
// SetDatabaseSettings set database setting informations
func (c *Configuration) SetDatabaseSettings(databaseSettings *DatabaseSettings) {
c.DatabaseSettings = databaseSettings
}
func (c *Configuration) convertSensors(sensors []*types.Sensor) []sensor.Sensor {
cachedSensors := make([]sensor.Sensor, 0)
+84 -37
View File
@@ -7,12 +7,13 @@ import (
"syscall"
"time"
"github.com/Masterminds/semver"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/db"
"github.com/go-flucky/flucky/pkg/logfile"
"github.com/go-flucky/flucky/pkg/logger"
"github.com/go-flucky/flucky/pkg/rgbled"
"github.com/go-flucky/flucky/pkg/sensor"
"github.com/go-flucky/flucky/pkg/storage/db"
"github.com/go-flucky/flucky/pkg/storage/logfile"
"github.com/go-flucky/flucky/pkg/types"
)
@@ -22,15 +23,25 @@ var (
postgresDatabase = "postgres"
postgresUser = "postgres"
postgresPassword = "postgres"
flogger logger.Logger
)
func init() {
flogger = logger.NewSilentLogger()
}
func SetLogger(logger logger.Logger) {
flogger = logger
}
// Start the daemon
func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compression bool, round float64, logger logger.Logger) {
func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compression bool, round float64, version *semver.Version) {
// Info
logger.Info("Use clean-cache-interval: %v", cleanCacheInterval.String())
logger.Info("Use compression: %v", compression)
logger.Info("Round: %v", round)
flogger.Info("Use clean-cache-interval: %v", cleanCacheInterval.String())
flogger.Info("Use compression: %v", compression)
flogger.Info("Round: %v", round)
ticker := time.Tick(cleanCacheInterval)
@@ -43,29 +54,44 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
ctx := context.Background()
childContext, cancel := context.WithCancel(ctx)
measuredValuesLogfile := logfile.New(cnf.Device.Logfile)
measuredValuesLogfile := logfile.New(cnf.Logfile)
measuredValuesCache := make([]*types.MeasuredValue, 0)
go sensor.ReadContinuously(childContext, cnf.GetSensors(config.ENABLED), measuredValuesChannel, errorChannel)
var postgres db.Database
if cnf.DatabaseSettings != nil {
p, err := db.New(cnf.DatabaseSettings)
if err != nil {
flogger.Error("%v", err)
}
if err := p.Schema(ctx, version); err != nil {
flogger.Error("%v", err)
}
postgres = p
checkDeviceInDatabase(ctx, cnf.Device, postgres)
checkSensorsInDatabase(ctx, cnf.Sensors, postgres)
defer postgres.Close()
}
rgbLEDs := cnf.GetRGBLEDs(config.ENABLED)
go sensor.ReadContinuously(childContext, cnf.GetSensors(config.ENABLED), measuredValuesChannel, errorChannel)
for {
err := rgbled.Run(rgbLEDs)
if err != nil {
logger.Error("Can not turn on green info light: %v", err)
flogger.Error("Can not turn on green info light: %v", err)
}
select {
case err, _ := <-errorChannel:
logger.Error("%v", err)
flogger.Error("%v", err)
err = rgbled.Error(rgbLEDs)
if err != nil {
logger.Error("Can not turn on red info light: %v", err)
flogger.Error("Can not turn on red info light: %v", err)
}
time.Sleep(time.Second * 2)
@@ -73,34 +99,25 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
case <-ticker:
err := rgbled.Logfile(rgbLEDs)
if err != nil {
logger.Error("Can not turn on blue info light: %v", err)
flogger.Error("Can not turn on blue info light: %v", err)
}
// err = logfile.Append(measuredValuesLogfile, compression, round, measuredValuesCache)
postgres, err := db.New(db.DBOTypePostgres, postgresHost, postgresPort, postgresDatabase, postgresUser, postgresPassword)
if err != nil {
err = rgbled.Error(rgbLEDs)
if err != nil {
logger.Error("Can not turn on red info light: %v", err)
if err := logfile.Append(measuredValuesLogfile, compression, round, measuredValuesCache); err != nil {
err2 := rgbled.Error(rgbLEDs)
if err2 != nil {
flogger.Error("Can not turn on red info light: %v", err2)
}
flogger.Error("Can not save caches measured values in logfile: %v", err)
}
cancel()
logger.Error("Can not open database connection: %v", err)
if postgres != nil {
if err := postgres.InsertMeasuredValues(ctx, measuredValuesCache); err != nil {
err2 := rgbled.Error(rgbLEDs)
if err2 != nil {
flogger.Error("Can not turn on red info light: %v", err)
}
postgresCtx := context.Background()
err = postgres.InsertMeasuredValues(postgresCtx, measuredValuesCache)
if err != nil {
err = rgbled.Error(rgbLEDs)
if err != nil {
logger.Error("Can not turn on red info light: %v", err)
flogger.Error("Can not save cached measured values in database: %v", err)
}
cancel()
logger.Error("Can not save caches measured values in database: %v", err)
}
measuredValuesCache = make([]*types.MeasuredValue, 0)
@@ -109,22 +126,52 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
measuredValuesCache = append(measuredValuesCache, measuredValues...)
case killSignal := <-interrupt:
logger.Warn("Daemon was interruped by system signal %v\n", killSignal)
flogger.Warn("Daemon was interruped by system signal %v\n", killSignal)
cancel()
err := rgbled.Error(rgbLEDs)
if err != nil {
logger.Error("Can not turn on red info light: %v", err)
flogger.Error("Can not turn on red info light: %v", err)
}
logger.Warn("Save remaining data from the cache")
flogger.Warn("Save remaining data from the cache")
err = logfile.Append(measuredValuesLogfile, compression, round, measuredValuesCache)
if err != nil {
logger.Fatal("%v", err)
flogger.Fatal("%v", err)
}
return
}
}
}
func checkDeviceInDatabase(ctx context.Context, device *types.Device, database db.Database) {
_, err := database.SelectDeviceByID(ctx, device.DeviceID)
if err != nil {
flogger.Debug("It's seems the current device is not registered in the database. Register the device now")
err2 := database.InsertDevices(ctx, []*types.Device{device})
if err2 != nil {
flogger.Fatal("Can not register device into database: %v", err2)
}
flogger.Debug("Device successfully registered into the database")
return
}
flogger.Debug("Device already registered into the database")
}
func checkSensorsInDatabase(ctx context.Context, sensors []*types.Sensor, database db.Database) {
for _, sensor := range sensors {
_, err := database.SelectSensorByID(ctx, sensor.SensorID)
if err != nil {
flogger.Debug("It's seems the sensor %v is not registered in the database. Register the sensor now", sensor.SensorName)
err2 := database.InsertSensors(ctx, []*types.Sensor{sensor})
if err2 != nil {
flogger.Fatal("Can not register sensor %v into database: %v", sensor.SensorName, err2)
}
flogger.Debug("Sensor %v successfully registered into the database", sensor.SensorName)
continue
}
flogger.Debug("Sensor %v is already registered into the database", sensor.SensorName)
}
}
-25
View File
@@ -1,25 +0,0 @@
package db
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
)
func New(dboType DBOType, host string, port string, database string, user string, password string) (Database, error) {
connStr := fmt.Sprintf("%v://%v:%v@%v:%v/%v?sslmode=disable", dboType.String(), user, password, host, port, database)
newDBO, err := sql.Open(dboType.String(), connStr)
if err != nil {
return nil, err
}
switch dboType {
case "postgres":
return &Postgres{
dbo: newDBO,
}, nil
default:
return nil, fmt.Errorf("Unknown Database Type")
}
}
-12
View File
@@ -1,12 +0,0 @@
package db
type DBOType string
func (dboType DBOType) String() string {
return string(dboType)
}
const (
DBOTypePostgres DBOType = "postgres"
DBOTypeOracle = "oracle"
)
-10
View File
@@ -1,10 +0,0 @@
package db
var (
postgreSQLSchemata []*schemaInformation
)
type schemaInformation struct {
Version string
Asset string
}
View File
Whitespace-only changes.
+39
View File
@@ -0,0 +1,39 @@
package db
import (
"database/sql"
"fmt"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/logger"
_ "github.com/lib/pq"
)
var (
flogger logger.Logger
)
func init() {
flogger = logger.NewSilentLogger()
}
func New(databaseSettings *config.DatabaseSettings) (Database, error) {
connStr := fmt.Sprintf("%v://%v:%v@%v:%v/%v?sslmode=disable", databaseSettings.Vendor.String(), databaseSettings.User, databaseSettings.Password, databaseSettings.Host, databaseSettings.Port, databaseSettings.Database)
newDBO, err := sql.Open(databaseSettings.Vendor.String(), connStr)
if err != nil {
return nil, err
}
switch databaseSettings.Vendor {
case config.VendorPostgreSQL:
return &Postgres{
dbo: newDBO,
}, nil
default:
return nil, fmt.Errorf("Unknown Database Type")
}
}
func SetLogger(logger logger.Logger) {
flogger = logger
}
File renamed without changes.
File renamed without changes.
+155 -102
View File
@@ -5,6 +5,7 @@ import (
"database/sql"
"fmt"
"path/filepath"
"sort"
"strings"
"github.com/Masterminds/semver"
@@ -13,71 +14,91 @@ import (
_ "github.com/lib/pq"
)
var (
postgresAssetPath = "pkg/storage/db/sql/psql"
)
type Postgres struct {
dbo *sql.DB
}
func (p *Postgres) Close() error {
return p.Close()
return p.dbo.Close()
}
// Schema create or upgrade database schema to the version of the flucky binary
func (p *Postgres) Schema(ctx context.Context, version *semver.Version) error {
query := "SELECT value FROM info WHERE key='version';"
schemaFunc := func(ctx context.Context, fromVersion *semver.Version, toVersion *semver.Version) error {
stmt, err := p.dbo.PrepareContext(ctx, query)
assetPath := fmt.Sprintf("%v/schema", postgresAssetPath)
sqlAssetFiles, err := AssetDir(assetPath)
if err != nil {
asset := "pkg/db/sql/psql/schema.sql"
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
return fmt.Errorf("Can not restore asset directory %v: %v", assetPath, err)
}
query = string(queryBytes)
_, err = p.dbo.ExecContext(ctx, query)
postgreSQLVersionChanges := make(map[*semver.Version]string, 0)
postgreSQLVersions := make([]*semver.Version, len(sqlAssetFiles))
for i, sqlAssetFile := range sqlAssetFiles {
fileSemVersion, err := semver.NewVersion(strings.ReplaceAll(sqlAssetFile, ".sql", ""))
if err != nil {
return fmt.Errorf("Can not create semantic version from file asset %v: %v", sqlAssetFile, err)
}
postgreSQLVersionChanges[fileSemVersion] = sqlAssetFile
postgreSQLVersions[i] = fileSemVersion
}
sort.Sort(semver.Collection(postgreSQLVersions))
for i, postgreSQLVersion := range postgreSQLVersions {
if fromVersion != nil {
if postgreSQLVersion.LessThan(fromVersion) || postgreSQLVersion.Equal(fromVersion) {
flogger.Debug("SKIP: PostgreSQL schema version '%v' is less or eqal then the local version changes '%v'", postgreSQLVersion.String(), fromVersion.String())
continue
}
}
asset := postgreSQLVersionChanges[postgreSQLVersion]
queryBytes, err := Asset(filepath.Join(assetPath, asset))
if err != nil {
return fmt.Errorf("Can not restore asset %v, %v", asset, err)
}
query := string(queryBytes)
if _, err := p.dbo.ExecContext(ctx, query); err != nil {
return fmt.Errorf("%v: %v", errorStatementExecute, err)
}
if i == 0 {
if err := p.InsertInfo(ctx, "version", postgreSQLVersion.String()); err != nil {
return fmt.Errorf("Can not insert version %v into info table: %v", postgreSQLVersion.String(), err)
}
} else {
if err := p.UpdateInfo(ctx, "version", postgreSQLVersion.String()); err != nil {
return fmt.Errorf("Can not update version %v into info table: %v", postgreSQLVersion.String(), err)
}
}
}
return nil
}
schemaVersion := ""
row := stmt.QueryRowContext(ctx)
err = row.Scan(&schemaVersion)
dbVersion, err := p.SelectInfo(ctx, "version")
if err != nil {
return fmt.Errorf("%v: %v", errorScanRow, err)
}
fromVersion, err := semver.NewVersion(schemaVersion)
// can not select version from database, maybe the schema is not initialize
// create db schema for the current flucky version
return schemaFunc(ctx, nil, version)
} else {
fromVersion, err := semver.NewVersion(dbVersion)
if err != nil {
return fmt.Errorf("Can not create new sematic version from database: %v", err)
return fmt.Errorf("Can not create semantic version from database entry %v: %v", dbVersion, err)
}
if err := schema(fromVersion, version); err != nil {
return err
return schemaFunc(ctx, fromVersion, version)
}
// The result will be 0 if from == to, -1 if from < to, or +1 if from > to.
switch fromVersion.Compare(version) {
case -1:
return schema(fromVersion, version)
case 0:
// fromVersion and toVersion are equal
return nil
case 1:
// fromVersion < toVersion
return fmt.Errorf("Can not downgrade the database schema. Update the flucky binary")
}
return nil
}
func (p *Postgres) DeleteDevices(ctx context.Context, devices []*types.Device) error {
asset := "pkg/db/sql/psql/deleteDevice.sql"
asset := fmt.Sprintf("%v/deleteDevice.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -101,7 +122,7 @@ func (p *Postgres) DeleteDevices(ctx context.Context, devices []*types.Device) e
}
func (p *Postgres) DeleteSensors(ctx context.Context, sensors []*types.Sensor) error {
asset := "pkg/db/sql/psql/deleteSensor.sql"
asset := fmt.Sprintf("%v/deleteSensor.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -161,7 +182,7 @@ func (p *Postgres) DeleteMeasuredValues(ctx context.Context, measuredValues []*t
for measuredValueType, sortedMeasuredValues := range sortedMeasuredValueTypes {
switch measuredValueType {
case types.MeasuredValueTypeHumidity:
query, err := assetFunc("pkg/db/sql/psql/deleteHumidity.sql")
query, err := assetFunc(fmt.Sprintf("%v/deleteHumidity.sql", postgresAssetPath))
if err != nil {
return err
}
@@ -170,7 +191,7 @@ func (p *Postgres) DeleteMeasuredValues(ctx context.Context, measuredValues []*t
return err
}
case types.MeasuredValueTypePressure:
query, err := assetFunc("pkg/db/sql/psql/deletePressure.sql")
query, err := assetFunc(fmt.Sprintf("%v/deletePressure.sql", postgresAssetPath))
if err != nil {
return err
}
@@ -179,7 +200,7 @@ func (p *Postgres) DeleteMeasuredValues(ctx context.Context, measuredValues []*t
return err
}
case types.MeasuredValueTypeTemperature:
query, err := assetFunc("pkg/db/sql/psql/deleteTemperature.sql")
query, err := assetFunc(fmt.Sprintf("%v/deleteTemperature.sql", postgresAssetPath))
if err != nil {
return err
}
@@ -194,7 +215,7 @@ func (p *Postgres) DeleteMeasuredValues(ctx context.Context, measuredValues []*t
}
func (p *Postgres) InsertDevices(ctx context.Context, devices []*types.Device) error {
asset := "pkg/db/sql/psql/insertDevice.sql"
asset := fmt.Sprintf("%v/insertDevice.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -217,6 +238,28 @@ func (p *Postgres) InsertDevices(ctx context.Context, devices []*types.Device) e
return nil
}
func (p *Postgres) InsertInfo(ctx context.Context, key string, value string) error {
asset := fmt.Sprintf("%v/insertInfo.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
}
query := string(queryBytes)
stmt, err := p.dbo.PrepareContext(ctx, query)
if err != nil {
return fmt.Errorf("%v: %v", errorPrepareStatement, err)
}
defer stmt.Close()
_, err = stmt.ExecContext(ctx, key, value)
if err != nil {
return fmt.Errorf("%v: %v", errorStatementExecute, err)
}
return nil
}
func (p *Postgres) InsertMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error {
sortedMeasuredValueTypes := make(map[types.MeasuredValueType][]*types.MeasuredValue)
@@ -250,7 +293,7 @@ func (p *Postgres) InsertMeasuredValues(ctx context.Context, measuredValues []*t
func (p *Postgres) insertHumidity(ctx context.Context, measuredValues []*types.MeasuredValue) error {
asset := "pkg/db/sql/psql/insertHumidity.sql"
asset := fmt.Sprintf("%v/insertHumidity.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -279,7 +322,7 @@ func (p *Postgres) insertHumidity(ctx context.Context, measuredValues []*types.M
func (p *Postgres) insertPressure(ctx context.Context, measuredValues []*types.MeasuredValue) error {
asset := "pkg/db/sql/psql/insertPressure.sql"
asset := fmt.Sprintf("%v/insertPressure.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -308,7 +351,7 @@ func (p *Postgres) insertPressure(ctx context.Context, measuredValues []*types.M
func (p *Postgres) insertTemperature(ctx context.Context, measuredValues []*types.MeasuredValue) error {
asset := "pkg/db/sql/psql/insertTemperature.sql"
asset := fmt.Sprintf("%v/insertTemperature.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -337,7 +380,7 @@ func (p *Postgres) insertTemperature(ctx context.Context, measuredValues []*type
func (p *Postgres) InsertSensors(ctx context.Context, sensors []*types.Sensor) error {
asset := "pkg/db/sql/psql/insertSensor.sql"
asset := fmt.Sprintf("%v/insertSensor.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -361,7 +404,7 @@ func (p *Postgres) InsertSensors(ctx context.Context, sensors []*types.Sensor) e
}
func (p *Postgres) SelectDeviceByID(ctx context.Context, id string) (*types.Device, error) {
asset := "pkg/db/sql/psql/selectDeviceByID.sql"
asset := fmt.Sprintf("%v/selectDeviceByID.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return nil, fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -387,21 +430,35 @@ func (p *Postgres) SelectDeviceByID(ctx context.Context, id string) (*types.Devi
return device, nil
}
func (p *Postgres) SelectMeasuredValuesByIDAndType(ctx context.Context, id string, valueType types.MeasuredValueType) (*types.MeasuredValue, error) {
switch valueType {
case types.MeasuredValueTypeHumidity:
return p.SelectHumidityByID(ctx, id)
case types.MeasuredValueTypePressure:
return p.SelectPressureByID(ctx, id)
case types.MeasuredValueTypeTemperature:
return p.SelectTemperatureByID(ctx, id)
default:
return nil, fmt.Errorf("%v: %v", errorUnknownMeasuredValueType, valueType)
func (p *Postgres) SelectInfo(ctx context.Context, key string) (string, error) {
asset := fmt.Sprintf("%v/selectInfo.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return "", fmt.Errorf("%v: %v", errorGetAsset, err)
}
query := string(queryBytes)
stmt, err := p.dbo.PrepareContext(ctx, query)
if err != nil {
return "", fmt.Errorf("%v: %v", errorPrepareStatement, err)
}
row := stmt.QueryRowContext(ctx, key)
if row == nil {
return "", errorRowNotFound
}
value := ""
err = row.Scan(&value)
if err != nil {
return "", fmt.Errorf("%v: %v", errorScanRow, err)
}
return value, nil
}
func (p *Postgres) SelectHumidities(ctx context.Context) ([]*types.MeasuredValue, error) {
queryFile := "pkg/db/sql/psql/selectHumidities.sql"
queryFile := fmt.Sprintf("%v/selectHumidities.sql", postgresAssetPath)
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeHumidity, queryFile, nil)
if err != nil {
return nil, err
@@ -410,7 +467,7 @@ func (p *Postgres) SelectHumidities(ctx context.Context) ([]*types.MeasuredValue
}
func (p *Postgres) SelectHumidityByID(ctx context.Context, id string) (*types.MeasuredValue, error) {
queryFile := "pkg/db/sql/psql/selectHumidityByID.sql"
queryFile := fmt.Sprintf("%v/selectHumidityByID.sql", postgresAssetPath)
args := []interface{}{id}
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeHumidity, queryFile, args)
if err != nil {
@@ -424,8 +481,21 @@ func (p *Postgres) SelectHumidityByID(ctx context.Context, id string) (*types.Me
return measuredValues[0], nil
}
func (p *Postgres) SelectMeasuredValuesByIDAndType(ctx context.Context, id string, valueType types.MeasuredValueType) (*types.MeasuredValue, error) {
switch valueType {
case types.MeasuredValueTypeHumidity:
return p.SelectHumidityByID(ctx, id)
case types.MeasuredValueTypePressure:
return p.SelectPressureByID(ctx, id)
case types.MeasuredValueTypeTemperature:
return p.SelectTemperatureByID(ctx, id)
default:
return nil, fmt.Errorf("%v: %v", errorUnknownMeasuredValueType, valueType)
}
}
func (p *Postgres) SelectPressures(ctx context.Context) ([]*types.MeasuredValue, error) {
queryFile := "pkg/db/sql/psql/selectPressures.sql"
queryFile := fmt.Sprintf("%v/selectPressures.sql", postgresAssetPath)
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypePressure, queryFile, nil)
if err != nil {
return nil, err
@@ -434,7 +504,7 @@ func (p *Postgres) SelectPressures(ctx context.Context) ([]*types.MeasuredValue,
}
func (p *Postgres) SelectPressureByID(ctx context.Context, id string) (*types.MeasuredValue, error) {
queryFile := "pkg/db/sql/psql/selectPressureByID.sql"
queryFile := fmt.Sprintf("%v/selectPressureByID.sql", postgresAssetPath)
args := []interface{}{id}
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypePressure, queryFile, args)
if err != nil {
@@ -449,7 +519,7 @@ func (p *Postgres) SelectPressureByID(ctx context.Context, id string) (*types.Me
}
func (p *Postgres) SelectSensorByID(ctx context.Context, id string) (*types.Sensor, error) {
asset := "pkg/db/sql/psql/selectSensorByID.sql"
asset := fmt.Sprintf("%v/selectSensorByID.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return nil, fmt.Errorf("%v: %v", errorGetAsset, err)
@@ -476,7 +546,7 @@ func (p *Postgres) SelectSensorByID(ctx context.Context, id string) (*types.Sens
}
func (p *Postgres) SelectTemperatures(ctx context.Context) ([]*types.MeasuredValue, error) {
queryFile := "pkg/db/sql/psql/selectTemperatures.sql"
queryFile := fmt.Sprintf("%v/selectTemperatures.sql", postgresAssetPath)
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeTemperature, queryFile, nil)
if err != nil {
return nil, err
@@ -485,7 +555,7 @@ func (p *Postgres) SelectTemperatures(ctx context.Context) ([]*types.MeasuredVal
}
func (p *Postgres) SelectTemperatureByID(ctx context.Context, id string) (*types.MeasuredValue, error) {
queryFile := "pkg/db/sql/psql/selectTemperatureByID.sql"
queryFile := fmt.Sprintf("%v/selectTemperatureByID.sql", postgresAssetPath)
args := []interface{}{id}
measuredValues, err := p.selectMeasuredValues(ctx, types.MeasuredValueTypeTemperature, queryFile, args)
if err != nil {
@@ -531,6 +601,28 @@ func (p *Postgres) UpdateDevices(ctx context.Context, devices []*types.Device) e
return nil
}
func (p *Postgres) UpdateInfo(ctx context.Context, key string, value string) error {
asset := fmt.Sprintf("%v/updateInfo.sql", postgresAssetPath)
queryBytes, err := Asset(asset)
if err != nil {
return fmt.Errorf("%v: %v", errorGetAsset, err)
}
query := string(queryBytes)
stmt, err := p.dbo.PrepareContext(ctx, query)
if err != nil {
return fmt.Errorf("%v: %v", errorPrepareStatement, err)
}
defer stmt.Close()
_, err = stmt.ExecContext(ctx, key, value)
if err != nil {
return fmt.Errorf("%v: %v", errorStatementExecute, err)
}
return nil
}
func (p *Postgres) UpdateMeasuredValues(ctx context.Context, measuredValues []*types.MeasuredValue) error {
return nil
}
@@ -538,42 +630,3 @@ func (p *Postgres) UpdateMeasuredValues(ctx context.Context, measuredValues []*t
func (p *Postgres) UpdateSensors(ctx context.Context, sensots []*types.Sensor) error {
return nil
}
func schema(fromVersion *semver.Version, toVersion *semver.Version) error {
sqlAssetFiles, err := parseAssetDir("pkg/db/sql/psql/schema")
if err != nil {
return fmt.Errorf("Can not restore sql files: %v", err)
}
for _, sqlAssetFile := range sqlAssetFiles {
version := strings.Replace()
sqlSchemaInformations := &schemaInformation{
Version: filepath.Split()
Asset: sqlAssetFile,
}
}
return nil
}
func parseAssetDir(dir string) ([]string, error) {
assetFiles, err := AssetDir(dir)
if err != nil {
return nil, fmt.Errorf("Can not load asset directory %v: %v", dir, err)
}
goldenAssetFiles := assetFiles
for i, assetFile := range assetFiles {
if strings.HasPrefix(assetFile, "/") {
// is directory- SKIP
goldenAssetFiles = append(goldenAssetFiles[:i], goldenAssetFiles[i+1:]...)
}
}
return goldenAssetFiles, nil
}
@@ -2,9 +2,12 @@ package db_test
import (
"context"
"strings"
"testing"
"github.com/go-flucky/flucky/pkg/db"
"github.com/Masterminds/semver"
"github.com/go-flucky/flucky/pkg/config"
"github.com/go-flucky/flucky/pkg/storage/db"
"github.com/go-flucky/flucky/pkg/types"
"github.com/go-flucky/flucky/test/goldenfiles"
"github.com/stretchr/testify/require"
@@ -19,11 +22,15 @@ var (
database db.Database
postgresContainerImage string = "docker.io/postgres/postgres"
postgresHost string = "localhost"
postgresPort string = "5432"
postgresUser string = "postgres"
postgresPassword string = "postgres"
postgresDatabase string = "postgres"
postgresSettings = &config.DatabaseSettings{
Vendor: config.VendorPostgreSQL,
Host: "localhost",
Port: "5432",
User: "postgres",
Password: "postgres",
Database: "postgres",
}
goldenDevicesFilePath string = "test/goldenfiles/json/goldenDevices.json"
goldenSensorsFilePath string = "test/goldenfiles/json/goldenSensors.json"
@@ -74,7 +81,7 @@ func TestPostgres(t *testing.T) {
load(t)
db, err := db.New(db.DBOTypePostgres, postgresHost, postgresPort, postgresDatabase, postgresUser, postgresPassword)
db, err := db.New(postgresSettings)
database = db
require.Nil(err)
@@ -83,54 +90,54 @@ func TestPostgres(t *testing.T) {
Name: "schema",
Test: testSchemaCreate,
},
// &test{
// Name: "insertDevices",
// Test: testInsertDevices,
// },
// &test{
// Name: "insertSensors",
// Test: testInsertSensors,
// },
// &test{
// Name: "insertHumidity",
// Test: testInsertHumidity,
// },
// &test{
// Name: "insertPressure",
// Test: testInsertPressure,
// },
// &test{
// Name: "insertTemperatures",
// Test: testInsertTemperatures,
// },
// &test{
// Name: "deleteHumidities",
// Test: testDeleteHumidity,
// },
// &test{
// Name: "deletePressures",
// Test: testDeletePressures,
// },
// &test{
// Name: "deleteTemperatures",
// Test: testDeleteTemperatures,
// },
// &test{
// Name: "insertMeasuredValues",
// Test: testInsertMeasuredValues,
// },
// &test{
// Name: "deleteMeasuredValues",
// Test: testDeleteMeasuredValues,
// },
// &test{
// Name: "deleteSensors",
// Test: testDeleteSensors,
// },
// &test{
// Name: "deleteDevices",
// Test: testDeleteDevices,
// },
&test{
Name: "insertDevices",
Test: testInsertDevices,
},
&test{
Name: "insertSensors",
Test: testInsertSensors,
},
&test{
Name: "insertHumidity",
Test: testInsertHumidity,
},
&test{
Name: "insertPressure",
Test: testInsertPressure,
},
&test{
Name: "insertTemperatures",
Test: testInsertTemperatures,
},
&test{
Name: "deleteHumidities",
Test: testDeleteHumidity,
},
&test{
Name: "deletePressures",
Test: testDeletePressures,
},
&test{
Name: "deleteTemperatures",
Test: testDeleteTemperatures,
},
&test{
Name: "insertMeasuredValues",
Test: testInsertMeasuredValues,
},
&test{
Name: "deleteMeasuredValues",
Test: testDeleteMeasuredValues,
},
&test{
Name: "deleteSensors",
Test: testDeleteSensors,
},
&test{
Name: "deleteDevices",
Test: testDeleteDevices,
},
}
for _, test := range tests {
@@ -140,9 +147,18 @@ func TestPostgres(t *testing.T) {
func testSchemaCreate(t *testing.T) {
require := require.New(t)
ctx := context.Background()
err := database.Schema(ctx, "v0.1.0")
homePath := "pkg/storage/db/sql/psql/schema"
sqlAssetFiles, err := db.AssetDir(homePath)
require.NoError(err)
ctx := context.Background()
for _, sqlAssetFile := range sqlAssetFiles {
fromVersion, err := semver.NewVersion(strings.ReplaceAll(sqlAssetFile, ".sql", ""))
require.NoError(err)
err = database.Schema(ctx, fromVersion)
require.NoError(err)
}
}
func testInsertDevices(t *testing.T) {
File renamed without changes.
File renamed without changes.
File renamed without changes.
+2
View File
@@ -0,0 +1,2 @@
INSERT INTO info (key, value)
VALUES ($1, $2);
File renamed without changes.
File renamed without changes.
+3
View File
@@ -0,0 +1,3 @@
SELECT value
FROM info
WHERE key = $1;
+3
View File
@@ -0,0 +1,3 @@
UPDATE info
SET value = $2
WHERE key = $1;
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
-1
View File
@@ -8,6 +8,5 @@ type Device struct {
DeviceName string `json:"device_name" xml:"device_name"`
DeviceLocation *string `json:"device_location" xml:"device_location"`
DeviceLastContact *time.Time `json:"device_last_contact" xml:"device_last_contact"`
Logfile string `json:"logfile" xml:"logfile"`
CreationDate time.Time `json:"creation_date" xml:"creation_date"`
}