goss-org / goss

Quick and Easy server testing/validation
https://goss.rocks
Apache License 2.0
5.53k stars 470 forks source link

Add a dynamic dependancy in order for a test to run #784

Open uk-bolly opened 1 year ago

uk-bolly commented 1 year ago

Describe the feature: Due to the nature and design of many estates some features only exist on certain servers. To make this more dynamic and extendable as well as portable and reuseable. that allows and enables the same config to be run across entire estates rather than individual files per possible server setup.

Problem: We only need to confirm some server spec if a certain value is true e.g. 1/ if auditd is installed 2/ then run the following tests.

It could be seen as setting a variable on the fly and ensure the variable value as part of the test. This would also mean certain test would need to run in order. Although as per #742 the subsequent tests may reuse the variable multiple times (example tries to show this too). This feels more like a programming feature but could extend it usage.

Describe the solution you'd like

A possible way, add a new option of discovery which runs prior to any other tests to capture and set dynamic variables used by the server spec tests. These could even be in a dedicated file ensuring that the run before all others.

An example could be (this is very ansible like i am aware)

Example 1

file name: discovery.yml

discovery:
  package:
    auditd:
      installed: true
      register: auditd_installed

sometest1.yml

{{ if .Discovered.auditd_installed }}
file:
  /etc/auditd/audit.conf:
    exists: true
    contains: 
     - 'some string = 1'
    meta:
      test: 1
 {{ end }}

sometest2.yml

{{ if .Discovered.auditd_installed }}
file:
  /etc/auditd/audit.conf:
    exists: true
    contains: 
     - 'enable = true'
     meta:
      test: 2
 {{ end }}

Aware this only gives a boolean value rather than a discovered output. It would be nice if you could capture the other outputs and assign a value. e.g.

Example 2

file name: discovery.yml

discovery:
  package:
    auditd:
      installed: true
      register: auditd_installed
      version: 1.1

sometest1.yml

{{ if .Discovered.auditd_installed.version < "1.1" }}
file:
  /etc/auditd/audit.conf:
    exists: true
    contains: 
     - 'some string = 1'
    meta:
      test: 1
 {{ end }}

sometest2.yml

{{ if eq .Discovered.auditd_installed.version >= "1.1" }}
file:
  /etc/auditd/audit.conf:
    exists: true
    contains: 
     - 'enable = true'
     meta:
      test: 2
 {{ end }}

Describe alternatives you've considered

This could met by using the command test module, but then that is just running a shell script. It doesn't add the efficiency and consistency in the modules already developed.

Thanks again for this project.

aelsabbahy commented 1 year ago

Thanks for the thorough explanation.

Reflecting on this, let's approach it from the other end and see where the gaps are.

Today goss can leverage external discovery tools as follows:

$ goss --vars <(ohai) validate $ goss --vars <(facter -j) validate

doc (for the above): https://github.com/aelsabbahy/goss/blob/master/docs/manual.md#examples-2

These tools are dedicated to system discovery and have been around for quite some time, thus having quite a bit of maturity and a rich feature set (ex. pluggability). The same can be said for ansibles fact engine and its plugins.

To better understand this enhancement, where do those tools fall short today as an end user?

ekelali commented 1 year ago

Perhaps there's a middle-ground opportunity here:

goss --vars <(goss validate -g discovery.yaml --format discovery) validate

uk-bolly commented 1 year ago

hi @ekelali

Thats a great solution. It allows goss to be the one required tool (which is perfect in restricted environments).

berney commented 1 year ago

@uk-bolly Does this mean this can be closed now?

Should there be a documentation update to show this example?

aelsabbahy commented 1 year ago

--format discovery does not exist in Goss today. Someone would have to implement that before this ticket is closed.

There's --format json but I don't think that meets @uk-bolly need.