YaleUniversity / packer-plugin-goss

Goss Provisioner for Packer
MIT License
136 stars 45 forks source link

Adds output_file as a attribute to redirect goss output to the specified file #100

Open FalcoSuessgott opened 2 weeks ago

FalcoSuessgott commented 2 weeks ago

merge after #99 fixes #89

Changes

Example

packer {
  required_version = ">= 1.9.0"

  required_plugins {
    goss = {
      version = "v0.0.1"
      source  = "github.com/YaleUniversity/goss"
    }
    docker = {
      source  = "github.com/hashicorp/docker"
      version = "v1.0.10"
    }
  }
}

# fetch a normal alpine container and export the image as alpine.tar
source "docker" "alpine" {
  image       = "alpine"
  export_path = "alpine.tar"
}

build {
  # apply build params against the alpine container
  sources = ["docker.alpine"]

  # run goss tests using goss provisioner
  provisioner "goss" {
    # download and install goss to /tmp/goss_install
    download_path = "/tmp/goss_install"

    # run goss tests in goss.yaml
    tests = ["./goss.yaml"]

    # output results as junit
    format = "junit"

    # write results to /tmp/goss_test_results.xml, which will be copied to the host
    output_file = "/tmp/goss_test_results.xml"
  }

  # output the test results just for demo purposes
  provisioner "shell-local" {
    inline = ["cat goss_test_results.xml"]
  }
}

running make local will build & install the plugin and execute it:

docker.alpine: output will be in this color.

==> docker.alpine: Creating a temporary directory for sharing data...
==> docker.alpine: Pulling Docker image: alpine
    docker.alpine: Using default tag: latest
    docker.alpine: latest: Pulling from library/alpine
    docker.alpine: Digest: sha256:b89d9c93e9ed3597455c90a0b88a8bbb5cb7188438f70953fede212a0c4394e0
    docker.alpine: Status: Image is up to date for alpine:latest
    docker.alpine: docker.io/library/alpine:latest
==> docker.alpine: Starting docker container...
    docker.alpine: Run command: docker run -v /home/morelly_t1/.config/packer/tmp3486027672:/packer-files -d -i -t --entrypoint=/bin/sh -- alpine
    docker.alpine: Container ID: d13395b14141df26c8a5e9e700fc72fd8dc6cf0c3060d8c34cea5ec5c5b95ab6
==> docker.alpine: Using docker communicator to connect: 172.17.0.3
==> docker.alpine: Provisioning with Goss
==> docker.alpine: Configured to run on Linux
    docker.alpine: Creating directory: /tmp/goss
    docker.alpine: Installing Goss from, https://github.com/goss-org/goss/releases/download/v0.4.7/goss-linux-amd64
    docker.alpine: Downloading Goss to /tmp/goss_install
==> docker.alpine: /bin/sh: curl: not found
    docker.alpine: goss version v0.4.7
==> docker.alpine: Uploading goss tests...
    docker.alpine: Uploading ./goss.yaml
==> docker.alpine: 
==> docker.alpine: 
==> docker.alpine: 
==> docker.alpine: Running goss tests...
==> docker.alpine: Running GOSS render command: cd /tmp/goss &&  /tmp/goss_install    render > /tmp/goss-spec.yaml
==> docker.alpine: Goss render ran successfully
==> docker.alpine: Running GOSS render debug command: cd /tmp/goss &&  /tmp/goss_install    render -d > /tmp/debug-goss-spec.yaml
==> docker.alpine: Goss render debug ran successfully
==> docker.alpine: Running GOSS validate command: cd /tmp/goss &&   /tmp/goss_install    validate --retry-timeout 0s --sleep 1s -f junit  | tee "/tmp/goss_test_results.xml"
    docker.alpine: <?xml version="1.0" encoding="UTF-8"?>
    docker.alpine: <testsuite name="goss" errors="0" tests="1" failures="1" skipped="0" time="0.000" timestamp="2024-07-06T05:14:34Z">
    docker.alpine: <testcase name="Process sshd running" time="0.000">
    docker.alpine: <system-err>Process: sshd: running: Expected false to equal true</system-err>
    docker.alpine: <failure>Process: sshd: running: Expected false to equal true</failure>
    docker.alpine: </testcase>
    docker.alpine: </testsuite>
