diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1f0a2c9..3092c9a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -2,8 +2,8 @@ name: tests -on: - push: +on: # yamllint disable-line rule:truthy + push: {} pull_request: branches: [main] diff --git a/Makefile b/Makefile index 9695762..fa2842d 100644 --- a/Makefile +++ b/Makefile @@ -52,18 +52,18 @@ PKG_DIST_DIR ?= $(abspath $(makefile_dir)/..) PKG_TGZ_NAME = chkok-$(CHKOK_VERSION)-$(OS)-$(ARCH).tar.gz PKG_TGZ_PATH = $(PKG_DIST_DIR)/$(PKG_TGZ_NAME) PKG_CHECKSUM_NAME = chkok-$(CHKOK_VERSION)-SHA256SUMS -PBUILDER_COMPONENTS ?= "main universe" -PBUILDER_RC ?= $(makefile_dir)build/package/pbuilderrc -PBUILDER_HOOKS_DIR ?= $(makefile_dir)build/package/pbuilder-hooks +# PBUILDER_COMPONENTS ?= "main universe" +# PBUILDER_RC ?= $(makefile_dir)build/package/pbuilderrc +# PBUILDER_HOOKS_DIR ?= $(makefile_dir)build/package/pbuilder-hooks RPM_DEV_TREE ?= $(HOME)/rpmbuild # find Debian package version from the changelog file. latest version # should be at the top, first matching 'chkok (0.1.0-1) ...' and sed clears chars not in version -CHKOK_DEB_VERSION := $(shell grep --only-matching --max-count 1 --perl-regexp "^\s*chkok\s+\(.+\)\s*" build/package/debian/changelog | sed 's/[^0-9.-]//g') -CHKOK_DEB_UPSTREAM_VERSION := $(shell echo $(CHKOK_DEB_VERSION) | grep --only-matching --perl-regexp '^[0-9.]+') -CHKOK_DEB_UPSTREAM_TARBAL_PATH := $(abspath $(makefile_dir)/..) -CHKOK_DEB_UPSTREAM_TARBAL := $(CHKOK_DEB_UPSTREAM_TARBAL_PATH)/chkok_$(CHKOK_DEB_UPSTREAM_VERSION).orig.tar.gz -DEB_BUILD_GIT_BRANCH := pkg-deb-$(CHKOK_DEB_VERSION)-$(TIMESTAMP_MINUTE) +# CHKOK_DEB_VERSION := $(shell grep --only-matching --max-count 1 --perl-regexp "^\s*chkok\s+\(.+\)\s*" build/package/debian/changelog | sed 's/[^0-9.-]//g') +# CHKOK_DEB_UPSTREAM_VERSION := $(shell echo $(CHKOK_DEB_VERSION) | grep --only-matching --perl-regexp '^[0-9.]+') +# CHKOK_DEB_UPSTREAM_TARBAL_PATH := $(abspath $(makefile_dir)/..) +# CHKOK_DEB_UPSTREAM_TARBAL := $(CHKOK_DEB_UPSTREAM_TARBAL_PATH)/chkok_$(CHKOK_DEB_UPSTREAM_VERSION).orig.tar.gz +# DEB_BUILD_GIT_BRANCH := pkg-deb-$(CHKOK_DEB_VERSION)-$(TIMESTAMP_MINUTE) # find rpm version from the spec file. latest version # should be in the top tags, first matching 'Version: 0.1.0' and sed clears chars not in version @@ -72,7 +72,7 @@ RPM_DEV_SRC_TGZ = $(RPM_DEV_TREE)/SOURCES/chkok-$(CHKOK_RPM_VERSION).tar.gz RPM_DEV_SPEC = $(RPM_DEV_TREE)/SPECS/chkok-$(CHKOK_RPM_VERSION).spec # command aliases -cowbuilder = env DISTRIBUTION=$(DIST) ARCH=$(ARCH) BASEPATH=/var/cache/pbuilder/base-$(DIST)-$(ARCH).cow cowbuilder +# cowbuilder = env DISTRIBUTION=$(DIST) ARCH=$(ARCH) BASEPATH=/var/cache/pbuilder/base-$(DIST)-$(ARCH).cow cowbuilder chkok: @@ -101,38 +101,38 @@ clean: distclean: clean # override prefix so .deb package installs binaries to /usr/bin instead of /usr/local/bin -pkg-deb: export prefix = /usr +# pkg-deb: export prefix = /usr # requires a cowbuilder environment. see pkg-deb-setup -pkg-deb: - git checkout -b $(DEB_BUILD_GIT_BRANCH) - rm -f $(CHKOK_DEB_UPSTREAM_TARBAL); tar --exclude-backups --exclude-vcs -zcf $(CHKOK_DEB_UPSTREAM_TARBAL) . - cp -r build/package/debian debian; git add debian; git commit -m 'add debian dir for packaging v$(CHKOK_DEB_VERSION)' - gbp buildpackage --git-ignore-new --git-verbose --git-pbuilder \ - --git-no-create-orig --git-tarball-dir=$(CHKOK_DEB_UPSTREAM_TARBAL_PATH) \ - --git-hooks \ - --git-dist=$(DIST) --git-arch=$(ARCH) \ - --git-ignore-new --git-ignore-branch \ - --git-pbuilder-options='--configfile=$(PBUILDER_RC) --hookdir=$(PBUILDER_HOOKS_DIR) --buildresult=$(PKG_DIST_DIR)' \ - -b -us -uc -sa - git checkout $(GIT_CURRENT_BRANCH) - git branch -D $(DEB_BUILD_GIT_BRANCH) +# pkg-deb: +# git checkout -b $(DEB_BUILD_GIT_BRANCH) +# rm -f $(CHKOK_DEB_UPSTREAM_TARBAL); tar --exclude-backups --exclude-vcs -zcf $(CHKOK_DEB_UPSTREAM_TARBAL) . +# cp -r build/package/debian debian; git add debian; git commit -m 'add debian dir for packaging v$(CHKOK_DEB_VERSION)' +# gbp buildpackage --git-ignore-new --git-verbose --git-pbuilder \ +# --git-no-create-orig --git-tarball-dir=$(CHKOK_DEB_UPSTREAM_TARBAL_PATH) \ +# --git-hooks \ +# --git-dist=$(DIST) --git-arch=$(ARCH) \ +# --git-ignore-new --git-ignore-branch \ +# --git-pbuilder-options='--configfile=$(PBUILDER_RC) --hookdir=$(PBUILDER_HOOKS_DIR) --buildresult=$(PKG_DIST_DIR)' \ +# -b -us -uc -sa +# git checkout $(GIT_CURRENT_BRANCH) +# git branch -D $(DEB_BUILD_GIT_BRANCH) # required: # sudo apt-get install build-essential debhelper pbuilder fakeroot cowbuilder git-buildpackage devscripts ubuntu-dev-tools -pkg-deb-setup: - echo "creating a git-pbuilder environment with apt repositories to install new go versions ..." - DIST=$(DIST) ARCH=$(ARCH) git-pbuilder create --components=$(PBUILDER_COMPONENTS) \ - --extrapackages="cowdancer curl wget" --configfile=$(PBUILDER_RC) \ - --hookdir=$(PBUILDER_HOOKS_DIR) +# pkg-deb-setup: +# echo "creating a git-pbuilder environment with apt repositories to install new go versions ..." +# DIST=$(DIST) ARCH=$(ARCH) git-pbuilder create --components=$(PBUILDER_COMPONENTS) \ +# --extrapackages="cowdancer curl wget" --configfile=$(PBUILDER_RC) \ +# --hookdir=$(PBUILDER_HOOKS_DIR) pkg-tgz: build - tar --create --gzip --exclude-vcs --exclude=docs/man/*.rst --file $(PKG_TGZ_PATH) chkok README.rst LICENSE + tar --create --gzip --exclude-vcs --exclude=docs/man/*.rst --file $(PKG_TGZ_PATH) chkok \ + README.rst LICENSE docs/man/chkok.1 examples/config.yaml # override prefix so .rpm package installs binaries to /usr/bin instead of /usr/local/bin pkg-rpm: export prefix = /usr -# requires golang compiler > 1.13, and rpmdevtools package +# requires golang compiler > 1.22, and rpmdevtools package pkg-rpm: - (go version | grep -q 'go1.[01]') && (echo "please install Go lang tools > 1.20. aborting!" && /bin/false) rm -f $(RPM_DEV_SRC_TGZ) tar --exclude-vcs -zcf $(RPM_DEV_SRC_TGZ) . cp build/package/chkok.spec $(RPM_DEV_SPEC) @@ -161,16 +161,16 @@ pkg-checksum: sync-version: @ # update first occurrence of version in man page source and regen the man page @ sed -i 's/^:Version:.*/:Version: $(CHKOK_VERSION)/;t' docs/man/chkok.rst && $(MAKE) docs - @ # update first occurrence of version in RPM spec + @ # update first occurrence of version in RPM spec @ sed -i 's/^Version:.*/Version: $(CHKOK_VERSION)/;t' build/package/chkok.spec - @ (grep --max 1 --only --perl-regexp '^chkok.+\(.+\).+' build/package/debian/changelog | grep -q -F $(CHKOK_VERSION)) || \ + @ # (grep --max 1 --only --perl-regexp '^chkok.+\(.+\).+' build/package/debian/changelog | grep -q -F $(CHKOK_VERSION)) || \ echo -e "\e[33m*** NOTE:\e[m version $(CHKOK_VERSION) maybe missing from Debian changelog" @ (grep --line-regexp '%changelog' -A 50 build/package/chkok.spec | grep -q -F $(CHKOK_VERSION)) || \ echo -e "\e[33m*** NOTE:\e[m version $(CHKOK_VERSION) maybe missing from RPM changelog" -# required: python docutils +# required: python docutils. install python3-docutils docs: - rst2man.py --input-encoding=utf8 --output-encoding=utf8 --strict docs/man/chkok.rst docs/man/chkok.1 + rst2man --input-encoding=utf8 --output-encoding=utf8 --strict docs/man/chkok.rst docs/man/chkok.1 .DEFAULT_GOAL := build .PHONY: test build test-build install pkg-deb pkg-clean pkg-deb-setup pkg-tgz pkg-checksum sync-version docs diff --git a/README.rst b/README.rst index ce31975..3e9722c 100644 --- a/README.rst +++ b/README.rst @@ -2,27 +2,93 @@ Chkok ***** -.. image:: https://travis-ci.org/farzadghanei/chkok.svg?branch=master - :target: https://travis-ci.org/farzadghanei/chkok - - -``chkok`` checks if system resources are OK, and provides a report to demonstrate system health and resource availablity. - +"chkok" checks if attributes of files and sockets match the provided conditions to ensure +system state is as expected. It can be used to monitor system health and resource availability. +Provides different running modes, useful for reporting to local and remote monitoring. It's written in Go, has a small resource overhead with no runtime dependencies. Usage ----- -todo +Run in CLI mode (default): + +``` +chkok -conf examples/config.yaml +``` + +Run in HTTP mode, starting an HTTP server on the configured port: + +``` +chkok -conf examples/config.yaml -verbose -mode http +``` Configuration ------------- -todo + +Configuration is done via a YAML file. + +`runners` section configures how the checks should be run. The runner configurations +are merged with the `default`` runner configuration. + +.. code-block:: yaml + + runners: + default: + timeout: 5m + # response_ok: "OK" + # response_fail: "FAILED" + # response_timeout: "TIMEOUT" + cli: {} # override default runner only for CLI mode + http: # override default runner only for HTTP mode + listen_address: "127.0.0.1:51234" + # request_read_timeout: 2s + # response_write_timeout: 2s + # timeout: 5s + # max_header_bytes: 8192 + # max_concurrent_requests: 1 # 0 means no limit + # request_required_headers: + # "X-Required-Header": "required-value" + # "X-Required-Header2": "" # header existence is required, not value + + +The `check_suites` section defines the checks to be run. Each check suite +is a logical group of checks that should run sequentially. +Each check defines the expected properties of the resource (file or socket) +to be checked. + +.. code-block:: yaml + + check_suites: + etc: + - type: dir + path: /etc + mode: 0755 + user: root + group: root + - type: file + path: /etc/passwd + min_size: 10 + - type: file + path: /etc/group + min_size: 5 + max_size: 10000 + default: + - type: file + path: /unwanted/file + absent: true + - type: dial + network: tcp + address: "localhost:22" + timeout: 500ms + + +See the `examples` directory for sample configuration files. License ------- -``chkok`` is an open source project released under the terms of the `MIT license `_. -See LICENSE file for more details. +"chkok" is an open source project released under the terms of the `MIT license `_. +It uses yaml.v3 library which is licensed under the MIT and Apache License 2.0 licenses. +See LICENSE file for more details. \ No newline at end of file diff --git a/build/package/chkok.spec b/build/package/chkok.spec new file mode 100644 index 0000000..35d6f06 --- /dev/null +++ b/build/package/chkok.spec @@ -0,0 +1,51 @@ +Name: chkok +Version: 0.3.0 +Release: 1%{?dist} +Summary: Checks if system resources are OK + +License: MIT +URL: https://github.com/farzadghanei/chkok +Source0: %{name}-%{version}.tar.gz + +# will use official golang tarballs instead, until go 1.22 rpm is in most repos +# BuildRequires: golang > 1.22, golang-gopkg-yaml-3-devel > 3.0.0 + +%description +"chkok" checks if system resources are OK, and provides a report to demonstrate +system health and resource availability. + +# go toolchain stores go build id in a different ELF note than GNU toolchain +# so RPM can't find the build id from the binaries after build. +# https://github.com/rpm-software-management/rpm/issues/367 +%global _missing_build_ids_terminate_build 0 +%define debug_package %{nil} + +%prep +%setup -c -q + +%build +%make_build + + +%install +rm -rf $RPM_BUILD_ROOT +%make_install +mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1 +cp -a docs/man/chkok.1 $RPM_BUILD_ROOT/usr/share/man/man1/%{name}.1 + + +%clean +rm -rf $RPM_BUILD_ROOT + + +%files +%license LICENSE +%doc README.rst +%{_bindir}/%{name} +%{_mandir}/man1/%{name}* + + +%changelog +* Sat May 11 2024 Farzad Ghanei 0.3.0-1 +- Add support for required headers for http runner +- Add maxHeaderBytes configuration for http runner diff --git a/docs/man/chkok.1 b/docs/man/chkok.1 new file mode 100644 index 0000000..34ce13f --- /dev/null +++ b/docs/man/chkok.1 @@ -0,0 +1,142 @@ +.\" Man page generated from reStructuredText. +. +. +.nr rst2man-indent-level 0 +. +.de1 rstReportMargin +\\$1 \\n[an-margin] +level \\n[rst2man-indent-level] +level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] +- +\\n[rst2man-indent0] +\\n[rst2man-indent1] +\\n[rst2man-indent2] +.. +.de1 INDENT +.\" .rstReportMargin pre: +. RS \\$1 +. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] +. nr rst2man-indent-level +1 +.\" .rstReportMargin post: +.. +.de UNINDENT +. RE +.\" indent \\n[an-margin] +.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] +.nr rst2man-indent-level -1 +.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] +.in \\n[rst2man-indent\\n[rst2man-indent-level]]u +.. +.TH "CHKOK" 1 "2024-05-11" "0.3.0" "General Command Manuals" +.SH NAME +chkok \- Check if file attributes are OK +.SH SYNOPSIS +.INDENT 0.0 +.INDENT 3.5 +chkok [OPTIONS] +.UNINDENT +.UNINDENT +.SH DESCRIPTION +.sp +chkok checks if attributes of files and sockets match the provided conditions to ensure +system state is as expected. It can be used to monitor system health and resource availability. +Provides different running modes, useful for reporting to local and remote monitoring. +.SH OPTIONS +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +\-conf string + path to configuration file in YAML format (default \(dq/etc/chkok.yaml\(dq) +\-mode string + running mode: cli,http (default \(dqcli\(dq) +\-verbose + more output, include logs +.ft P +.fi +.UNINDENT +.UNINDENT +.SH CONFIGURATION +.sp +Configuration is done via a YAML file. +.sp +\fIrunners\fP section configures how the checks should be run. The runner configurations +are merged with the \fIdefault\fP runner configuration. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +runners: + default: + timeout: 5m + # response_ok: \(dqOK\(dq + # response_fail: \(dqFAILED\(dq + # response_timeout: \(dqTIMEOUT\(dq + cli: {} # override default runner only for CLI mode + http: # override default runner only for HTTP mode + listen_address: \(dq127.0.0.1:51234\(dq + # request_read_timeout: 2s + # response_write_timeout: 2s + # timeout: 5s + # max_header_bytes: 8192 + # max_concurrent_requests: 1 # 0 means no limit + # request_required_headers: + # \(dqX\-Required\-Header\(dq: \(dqrequired\-value\(dq + # \(dqX\-Required\-Header2\(dq: \(dq\(dq # header existence is required, not value +.ft P +.fi +.UNINDENT +.UNINDENT +.sp +The \fIcheck_suites\fP section defines the checks to be run. Each check suite +is a logical group of checks that should run sequentially. +Each check defines the expected properties of the resource (file or socket) +to be checked. +.INDENT 0.0 +.INDENT 3.5 +.sp +.nf +.ft C +check_suites: + etc: + \- type: dir + path: /etc + mode: 0755 + user: root + group: root + \- type: file + path: /etc/passwd + min_size: 10 + \- type: file + path: /etc/group + min_size: 5 + max_size: 10000 + default: + \- type: file + path: /unwanted/file + absent: true + \- type: dial + network: tcp + address: \(dqlocalhost:22\(dq + timeout: 500ms +.ft P +.fi +.UNINDENT +.UNINDENT +.SH FILES +.INDENT 0.0 +.TP +.B \fB/etc/chkok.yaml\fP +The default configuration file, if available should contain valid configuration in YAML format. +.UNINDENT +.SH REPORTING BUGS +.sp +Bugs can be reported with \fI\%https://github.com/farzadghanei/chkok/issues\fP +.SH AUTHOR +Farzad Ghanei +.SH COPYRIGHT +Copyright (c) 2024 Farzad Ghanei. chkok is an open source project released under the terms of the MIT license. +.\" Generated by docutils manpage writer. +. diff --git a/docs/man/chkok.rst b/docs/man/chkok.rst new file mode 100644 index 0000000..a453733 --- /dev/null +++ b/docs/man/chkok.rst @@ -0,0 +1,110 @@ +===== +chkok +===== + +------------------------------- +Check if file attributes are OK +------------------------------- + +:Author: Farzad Ghanei +:Date: 2024-05-11 +:Copyright: Copyright (c) 2024 Farzad Ghanei. chkok is an open source project released under the terms of the MIT license. +:Version: 0.3.0 +:Manual section: 1 +:Manual group: General Command Manuals + + +SYNOPSIS +======== + chkok [OPTIONS] + + +DESCRIPTION +=========== +chkok checks if attributes of files and sockets match the provided conditions to ensure +system state is as expected. It can be used to monitor system health and resource availability. +Provides different running modes, useful for reporting to local and remote monitoring. + +OPTIONS +======= + +.. code-block:: + + -conf string + path to configuration file in YAML format (default "/etc/chkok.yaml") + -mode string + running mode: cli,http (default "cli") + -verbose + more output, include logs + + +CONFIGURATION +============= + +Configuration is done via a YAML file. + +`runners` section configures how the checks should be run. The runner configurations +are merged with the `default` runner configuration. + +.. code-block:: yaml + + runners: + default: + timeout: 5m + # response_ok: "OK" + # response_fail: "FAILED" + # response_timeout: "TIMEOUT" + cli: {} # override default runner only for CLI mode + http: # override default runner only for HTTP mode + listen_address: "127.0.0.1:51234" + # request_read_timeout: 2s + # response_write_timeout: 2s + # timeout: 5s + # max_header_bytes: 8192 + # max_concurrent_requests: 1 # 0 means no limit + # request_required_headers: + # "X-Required-Header": "required-value" + # "X-Required-Header2": "" # header existence is required, not value + + +The `check_suites` section defines the checks to be run. Each check suite +is a logical group of checks that should run sequentially. +Each check defines the expected properties of the resource (file or socket) +to be checked. + +.. code-block:: yaml + + check_suites: + etc: + - type: dir + path: /etc + mode: 0755 + user: root + group: root + - type: file + path: /etc/passwd + min_size: 10 + - type: file + path: /etc/group + min_size: 5 + max_size: 10000 + default: + - type: file + path: /unwanted/file + absent: true + - type: dial + network: tcp + address: "localhost:22" + timeout: 500ms + + +FILES +===== + +**\/etc\/chkok.yaml** + The default configuration file, if available should contain valid configuration in YAML format. + + +REPORTING BUGS +============== +Bugs can be reported with https://github.com/farzadghanei/chkok/issues diff --git a/examples/config.yaml b/examples/config.yaml index f15eafb..04265b5 100644 --- a/examples/config.yaml +++ b/examples/config.yaml @@ -4,7 +4,6 @@ runners: default: timeout: 5m # response_ok: "OK" - response_ok: "↑" # any unicode string can be used, '↑' is just an example # response_fail: "FAILED" # response_timeout: "TIMEOUT" cli: {} # override default runner only for CLI mode @@ -23,7 +22,7 @@ runners: # max_concurrent_requests: 1 # 0 means no limit # request_required_headers: # "X-Required-Header": "required-value" - # "X-Required-Header2": "" # header existance is required, not value + # "X-Required-Header2": "" # header existence is required, not value check_suites: @@ -39,19 +38,19 @@ check_suites: - type: file path: /etc/group min_size: 5 - max_size: 10 + max_size: 10000 default: - type: file path: /unwanted/file absent: true - type: dial network: tcp - address: "localhost:8080" + address: "localhost:123" absent: true timeout: 500ms - type: dial network: tcp - address: "localhost:80" + address: "localhost:22" timeout: 500ms ... diff --git a/examples/test-http.yaml b/examples/test-http.yaml index 69cc91c..a3b6d86 100644 --- a/examples/test-http.yaml +++ b/examples/test-http.yaml @@ -18,7 +18,7 @@ runners: shutdown_signal_header: "test-shutdown-signal" timeout: 5s request_required_headers: - "X-Required-Header2": "" # header existance is required + "X-Required-Header2": "" # header existence is required check_suites: diff --git a/internal/conf_test.go b/internal/conf_test.go index 38ce68d..d032269 100644 --- a/internal/conf_test.go +++ b/internal/conf_test.go @@ -36,13 +36,9 @@ func TestReadConf(t *testing.T) { t.Errorf("invalid read conf, want default runner") } wantMinutes := 5 - wantResponseOK := "↑" // test unicode support if runner.Timeout.Minutes() != float64(wantMinutes) { t.Errorf("invalid read conf default runner, want %v timeout got %v", wantMinutes, runner.Timeout.Minutes()) } - if *runner.ResponseOK != wantResponseOK { - t.Errorf("invalid read conf default runner, want %v response got %v", wantResponseOK, runner.ResponseOK) - } etcChecks, ok := conf.CheckSuites["etc"] if !ok { t.Errorf("read conf found no etc checks")