fix(pkg/daemon): save measured values into postgres database if defined
This commit is contained in:
		| @@ -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
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| FROM busybox:latest | ||||
| COPY bin/linux/amd64/flucky /usr/bin/flucky | ||||
| ENTRYPOINT [ "/usr/bin/flucky" ] | ||||
							
								
								
									
										306
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										306
									
								
								Makefile
									
									
									
									
									
								
							| @@ -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) \ | ||||
| UNIX_EXECUTABLES:= \ | ||||
| 	${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} | ||||
							
								
								
									
										20
									
								
								cmd/cmd.go
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								cmd/cmd.go
									
									
									
									
									
								
							| @@ -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() | ||||
| } | ||||
|   | ||||
| @@ -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" | ||||
| ) | ||||
|   | ||||
| @@ -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" | ||||
| ) | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
							
								
								
									
										11
									
								
								cmd/db/db.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								cmd/db/db.go
									
									
									
									
									
								
							| @@ -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) | ||||
| 		} | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.mod
									
									
									
									
									
								
							| @@ -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
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								go.sum
									
									
									
									
									
								
							| @@ -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= | ||||
|   | ||||
							
								
								
									
										4
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.go
									
									
									
									
									
								
							| @@ -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
									
								
								pkg/config/dbsettings.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								pkg/config/dbsettings.go
									
									
									
									
									
										Normal 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" | ||||
| ) | ||||
| @@ -32,9 +32,11 @@ var temperatureSensorModels = map[types.SensorModel]types.SensorModel{ | ||||
|  | ||||
| // Configuration of flucky | ||||
| type Configuration struct { | ||||
| 	Device  *types.Device   `json:"device"` | ||||
| 	RGBLEDs []*types.RGBLED `json:"rgb_leds"` | ||||
| 	Sensors []*types.Sensor `json:"sensors"` | ||||
| 	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"` | ||||
| } | ||||
|  | ||||
| // AddRGBLED add a new RGBLED | ||||
| @@ -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) | ||||
|  | ||||
|   | ||||
| @@ -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) | ||||
| 				} | ||||
|  | ||||
| 				cancel() | ||||
| 				logger.Error("Can not open database connection: %v", err) | ||||
| 				flogger.Error("Can not save caches measured values in logfile: %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) | ||||
| 			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) | ||||
| 					} | ||||
| 					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
									
								
								pkg/db/db.go
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								pkg/db/db.go
									
									
									
									
									
								
							| @@ -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") | ||||
| 	} | ||||
| } | ||||
| @@ -1,12 +0,0 @@ | ||||
| package db | ||||
|  | ||||
| type DBOType string | ||||
|  | ||||
| func (dboType DBOType) String() string { | ||||
| 	return string(dboType) | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	DBOTypePostgres DBOType = "postgres" | ||||
| 	DBOTypeOracle           = "oracle" | ||||
| ) | ||||
| @@ -1,10 +0,0 @@ | ||||
| package db | ||||
|  | ||||
| var ( | ||||
| 	postgreSQLSchemata []*schemaInformation | ||||
| ) | ||||
|  | ||||
| type schemaInformation struct { | ||||
| 	Version string | ||||
| 	Asset   string | ||||
| } | ||||
							
								
								
									
										39
									
								
								pkg/storage/db/db.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								pkg/storage/db/db.go
									
									
									
									
									
										Normal 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 | ||||
| } | ||||
| @@ -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) | ||||
| 	if err != nil { | ||||
| 
 | ||||
| 		asset := "pkg/db/sql/psql/schema.sql" | ||||
| 		queryBytes, err := Asset(asset) | ||||
| 		assetPath := fmt.Sprintf("%v/schema", postgresAssetPath) | ||||
| 		sqlAssetFiles, err := AssetDir(assetPath) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorGetAsset, err) | ||||
| 		} | ||||
| 		query = string(queryBytes) | ||||
| 
 | ||||
| 		_, err = p.dbo.ExecContext(ctx, query) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("%v: %v", errorStatementExecute, err) | ||||
| 			return fmt.Errorf("Can not restore asset directory %v: %v", assetPath, err) | ||||
| 		} | ||||
| 
 | ||||
| 		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) | ||||
| 		// 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 semantic version from database entry %v: %v", dbVersion, err) | ||||
| 		} | ||||
| 		return schemaFunc(ctx, fromVersion, version) | ||||
| 	} | ||||
| 
 | ||||
| 	fromVersion, err := semver.NewVersion(schemaVersion) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("Can not create new sematic version from database: %v", err) | ||||
| 	} | ||||
| 
 | ||||
| 	if err := schema(fromVersion, version); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	// 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) { | ||||
							
								
								
									
										2
									
								
								pkg/storage/db/sql/psql/insertInfo.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								pkg/storage/db/sql/psql/insertInfo.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| INSERT INTO info (key, value) | ||||
| VALUES ($1, $2); | ||||
							
								
								
									
										3
									
								
								pkg/storage/db/sql/psql/selectInfo.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								pkg/storage/db/sql/psql/selectInfo.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| SELECT value | ||||
| FROM info | ||||
| WHERE key = $1; | ||||
							
								
								
									
										3
									
								
								pkg/storage/db/sql/psql/updateInfo.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								pkg/storage/db/sql/psql/updateInfo.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| UPDATE info | ||||
| SET value = $2 | ||||
| WHERE key = $1; | ||||
| @@ -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"` | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user