diff --git a/.gitignore b/.gitignore index 1e6cd20..251e7d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.idea /mittnite -/dist \ No newline at end of file +/dist +examples/mittnite.d/local.hcl \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index aff356e..013c27d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,4 +2,4 @@ FROM alpine:3.9 COPY mittnite /usr/bin/mittnite EXPOSE 9102 ENTRYPOINT ["mittnite"] -CMD ["-config-dir", "/etc/mittnite.d"] \ No newline at end of file +CMD ["up","--config-dir", "/etc/mittnite.d"] \ No newline at end of file diff --git a/README.md b/README.md index 3eaf249..9591a35 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ It offers the following features: Start as follows: ``` -$ mittnite -config-dir /etc/mittnite.d +$ mittnite up --config-dir /etc/mittnite.d ``` Or use it in a container image: @@ -25,10 +25,10 @@ Or use it in a container image: FROM quay.io/mittwald/mittnite:stable COPY nginx.hcl /etc/mittnite.d/webserver.hcl COPY fpm.hcl /etc/mittnite.d/fpm.hcl -CMD ["-config-dir", "/etc/mittnite.d"] +CMD ["up", "--config-dir", "/etc/mittnite.d"] ``` -The directory specified with `-config-dir` can contain any number of `.hcl` configuration files; all files in that directory are loaded by Mittnite on startup and can contain any of the configuration directives described in the following section: +The directory specified with `--config-dir` or the shorthand `-c` can contain any number of `.hcl` configuration files; all files in that directory are loaded by Mittnite on startup and can contain any of the configuration directives described in the following section: ## Configuration directives diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..3c8a6f2 --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,28 @@ +package cmd + +import ( + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +var configDir string + +func init() { + rootCmd.PersistentFlags().StringVarP(&configDir, "config-dir", "c", "/etc/mittnite.d", "") +} + +var rootCmd = &cobra.Command{ + Use: "up", + Short: "Mittnite - Smart init system for containers", + Long: "Mittnite is a small, but smart init system designed for usage as `ENTRYPOINT` in container images.", + Run: func(cmd *cobra.Command, args []string) { + log.Warn("Using mittnite without 'up'. This will change in future releases!") + up.Run(cmd, args) + }, +} + +func Execute() { + if err := rootCmd.Execute(); err != nil { + log.Fatal(err) + } +} diff --git a/cmd/up.go b/cmd/up.go new file mode 100644 index 0000000..83e8912 --- /dev/null +++ b/cmd/up.go @@ -0,0 +1,120 @@ +package cmd + +import ( + "fmt" + "github.com/hashicorp/hcl" + "github.com/mittwald/mittnite/internal/types" + "github.com/mittwald/mittnite/pkg/files" + "github.com/mittwald/mittnite/pkg/probe" + "github.com/mittwald/mittnite/pkg/proc" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" + "io/ioutil" + "os" + "os/signal" + "path/filepath" + "strings" +) + +var ( + Version string + Commit string + BuiltAt string +) + +func init() { + rootCmd.AddCommand(up) +} + +var up = &cobra.Command{ + Use: "up", + Run: func(cmd *cobra.Command, args []string) { + + log.Infof("mittnite process manager, version %s (commit %s), built at %s", Version, Commit, BuiltAt) + log.Infof("looking for configuration files in %s", configDir) + + configDir = strings.TrimRight(configDir, "/") + + var matches []string + + err := filepath.Walk(configDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + log.Fatal(err) + } + if strings.HasSuffix(info.Name(), "hcl") { + matches = append(matches, path) + } + return nil + }) + if err != nil { + log.Fatal(err) + } + + if len(matches) == 0 { + log.Fatalf("could not find any configuration files in %s", configDir) + } + + ignitionConfig := types.IgnitionConfig{} + + for _, m := range matches { + log.Infof("found config file: %s", m) + + contents, err := ioutil.ReadFile(m) + if err != nil { + panic(err) + } + + err = hcl.Unmarshal(contents, &ignitionConfig) + if err != nil { + err = fmt.Errorf("could not parse configuration file %s: %s", m, err.Error()) + panic(err) + } + } + + err = files.RenderConfigurationFiles(ignitionConfig.Files) + if err != nil { + panic(err) + } + + signals := make(chan os.Signal) + signal.Notify(signals) + + readinessSignals := make(chan os.Signal, 1) + probeSignals := make(chan os.Signal, 1) + procSignals := make(chan os.Signal, 1) + + go func() { + for s := range signals { + log.Infof("received event %s", s.String()) + + readinessSignals <- s + probeSignals <- s + procSignals <- s + } + }() + + probeHandler, _ := probe.NewProbeHandler(&ignitionConfig) + + go func() { + err := probe.RunProbeServer(probeHandler, probeSignals) + if err != nil { + log.Fatalf("probe server stopped with error: %s", err) + panic(err) + } else { + log.Info("probe server stopped without error") + } + }() + + err = probeHandler.Wait(readinessSignals) + if err != nil { + panic(err) + } + + err = proc.RunServices(&ignitionConfig, procSignals) + if err != nil { + log.Fatalf("service runner stopped with error: %s", err) + } else { + log.Print("service runner stopped without error") + } + }, +} diff --git a/examples/mittnite.d/jobs/sleep.hcl b/examples/mittnite.d/jobs/sleep.hcl new file mode 100644 index 0000000..4718d2a --- /dev/null +++ b/examples/mittnite.d/jobs/sleep.hcl @@ -0,0 +1,5 @@ +job sleep { + command = "/bin/sleep" + args = ["500s"] + canFail = true +} \ No newline at end of file diff --git a/examples/mittnite.d/probes/redis.hcl b/examples/mittnite.d/probes/redis.hcl new file mode 100644 index 0000000..c26dfa2 --- /dev/null +++ b/examples/mittnite.d/probes/redis.hcl @@ -0,0 +1,9 @@ +probe redis { + wait = true + redis { + host = { + url = "localhost" + port = 6379 + } + } +} \ No newline at end of file diff --git a/test.d/database.hcl b/examples/test.d/database.hcl similarity index 100% rename from test.d/database.hcl rename to examples/test.d/database.hcl diff --git a/test.d/mounts.hcl b/examples/test.d/mounts.hcl similarity index 100% rename from test.d/mounts.hcl rename to examples/test.d/mounts.hcl diff --git a/test.d/processes.hcl b/examples/test.d/processes.hcl similarity index 100% rename from test.d/processes.hcl rename to examples/test.d/processes.hcl diff --git a/test.d/test.txt.tpl b/examples/test.d/test.txt.tpl similarity index 100% rename from test.d/test.txt.tpl rename to examples/test.d/test.txt.tpl diff --git a/go.mod b/go.mod index fac6912..2712f61 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,6 @@ module github.com/mittwald/mittnite require ( - github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-redis/redis v6.7.4+incompatible github.com/go-sql-driver/mysql v1.3.0 github.com/go-stack/stack v1.8.0 // indirect @@ -9,9 +8,12 @@ require ( github.com/google/go-cmp v0.3.0 // indirect github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f // indirect github.com/gorilla/mux v1.6.0 - github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb + github.com/hashicorp/hcl v1.0.0 + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect github.com/onsi/ginkgo v1.8.0 // indirect github.com/onsi/gomega v1.5.0 // indirect + github.com/sirupsen/logrus v1.4.2 + github.com/spf13/cobra v0.0.5 github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 github.com/stretchr/testify v1.3.0 // indirect github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 // indirect @@ -20,5 +22,6 @@ require ( go.mongodb.org/mongo-driver v1.0.1 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 // indirect golang.org/x/sync v0.0.0-20190423024810-112230192c58 // indirect + golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa // indirect golang.org/x/text v0.3.2 // indirect ) diff --git a/go.sum b/go.sum index 272898e..9bb22c3 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,9 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -19,30 +25,63 @@ github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f h1:9oNbS1z4rVpbnkH github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.0 h1:UykbtMB/w5No2LmE16gINgLj+r/vbziTgaoERQv6U+0= github.com/gorilla/mux v1.6.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb h1:1OvvPvZkn/yCQ3xBcM8y4020wdkMXPHLB4+NfoGWh4U= -github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 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/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 h1:0ngsPmuP6XIjiFRNFYlvKwSr5zff2v+uPHaffZ6/M4k= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65 h1:rQ229MBgvW68s1/g6f1/63TgYwYxfF4E+bi/KC19P8g= github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV0YCnDjqSL7/q/JyPhhJSPk= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0 h1:d9X0esnoa3dFsV0FG35rAT0RIhYFlPq7MiP+DW89La0= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.mongodb.org/mongo-driver v1.0.1 h1:r2xNB8juGGrZVcIjX2TpY7HUfz+pNYq+GIuC9h6URZg= go.mongodb.org/mongo-driver v1.0.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529 h1:iMGN4xG0cnqj3t+zOM8wUB0BiPKHEwSxEZCvzcbZuvk= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -53,9 +92,14 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa h1:KIDDMLT1O0Nr7TSxp8xM5tJcdn8tgyAONntO829og1M= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -68,3 +112,5 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/probe/helper.go b/internal/helper/helper.go similarity index 68% rename from probe/helper.go rename to internal/helper/helper.go index 1e9919c..00620e7 100644 --- a/probe/helper.go +++ b/internal/helper/helper.go @@ -1,11 +1,11 @@ -package probe +package helper import ( "os" "strings" ) -func resolveEnv(in string) string { +func ResolveEnv(in string) string { if strings.HasPrefix(in, "ENV:") { return os.Getenv(in[4:]) } diff --git a/config/config.go b/internal/types/types.go similarity index 83% rename from config/config.go rename to internal/types/types.go index e85edcf..3661670 100644 --- a/config/config.go +++ b/internal/types/types.go @@ -1,35 +1,41 @@ -package config +package types -type MySQLConfig struct { +type Credentials struct { User string Password string - Host string +} + +type Host struct { + Hostname string + Port string +} + +type MySQLConfig struct { + Credentials + Host Database string } type AmqpConfig struct { - User string - Password string - Hostname string + Credentials + Host VirtualHost string } type MongoDBConfig struct { - User string - Password string - Host string + Credentials + Host Database string } type RedisConfig struct { - Host string + Host Password string } type HttpGetConfig struct { - Scheme string - Host string - Port string + Scheme string + Host Path string Timeout string } @@ -56,6 +62,7 @@ type JobConfig struct { Args []string `hcl:"args"` Watches []WatchConfig `hcl:"watch"` MaxAttempts int `hcl:"max_attempts"` + CanFail bool `hcl:"canFail"` } type FileConfig struct { diff --git a/main.go b/main.go index 944cbea..ecbe5b5 100644 --- a/main.go +++ b/main.go @@ -1,114 +1,17 @@ package main import ( - "flag" - "fmt" - "github.com/hashicorp/hcl" - "github.com/mittwald/mittnite/config" - "github.com/mittwald/mittnite/files" - "github.com/mittwald/mittnite/probe" - "github.com/mittwald/mittnite/proc" - "io/ioutil" - "log" - "os" - "os/signal" - "path/filepath" - "strings" + "github.com/mittwald/mittnite/cmd" + log "github.com/sirupsen/logrus" ) -type InitFlags struct { - ConfigDir string +func init() { + Formatter := new(log.TextFormatter) + Formatter.TimestampFormat = "02-01-2006 15:04:05" + Formatter.FullTimestamp = true + log.SetFormatter(Formatter) } -var ( - Version string - Commit string - BuiltAt string -) - func main() { - initFlags := InitFlags{} - - flag.StringVar(&initFlags.ConfigDir, "config-dir", "/etc/mittnite.d", "Directory from which to read configuration files") - flag.Parse() - - log.Printf("mittnite process manager, version %s (commit %s), built at %s", Version, Commit, BuiltAt) - log.Printf("looking for configuration files in %s", initFlags.ConfigDir) - - initFlags.ConfigDir = strings.TrimRight(initFlags.ConfigDir, "/") - - matches, err := filepath.Glob(initFlags.ConfigDir + "/*.hcl") - if err != nil { - panic(err) - } - - if len(matches) == 0 { - log.Fatalf("could not find any configuration files in %s", initFlags.ConfigDir) - } - - ignitionConfig := config.IgnitionConfig{} - - for _, m := range matches { - log.Printf("found config file: %s", m) - - contents, err := ioutil.ReadFile(m) - if err != nil { - panic(err) - } - - err = hcl.Unmarshal(contents, &ignitionConfig) - if err != nil { - err = fmt.Errorf("could not parse configuration file %s: %s", m, err.Error()) - panic(err) - } - } - - log.Println(ignitionConfig) - - err = files.RenderConfigurationFiles(ignitionConfig.Files) - if err != nil { - panic(err) - } - - signals := make(chan os.Signal) - signal.Notify(signals) - - readinessSignals := make(chan os.Signal, 1) - probeSignals := make(chan os.Signal, 1) - procSignals := make(chan os.Signal, 1) - - go func() { - for s := range signals { - log.Printf("received event %s", s.String()) - - readinessSignals <- s - probeSignals <- s - procSignals <- s - } - }() - - probeHandler, _ := probe.NewProbeHandler(&ignitionConfig) - - go func() { - err := probe.RunProbeServer(probeHandler, probeSignals) - if err != nil { - log.Printf("probe server stopped with error: %s", err) - panic(err) - } else { - log.Print("probe server stopped without error") - } - }() - - err = probeHandler.Wait(readinessSignals) - if err != nil { - panic(err) - } - - err = proc.RunServices(&ignitionConfig, procSignals) - if err != nil { - log.Printf("service runner stopped with error: %s", err) - panic(err) - } else { - log.Print("service runner stopped without error") - } + cmd.Execute() } diff --git a/files/render.go b/pkg/files/render.go similarity index 77% rename from files/render.go rename to pkg/files/render.go index 9b7eb59..29baabc 100644 --- a/files/render.go +++ b/pkg/files/render.go @@ -2,9 +2,9 @@ package files import ( "fmt" - "github.com/mittwald/mittnite/config" + "github.com/mittwald/mittnite/internal/types" + log "github.com/sirupsen/logrus" "io/ioutil" - "log" "os" "path/filepath" "strings" @@ -16,8 +16,8 @@ type templateData struct { Params map[string]interface{} } -func RenderConfigurationFiles(configs []config.FileConfig) error { - log.Printf("generating configuration files") +func RenderConfigurationFiles(configs []types.FileConfig) error { + log.Info("generating configuration files") for i := range configs { err := RenderConfigurationFile(&configs[i]) @@ -29,9 +29,9 @@ func RenderConfigurationFiles(configs []config.FileConfig) error { return nil } -func RenderConfigurationFile(cfg *config.FileConfig) error { +func RenderConfigurationFile(cfg *types.FileConfig) error { if cfg.Template != "" { - log.Printf("creating configuration file %s from template %s", cfg.Target, cfg.Template) + log.Infof("creating configuration file %s from template %s", cfg.Target, cfg.Template) tplContents, err := ioutil.ReadFile(cfg.Template) if err != nil { diff --git a/probe/probe_amqp.go b/pkg/probe/probe_amqp.go similarity index 60% rename from probe/probe_amqp.go rename to pkg/probe/probe_amqp.go index 7ca7b7f..9283b57 100644 --- a/probe/probe_amqp.go +++ b/pkg/probe/probe_amqp.go @@ -2,9 +2,10 @@ package probe import ( "fmt" - "github.com/mittwald/mittnite/config" + "github.com/mittwald/mittnite/internal/helper" + "github.com/mittwald/mittnite/internal/types" + log "github.com/sirupsen/logrus" "github.com/streadway/amqp" - "log" "net/url" ) @@ -17,13 +18,15 @@ type amqpProbe struct { password string hostname string virtualHost string + port string } -func NewAmqpProbe(cfg *config.AmqpConfig) *amqpProbe { - cfg.User = resolveEnv(cfg.User) - cfg.Password = resolveEnv(cfg.Password) - cfg.Hostname = resolveEnv(cfg.Hostname) - cfg.VirtualHost = resolveEnv(cfg.VirtualHost) +func NewAmqpProbe(cfg *types.AmqpConfig) *amqpProbe { + cfg.User = helper.ResolveEnv(cfg.User) + cfg.Password = helper.ResolveEnv(cfg.Password) + cfg.Hostname = helper.ResolveEnv(cfg.Hostname) + cfg.Port = helper.ResolveEnv(cfg.Port) + cfg.VirtualHost = helper.ResolveEnv(cfg.VirtualHost) if cfg.VirtualHost == "" { cfg.VirtualHost = defaultVirtualHost } @@ -33,6 +36,7 @@ func NewAmqpProbe(cfg *config.AmqpConfig) *amqpProbe { password: cfg.Password, hostname: cfg.Hostname, virtualHost: cfg.VirtualHost, + port: cfg.Port, } return &connCfg @@ -41,7 +45,7 @@ func NewAmqpProbe(cfg *config.AmqpConfig) *amqpProbe { func (a *amqpProbe) Exec() error { u := url.URL{ Scheme: "amqp", - Host: fmt.Sprintf("%s:%d", a.hostname, 5672), + Host: fmt.Sprintf("%s:%s", a.hostname, a.port), Path: a.virtualHost, } @@ -55,7 +59,7 @@ func (a *amqpProbe) Exec() error { } defer conn.Close() - log.Println("amqp is alive") + log.Info("amqp is alive") return nil } diff --git a/probe/probe_fs.go b/pkg/probe/probe_fs.go similarity index 100% rename from probe/probe_fs.go rename to pkg/probe/probe_fs.go diff --git a/probe/probe_http.go b/pkg/probe/probe_http.go similarity index 63% rename from probe/probe_http.go rename to pkg/probe/probe_http.go index 48c1760..3029730 100644 --- a/probe/probe_http.go +++ b/pkg/probe/probe_http.go @@ -2,8 +2,9 @@ package probe import ( "fmt" - "github.com/mittwald/mittnite/config" - "log" + "github.com/mittwald/mittnite/internal/helper" + "github.com/mittwald/mittnite/internal/types" + log "github.com/sirupsen/logrus" "net/http" "net/url" "time" @@ -16,20 +17,20 @@ type httpGetProbe struct { timeout string } -func NewHttpProbe(cfg *config.HttpGetConfig) *httpGetProbe { - cfg.Scheme = resolveEnv(cfg.Scheme) - cfg.Host = resolveEnv(cfg.Host) - cfg.Port = resolveEnv(cfg.Port) - cfg.Path = resolveEnv(cfg.Path) - cfg.Timeout = resolveEnv(cfg.Timeout) +func NewHttpProbe(cfg *types.HttpGetConfig) *httpGetProbe { + cfg.Scheme = helper.ResolveEnv(cfg.Scheme) + cfg.Hostname = helper.ResolveEnv(cfg.Hostname) + cfg.Port = helper.ResolveEnv(cfg.Port) + cfg.Path = helper.ResolveEnv(cfg.Path) + cfg.Timeout = helper.ResolveEnv(cfg.Timeout) if cfg.Scheme == "" { cfg.Scheme = "http" } - host := cfg.Host - if cfg.Port != "" { - host += ":" + cfg.Port + host := cfg.Host.Hostname + if cfg.Host.Port != "" { + host += fmt.Sprintf("%s:%s", cfg.Hostname, cfg.Port) } connCfg := httpGetProbe{ @@ -69,7 +70,7 @@ func (h *httpGetProbe) Exec() error { } if res.StatusCode >= 200 && res.StatusCode < 400 { - log.Printf("http service '%s' is alive", urlStr) + log.Infof("http service '%s' is alive", urlStr) return nil } diff --git a/probe/probe_mongodb.go b/pkg/probe/probe_mongodb.go similarity index 63% rename from probe/probe_mongodb.go rename to pkg/probe/probe_mongodb.go index c226002..d1463e6 100644 --- a/probe/probe_mongodb.go +++ b/pkg/probe/probe_mongodb.go @@ -3,11 +3,12 @@ package probe import ( "context" "fmt" - "github.com/mittwald/mittnite/config" + "github.com/mittwald/mittnite/internal/helper" + "github.com/mittwald/mittnite/internal/types" + log "github.com/sirupsen/logrus" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/readpref" - "log" "net/url" "time" ) @@ -17,19 +18,21 @@ type mongoDBProbe struct { password string hostname string database string + port string } -func NewMongoDBProbe(cfg *config.MongoDBConfig) *mongoDBProbe { - cfg.User = resolveEnv(cfg.User) - cfg.Password = resolveEnv(cfg.Password) - cfg.Host = resolveEnv(cfg.Host) - cfg.Database = resolveEnv(cfg.Database) +func NewMongoDBProbe(cfg *types.MongoDBConfig) *mongoDBProbe { + cfg.User = helper.ResolveEnv(cfg.User) + cfg.Password = helper.ResolveEnv(cfg.Password) + cfg.Hostname = helper.ResolveEnv(cfg.Hostname) + cfg.Database = helper.ResolveEnv(cfg.Database) connCfg := mongoDBProbe{ user: cfg.User, password: cfg.Password, - hostname: cfg.Host, + hostname: cfg.Hostname, database: cfg.Database, + port: cfg.Port, } return &connCfg @@ -38,7 +41,7 @@ func NewMongoDBProbe(cfg *config.MongoDBConfig) *mongoDBProbe { func (m *mongoDBProbe) Exec() error { u := url.URL{ Scheme: "mongodb", - Host: fmt.Sprintf("%s:%d", m.hostname, 27017), + Host: fmt.Sprintf("%s:%s", m.hostname, m.port), Path: m.database, } @@ -61,7 +64,7 @@ func (m *mongoDBProbe) Exec() error { return err } - log.Println("mongodb is alive") + log.Info("mongodb is alive") return nil } diff --git a/pkg/probe/probe_mysql.go b/pkg/probe/probe_mysql.go new file mode 100644 index 0000000..96de04c --- /dev/null +++ b/pkg/probe/probe_mysql.go @@ -0,0 +1,55 @@ +package probe + +import ( + "database/sql" + "fmt" + "github.com/go-sql-driver/mysql" + "github.com/mittwald/mittnite/internal/helper" + "github.com/mittwald/mittnite/internal/types" + log "github.com/sirupsen/logrus" +) + +type mySQLProbe struct { + dsn string +} + +func NewMySQLProbe(cfg *types.MySQLConfig) *mySQLProbe { + cfg.User = helper.ResolveEnv(cfg.User) + cfg.Database = helper.ResolveEnv(cfg.Database) + cfg.Password = helper.ResolveEnv(cfg.Password) + cfg.Hostname = helper.ResolveEnv(cfg.Hostname) + cfg.Port = helper.ResolveEnv(cfg.Port) + + connCfg := mysql.Config{ + User: cfg.User, + Passwd: cfg.Password, + Net: "tcp", + Addr: fmt.Sprintf("%s:%s", cfg.Host, cfg.Port), + DBName: cfg.Database, + } + + return &mySQLProbe{ + dsn: connCfg.FormatDSN(), + } +} + +func (m *mySQLProbe) Exec() error { + db, err := sql.Open("mysql", m.dsn) + if err != nil { + return err + } + + log.Info("connected") + + defer db.Close() + r, err := db.Query("SELECT 1") + if err != nil { + return err + } + + log.Info("selected successfully") + + r.Close() + + return nil +} diff --git a/pkg/probe/probe_redis.go b/pkg/probe/probe_redis.go new file mode 100644 index 0000000..e3723b3 --- /dev/null +++ b/pkg/probe/probe_redis.go @@ -0,0 +1,39 @@ +package probe + +import ( + "fmt" + "github.com/go-redis/redis" + "github.com/mittwald/mittnite/internal/helper" + "github.com/mittwald/mittnite/internal/types" + log "github.com/sirupsen/logrus" +) + +type redisProbe struct { + addr string + password string +} + +func NewRedisProbe(cfg *types.RedisConfig) *redisProbe { + cfg.Hostname = helper.ResolveEnv(cfg.Hostname) + cfg.Password = helper.ResolveEnv(cfg.Password) + cfg.Port = helper.ResolveEnv(cfg.Port) + + return &redisProbe{ + addr: fmt.Sprintf("%s:%s", cfg.Hostname, cfg.Port), + password: cfg.Password, + } +} + +func (r *redisProbe) Exec() error { + client := redis.NewClient(&redis.Options{ + Addr: r.addr, + Password: r.password, + }) + + _, err := client.Ping().Result() + if err != nil { + return err + } + log.Info("redis is alive") + return nil +} diff --git a/probe/server.go b/pkg/probe/server.go similarity index 85% rename from probe/server.go rename to pkg/probe/server.go index 7f97e9d..ab59c94 100644 --- a/probe/server.go +++ b/pkg/probe/server.go @@ -4,10 +4,9 @@ import ( "context" "encoding/json" "errors" - "fmt" "github.com/gorilla/mux" - "github.com/mittwald/mittnite/config" - "log" + "github.com/mittwald/mittnite/internal/types" + log "github.com/sirupsen/logrus" "net/http" "os" "syscall" @@ -15,14 +14,13 @@ import ( ) type ProbeHandler struct { - cfg *config.IgnitionConfig - + cfg *types.IgnitionConfig probes map[string]Probe waitProbes map[string]Probe } func (s *ProbeHandler) Wait(interrupt chan os.Signal) error { - log.Println("waiting for probe readiness") + log.Info("waiting for probe readiness") timer := time.NewTicker(1 * time.Second) @@ -34,7 +32,7 @@ func (s *ProbeHandler) Wait(interrupt chan os.Signal) error { for i := range s.waitProbes { err := s.waitProbes[i].Exec() if err != nil { - log.Printf("probe %s is not yet ready: %s", i, err) + log.Warnf("probe %s is not yet ready: %s", i, err) ready = false } } @@ -81,7 +79,7 @@ func (s *ProbeHandler) HandleStatus(res http.ResponseWriter, req *http.Request) success = success && result.OK case <-timeout.C: success = false - fmt.Println("probe timed out") + log.Error("probe timed out") break } } @@ -95,7 +93,7 @@ func (s *ProbeHandler) HandleStatus(res http.ResponseWriter, req *http.Request) _ = json.NewEncoder(res).Encode(&response) } -func NewProbeHandler(cfg *config.IgnitionConfig) (*ProbeHandler, error) { +func NewProbeHandler(cfg *types.IgnitionConfig) (*ProbeHandler, error) { probes := buildProbesFromConfig(cfg) waitProbes := filterWaitProbes(cfg, probes) @@ -115,7 +113,7 @@ func RunProbeServer(ph *ProbeHandler, signals chan os.Signal) error { go func() { for s := range signals { if s == syscall.SIGINT || s == syscall.SIGTERM { - log.Printf("shutting down monitoring server after receiving %s", s.String()) + log.Fatalf("shutting down monitoring server after receiving %s", s.String()) _ = server.Shutdown(context.Background()) } } @@ -129,7 +127,7 @@ func RunProbeServer(ph *ProbeHandler, signals chan os.Signal) error { return nil } -func filterWaitProbes(cfg *config.IgnitionConfig, probes map[string]Probe) map[string]Probe { +func filterWaitProbes(cfg *types.IgnitionConfig, probes map[string]Probe) map[string]Probe { result := make(map[string]Probe) for i := range cfg.Probes { if cfg.Probes[i].Wait { @@ -139,7 +137,7 @@ func filterWaitProbes(cfg *config.IgnitionConfig, probes map[string]Probe) map[s return result } -func buildProbesFromConfig(cfg *config.IgnitionConfig) map[string]Probe { +func buildProbesFromConfig(cfg *types.IgnitionConfig) map[string]Probe { result := make(map[string]Probe) for i := range cfg.Probes { if cfg.Probes[i].Filesystem != "" { diff --git a/probe/types.go b/pkg/probe/types.go similarity index 100% rename from probe/types.go rename to pkg/probe/types.go diff --git a/proc/runner.go b/pkg/proc/runner.go similarity index 57% rename from proc/runner.go rename to pkg/proc/runner.go index 4163028..b4fd584 100644 --- a/proc/runner.go +++ b/pkg/proc/runner.go @@ -2,8 +2,8 @@ package proc import ( "fmt" - "github.com/mittwald/mittnite/config" - "log" + "github.com/mittwald/mittnite/internal/types" + log "github.com/sirupsen/logrus" "os" "os/exec" "sync" @@ -11,7 +11,7 @@ import ( "time" ) -func RunServices(cfg *config.IgnitionConfig, signals chan os.Signal) error { +func RunServices(cfg *types.IgnitionConfig, signals chan os.Signal) error { errs := make(chan error) signalsOut := make([]chan os.Signal, len(cfg.Jobs)) @@ -23,9 +23,9 @@ func RunServices(cfg *config.IgnitionConfig, signals chan os.Signal) error { go func() { for sig := range signals { - log.Printf("jobrunner: received signal %s", sig.String()) + log.Infof("jobrunner: received signal %s", sig.String()) if sig == syscall.SIGINT || sig == syscall.SIGTERM { - log.Printf("stopping service runner") + log.Info("stopping service runner") stop = true } @@ -40,22 +40,22 @@ func RunServices(cfg *config.IgnitionConfig, signals chan os.Signal) error { for i := range cfg.Jobs { var cmd *exec.Cmd - go func(job *config.JobConfig, signals <-chan os.Signal) { + go func(job *types.JobConfig, signals <-chan os.Signal) { for sig := range signals { if cmd != nil && cmd.Process != nil { - log.Printf("passing signal %s to job %s", sig.String(), job.Name) + log.Infof("passing signal %s to job %s", sig.String(), job.Name) _ = cmd.Process.Signal(sig) } } }(&cfg.Jobs[i], signalsOut[i]) for i := range cfg.Jobs[i].Watches { - go func(j int, w *config.WatchConfig) { + go func(j int, w *types.WatchConfig) { var mtime time.Time stat, err := os.Stat(w.Filename) if err == nil { - log.Printf("file %s's last modification was %s", w.Filename, stat.ModTime().String()) + log.Infof("file %s's last modification was %s", w.Filename, stat.ModTime().String()) mtime = stat.ModTime() } @@ -64,7 +64,7 @@ func RunServices(cfg *config.IgnitionConfig, signals chan os.Signal) error { for range timer.C { stat, err = os.Stat(w.Filename) if err == nil && mtime != stat.ModTime() && cmd != nil && cmd.Process != nil { - log.Printf("file %s changed, signalling process %s", w.Filename, cfg.Jobs[j].Name) + log.Infof("file %s changed, signalling process %s", w.Filename, cfg.Jobs[j].Name) _ = cmd.Process.Signal(syscall.Signal(w.Signal)) mtime = stat.ModTime() } @@ -73,7 +73,7 @@ func RunServices(cfg *config.IgnitionConfig, signals chan os.Signal) error { } wg.Add(1) - go func(job config.JobConfig, errs chan<- error) { + go func(job types.JobConfig, errs chan<- error) { defer wg.Done() maxAttempts := job.MaxAttempts @@ -84,7 +84,7 @@ func RunServices(cfg *config.IgnitionConfig, signals chan os.Signal) error { } for !stop { - log.Printf("starting job %s", job.Name) + log.Infof("starting job %s", job.Name) cmd = exec.Command(job.Command, job.Args...) cmd.Stdout = os.Stdout @@ -94,18 +94,27 @@ func RunServices(cfg *config.IgnitionConfig, signals chan os.Signal) error { err := cmd.Wait() if err != nil { - log.Printf("job %s exited with error: %s", job.Name, err) + if job.CanFail { + log.Warnf("Failable job %s exited with error: %s", job.Name, err) + } else { + log.Errorf("job %s exited with error: %s", job.Name, err) + } failedAttempts++ if failedAttempts >= maxAttempts { - log.Printf("reached max retries for job %s", job.Name) - errs <- fmt.Errorf("reached max retries for job %s", job.Name) - break + if job.CanFail { + log.Warnf("reached max retries for job %s", job.Name) + stop = true + } else { + log.Errorf("reached max retries for job %s", job.Name) + errs <- fmt.Errorf("reached max retries for job %s", job.Name) + break + } } } } - log.Printf("ending job %s", job.Name) + log.Infof("ending job %s", job.Name) }(cfg.Jobs[i], errs) } @@ -120,8 +129,8 @@ func RunServices(cfg *config.IgnitionConfig, signals chan os.Signal) error { select { case <-allDone: case err := <-errs: - log.Println("job return error, shutting down other services") - signals <- syscall.SIGINT //notify other (already running) jobs to shut down + log.Error("job return error, shutting down other services") + signals <- syscall.SIGINT // notify other (already running) jobs to shut down return err } diff --git a/probe/probe_mysql.go b/probe/probe_mysql.go deleted file mode 100644 index e87a4f6..0000000 --- a/probe/probe_mysql.go +++ /dev/null @@ -1,52 +0,0 @@ -package probe - -import ( - "database/sql" - "github.com/go-sql-driver/mysql" - "github.com/mittwald/mittnite/config" - "log" -) - -type mySQLProbe struct { - dsn string -} - -func NewMySQLProbe(cfg *config.MySQLConfig) *mySQLProbe { - cfg.User = resolveEnv(cfg.User) - cfg.Database = resolveEnv(cfg.Database) - cfg.Password = resolveEnv(cfg.Password) - cfg.Host = resolveEnv(cfg.Host) - - connCfg := mysql.Config{ - User: cfg.User, - Passwd: cfg.Password, - Net: "tcp", - Addr: cfg.Host + ":3306", - DBName: cfg.Database, - } - - return &mySQLProbe{ - dsn: connCfg.FormatDSN(), - } -} - -func (m *mySQLProbe) Exec() error { - db, err := sql.Open("mysql", m.dsn) - if err != nil { - return err - } - - log.Println("connected") - - defer db.Close() - r, err := db.Query("SELECT 1") - if err != nil { - return err - } - - log.Println("selected successfully") - - r.Close() - - return nil -} diff --git a/probe/probe_redis.go b/probe/probe_redis.go deleted file mode 100644 index 569298f..0000000 --- a/probe/probe_redis.go +++ /dev/null @@ -1,31 +0,0 @@ -package probe - -import ( - "github.com/go-redis/redis" - "github.com/mittwald/mittnite/config" -) - -type redisProbe struct { - addr string - password string -} - -func NewRedisProbe(cfg *config.RedisConfig) *redisProbe { - cfg.Host = resolveEnv(cfg.Host) - cfg.Password = resolveEnv(cfg.Password) - - return &redisProbe{ - addr: cfg.Host + ":6379", - password: cfg.Password, - } -} - -func (r *redisProbe) Exec() error { - client := redis.NewClient(&redis.Options{ - Addr: r.addr, - Password: r.password, - }) - - _, err := client.Ping().Result() - return err -}