diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..84c048a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/Dockerfile b/Dockerfile index c04d8807..086897bb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,20 +5,15 @@ ENV CGO_ENABLED 0 COPY . /src/icinga-notifications WORKDIR /src/icinga-notifications -RUN mkdir bin RUN --mount=type=cache,target=/go/pkg/mod \ --mount=type=cache,target=/root/.cache/go-build \ - go build -o bin/ ./cmd/icinga-notifications + make all -RUN mkdir bin/channel -RUN --mount=type=cache,target=/go/pkg/mod \ - --mount=type=cache,target=/root/.cache/go-build \ - go build -o bin/channel/ ./cmd/channel/... +RUN make DESTDIR=/target install FROM docker.io/library/alpine -COPY --from=build /src/icinga-notifications/bin/icinga-notifications /usr/bin/icinga-notifications -COPY --from=build /src/icinga-notifications/bin/channel /usr/libexec/icinga-notifications/channel +COPY --from=build /target / RUN apk add tzdata @@ -28,4 +23,4 @@ RUN adduser -u 1000 -H -D -G $username $username USER $username EXPOSE 5680 -CMD ["/usr/bin/icinga-notifications", "--config", "/etc/icinga-notifications/config.yml"] +CMD ["/usr/sbin/icinga-notifications"] diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..e41bbe51 --- /dev/null +++ b/Makefile @@ -0,0 +1,43 @@ +# These variables follow the naming convention from the GNU Make documentation +# but their defaults correspond to the rest of the code (note that changing +# libexecdir here wouldn't affect the default path for the channel plugin +# directory used by the dameon for example). +# +# https://www.gnu.org/software/make/manual/html_node/Directory-Variables.html +prefix ?= /usr +sbindir ?= $(prefix)/sbin +libexecdir ?= $(prefix)/libexec +datadir ?= $(prefix)/share +sysconfdir ?= /etc + +all: pkg = github.com/icinga/icinga-notifications/internal +all: + mkdir -p build + go build \ + -o build/ \ + -ldflags "-X '$(pkg).LibExecDir=$(libexecdir)' -X '$(pkg).SysConfDir=$(sysconfdir)'" \ + ./cmd/icinga-notifications + go build -o build/channel/ ./cmd/channel/... + +test: + go test ./... + +install: + @# config + install -d $(DESTDIR)$(sysconfdir)/icinga-notifications + install -m644 config.example.yml $(DESTDIR)$(sysconfdir)/icinga-notifications/config.yml + @# dameon + install -D build/icinga-notifications $(DESTDIR)$(sbindir)/icinga-notifications + @# channel plugins + install -d $(DESTDIR)$(libexecdir)/icinga-notifications/channel + install build/channel/* $(DESTDIR)$(libexecdir)/icinga-notifications/channel/ + @# database schema + install -d $(DESTDIR)$(datadir)/icinga-notifications + cp -rv --no-dereference schema $(DESTDIR)$(datadir)/icinga-notifications + @# chmod ensures consistent permissions when cp is called with umask != 022 + chmod -R u=rwX,go=rX $(DESTDIR)$(datadir)/icinga-notifications/schema + +clean: + rm -rf build + +.PHONY: all test install clean diff --git a/cmd/icinga-notifications/main.go b/cmd/icinga-notifications/main.go index 23d0bfa7..3dea365f 100644 --- a/cmd/icinga-notifications/main.go +++ b/cmd/icinga-notifications/main.go @@ -26,7 +26,7 @@ func main() { var configPath string var showVersion bool - flag.StringVar(&configPath, "config", "", "path to config file") + flag.StringVar(&configPath, "config", internal.SysConfDir+"/icinga-notifications/config.yml", "path to config file") flag.BoolVar(&showVersion, "version", false, "print version") flag.Parse() @@ -43,11 +43,6 @@ func main() { return } - if configPath == "" { - _, _ = fmt.Fprintln(os.Stderr, "missing -config flag") - os.Exit(1) - } - err := daemon.LoadConfig(configPath) if err != nil { _, _ = fmt.Fprintln(os.Stderr, "cannot load config:", err) diff --git a/config.example.yml b/config.example.yml index 8b800d05..3d126a63 100644 --- a/config.example.yml +++ b/config.example.yml @@ -7,7 +7,7 @@ #debug-password: "put-something-secret-here" icingaweb2-url: http://localhost/icingaweb2/ -channel-plugin-dir: /usr/libexec/icinga-notifications/channel +#channel-plugin-dir: /usr/libexec/icinga-notifications/channel api-timeout: 1m database: diff --git a/internal/daemon/config.go b/internal/daemon/config.go index 309f53b5..e612cc6a 100644 --- a/internal/daemon/config.go +++ b/internal/daemon/config.go @@ -6,6 +6,7 @@ import ( "github.com/goccy/go-yaml" "github.com/icinga/icinga-go-library/database" "github.com/icinga/icinga-go-library/logging" + "github.com/icinga/icinga-notifications/internal" "os" "time" ) @@ -13,13 +14,23 @@ import ( type ConfigFile struct { Listen string `yaml:"listen" default:"localhost:5680"` DebugPassword string `yaml:"debug-password"` - ChannelPluginDir string `yaml:"channel-plugin-dir" default:"/usr/libexec/icinga-notifications/channel"` + ChannelPluginDir string `yaml:"channel-plugin-dir"` ApiTimeout time.Duration `yaml:"api-timeout" default:"1m"` Icingaweb2URL string `yaml:"icingaweb2-url"` Database database.Config `yaml:"database"` Logging logging.Config `yaml:"logging"` } +// SetDefaults implements the defaults.Setter interface. +func (c *ConfigFile) SetDefaults() { + if defaults.CanUpdate(c.ChannelPluginDir) { + c.ChannelPluginDir = internal.LibExecDir + "/icinga-notifications/channel" + } +} + +// Assert interface compliance. +var _ defaults.Setter = (*ConfigFile)(nil) + // config holds the configuration state as a singleton. It is used from LoadConfig and Config var config *ConfigFile diff --git a/internal/paths.go b/internal/paths.go new file mode 100644 index 00000000..01f2681c --- /dev/null +++ b/internal/paths.go @@ -0,0 +1,7 @@ +package internal + +// These variables exist to allow overwriting the paths using `go build -ldflags "-X ...", see Makefile. +var ( + LibExecDir = "/usr/libexec" + SysConfDir = "/etc" +)