Possible for Packer to only push a Docker image based on successful execution of a custom script?

60 views
Skip to first unread message

njgr...@gmail.com

unread,
Nov 19, 2018, 10:49:03 AM11/19/18
to Packer
I'm trying to get Packer to build a Docker image, then run a container from that image and execute a few tests against the running container _before_ pushing the image back to a Docker registry.  I want to _only_ push the image if tests pass.  Otherwise, I want the build to fail and _not_ push anything.  

I've tried putting a "shell-local" post-processing step in between the "docker-tag" and the "docker-push" post-processing steps (pasted below).  The tests run as expected, but then the build fails on "docker-push" with "Can only import from docker-import and docker-tag artifacts".  This makes sense I guess - I lose the Docker artifact once I run the shell-local step so it doesn't know what I'm asking it to push.  I've explored "manifest" and "artifice" post-processors among other things but I haven't yet figured out how to make it work the way I want.

Is what I'm trying to do possible with Packer?

Thanks!

...
    "builders": [
        {
            "type": "docker",
            "image": "{{user `base_image_repository`}}:latest",
            "commit": true,
            "ecr_login": true,
            "login_server": "{{user `ecr_login_server`}}",
            "changes": [
                "CMD /opt/app/run.sh"
              ]
        }
    ],
    "provisioners": [
    ...
    ],
    "post-processors": [
        [
            {
                "type": "docker-tag",
                "repository": "{{user `docker_repository`}}",
                "tag": "{{user `version`}}"
            },
            {
                "type": "shell-local",
                "script": "./test-container.sh",
                "environment_vars": ["IMAGE_AND_TAG={{user `docker_repository`}}:{{user `version`}}", "LEVEL={{user `level`}}"]
            },
            {
                "type": "docker-push",
                "ecr_login": true,
                "login_server": "{{user `ecr_login_server`}}"
            }
        ]
    ]
}

Megan Marsh

unread,
Nov 19, 2018, 2:50:27 PM11/19/18
to packe...@googlegroups.com
You may be able to get the behavior you want by setting `keep_input_artifact` in your shell-local post-processor. https://www.packer.io/docs/templates/post-processors.html#input-artifacts

--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
 
GitHub Issues: https://github.com/mitchellh/packer/issues
IRC: #packer-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Packer" group.
To unsubscribe from this group and stop receiving emails from it, send an email to packer-tool...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/packer-tool/08bec5d1-4c5e-4161-b0b6-cca6de9ae533%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

njgr...@gmail.com

unread,
Nov 20, 2018, 9:07:35 AM11/20/18
to Packer
Thanks for the response!

I did try that but the result was the same.  It occurs to me that a flag like "passthrough_input_artifact" would be useful in this case.  I briefly glanced at some of the post-processing code and it seems like it wouldn't be too difficult to write a plugin (or, modify the existing shell-local post-processor).  But, for now, I think I'll take the approach of running the test(s) outside of the Packer build/tag/push phase.  I'd rather not even push an image that doesn't pass the test(s) but it's not a hard requirement.

I certainly will continue to welcome ideas/suggestions. 

Regards,

Nathan

Alvaro Miranda Aguilera

unread,
Nov 20, 2018, 11:57:59 AM11/20/18
to packe...@googlegroups.com
Hello.

What is the exit code when the test fails ?




For more options, visit https://groups.google.com/d/optout.


--
Alvaro

Megan Marsh

unread,
Nov 20, 2018, 11:59:35 AM11/20/18
to packe...@googlegroups.com
I'm not sure what the difference between the "passthrough_input_artifact" and "keep_input_artifact" behaviors would be. Can you elaborate?

njgr...@gmail.com

unread,
Nov 21, 2018, 9:34:30 AM11/21/18
to Packer
The exit code of the test script is 1 on test failure.  The return code is 0 on success.

I can definitely get the Packer build to fail on a failed test run - I've tested by altering the script so it'll always fail in a realistic way.  It's just that after the test passes, I can't get the next step of pushing the Docker image to actually work - it instead fails with "Can only import from docker-import and docker-tag artifacts".

--
Nathan

njgr...@gmail.com

unread,
Nov 21, 2018, 10:02:59 AM11/21/18
to Packer
Good question - perhaps the behavior of "keep_input_artifact" is supposed to be exactly what I want which is:

* I want a "docker-tag" to run as the first post-processor step.  Then, I want the "docker-tag" step to pass an appropriate Docker artifact to the next step - "shell-local" (though, "shell-local" won't use that artifact for anything - just keep track of it for subsequent steps).
* I want "shell-local" to run a bash script which starts up a container based on the newly tagged image.  If the test fails, I want the Packer build to fail (this works great right now!).  If the test passes, I want the "shell-local" post-processor to pass the same artifact it was given to the next post-processor step - "docker-push" so that the now tested image will be pushed to ECR.

Now, perhaps "keep_input_artifact" is indeed passing along the appropriate artifact - in fact, when I look at the code for the "shell-local" post processor, it looks like it _always_ passes along the input artifact.  Though, admittedly, I haven't familiarized myself with the rest of the code and I'm not proficient in the Go language.  But, it sure looks like it should work.

But, instead, what actually happens is that the "docker-push" step fails with "Can only import from docker-import and docker-tag artifacts".  If I remove the "shell-local" post-processing step from between "docker-tag" and "docker-push" (see original post for example), it works great - the appropriate image is pushed to ECR (though, obviously untested).

If I look at the "docker-push" post-processor code, I believe I see the exact condition check that's leading to the error:

if artifact.BuilderId() != dockerimport.BuilderId &&
artifact.BuilderId() != dockertag.BuilderId {
err := fmt.Errorf(
"Unknown artifact type: %s\nCan only import from docker-import and docker-tag artifacts.",
artifact.BuilderId())
return nil, false, err

My comment about the "passthrough_input_artifact" might be irrelevant - what I was trying to say was that I want it to work like I describe above - such that "shell-local" can be put between "docker-tag" and "docker-push" without breaking the build.  Does this make sense?

--
Nathan

Megan Marsh

unread,
Nov 26, 2018, 6:28:36 PM11/26/18
to packe...@googlegroups.com
Yeah, that makes sense. This is a reasonable request. Right now we're working on adding HCL2 to Packer, which will probably not come out until Packer 2.0, but that will probably solve this problem.  

Meanwhile, you may be better off using a local shell script to push the container rather than the docker-push post-processor. 
Reply all
Reply to author
Forward
0 new messages