==> docker.alpine: Goss validate ran successfully
==> docker.alpine: 
==> docker.alpine: 
==> docker.alpine: 
==> docker.alpine: Downloading Goss test result file
    docker.alpine: Downloading Goss test results from /tmp/goss_test_results.xml to current dir
==> docker.alpine: 
==> docker.alpine: 
==> docker.alpine: 
==> docker.alpine: Downloading spec file and debug info
    docker.alpine: Downloading Goss specs from, /tmp/goss-spec.yaml and /tmp/debug-goss-spec.yaml to current dir
==> docker.alpine: Running local shell script: /tmp/packer-shell2227336962
    docker.alpine: <?xml version="1.0" encoding="UTF-8"?>
    docker.alpine: <testsuite name="goss" errors="0" tests="1" failures="1" skipped="0" time="0.000" timestamp="2024-07-06T05:14:34Z">
    docker.alpine: <testcase name="Process sshd running" time="0.000">
    docker.alpine: <system-err>Process: sshd: running: Expected false to equal true</system-err>
    docker.alpine: <failure>Process: sshd: running: Expected false to equal true</failure>
    docker.alpine: </testcase>
    docker.alpine: </testsuite>
==> docker.alpine: Exporting the container
==> docker.alpine: Killing the container: d13395b14141df26c8a5e9e700fc72fd8dc6cf0c3060d8c34cea5ec5c5b95ab6
Build 'docker.alpine' finished after 11 seconds 770 milliseconds.

==> Wait completed after 11 seconds 770 milliseconds

==> Builds finished. The artifacts of successful builds are:
--> docker.alpine: Exported Docker file: alpine.tar
mattlorimor commented 1 week ago

I couldn't find anything in the goss-org/goss code nor documentation that allows one to tell Goss itself to write the test results to an output file.

I like that this provisioner has a possible workaround for that, but this also seems like something that should be an argument on goss validate that this provisioner simply has to inject if configured.

I may take a look and see how hard it'd be to add that functionality to goss. In the event that it does get added, I'd expect that this provisioner would just have to switch from using tee to injecting the argument instead.

mattlorimor commented 1 week ago

You could look at utilizing Tee-Object for the Windows use case.

FalcoSuessgott commented 1 week ago

Thanks for the tip. I will have a look at it on the weekend. I agree with this, should have already been an option in upstream goss. Maybe you can have a look at it :D

mattlorimor commented 1 week ago

Oh this actually is a request in goss already: https://github.com/goss-org/goss/issues/875.

FalcoSuessgott commented 1 week ago

You could look at utilizing Tee-Object for the Windows use case.

Is this included in the default powershell installation in all Windows Versions?

mattlorimor commented 1 week ago

I think so. It's part of Microsoft.PowerShell.Utility. Which, I'm fairly certain, has been included on Windows installations for a while - especially server OS flavors.

Microsoft is even nice enough to include a tee alias.

mattlorimor commented 1 week ago

I guess I wouldn't say all Windows versions. But it would appear to be present on pretty much anything anybody would be building today. The documentation links I included show it going as far back as PowerShell 5.0, which was released in February of 2016.

mattlorimor commented 1 week ago

If you want to be cautious, you could simply include in the documentation for the new output argument/parameter that, when using it on Windows, PowerShell is expected to be present at a version of at least 5.0 or higher due to the dependency on Tee-Object.

FalcoSuessgott commented 1 week ago

Thanks for the information. Will update the PR accordingly and hopefully get it merged very soon.

FalcoSuessgott commented 1 week ago

Alright, added some more examples/docs and implemented the Windows Version using Tee-Object, now waiting for some reviews