diff --git a/.codeclimate.yml b/.codeclimate.yml
deleted file mode 100644
index ea45cf1d1..000000000
--- a/.codeclimate.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-version: "2"
-checks:
- return-statements:
- config:
- threshold: 6
-plugins:
- gofmt:
- enabled: true
- golint:
- enabled: true
- govet:
- enabled: true
-
-exclude_patterns:
- - "!**/**.go"
- - "**/*_test.go"
- - "resource/resource_list.go"
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 5286f7f65..5b773c6a8 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -13,3 +13,14 @@ updates:
- "aelsabbahy"
open-pull-requests-limit: 0
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ day: "saturday"
+
+ - package-ecosystem: "pip"
+ directory: "/docs"
+ schedule:
+ interval: "weekly"
+ day: "saturday"
diff --git a/.github/workflows/docker-goss.yaml b/.github/workflows/docker-goss.yaml
new file mode 100644
index 000000000..78e07bdcd
--- /dev/null
+++ b/.github/workflows/docker-goss.yaml
@@ -0,0 +1,98 @@
+name: Docker image for Goss
+
+on:
+ push:
+ branches:
+ - master
+ tags:
+ - "v*"
+ workflow_dispatch:
+
+env:
+ PLATFORMS: "linux/amd64,linux/arm64"
+
+jobs:
+ goss:
+ name: Build and push Docker image
+ runs-on: ubuntu-latest
+ permissions:
+ packages: write
+ contents: read
+ security-events: write # To upload Trivy sarif files
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to GHCR
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.repository_owner }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels) for Docker
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: |
+ ghcr.io/${{ github.repository_owner }}/goss
+
+ - name: Get latest git tag
+ uses: actions-ecosystem/action-get-latest-tag@v1
+ id: get-latest-tag
+
+ - name: Set short git commit SHA
+ run: |
+ calculatedSha=$(git rev-parse --short ${{ github.sha }})
+ echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV
+
+ - name: Get the current version of Go from project.
+ run: echo "GO_VERSION_FROM_PROJECT=$(go mod edit -json | jq -r .Go)" >> $GITHUB_ENV
+
+ - name: Build master goss image
+ if: github.ref_name == 'master'
+ uses: docker/build-push-action@v5
+ with:
+ build-args: |
+ GO_VERSION=${{ env.GO_VERSION_FROM_PROJECT }}
+ GOSS_VERSION=${{ steps.get-latest-tag.outputs.tag }}-${{ github.ref_name }}+${{ env.COMMIT_SHORT_SHA }}
+ context: .
+ push: true
+ tags: |
+ ghcr.io/${{ github.repository_owner }}/goss:master
+ labels: ${{ steps.meta.outputs.labels }}
+ platforms: ${{ env.PLATFORMS }}
+
+ - name: Build release goss image
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
+ uses: docker/build-push-action@v5
+ with:
+ build-args: |
+ GO_VERSION=${{ env.GO_VERSION_FROM_PROJECT }}
+ GOSS_VERSION=${{ github.ref_name }}
+ context: .
+ push: true
+ tags: |
+ ghcr.io/${{ github.repository_owner }}/goss:latest
+ ghcr.io/${{ github.repository_owner }}/goss:${{ github.ref_name }}
+ labels: ${{ steps.meta.outputs.labels }}
+ platforms: ${{ env.PLATFORMS }}
+
+ - name: Run Trivy vulnerability scanner
+ uses: aquasecurity/trivy-action@master
+ with:
+ image-ref: ghcr.io/${{ github.repository_owner }}/goss:master
+ format: "sarif"
+ output: "trivy-results.sarif"
+
+ - name: Upload Trivy scan results to GitHub Security tab
+ uses: github/codeql-action/upload-sarif@v3
+ with:
+ sarif_file: "trivy-results.sarif"
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index 6a80c4abd..f7a871e6c 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -7,7 +7,7 @@ on:
pull_request:
paths:
- mkdocs.yml
- - docs/
+ - docs/**
- README.md
- LICENSE
- extras/**/README.md
@@ -20,28 +20,31 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- - uses: DavidAnson/markdownlint-cli2-action@v13
+ - uses: DavidAnson/markdownlint-cli2-action@v16
with:
globs: |
docs/**/*.md
+ README.md
+ extras/**/README.md
+ .github/CONTRIBUTING.md
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- - uses: actions/setup-python@v4
+ - uses: actions/setup-python@v5
with:
- python-version: "3.11"
+ python-version: "3.12"
cache: 'pip'
- name: Install dependencies
run: |
pip install --upgrade pip
- pip install --requirement docs/requirements.pip
+ pip install --requirement docs/requirements.txt
- name: Build documentation
run: mkdocs build
# To remove if not using github pages
- name: Upload artifact
- uses: actions/upload-pages-artifact@v2
+ uses: actions/upload-pages-artifact@v3
with:
path: site
diff --git a/.github/workflows/golangci.yaml b/.github/workflows/golangci.yaml
new file mode 100644
index 000000000..c04a58a99
--- /dev/null
+++ b/.github/workflows/golangci.yaml
@@ -0,0 +1,55 @@
+name: Golang ci
+on:
+ # don't build any branch other than master (and prs) when git pushed
+ pull_request: {}
+ push:
+ branches:
+ - master
+ - "/^v\\d+\\.\\d+(\\.\\d+)?(-\\S*)?$/"
+ paths-ignore:
+ - "**/*.md"
+
+permissions:
+ contents: read
+ pull-requests: read
+
+jobs:
+ lint:
+ name: lint
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+
+ - name: golangci-lint
+ uses: golangci/golangci-lint-action@v6
+ with:
+ version: v1.59
+
+ coverage:
+ needs: [lint]
+ name: coverage
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+
+ - name: Unit tests and coverage
+ run: make cov
+
+ integartion-test:
+ needs: [coverage]
+ name: Integration tests
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+
+ - name: Integration tests
+ run: make test-int-all
diff --git a/.github/workflows/preview-docs.yaml b/.github/workflows/preview-docs.yaml
index e2aebafa7..37a47a597 100644
--- a/.github/workflows/preview-docs.yaml
+++ b/.github/workflows/preview-docs.yaml
@@ -5,7 +5,7 @@ on:
- opened
paths:
- mkdocs.yml
- - docs/
+ - docs/**
- README.md
- LICENSE
- extras/**/README.md
diff --git a/.golangci.yaml b/.golangci.yaml
new file mode 100644
index 000000000..52977cfd6
--- /dev/null
+++ b/.golangci.yaml
@@ -0,0 +1,16 @@
+linters:
+ # Disable all linters.
+ # Default: false
+ disable-all: true
+ # Enable specific linter
+ # https://golangci-lint.run/usage/linters/#enabled-by-default
+ enable:
+ # default linter
+ # - errcheck # there are to many failures at the moment
+ - gosimple
+ - govet
+ - ineffassign
+ - staticcheck
+ - unused
+ # custom linter
+ - gofmt
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 3166424d8..015eb5de8 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -16,4 +16,4 @@ mkdocs:
# Optionally declare the Python requirements required to build your docs
python:
install:
- - requirements: docs/requirements.pip
+ - requirements: docs/requirements.txt
diff --git a/.travis.yml b/.travis.yml
index 8d6f824f9..caaa00d1c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,4 @@
---
-env:
- global:
- - secure: IH/xOtRl9rcek+YTz1s2lv2njdV1gob0AY21/kGhqUBH2sdztQ/02CteGz5E0c+LfqoUYQglLsejVCNLXQJI39CyZRzysB1wlVOz7YIPNaOLATtMGg0/8Mb7dpeqAV1u3agIi87q3ims1EkmGE9UGNj/qL75oTXBiozEfkbcsheH3Ju9CcO0i006UlNqAG4T++l1JZ4kPmr1r5eNjRu52oWQrlxaOYpZJGnT3qjxkvxcnI/Pgiem0+2aZ7Yluu0lA7UCFWyORoDRUz4pQR3uDG4ADPG4WcpJ601LDZyWtS7EOXVBgWZX9vV9ZVx63nK5w0W8NN6PQOuz0niN9iwR+FsShrPIsh6P9wVZfGifwXK4g2FL2XMBRuZCsQfrpRY6JbnuyGeMqN53ta95y0Yv4H65UQ7bulr4Lnic4+W52G/fl1VUYX8Bts+ecUydIu+afcDZ6GkpVLEURjaek99uO5ewHH7lfVAOQv4wUP8GFUyLXJumJZHvMzyiAXsTHdUZdm+Ap8EPzWFYYnMxySU39MEkIvhfG47X6sA7zAppuoNwd8vU4ZaxSdsme2InUSalETGJZ7ohL+M/tkTMyuyq8uLMRuwscNdgcCjGaHM19NQMrv4nsPmmzTeiDRoFk2wad07Mgsjy07esxw52rs3zAsa37+h74GYFWYo523AiYjw=
-
language: go
go:
@@ -31,18 +27,9 @@ before_install:
# bash from macOS is too old to have readarray. Install newer version.
- if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then HOMEBREW_NO_AUTO_UPDATE=1 brew install bash; fi
-install:
- - ./ci/install.sh
-
-before_script:
- - ./ci/before-build.sh
-
script:
- ./ci/build.sh
-after_script:
- - ./ci/after-build.sh
-
# deploy:
# provider: releases
# api_key:
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 000000000..93a143a3d
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,19 @@
+ARG GO_VERSION=1.21
+
+FROM docker.io/golang:${GO_VERSION}-alpine AS base
+
+ARG GOSS_VERSION=v0.0.0
+WORKDIR /build
+
+RUN --mount=target=. \
+ CGO_ENABLED=0 go build \
+ -ldflags "-X github.com/goss-org/goss/util.Version=${GOSS_VERSION} -s -w" \
+ -o "/release/goss" \
+ ./cmd/goss
+
+FROM alpine:3.19
+
+COPY --from=base /release/* /usr/bin/
+
+RUN mkdir /goss
+VOLUME /goss
diff --git a/Makefile b/Makefile
index 99cbb7514..724e66187 100644
--- a/Makefile
+++ b/Makefile
@@ -35,10 +35,10 @@ htmlcov:
go test -v -coverpkg=./... -coverprofile=c.out ./...
go tool cover -html ./c.out
-
lint:
$(info INFO: Starting build $@)
- golint $(pkgs) || true
+ go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59
+ golangci-lint run --timeout 5m $(pkgs) || true
vet:
$(info INFO: Starting build $@)
@@ -96,8 +96,8 @@ test-darwin-all: test-short-all test-int-darwin-all
test-linux-all: test-short-all test-int-64 test-int-32
test-windows-all: test-short-all test-int-windows-all
-test-int-64: centos7 wheezy trusty alpine3 arch test-int-serve-linux-amd64
-test-int-32: centos7-32 wheezy-32 trusty-32 alpine3-32 arch-32
+test-int-64: rockylinux9 wheezy trusty alpine3 arch test-int-serve-linux-amd64
+test-int-32: rockylinux9-32 wheezy-32 trusty-32 alpine3-32 arch-32
test-int-darwin-all: test-int-validate-darwin-amd64 test-int-serve-darwin-amd64
test-int-windows-all: test-int-validate-windows-amd64 test-int-serve-windows-amd64
test-int-all: test-int-32 test-int-64
@@ -105,6 +105,10 @@ test-int-all: test-int-32 test-int-64
centos7-32: build
$(info INFO: Starting build $@)
cd integration-tests/ && ./test.sh centos7 386
+.PHONY: rockylinux9-32
+rockylinux9-32: build
+ $(info INFO: Starting build $@)
+ cd integration-tests/ && ./test.sh rockylinux9 386
wheezy-32: build
$(info INFO: Starting build $@)
cd integration-tests/ && ./test.sh wheezy 386
@@ -120,6 +124,10 @@ arch-32: build
centos7: build
$(info INFO: Starting build $@)
cd integration-tests/ && ./test.sh centos7 amd64
+.PHONY: rockylinux9
+rockylinux9: build
+ $(info INFO: Starting build $@)
+ cd integration-tests/ && ./test.sh rockylinux9 amd64
wheezy: build
$(info INFO: Starting build $@)
cd integration-tests/ && ./test.sh wheezy amd64
@@ -146,10 +154,10 @@ $(PYTHON):
$(info Creating virtualenv in $(VENV))
@python -m venv $(VENV)
-$(DOCS_DEPS): $(PYTHON) docs/requirements.pip
+$(DOCS_DEPS): $(PYTHON) docs/requirements.txt
$(info Installing dependencies)
@pip install --upgrade pip
- @pip install --requirement docs/requirements.pip
+ @pip install --requirement docs/requirements.txt
@touch $(DOCS_DEPS)
docs/setup: $(DOCS_DEPS)
diff --git a/README.md b/README.md
index 02ede20cb..cc5d40434 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@
-**Note:** For testing docker containers see the [dgoss](https://github.com/goss-org/goss/tree/master/extras/dgoss) wrapper.
+**Note:** For testing containers see the [dgoss](https://github.com/goss-org/goss/tree/master/extras/dgoss) wrapper.
Also, user submitted wrapper scripts for Kubernetes [kgoss](https://github.com/goss-org/goss/tree/master/extras/kgoss)
and Docker Compose [dcgoss](https://github.com/goss-org/goss/tree/master/extras/dcgoss).
@@ -95,6 +95,10 @@ make build
[Full Documentation](https://github.com/goss-org/goss/blob/e73553f9c3065ac297499dafb4f8abef6acb24ad/docs/manual.md)
+## Using the container image
+
+[Using the Goss container image](docs/container_image.md)
+
## Quick start
diff --git a/ci/after-build.sh b/ci/after-build.sh
deleted file mode 100755
index 8970a6375..000000000
--- a/ci/after-build.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-os_name="$(go env GOOS)"
-
-if [[ "${os_name}" != "windows" ]]; then
- ./cc-test-reporter after-build --exit-code "${TRAVIS_TEST_RESULT}" -d
-fi
diff --git a/ci/before-build.sh b/ci/before-build.sh
deleted file mode 100755
index 0c5475d4f..000000000
--- a/ci/before-build.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-os_name="$(go env GOOS)"
-
-if [[ "${os_name}" != "windows" ]]; then
- ./cc-test-reporter before-build
-fi
diff --git a/ci/install.sh b/ci/install.sh
deleted file mode 100755
index 8dea0dab3..000000000
--- a/ci/install.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-os_name="$(go env GOOS)"
-
-go get -u golang.org/x/lint/golint
-
-if [[ "${os_name}" != "windows" ]]; then
- curl -L "https://codeclimate.com/downloads/test-reporter/test-reporter-latest-${os_name}-amd64" > "./cc-test-reporter"
- chmod +x "./cc-test-reporter"
-fi
diff --git a/cmd/goss/goss.go b/cmd/goss/goss.go
index e7ff90540..0c6a061a2 100644
--- a/cmd/goss/goss.go
+++ b/cmd/goss/goss.go
@@ -423,14 +423,6 @@ func addAlphaFlagIfNeeded(app *cli.App) {
}
}
-const msgFormat string = `WARNING: goss for this platform (%q) is alpha-quality, work-in-progress and community-supported.
-
-You should not expect everything to work. Treat linux as the canonical behaviour to expect.
-
-Please see https://github.com/goss-org/goss/tree/master/docs/platform-feature-parity.md to set your expectations and see progress.
-Please file issues via https://github.com/goss-org/goss/issues/new/choose
-Pull requests and bug reports very welcome.`
-
func fatalAlphaIfNeeded(c *cli.Context) {
if runtime.GOOS == "darwin" || runtime.GOOS == "windows" {
if c.GlobalString("use-alpha") != "1" {
diff --git a/docs/.pages b/docs/.pages
index 67373453b..bed10fe4c 100644
--- a/docs/.pages
+++ b/docs/.pages
@@ -2,6 +2,7 @@ nav:
- Home: index.md
- installation.md
- quickstart.md
+ - container_image.md
- Command Reference: cli.md
- The gossfile: gossfile.md
- migrations.md
diff --git a/docs/cli.md b/docs/cli.md
index d7b1bf62e..f72b0bfb4 100644
--- a/docs/cli.md
+++ b/docs/cli.md
@@ -62,12 +62,12 @@ GLOBAL OPTIONS:
## Commands
Commands are the actions goss can run.
-- [add](#add): add a single test for a resource
-- [autoadd](#autoadd): automatically add multiple tests for a resource
-- [render](#render): renders and outputs the gossfile, importing all included gossfiles
-- [serve](#serve): serves the gossfile validation as an HTTP endpoint on a specified address and port,
+* [add](#add): add a single test for a resource
+* [autoadd](#autoadd): automatically add multiple tests for a resource
+* [render](#render): renders and outputs the gossfile, importing all included gossfiles
+* [serve](#serve): serves the gossfile validation as an HTTP endpoint on a specified address and port,
so you can use your gossfile as a health report for the host
-- [validate](#validate): runs the goss test suite on your server
+* [validate](#validate): runs the goss test suite on your server
### `add`
@@ -123,22 +123,22 @@ A sub-command *resource type* has to be provided when running `add`.
Automatically [adds](#add) all **existing** resources matching the provided argument.
Will automatically add the following matching resources:
-- `file` - only if argument contains `/`
-- `group`
-- `package`
-- `port`
-- `process` - Also adding any ports it's listening to (if run as root)
-- `service`
-- `user`
+* `file` - only if argument contains `/`
+* `group`
+* `package`
+* `port`
+* `process` - Also adding any ports it's listening to (if run as root)
+* `service`
+* `user`
Will **NOT** automatically add:
-- `addr`
-- `command` - for safety
-- `dns`
-- `http`
-- `interface`
-- `kernel-param`
-- `mount`
+* `addr`
+* `command` - for safety
+* `dns`
+* `http`
+* `interface`
+* `kernel-param`
+* `mount`
!!! example
```console
diff --git a/docs/container_image.md b/docs/container_image.md
new file mode 100644
index 000000000..ba12d30f7
--- /dev/null
+++ b/docs/container_image.md
@@ -0,0 +1,53 @@
+# Goss container image
+
+## Dockerfiles
+
+* [latest](https://github.com/goss-org/goss/blob/master/Dockerfile)
+
+## Using the base image
+
+This is a simple alpine image with Goss preinstalled on it.
+Can be used as a base image for your projects to allow for easy health checking.
+
+### Mount example
+
+Create the container
+
+```sh
+docker run --name goss ghcr.io/goss-org/goss goss
+```
+
+Create your container and mount goss
+
+```sh
+docker run --rm -it --volumes-from goss --name weby nginx
+```
+
+Run goss inside your container
+
+```sh
+docker exec weby /goss/goss autoadd nginx
+```
+
+### HEALTHCHECK example
+
+```dockerfile
+FROM ghcr.io/goss-org/goss:latest
+
+COPY goss/ /goss/
+HEALTHCHECK --interval=1s --timeout=6s CMD goss -g /goss/goss.yaml validate
+
+# your stuff..
+```
+
+### Startup delay example
+
+```dockerfile
+FROM ghcr.io/goss-org/goss:latest
+
+COPY goss/ /goss/
+
+# Alternatively, the -r option can be set
+# using the GOSS_RETRY_TIMEOUT env variable
+CMD goss -g /goss/goss.yaml validate -r 5m && exec real_comand..
+```
diff --git a/docs/containers/docker-compose.md b/docs/containers/docker-compose.md
index 9219adf97..3955acc5a 100644
--- a/docs/containers/docker-compose.md
+++ b/docs/containers/docker-compose.md
@@ -1 +1,2 @@
+
--8<-- "extras/dcgoss/README.md"
diff --git a/docs/containers/docker.md b/docs/containers/docker.md
index 07daf5c87..e17d0e635 100644
--- a/docs/containers/docker.md
+++ b/docs/containers/docker.md
@@ -1 +1,2 @@
+
--8<-- "extras/dgoss/README.md"
diff --git a/docs/containers/kubernetes.md b/docs/containers/kubernetes.md
index b696d2f54..83a0bbb53 100644
--- a/docs/containers/kubernetes.md
+++ b/docs/containers/kubernetes.md
@@ -1 +1,2 @@
+
--8<-- "extras/kgoss/README.md"
diff --git a/docs/contributing.md b/docs/contributing.md
index 0c7bc9cbf..1a1055c5e 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -1 +1,2 @@
+
--8<-- ".github/CONTRIBUTING.md"
diff --git a/docs/gossfile.md b/docs/gossfile.md
index 31f259adf..a463c2ceb 100644
--- a/docs/gossfile.md
+++ b/docs/gossfile.md
@@ -918,6 +918,27 @@ Available functions:
`toUpper`
: Changes piped input to UPPERCASE
+ `findStringSubmatch regex string`
+ : Returns map[string]interface{} with the names of the parenthesized subexpressions, like `(?P[a-z])`
+
+ {{ $regexDBrc := "\\'mysql:\\/\\/(?P[a-z0-9]+):(?P[a-z0-9]+)@localhost\\/(?Proundcube_[a-z0-9]+)\\';"}}
+
+ {{ $rcConf := readFile /home/user/roundcube/config.inc.php | findStringSubmatch $regexDBrc }}
+ {{ $UserDBrc := get $rcConf "login" }}
+ {{ $PassDBrc := get $rcConf "password" }}
+ {{ $DBrc := get $rcConf "database" }}
+
+ If not exists named parenthesized subexps, returns stringfied array string:
+
+ {{ $regexDBrc := "\\'mysql:\\/\\/([a-z0-9]+):([a-z0-9]+)@localhost\\/(roundcube_[a-z0-9]+)\\';"}}
+
+ {{ $rcConf := readFile /home/user/roundcube/config.inc.php | findStringSubmatch $regexDBrc }}
+ {{ $UserDBrc := get $rcConf "1" }}
+ {{ $PassDBrc := get $rcConf "2" }}
+ {{ $DBrc := get $rcConf "3" }}
+
+ NOTE: stringfied string array begins with "1" ("0" is all the string matched)
+
!!! warning
gossfiles containing text/template `{{}}` controls will no longer work with `goss add/autoadd`.
diff --git a/docs/license.md b/docs/license.md
index f409d4523..e47f1b546 100644
--- a/docs/license.md
+++ b/docs/license.md
@@ -1 +1,2 @@
+
--8<-- "LICENSE"
diff --git a/docs/migrations.md b/docs/migrations.md
index f6981f4c0..9b4ef5ec4 100644
--- a/docs/migrations.md
+++ b/docs/migrations.md
@@ -16,8 +16,8 @@ user:
- root
```
-Goss v0.4.x, will fail with the above as group "root" is only in the slice once. However, with goss v0.4.x the array may contain
-matchers. The test below is valid for v0.4.x but not valid for v0.3.x
+Goss v0.4.x, will fail with the above as group "root" is only in the slice once. However, with goss v0.4.x the array may
+contain matchers. The test below is valid for v0.4.x but not valid for v0.3.x
```yaml
user:
diff --git a/docs/requirements.pip b/docs/requirements.txt
similarity index 58%
rename from docs/requirements.pip
rename to docs/requirements.txt
index cfa4c09da..7e1b447f5 100644
--- a/docs/requirements.pip
+++ b/docs/requirements.txt
@@ -1,6 +1,6 @@
-mkdocs-material==9.5.3
+mkdocs-material==9.5.23
mkdocs-macros-plugin==1.0.5
mkdocs-awesome-pages-plugin==2.9.2
+mkdocs-exclude==1.0.2
mdx-breakless-lists==1.0.1
-pygments==2.17.2
-
+pygments==2.18.0
diff --git a/extras/dcgoss/README.md b/extras/dcgoss/README.md
index 06d64498a..9eedf65ec 100644
--- a/extras/dcgoss/README.md
+++ b/extras/dcgoss/README.md
@@ -1,6 +1,7 @@
# dcgoss
-dcgoss is a convenience wrapper around goss that aims to bring the simplicity of goss to docker-compose managed containers. It is based on `dgoss`.
+dcgoss is a convenience wrapper around goss that aims to bring the simplicity of goss to docker-compose managed
+containers. It is based on `dgoss`.
## Usage
@@ -8,7 +9,9 @@ dcgoss is a convenience wrapper around goss that aims to bring the simplicity of
### Run
-Run is used to validate a docker container defined in `docker-compose.yml`. It expects both a `docker-compose.yml` and `goss.yaml` file to exist in the directory it was invoked from. Container configuration is used from the compose file, for example:
+Run is used to validate a docker container defined in `docker-compose.yml`. It expects both a `docker-compose.yml`
+and `goss.yaml` file to exist in the directory it was invoked from. Container configuration is used from the
+compose file, for example:
**run:**
@@ -43,7 +46,7 @@ The following environment variables can be set to change the behavior of dcgoss.
#### DEBUG
Enables debug output of `dcgoss`.
-
+
When running in debug mode, the tmp dir with the container output will not be cleaned up.
**Default:** empty
@@ -54,7 +57,7 @@ When running in debug mode, the tmp dir with the container output will not be cl
#### GOSS_PATH
-Location of the goss binary to use.
+Location of the goss binary to use.
**Default:** `$(which goss)`
@@ -104,8 +107,9 @@ If unset (or empty), the `--vars` flag is omitted, which is the normal behavior.
#### GOSS_FILES_STRATEGY
-Strategy used for copying goss files into the docker container.
-If set to `'mount'` a volume with goss files is mounted and log output is streamed into the container as `/goss/docker_output.log` file.
+Strategy used for copying goss files into the docker container.
+If set to `'mount'` a volume with goss files is mounted and log output is streamed into the container as
+`/goss/docker_output.log` file.
Other strategy is `'cp'` which uses `'docker cp'` command to copy goss files into docker container.
With the `'cp'` strategy you lose the ability to write tests or waits against the docker output.
The `'cp'` strategy is required especially when docker daemon is not on the local machine.
@@ -114,7 +118,8 @@ The `'cp'` strategy is required especially when docker daemon is not on the loca
## Debugging test runs
-When debugging test execution its beneficual to set both `DEBUG=true` and `GOSS_WAIT_OPTS=-r 60s -s 5s` (without the redirect to `/dev/null`).
+When debugging test execution its beneficual to set both `DEBUG=true` and `GOSS_WAIT_OPTS=-r 60s -s 5s`
+(without the redirect to `/dev/null`).
**Example:**
diff --git a/extras/dgoss/README.md b/extras/dgoss/README.md
index 324e850a2..ebe7fd3fd 100644
--- a/extras/dgoss/README.md
+++ b/extras/dgoss/README.md
@@ -1,12 +1,14 @@
# dgoss
-dgoss is a convenience wrapper around goss that aims to bring the simplicity of goss to docker containers.
+dgoss is a convenience wrapper around goss that aims to bring the simplicity of goss to containers.
## Examples and Tutorials
-* [blog tutorial](https://medium.com/@aelsabbahy/tutorial-how-to-test-your-docker-image-in-half-a-second-bbd13e06a4a9) - Introduction to dgoss tutorial
+* [blog tutorial](https://medium.com/@aelsabbahy/tutorial-how-to-test-your-docker-image-in-half-a-second-bbd13e06a4a9) -
+Introduction to dgoss tutorial
* [video tutorial](https://youtu.be/PEHz5EnZ-FM) - Same as above, but in video format
-* [dgoss-examples](https://github.com/aelsabbahy/dgoss-examples) - Repo containing examples of using dgoss to validate docker images
+* [dgoss-examples](https://github.com/aelsabbahy/dgoss-examples) - Repo containing examples of using dgoss to validate
+container images
## Installation
@@ -43,9 +45,10 @@ dgoss run ...
### Run
-Run is used to validate a docker container.
+Run is used to validate a container.
It expects a `./goss.yaml` file to exist in the directory it was invoked from.
-In most cases one can just substitute the docker command for the dgoss command, for example:
+In most cases one can just substitute the runtime command (`docker` or `podman`)
+for the dgoss command, for example:
**run:**
@@ -59,13 +62,15 @@ In most cases one can just substitute the docker command for the dgoss command,
* Run the container with the flags you specified.
* Stream the containers log output into the container as `/goss/docker_output.log`
- * This allows writing tests or waits against the docker output
+ * This allows writing tests or waits against the container output
* (optional) Run `goss` with `$GOSS_WAIT_OPTS` if `./goss_wait.yaml` file exists in the current dir
* Run `goss` with `$GOSS_OPTS` using `./goss.yaml`
### Edit
-Edit will launch a docker container, install goss, and drop the user into an interactive shell. Once the user quits the interactive shell, any `goss.yaml` or `goss_wait.yaml` are copied out into the current directory. This allows the user to leverage the `goss add|autoadd` commands to write tests as they would on a regular machine.
+Edit will launch a container, install goss, and drop the user into an interactive shell.
+Once the user quits the interactive shell, any `goss.yaml` or `goss_wait.yaml` are copied out into the current directory.
+This allows the user to leverage the `goss add|autoadd` commands to write tests as they would on a regular machine.
**Example:**
@@ -113,20 +118,25 @@ directory `DGOSS_TEMP_DIR`. (Default: `''`)
#### GOSS_VARS
The name of the variables file relative to `GOSS_FILES_PATH` to copy into the
-docker container and use for valiation (i.e. `dgoss run`) and copy out of the
-docker container when writing tests (i.e. `dgoss edit`). If set, the
+container and use for valiation (i.e. `dgoss run`) and copy out of the
+container when writing tests (i.e. `dgoss edit`). If set, the
`--vars` flag is passed to `goss validate` commands inside the container.
If unset (or empty), the `--vars` flag is omitted, which is the normal behavior.
(Default: `''`).
#### GOSS_FILES_STRATEGY
-Strategy used for copying goss files into the docker container. If set to `'mount'` a volume with goss files is mounted and log output is streamed into the container as `/goss/docker_output.log` file. Other strategy is `'cp'` which uses `'docker cp'` command to copy goss files into docker container. With the `'cp'` strategy you lose the ability to write tests or waits against the docker output. The `'cp'` strategy is required especially when docker daemon is not on the local machine.
+Strategy used for copying goss files into the container. If set to `'mount'` a volume with goss files is mounted
+and log output is streamed into the container as `/goss/docker_output.log` file. Other strategy is `'cp'` which uses
+`'docker cp'` command to copy goss files into container. With the `'cp'` strategy you lose the ability to write
+tests or waits against the container output. The `'cp'` strategy is required especially when container daemon is not on the
+local machine.
(Default `'mount'`)
#### CONTAINER_LOG_OUTPUT
-Location of the file that contains tested container logs. Logs are retained only if the variable is set to a non-empty string. (Default `''`)
+Location of the file that contains tested container logs. Logs are retained only if the variable is set to a non-empty
+string. (Default `''`)
#### DGOSS_TEMP_DIR
@@ -134,4 +144,5 @@ Location of the temporary directory used by dgoss. (Default `'$(mktemp -d /tmp/t
#### CONTAINER_RUNTIME
-Container runtime to use - `docker` or `podman`. Defaults to `docker`. Note that `podman` requires a run command to keep the container running. This defaults to `sleep infinity` in case only an image is passed to `dgoss` commands.
\ No newline at end of file
+Container runtime to use - `docker` or `podman`. Defaults to `docker`. Note that `podman` requires a run command to keep
+the container running. This defaults to `sleep infinity` in case only an image is passed to `dgoss` commands.
diff --git a/extras/kgoss/README.md b/extras/kgoss/README.md
index ae3cbb047..eb9f14d47 100644
--- a/extras/kgoss/README.md
+++ b/extras/kgoss/README.md
@@ -23,10 +23,10 @@ You can manually install kgoss and goss by going through the Web UI, getting
the files and putting them in the right path. To get each of them:
* **kgoss**: Run `curl -sSLO
- https://raw.githubusercontent.com/goss-org/goss/master/extras/kgoss/kgoss`.
+ https://raw.githubusercontent.com/goss-org/goss/master/extras/kgoss/kgoss`.
* **goss**: Download the `goss-linux-amd64` asset from
and rename it `goss`. Place it
- in your HOME directory, e.g. C:\\Users\\ on Windows; or set the
+ in your HOME directory, e.g. `C:\Users\` on Windows; or set the
environment variable `GOSS_PATH` to its path.
### Automatic / CLI
@@ -96,7 +96,7 @@ To find `goss.yaml` in another directory specify that directory's path in `GOSS_
### Run
-The `run` command is used to validate a docker container. It expects a
+The `run` command is used to validate a container. It expects a
`./goss.yaml` file to exist in the directory it was invoked from.
**Example:**
@@ -111,7 +111,7 @@ The `run` command is used to validate a docker container. It expects a
### Edit
-Edit will launch a docker container, install goss, and drop the user into an
+Edit will launch a container, install goss, and drop the user into an
interactive shell. Once the user quits the interactive shell, any `goss.yaml`
or `goss_wait.yaml` are copied out into the current directory. This allows the
user to leverage the `goss add|autoadd` commands to write tests as they would
diff --git a/integration-tests/Dockerfile_alpine3 b/integration-tests/Dockerfile_alpine3
index 153bc0c68..c573021ee 100644
--- a/integration-tests/Dockerfile_alpine3
+++ b/integration-tests/Dockerfile_alpine3
@@ -1,9 +1,10 @@
-FROM alpine:3.12
+FROM alpine:3.19
MAINTAINER Ahmed
# install apache2 and remove un-needed services
RUN apk update && \
- apk add openrc apache2 bash ca-certificates tinyproxy && \
+ apk add --no-cache openrc apache2=2.4.59-r0 bash ca-certificates tinyproxy && \
+ sed -i 's/Listen 80/Listen 0.0.0.0:80/g' /etc/apache2/httpd.conf && \
rc-update add apache2 && \
rc-update add tinyproxy && \
rm -rf /etc/init.d/networking /etc/init.d/hwdrivers /var/cache/apk/* /tmp/*
diff --git a/integration-tests/Dockerfile_alpine3.md5 b/integration-tests/Dockerfile_alpine3.md5
index 0526fed52..f4bdce743 100644
--- a/integration-tests/Dockerfile_alpine3.md5
+++ b/integration-tests/Dockerfile_alpine3.md5
@@ -1 +1 @@
-f2b97c4629a92aa7f9b378b49f6e1b42 Dockerfile_alpine3
+f9c8c187e94693c4625a8c8d01fae3bf Dockerfile_alpine3
diff --git a/integration-tests/Dockerfile_rockylinux9 b/integration-tests/Dockerfile_rockylinux9
new file mode 100644
index 000000000..5416e89b0
--- /dev/null
+++ b/integration-tests/Dockerfile_rockylinux9
@@ -0,0 +1,25 @@
+FROM rockylinux:9
+
+ENV container docker
+
+RUN dnf install -y systemd httpd diffutils 'dnf-command(config-manager)' && \
+ dnf config-manager --set-enabled crb && \
+ dnf install -y epel-release && \
+ dnf install -y tinyproxy && \
+ dnf remove -y 'dnf-command(config-manager)' epel-release
+
+RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == systemd-tmpfiles-setup.service ] || rm -f $i; done); \
+ rm -f /lib/systemd/system/multi-user.target.wants/*;\
+ rm -f /etc/systemd/system/*.wants/*;\
+ rm -f /lib/systemd/system/local-fs.target.wants/*; \
+ rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
+ rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
+ rm -f /lib/systemd/system/basic.target.wants/*;\
+ rm -f /lib/systemd/system/anaconda.target.wants/*;
+
+CMD ["/usr/sbin/init"]
+
+RUN systemctl enable httpd
+RUN systemctl enable tinyproxy
+RUN chmod 700 ~root
+RUN mkfifo /pipe
diff --git a/integration-tests/Dockerfile_trusty.md5 b/integration-tests/Dockerfile_trusty.md5
index 7e049058a..5a2c288f6 100644
--- a/integration-tests/Dockerfile_trusty.md5
+++ b/integration-tests/Dockerfile_trusty.md5
@@ -1 +1 @@
-5117819dc7907aa1100e2ff0f2edb68f Dockerfile_trusty
+ac8c8df3415c0eecdbedc322480e696e Dockerfile_trusty
diff --git a/integration-tests/goss/alpine3/goss-aa-expected.yaml b/integration-tests/goss/alpine3/goss-aa-expected.yaml
index 2d95f3e6b..ea7c1180b 100644
--- a/integration-tests/goss/alpine3/goss-aa-expected.yaml
+++ b/integration-tests/goss/alpine3/goss-aa-expected.yaml
@@ -2,7 +2,7 @@ package:
apache2:
installed: true
versions:
- - 2.4.46-r1
+ - 2.4.59-r0
service:
apache2:
enabled: true
diff --git a/integration-tests/goss/alpine3/goss-expected.yaml b/integration-tests/goss/alpine3/goss-expected.yaml
index 0953e91d8..b3fc9f83e 100644
--- a/integration-tests/goss/alpine3/goss-expected.yaml
+++ b/integration-tests/goss/alpine3/goss-expected.yaml
@@ -13,7 +13,7 @@ package:
apache2:
installed: true
versions:
- - 2.4.46-r1
+ - 2.4.59-r0
foobar:
installed: false
vim-tiny:
diff --git a/integration-tests/goss/generate_goss.sh b/integration-tests/goss/generate_goss.sh
index e07cb28d5..096bfa89d 100755
--- a/integration-tests/goss/generate_goss.sh
+++ b/integration-tests/goss/generate_goss.sh
@@ -18,8 +18,8 @@ for x in /etc/passwd /tmp/goss/foobar;do
goss a "${args[@]}" file $x
done
-[[ $OS == "centos7" ]] && package="httpd" || package="apache2"
-[[ $OS == "centos7" ]] && user="apache" || user="www-data"
+[[ $OS == "centos7" || $OS == "rockylinux9" ]] && package="httpd" || package="apache2"
+[[ $OS == "centos7" || $OS == "rockylinux9" ]] && user="apache" || user="www-data"
goss a "${args[@]}" package $package foobar vim-tiny
goss a "${args[@]}" addr --timeout 1s httpbin:80 httpbin:22
diff --git a/integration-tests/goss/goss-service.yaml b/integration-tests/goss/goss-service.yaml
index 102c92cbf..08633b078 100644
--- a/integration-tests/goss/goss-service.yaml
+++ b/integration-tests/goss/goss-service.yaml
@@ -3,7 +3,7 @@ service:
foobar:
enabled: false
running: false
-{{ if .Env.OS | regexMatch "centos[7]" }}
+{{ if .Env.OS | regexMatch "centos[7]|rockylinux[9]" }}
httpd:
{{else}}
apache2:
diff --git a/integration-tests/goss/rockylinux9/goss-aa-expected.yaml b/integration-tests/goss/rockylinux9/goss-aa-expected.yaml
new file mode 100644
index 000000000..7fd1552f4
--- /dev/null
+++ b/integration-tests/goss/rockylinux9/goss-aa-expected.yaml
@@ -0,0 +1,17 @@
+package:
+ httpd:
+ installed: true
+ versions:
+ - 2.4.57-8.el9
+port:
+ tcp:80:
+ listening: true
+ ip:
+ - 0.0.0.0
+service:
+ httpd:
+ enabled: true
+ running: true
+process:
+ httpd:
+ running: true
diff --git a/integration-tests/goss/rockylinux9/goss-expected-q.yaml b/integration-tests/goss/rockylinux9/goss-expected-q.yaml
new file mode 100644
index 000000000..b66ad535a
--- /dev/null
+++ b/integration-tests/goss/rockylinux9/goss-expected-q.yaml
@@ -0,0 +1,127 @@
+file:
+ /etc/passwd:
+ exists: true
+ contents: []
+ /tmp/goss/foobar:
+ exists: false
+ contents: []
+package:
+ foobar:
+ installed: false
+ httpd:
+ installed: true
+ vim-tiny:
+ installed: false
+addr:
+ tcp://httpbin:22:
+ reachable: false
+ timeout: 1000
+ tcp://httpbin:80:
+ reachable: true
+ timeout: 1000
+ udp://8.8.8.8:53:
+ reachable: true
+ timeout: 1000
+port:
+ tcp:80:
+ listening: true
+ tcp:9999:
+ listening: false
+ tcp6:80:
+ listening: false
+service:
+ foobar:
+ enabled: false
+ running: false
+ httpd:
+ enabled: true
+ running: true
+user:
+ apache:
+ exists: true
+ foobar:
+ exists: false
+group:
+ apache:
+ exists: true
+ foobar:
+ exists: false
+command:
+ echo 'hi':
+ exit-status: 0
+ stdout: ""
+ stderr: ""
+ timeout: 10000
+ foobar:
+ exit-status: 127
+ stdout: ""
+ stderr: ""
+ timeout: 10000
+dns:
+ CAA:dnstest.io:
+ resolvable: true
+ timeout: 1000
+ server: 8.8.8.8
+ CNAME:c.dnstest.io:
+ resolvable: true
+ timeout: 1000
+ server: 8.8.8.8
+ MX:dnstest.io:
+ resolvable: true
+ timeout: 1000
+ server: 8.8.8.8
+ NS:dnstest.io:
+ resolvable: true
+ timeout: 1000
+ server: 8.8.8.8
+ PTR:54.243.154.1:
+ resolvable: true
+ timeout: 1000
+ server: 8.8.8.8
+ SRV:_https._tcp.dnstest.io:
+ resolvable: true
+ timeout: 1000
+ server: 8.8.8.8
+ TXT:txt._test.dnstest.io:
+ resolvable: true
+ timeout: 1000
+ server: 8.8.8.8
+ ip6.dnstest.io:
+ resolvable: true
+ timeout: 1000
+ server: 8.8.8.8
+ localhost:
+ resolvable: true
+ timeout: 1000
+process:
+ foobar:
+ running: false
+ httpd:
+ running: true
+kernel-param:
+ kernel.ostype:
+ value: Linux
+mount:
+ /dev:
+ exists: true
+ timeout: 1000
+http:
+ http://google.com:
+ status: 301
+ allow-insecure: false
+ no-follow-redirects: true
+ timeout: 5000
+ body: []
+ https://www.apple.com:
+ status: 200
+ allow-insecure: false
+ no-follow-redirects: false
+ timeout: 5000
+ body: []
+ proxy: http://127.0.0.1:8888
+ https://www.google.com:
+ status: 200
+ allow-insecure: false
+ no-follow-redirects: false
+ timeout: 5000
+ body: []
diff --git a/integration-tests/goss/rockylinux9/goss-expected.yaml b/integration-tests/goss/rockylinux9/goss-expected.yaml
new file mode 100644
index 000000000..bbd4249ea
--- /dev/null
+++ b/integration-tests/goss/rockylinux9/goss-expected.yaml
@@ -0,0 +1,177 @@
+file:
+ /etc/passwd:
+ exists: true
+ mode: "0644"
+ owner: root
+ group: root
+ filetype: file
+ contents: []
+ /tmp/goss/foobar:
+ exists: false
+ contents: []
+package:
+ foobar:
+ installed: false
+ httpd:
+ installed: true
+ versions:
+ - 2.4.57-8.el9
+ vim-tiny:
+ installed: false
+addr:
+ tcp://httpbin:22:
+ reachable: false
+ timeout: 1000
+ tcp://httpbin:80:
+ reachable: true
+ timeout: 1000
+ udp://8.8.8.8:53:
+ reachable: true
+ timeout: 1000
+port:
+ tcp:80:
+ listening: true
+ ip:
+ - 0.0.0.0
+ tcp:9999:
+ listening: false
+ ip: []
+ tcp6:80:
+ listening: false
+ ip: []
+service:
+ foobar:
+ enabled: false
+ running: false
+ httpd:
+ enabled: true
+ running: true
+user:
+ apache:
+ exists: true
+ uid: 48
+ gid: 48
+ groups:
+ - apache
+ home: /usr/share/httpd
+ shell: /sbin/nologin
+ foobar:
+ exists: false
+group:
+ apache:
+ exists: true
+ gid: 48
+ foobar:
+ exists: false
+command:
+ echo 'hi':
+ exit-status: 0
+ stdout:
+ - hi
+ stderr: ""
+ timeout: 10000
+ foobar:
+ exit-status: 127
+ stdout: ""
+ stderr:
+ - 'sh: line 1: foobar: command not found'
+ timeout: 10000
+dns:
+ CAA:dnstest.io:
+ resolvable: true
+ addrs:
+ - 0 issue comodoca.com
+ - 0 issue letsencrypt.org
+ - 0 issuewild ;
+ timeout: 1000
+ server: 8.8.8.8
+ CNAME:c.dnstest.io:
+ resolvable: true
+ addrs:
+ - a.dnstest.io.
+ timeout: 1000
+ server: 8.8.8.8
+ MX:dnstest.io:
+ resolvable: true
+ addrs:
+ - 10 b.dnstest.io.
+ - 5 a.dnstest.io.
+ timeout: 1000
+ server: 8.8.8.8
+ NS:dnstest.io:
+ resolvable: true
+ addrs:
+ - ns1.dnstest.io.
+ - ns2.dnstest.io.
+ timeout: 1000
+ server: 8.8.8.8
+ PTR:54.243.154.1:
+ resolvable: true
+ addrs:
+ - ec2-54-243-154-1.compute-1.amazonaws.com.
+ timeout: 1000
+ server: 8.8.8.8
+ SRV:_https._tcp.dnstest.io:
+ resolvable: true
+ addrs:
+ - 0 5 443 a.dnstest.io.
+ - 10 10 443 b.dnstest.io.
+ timeout: 1000
+ server: 8.8.8.8
+ TXT:txt._test.dnstest.io:
+ resolvable: true
+ addrs:
+ - Hello DNS
+ timeout: 1000
+ server: 8.8.8.8
+ ip6.dnstest.io:
+ resolvable: true
+ addrs:
+ - 2404:6800:4001:807::200e
+ timeout: 1000
+ server: 8.8.8.8
+ localhost:
+ resolvable: true
+ addrs:
+ - 127.0.0.1
+ - ::1
+ timeout: 1000
+process:
+ foobar:
+ running: false
+ httpd:
+ running: true
+kernel-param:
+ kernel.ostype:
+ value: Linux
+mount:
+ /dev:
+ exists: true
+ opts:
+ - rw
+ - nosuid
+ vfs-opts:
+ - rw
+ source: tmpfs
+ filesystem: tmpfs
+ timeout: 1000
+http:
+ http://google.com:
+ status: 301
+ allow-insecure: false
+ no-follow-redirects: true
+ timeout: 5000
+ body: []
+ https://www.apple.com:
+ status: 200
+ allow-insecure: false
+ no-follow-redirects: false
+ timeout: 5000
+ body: []
+ proxy: http://127.0.0.1:8888
+ https://www.google.com:
+ status: 200
+ allow-insecure: false
+ no-follow-redirects: false
+ timeout: 5000
+ body: []
diff --git a/integration-tests/goss/rockylinux9/goss.yaml b/integration-tests/goss/rockylinux9/goss.yaml
new file mode 100644
index 000000000..818b2c34d
--- /dev/null
+++ b/integration-tests/goss/rockylinux9/goss.yaml
@@ -0,0 +1,33 @@
+service:
+ autofs:
+ enabled: false
+ running: false
+user:
+ apache:
+ exists: true
+ uid: 48
+ gid: 48
+ groups:
+ - apache
+ home: "/usr/share/httpd"
+group:
+ apache:
+ exists: true
+ gid: 48
+process:
+ httpd:
+ running: true
+port:
+ tcp:80:
+ listening: true
+ ip:
+ - '0.0.0.0'
+addr:
+ tcp://127.0.0.1:80:
+ reachable: true
+ timeout: 500
+ local-address: 127.0.0.1
+gossfile:
+ "../goss-s*.yaml": {}
+ bypath:
+ file: "../goss-dummy.yaml"
diff --git a/integration-tests/goss/vars.yaml b/integration-tests/goss/vars.yaml
index cbf6df778..0cc72dbab 100644
--- a/integration-tests/goss/vars.yaml
+++ b/integration-tests/goss/vars.yaml
@@ -2,7 +2,7 @@
alpine3:
proxy: http://127.0.0.1:8888
packages:
- apache2: "2.4.46-r1"
+ apache2: "2.4.59-r0"
services:
apache2: [sysinit]
arch:
@@ -13,6 +13,12 @@ centos7:
httpd: "2.4.6-95.el7.centos"
services:
httpd: []
+rockylinux9:
+ proxy: http://127.0.0.1:8888
+ packages:
+ httpd: "2.4.57-8.el9"
+ services:
+ httpd: []
trusty:
proxy: http://127.0.0.1:8888
packages:
diff --git a/integration-tests/test.sh b/integration-tests/test.sh
index 3225d37bf..2b9936d19 100755
--- a/integration-tests/test.sh
+++ b/integration-tests/test.sh
@@ -4,7 +4,7 @@ source "$(dirname "${BASH_SOURCE[0]}")/../ci/lib/setup.sh" || exit 67
# preserve current behaviour
set -x
-os="${1:?"Need OS as 1st arg. e.g. alpine arch centos7 trusty wheezy"}"
+os="${1:?"Need OS as 1st arg. e.g. alpine arch centos7 rockylinux9 trusty wheezy"}"
arch="${2:?"Need arch as 2nd arg. e.g. amd64 386"}"
vars_inline="{inline: bar, overwrite: bar}"
@@ -36,7 +36,7 @@ fi
network=goss-test
docker network create --driver bridge --subnet '172.19.0.0/16' $network
docker run -d --name httpbin --network $network kennethreitz/httpbin
-opts=(--env OS=$os --cap-add SYS_ADMIN -v "$PWD/goss:/goss" -d --name "$container_name" --security-opt seccomp:unconfined --security-opt label:disable)
+opts=(--env OS=$os --cap-add SYS_ADMIN -v "$PWD/goss:/goss" -d --name "$container_name" --security-opt seccomp:unconfined --security-opt label:disable --privileged)
id=$(docker run "${opts[@]}" --network $network "aelsabbahy/goss_$os" /sbin/init)
ip=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$id")
trap "rv=\$?; docker rm -vf $id;docker rm -vf httpbin;docker network rm $network; exit \$rv" INT TERM EXIT
diff --git a/matchers/have_patterns.go b/matchers/have_patterns.go
index fd7c92897..cf2bcd139 100644
--- a/matchers/have_patterns.go
+++ b/matchers/have_patterns.go
@@ -146,14 +146,6 @@ func (m *HavePatternsMatcher) NegatedFailureResult(actual interface{}) MatcherRe
}
}
-func appendMissingStrings(message string, missingElements []string) string {
- if len(missingElements) == 0 {
- return message
- }
- return fmt.Sprintf("%s\nthe missing elements were\n%s", message,
- format.Object(missingElements, 1))
-}
-
type patternMatcher interface {
Match(string) bool
Pattern() string
diff --git a/matchers/type_conversion.go b/matchers/type_conversion.go
index 0d425bb4f..29fb96db8 100644
--- a/matchers/type_conversion.go
+++ b/matchers/type_conversion.go
@@ -4,7 +4,6 @@ import (
"encoding/json"
"fmt"
"io"
- "io/ioutil"
"strconv"
"strings"
@@ -108,7 +107,7 @@ func (t ReaderToString) Transform(i interface{}) (interface{}, error) {
return nil, fmt.Errorf("Expected io.reader, Got:%s", format.Object(i, 1))
}
- b, err := ioutil.ReadAll(r)
+ b, err := io.ReadAll(r)
if err != nil {
return "", err
}
diff --git a/mkdocs.yml b/mkdocs.yml
index 547aaaa90..7156db5e6 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -46,6 +46,9 @@ plugins:
- awesome-pages
- macros:
render_by_default: false
+ - exclude:
+ glob:
+ - requirements.txt
markdown_extensions:
- abbr
@@ -78,14 +81,12 @@ markdown_extensions:
check_paths: true
- pymdownx.superfences
-copyright: Copyright © 2015 - 2023 Ahmed Elsabbahy
+copyright: Copyright © 2015 - 2024 Ahmed Elsabbahy
extra:
social:
- icon: fontawesome/brands/github
- link: https://github.com/gooss-org/goss
- - icon: simple/codeclimate
- link: https://codeclimate.com/github/goss-org/goss
+ link: https://github.com/goss-org/goss
- icon: simple/travisci
link: https://travis-ci.org/goss-org/goss
- icon: fontawesome/brands/medium
diff --git a/outputs/json.go b/outputs/json.go
index 0d7063d0c..c2413aaf4 100644
--- a/outputs/json.go
+++ b/outputs/json.go
@@ -24,8 +24,7 @@ func (r Json) ValidOptions() []*formatOption {
func (r Json) Output(w io.Writer, results <-chan []resource.TestResult,
outConfig util.OutputConfig) (exitCode int) {
- var pretty bool
- pretty = util.IsValueInList(foPretty, outConfig.FormatOptions)
+ var pretty bool = util.IsValueInList(foPretty, outConfig.FormatOptions)
includeRaw := !util.IsValueInList(foExcludeRaw, outConfig.FormatOptions)
sort := util.IsValueInList(foSort, outConfig.FormatOptions)
diff --git a/outputs/junit.go b/outputs/junit.go
index 3e7de6ead..d50e3677e 100644
--- a/outputs/junit.go
+++ b/outputs/junit.go
@@ -34,8 +34,7 @@ func (r JUnit) Output(w io.Writer, results <-chan []resource.TestResult,
// ISO8601 timeformat
timestamp := time.Now().Format(time.RFC3339)
- var summary map[int]string
- summary = make(map[int]string)
+ var summary map[int]string = make(map[int]string)
var startTime time.Time
var endTime time.Time
diff --git a/outputs/nagios.go b/outputs/nagios.go
index d91776dba..2940d2235 100644
--- a/outputs/nagios.go
+++ b/outputs/nagios.go
@@ -31,8 +31,7 @@ func (r Nagios) Output(w io.Writer, results <-chan []resource.TestResult,
var startTime time.Time
var endTime time.Time
- var summary map[int]string
- summary = make(map[int]string)
+ var summary map[int]string = make(map[int]string)
for resultGroup := range results {
for _, testResult := range resultGroup {
diff --git a/outputs/rspecish.go b/outputs/rspecish.go
index cdeae891f..7fb5f2f9f 100644
--- a/outputs/rspecish.go
+++ b/outputs/rspecish.go
@@ -43,15 +43,15 @@ func (r Rspecish) Output(w io.Writer, results <-chan []resource.TestResult,
switch testResult.Result {
case resource.SUCCESS:
logTrace("TRACE", "SUCCESS", testResult, false)
- fmt.Fprintf(w, green("."))
+ fmt.Fprint(w, green("."))
case resource.SKIP:
logTrace("TRACE", "SKIP", testResult, false)
- fmt.Fprintf(w, yellow("S"))
+ fmt.Fprint(w, yellow("S"))
failedOrSkippedGroup = append(failedOrSkippedGroup, testResult)
skipped++
case resource.FAIL:
logTrace("TRACE", "FAIL", testResult, false)
- fmt.Fprintf(w, red("F"))
+ fmt.Fprint(w, red("F"))
failedOrSkippedGroup = append(failedOrSkippedGroup, testResult)
failed++
}
diff --git a/outputs/tap.go b/outputs/tap.go
index 341e2a0ef..a5d6166ca 100644
--- a/outputs/tap.go
+++ b/outputs/tap.go
@@ -27,8 +27,7 @@ func (r Tap) Output(w io.Writer, results <-chan []resource.TestResult,
testCount := 0
failed := 0
- var summary map[int]string
- summary = make(map[int]string)
+ var summary map[int]string = make(map[int]string)
for resultGroup := range results {
for _, testResult := range resultGroup {
diff --git a/resource/addr.go b/resource/addr.go
index 2347583e9..f98eb630f 100644
--- a/resource/addr.go
+++ b/resource/addr.go
@@ -20,6 +20,8 @@ type Addr struct {
Skip bool `json:"skip,omitempty" yaml:"skip,omitempty"`
}
+type idKey struct{}
+
const (
AddrResourceKey = "addr"
AddResourceName = "Addr"
@@ -51,7 +53,7 @@ func (a *Addr) GetAddress() string {
}
func (a *Addr) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", a.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, a.ID())
skip := a.Skip
if a.Timeout == 0 {
diff --git a/resource/command.go b/resource/command.go
index 79a1671e7..365867d24 100644
--- a/resource/command.go
+++ b/resource/command.go
@@ -49,7 +49,7 @@ func (c *Command) GetExec() string {
}
func (c *Command) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", c.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, c.ID())
skip := c.Skip
if c.Timeout == 0 {
diff --git a/resource/dns.go b/resource/dns.go
index bd3274d99..6cd114002 100644
--- a/resource/dns.go
+++ b/resource/dns.go
@@ -52,7 +52,7 @@ func (d *DNS) GetResolve() string {
}
func (d *DNS) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", d.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, d.ID())
skip := d.Skip
if d.Timeout == 0 {
d.Timeout = 500
diff --git a/resource/file.go b/resource/file.go
index 97356a193..6b3c94c4c 100644
--- a/resource/file.go
+++ b/resource/file.go
@@ -61,7 +61,7 @@ func (f *File) GetPath() string {
}
func (f *File) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", f.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, f.ID())
skip := f.Skip
sysFile := sys.NewFile(ctx, f.GetPath(), sys, util.Config{})
diff --git a/resource/group.go b/resource/group.go
index 7ca928108..cfd71a3a3 100644
--- a/resource/group.go
+++ b/resource/group.go
@@ -47,7 +47,7 @@ func (g *Group) GetGroupname() string {
}
func (g *Group) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", g.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, g.ID())
skip := g.Skip
sysgroup := sys.NewGroup(ctx, g.GetGroupname(), sys, util.Config{})
diff --git a/resource/http.go b/resource/http.go
index b9a1006de..bbd820098 100644
--- a/resource/http.go
+++ b/resource/http.go
@@ -63,7 +63,7 @@ func (r *HTTP) getURL() string {
}
func (u *HTTP) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", u.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, u.ID())
skip := u.Skip
if u.Timeout == 0 {
u.Timeout = 5000
diff --git a/resource/interface.go b/resource/interface.go
index 14921d133..68e3fa3d6 100644
--- a/resource/interface.go
+++ b/resource/interface.go
@@ -50,7 +50,7 @@ func (i *Interface) GetName() string {
}
func (i *Interface) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", i.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, i.ID())
skip := i.Skip
sysInterface := sys.NewInterface(ctx, i.GetName(), sys, util.Config{})
diff --git a/resource/kernel_param.go b/resource/kernel_param.go
index 494597a96..7f50270bd 100644
--- a/resource/kernel_param.go
+++ b/resource/kernel_param.go
@@ -50,7 +50,7 @@ func (k *KernelParam) GetName() string {
}
func (k *KernelParam) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", k.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, k.ID())
skip := k.Skip
sysKernelParam := sys.NewKernelParam(ctx, k.GetName(), sys, util.Config{})
diff --git a/resource/mount.go b/resource/mount.go
index 401c172ec..4410cbb2f 100644
--- a/resource/mount.go
+++ b/resource/mount.go
@@ -54,7 +54,7 @@ func (m *Mount) GetMountPoint() string {
}
func (m *Mount) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", m.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, m.ID())
skip := m.Skip
if m.Timeout == 0 {
diff --git a/resource/package.go b/resource/package.go
index f8afffcb5..6d393a1b2 100644
--- a/resource/package.go
+++ b/resource/package.go
@@ -47,7 +47,7 @@ func (p *Package) GetName() string {
}
func (p *Package) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", p.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, p.ID())
skip := p.Skip
sysPkg := sys.NewPackage(ctx, p.GetName(), sys, util.Config{})
diff --git a/resource/port.go b/resource/port.go
index 70f72ae93..02c32859c 100644
--- a/resource/port.go
+++ b/resource/port.go
@@ -47,7 +47,7 @@ func (p *Port) GetPort() string {
}
func (p *Port) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", p.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, p.ID())
skip := p.Skip
sysPort := sys.NewPort(ctx, p.GetPort(), sys, util.Config{})
diff --git a/resource/process.go b/resource/process.go
index 9012760e9..c7413d7ef 100644
--- a/resource/process.go
+++ b/resource/process.go
@@ -46,7 +46,7 @@ func (p *Process) GetComm() string {
}
func (p *Process) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", p.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, p.ID())
skip := p.Skip
sysProcess := sys.NewProcess(ctx, p.GetComm(), sys, util.Config{})
diff --git a/resource/resource.go b/resource/resource.go
index bff257e02..104972ad5 100644
--- a/resource/resource.go
+++ b/resource/resource.go
@@ -5,11 +5,9 @@ import (
"os"
"path/filepath"
"strconv"
- "strings"
"sync"
"github.com/goss-org/goss/system"
- "github.com/oleiade/reflections"
)
type Resource interface {
@@ -66,18 +64,6 @@ func deprecateAtoI(depr any, desc string) any {
return float64(i)
}
-func validAttrs(i any, t string) (map[string]bool, error) {
- validAttrs := make(map[string]bool)
- tags, err := reflections.Tags(i, t)
- if err != nil {
- return nil, err
- }
- for _, v := range tags {
- validAttrs[strings.Split(v, ",")[0]] = true
- }
- return validAttrs, nil
-}
-
func shouldSkip(results []TestResult) bool {
if len(results) < 1 {
return false
diff --git a/resource/resource_list.go b/resource/resource_list.go
index e3aedb633..61b381596 100644
--- a/resource/resource_list.go
+++ b/resource/resource_list.go
@@ -18,7 +18,7 @@ import (
type AddrMap map[string]*Addr
func (r AddrMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Addr, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewAddr(ctx, sr, sys, config)
res, err := NewAddr(sysres, config)
if err != nil {
@@ -33,13 +33,13 @@ func (r AddrMap) AppendSysResource(sr string, sys *system.System, config util.Co
}
func (r AddrMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Addr, system.Addr, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewAddr(ctx, sr, sys, util.Config{})
res, err := NewAddr(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -119,7 +119,7 @@ func (ret *AddrMap) UnmarshalYAML(unmarshal func(v interface{}) error) error {
type CommandMap map[string]*Command
func (r CommandMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Command, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewCommand(ctx, sr, sys, config)
res, err := NewCommand(sysres, config)
if err != nil {
@@ -134,13 +134,13 @@ func (r CommandMap) AppendSysResource(sr string, sys *system.System, config util
}
func (r CommandMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Command, system.Command, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewCommand(ctx, sr, sys, util.Config{})
res, err := NewCommand(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -220,7 +220,7 @@ func (ret *CommandMap) UnmarshalYAML(unmarshal func(v interface{}) error) error
type DNSMap map[string]*DNS
func (r DNSMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*DNS, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewDNS(ctx, sr, sys, config)
res, err := NewDNS(sysres, config)
if err != nil {
@@ -235,13 +235,13 @@ func (r DNSMap) AppendSysResource(sr string, sys *system.System, config util.Con
}
func (r DNSMap) AppendSysResourceIfExists(sr string, sys *system.System) (*DNS, system.DNS, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewDNS(ctx, sr, sys, util.Config{})
res, err := NewDNS(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -321,7 +321,7 @@ func (ret *DNSMap) UnmarshalYAML(unmarshal func(v interface{}) error) error {
type FileMap map[string]*File
func (r FileMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*File, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewFile(ctx, sr, sys, config)
res, err := NewFile(sysres, config)
if err != nil {
@@ -336,13 +336,13 @@ func (r FileMap) AppendSysResource(sr string, sys *system.System, config util.Co
}
func (r FileMap) AppendSysResourceIfExists(sr string, sys *system.System) (*File, system.File, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewFile(ctx, sr, sys, util.Config{})
res, err := NewFile(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -422,7 +422,7 @@ func (ret *FileMap) UnmarshalYAML(unmarshal func(v interface{}) error) error {
type GossfileMap map[string]*Gossfile
func (r GossfileMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Gossfile, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewGossfile(ctx, sr, sys, config)
res, err := NewGossfile(sysres, config)
if err != nil {
@@ -437,13 +437,13 @@ func (r GossfileMap) AppendSysResource(sr string, sys *system.System, config uti
}
func (r GossfileMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Gossfile, system.Gossfile, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewGossfile(ctx, sr, sys, util.Config{})
res, err := NewGossfile(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -523,7 +523,7 @@ func (ret *GossfileMap) UnmarshalYAML(unmarshal func(v interface{}) error) error
type GroupMap map[string]*Group
func (r GroupMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Group, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewGroup(ctx, sr, sys, config)
res, err := NewGroup(sysres, config)
if err != nil {
@@ -538,13 +538,13 @@ func (r GroupMap) AppendSysResource(sr string, sys *system.System, config util.C
}
func (r GroupMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Group, system.Group, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewGroup(ctx, sr, sys, util.Config{})
res, err := NewGroup(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -624,7 +624,7 @@ func (ret *GroupMap) UnmarshalYAML(unmarshal func(v interface{}) error) error {
type PackageMap map[string]*Package
func (r PackageMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Package, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewPackage(ctx, sr, sys, config)
res, err := NewPackage(sysres, config)
if err != nil {
@@ -639,13 +639,13 @@ func (r PackageMap) AppendSysResource(sr string, sys *system.System, config util
}
func (r PackageMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Package, system.Package, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewPackage(ctx, sr, sys, util.Config{})
res, err := NewPackage(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -725,7 +725,7 @@ func (ret *PackageMap) UnmarshalYAML(unmarshal func(v interface{}) error) error
type PortMap map[string]*Port
func (r PortMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Port, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewPort(ctx, sr, sys, config)
res, err := NewPort(sysres, config)
if err != nil {
@@ -740,13 +740,13 @@ func (r PortMap) AppendSysResource(sr string, sys *system.System, config util.Co
}
func (r PortMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Port, system.Port, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewPort(ctx, sr, sys, util.Config{})
res, err := NewPort(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -826,7 +826,7 @@ func (ret *PortMap) UnmarshalYAML(unmarshal func(v interface{}) error) error {
type ProcessMap map[string]*Process
func (r ProcessMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Process, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewProcess(ctx, sr, sys, config)
res, err := NewProcess(sysres, config)
if err != nil {
@@ -841,13 +841,13 @@ func (r ProcessMap) AppendSysResource(sr string, sys *system.System, config util
}
func (r ProcessMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Process, system.Process, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewProcess(ctx, sr, sys, util.Config{})
res, err := NewProcess(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -927,7 +927,7 @@ func (ret *ProcessMap) UnmarshalYAML(unmarshal func(v interface{}) error) error
type ServiceMap map[string]*Service
func (r ServiceMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Service, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewService(ctx, sr, sys, config)
res, err := NewService(sysres, config)
if err != nil {
@@ -942,13 +942,13 @@ func (r ServiceMap) AppendSysResource(sr string, sys *system.System, config util
}
func (r ServiceMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Service, system.Service, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewService(ctx, sr, sys, util.Config{})
res, err := NewService(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -1028,7 +1028,7 @@ func (ret *ServiceMap) UnmarshalYAML(unmarshal func(v interface{}) error) error
type UserMap map[string]*User
func (r UserMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*User, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewUser(ctx, sr, sys, config)
res, err := NewUser(sysres, config)
if err != nil {
@@ -1043,13 +1043,13 @@ func (r UserMap) AppendSysResource(sr string, sys *system.System, config util.Co
}
func (r UserMap) AppendSysResourceIfExists(sr string, sys *system.System) (*User, system.User, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewUser(ctx, sr, sys, util.Config{})
res, err := NewUser(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -1129,7 +1129,7 @@ func (ret *UserMap) UnmarshalYAML(unmarshal func(v interface{}) error) error {
type KernelParamMap map[string]*KernelParam
func (r KernelParamMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*KernelParam, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewKernelParam(ctx, sr, sys, config)
res, err := NewKernelParam(sysres, config)
if err != nil {
@@ -1144,13 +1144,13 @@ func (r KernelParamMap) AppendSysResource(sr string, sys *system.System, config
}
func (r KernelParamMap) AppendSysResourceIfExists(sr string, sys *system.System) (*KernelParam, system.KernelParam, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewKernelParam(ctx, sr, sys, util.Config{})
res, err := NewKernelParam(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -1230,7 +1230,7 @@ func (ret *KernelParamMap) UnmarshalYAML(unmarshal func(v interface{}) error) er
type MountMap map[string]*Mount
func (r MountMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Mount, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewMount(ctx, sr, sys, config)
res, err := NewMount(sysres, config)
if err != nil {
@@ -1245,13 +1245,13 @@ func (r MountMap) AppendSysResource(sr string, sys *system.System, config util.C
}
func (r MountMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Mount, system.Mount, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewMount(ctx, sr, sys, util.Config{})
res, err := NewMount(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -1331,7 +1331,7 @@ func (ret *MountMap) UnmarshalYAML(unmarshal func(v interface{}) error) error {
type InterfaceMap map[string]*Interface
func (r InterfaceMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*Interface, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewInterface(ctx, sr, sys, config)
res, err := NewInterface(sysres, config)
if err != nil {
@@ -1346,13 +1346,13 @@ func (r InterfaceMap) AppendSysResource(sr string, sys *system.System, config ut
}
func (r InterfaceMap) AppendSysResourceIfExists(sr string, sys *system.System) (*Interface, system.Interface, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewInterface(ctx, sr, sys, util.Config{})
res, err := NewInterface(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
@@ -1432,7 +1432,7 @@ func (ret *InterfaceMap) UnmarshalYAML(unmarshal func(v interface{}) error) erro
type HTTPMap map[string]*HTTP
func (r HTTPMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*HTTP, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewHTTP(ctx, sr, sys, config)
res, err := NewHTTP(sysres, config)
if err != nil {
@@ -1447,13 +1447,13 @@ func (r HTTPMap) AppendSysResource(sr string, sys *system.System, config util.Co
}
func (r HTTPMap) AppendSysResourceIfExists(sr string, sys *system.System) (*HTTP, system.HTTP, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewHTTP(ctx, sr, sys, util.Config{})
res, err := NewHTTP(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
diff --git a/resource/resource_list_genny.go b/resource/resource_list_genny.go
index a483bc4ea..fccdea348 100644
--- a/resource/resource_list_genny.go
+++ b/resource/resource_list_genny.go
@@ -26,7 +26,7 @@ type ResourceType generic.Type
type ResourceTypeMap map[string]*ResourceType
func (r ResourceTypeMap) AppendSysResource(sr string, sys *system.System, config util.Config) (*ResourceType, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewResourceType(ctx, sr, sys, config)
res, err := NewResourceType(sysres, config)
if err != nil {
@@ -41,13 +41,13 @@ func (r ResourceTypeMap) AppendSysResource(sr string, sys *system.System, config
}
func (r ResourceTypeMap) AppendSysResourceIfExists(sr string, sys *system.System) (*ResourceType, system.ResourceType, bool, error) {
- ctx := context.WithValue(context.Background(), "id", sr)
+ ctx := context.WithValue(context.Background(), idKey{}, sr)
sysres := sys.NewResourceType(ctx, sr, sys, util.Config{})
res, err := NewResourceType(sysres, util.Config{})
if err != nil {
return nil, nil, false, err
}
- if e, _ := sysres.Exists(); e != true {
+ if e, _ := sysres.Exists(); !e {
return res, sysres, false, nil
}
if old_res, ok := r[res.ID()]; ok {
diff --git a/resource/service.go b/resource/service.go
index 2285c3e1f..2f35e9d3d 100644
--- a/resource/service.go
+++ b/resource/service.go
@@ -48,7 +48,7 @@ func (s *Service) GetName() string {
}
func (s *Service) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", s.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, s.ID())
skip := s.Skip
sysservice := sys.NewService(ctx, s.GetName(), sys, util.Config{})
diff --git a/resource/user.go b/resource/user.go
index 3895f8067..c1b64b06f 100644
--- a/resource/user.go
+++ b/resource/user.go
@@ -51,7 +51,7 @@ func (u *User) GetUsername() string {
}
func (u *User) Validate(sys *system.System) []TestResult {
- ctx := context.WithValue(context.Background(), "id", u.ID())
+ ctx := context.WithValue(context.Background(), idKey{}, u.ID())
skip := u.Skip
sysuser := sys.NewUser(ctx, u.GetUsername(), sys, util.Config{})
diff --git a/resource/validate.go b/resource/validate.go
index c7abb4428..720c7b7d5 100644
--- a/resource/validate.go
+++ b/resource/validate.go
@@ -41,10 +41,6 @@ func HumanOutcomes() map[int]string {
return humanOutcomes
}
-const (
- maxScanTokenSize = 10 * 1024 * 1024
-)
-
type ValidateError string
func (g ValidateError) Error() string { return string(g) }
diff --git a/serve.go b/serve.go
index 3adb34270..d30973adf 100644
--- a/serve.go
+++ b/serve.go
@@ -85,7 +85,7 @@ func (h healthHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
log.Printf("[TRACE] %v: requesting health probe", r.RemoteAddr)
resp := h.processAndEnsureCached(negotiatedContentType, outputer)
- w.Header().Set(http.CanonicalHeaderKey("Content-Type"), negotiatedContentType)
+ w.Header().Set(http.CanonicalHeaderKey("Content-Type"), negotiatedContentType) //nolint:gosimple
w.WriteHeader(resp.statusCode)
logBody := ""
if resp.statusCode != http.StatusOK {
diff --git a/serve_test.go b/serve_test.go
index b29fe3baf..8b19d048d 100644
--- a/serve_test.go
+++ b/serve_test.go
@@ -66,7 +66,7 @@ func TestServeWithNoContentNegotiation(t *testing.T) {
t.Logf("testName %q log output:\n%s", testName, logOutput.String())
assert.Equal(t, tc.expectedHTTPStatus, rr.Code)
if tc.expectedContentType != "" {
- assert.Equal(t, []string{tc.expectedContentType}, rr.HeaderMap["Content-Type"])
+ assert.Equal(t, tc.expectedContentType, rr.Result().Header.Get("Content-Type"))
}
})
}
@@ -173,7 +173,7 @@ func TestServeNegotiatingContent(t *testing.T) {
t.Logf("testName %q log output:\n%s", testName, logOutput.String())
assert.Equal(t, tc.expectedHTTPStatus, rr.Code)
if tc.expectedContentType != "" {
- assert.Equal(t, []string{tc.expectedContentType}, rr.HeaderMap["Content-Type"])
+ assert.Equal(t, tc.expectedContentType, rr.Result().Header.Get("Content-Type"))
}
})
}
@@ -297,11 +297,9 @@ func TestServeCacheNegotiatingContent(t *testing.T) {
func makeRequest(t *testing.T, config *util.Config, headers map[string][]string) *http.Request {
req, err := http.NewRequest("GET", config.Endpoint, nil)
require.NoError(t, err)
- if headers != nil {
- for header, vals := range headers {
- for _, v := range vals {
- req.Header.Add(header, v)
- }
+ for header, vals := range headers {
+ for _, v := range vals {
+ req.Header.Add(header, v)
}
}
return req
diff --git a/system/file.go b/system/file.go
index 6927d910f..a6f1efaef 100644
--- a/system/file.go
+++ b/system/file.go
@@ -38,14 +38,13 @@ type hashFuncType string
const (
md5Hash hashFuncType = "md5"
- sha256Hash = "sha256"
- sha512Hash = "sha512"
+ sha256Hash hashFuncType = "sha256"
+ sha512Hash hashFuncType = "sha512"
)
type DefFile struct {
path string
realPath string
- fi os.FileInfo
loaded bool
err error
}
@@ -167,7 +166,7 @@ func realPath(path string) (string, error) {
if f == "~" {
usr, err = user.Current()
} else {
- usr, err = user.Lookup(f[1:len(f)])
+ usr, err = user.Lookup(f[1:])
}
if err != nil {
return "", err
diff --git a/system/kernel_param.go b/system/kernel_param.go
index 867e08f65..c7b6e29f8 100644
--- a/system/kernel_param.go
+++ b/system/kernel_param.go
@@ -14,8 +14,7 @@ type KernelParam interface {
}
type DefKernelParam struct {
- key string
- value string
+ key string
}
func NewDefKernelParam(_ context.Context, key string, system *System, config util.Config) KernelParam {
diff --git a/system/service.go b/system/service.go
index df2a43dc7..bdb280702 100644
--- a/system/service.go
+++ b/system/service.go
@@ -11,8 +11,5 @@ type Service interface {
}
func invalidService(s string) bool {
- if strings.ContainsRune(s, '/') {
- return true
- }
- return false
+ return strings.ContainsRune(s, '/')
}
diff --git a/template.go b/template.go
index 1d524eacd..8621ce9d4 100644
--- a/template.go
+++ b/template.go
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
"regexp"
+ "strconv"
"strings"
"text/template"
@@ -76,11 +77,37 @@ func regexMatch(re, s string) (bool, error) {
return compiled.MatchString(s), nil
}
+// return named parenthesized subexpresions, if received, or stringfied (Sprig "get" need strings) keys like array
+func findStringSubmatch(pattern, input string) map[string]interface{} {
+ re := regexp.MustCompile(pattern)
+ els := re.FindStringSubmatch(input)
+
+ elsMap := make(map[string]interface{})
+ elsMapNamed := make(map[string]interface{})
+
+ // create always elsMaps but returns elsMapNamed if exists named parenthesized subexps
+ for i := 0; i < len(els); i++ {
+ // convert i to string according returned (https://github.com/goss-org/goss/pull/895#issuecomment-2075716706)
+ elsMap[strconv.Itoa(i)] = els[i]
+
+ if re.SubexpNames()[i] != "" {
+ elsMapNamed[re.SubexpNames()[i]] = els[i]
+ }
+ }
+
+ // returns elsMapNamed if exists named parenthesized subexps
+ if len(elsMapNamed) > 0 {
+ return elsMapNamed
+ }
+ return elsMap
+}
+
var funcMap = template.FuncMap{
- "mkSlice": mkSlice,
- "readFile": readFile,
- "getEnv": getEnv,
- "regexMatch": regexMatch,
- "toUpper": strings.ToUpper,
- "toLower": strings.ToLower,
+ "mkSlice": mkSlice,
+ "readFile": readFile,
+ "getEnv": getEnv,
+ "regexMatch": regexMatch,
+ "toUpper": strings.ToUpper,
+ "toLower": strings.ToLower,
+ "findStringSubmatch": findStringSubmatch,
}
diff --git a/util/config.go b/util/config.go
index 8c0a68d19..3be5fa84e 100644
--- a/util/config.go
+++ b/util/config.go
@@ -271,7 +271,7 @@ func ValidateSections(unmarshal func(any) error, i any, whitelist map[string]boo
typ := reflect.TypeOf(i)
typs := strings.Split(typ.String(), ".")[1]
for id, v := range toValidate {
- for k, _ := range v {
+ for k := range v {
if !whitelist[k] {
return fmt.Errorf("invalid Attribute for %s:%s: %s", typs, id, k)
}
@@ -295,7 +295,7 @@ func WhitelistAttrs(i any, format format) (map[string]bool, error) {
func IsValueInList(value string, list []string) bool {
for _, v := range list {
- if strings.ToLower(v) == strings.ToLower(value) {
+ if strings.EqualFold(v, value) {
return true
}
}