-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for taskRun to expose digest of built images #721
Conversation
/test pull-tekton-pipeline-integration-tests |
@bobcatfish the YAML tests are failing because getting latest from |
/test pull-tekton-pipeline-integration-tests |
/test pull-tekton-pipeline-integration-tests |
So after each step we'll inject a container that checks for contents in A requested step like this:
will end up as a pair of containers:
This requires the task author to know where the builder will write its I wonder if we can (ab)use termination message paths to specify a path in original container where it should write output data, then this will be directly available via the pod's status, without having to inject more containers or parse container logs. This frees us from having to inject containers after each step, and from having to scrape logs, which might become brittle. It also means the controller tells the builder where it expects to read logs, rather than requiring the task author to know where the builder typically writes logs. So a step defined as:
will end up as a pod container like:
If the builder sees that One downside: docs for termination messages says:
Though elsewhere it says:
It might be possible to increase this limitation, or we might need to compress output or strip out unnecessary fields, or else risk only collecting partial data. Am I understanding your approach correctly? Let me know if you'd prefer to chat over video, either at the next WG or ad-hoc. Sorry it's taken me so long to review this. |
@imjasonh I added a field for the indexpath location in the resource, so users can specify where the builder they are using will output this file. I thought about using the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work, I'm very excited about this functionality @nader-ziada !! 🎉 ❤️ 🎉
I left some miscellaneous feedback but it sounds like you and @imjasonh have a solid design in general!
My only question, and if this is something you're planning to address in a future iteration which is totally cool, but it's not clear to me how the pipelinerun controller is going to take the digest of the built image and make it available for downstream tasks (which can be using it in their templating e.g. "${inputs.resources.image.url}@${inputs.resources.image.digest}"
) ?
ii, err := layout.ImageIndexFromPath(imageResource.IndexPath) | ||
if err != nil { | ||
// if this image doesn't have a builder that supports index.josn file, | ||
// then it will be skipped |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe log something in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bumping this! :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to log something here because the controller will be trying to parse the output of that container, also because not all builder will support this, I want it to be optional without errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hm okay :( too bad it looks like you couldn't have the controller only grab only stdout :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me give that a try :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bobcatfish as far as I understand you have to attach to the pod to get the Stdout
only, which would not work if the pod is completed. I think the get logs would be a safer bet in that case, wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the issue with using log here, however silently skipping the image if the builder is not supported will make things easier to troubleshoot. You may also have the case of a supported image builder which is malfunctioning in a specific case and not producing the index.json.
Would it be an option to use the digest field itself to output a standard string e.g. "builder did not produce index.json" or so?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the controller could be aware of that error and not try to parse if it sees the error?
pkg/reconciler/v1alpha1/taskrun/resources/image_exporter_test.go
Outdated
Show resolved
Hide resolved
c73b1b2
to
80888fa
Compare
- run the image digest exporter after each step - move the index path to the task definition instead of the resource since the user needs to know this at the time of creating the task so it can be used as part of the steps scripting if needed - rename indexpath to outputimagepath - add example yaml
/hold pushed some changes but still work in progress |
e3e3ee1
to
e699154
Compare
- run the image digest exporter after each step - move the index path to the task definition instead of the resource since the user needs to know this at the time of creating the task so it can be used as part of the steps scripting if needed - rename indexpath to outputimagepath - add example yaml
e699154
to
6232343
Compare
- run the image digest exporter after each step - move the index path to the task definition instead of the resource since the user needs to know this at the time of creating the task so it can be used as part of the steps scripting if needed - rename indexpath to outputimagepath - add example yaml - refactor image exporter code and add more unit tests
/hold cancel |
@bobcatfish @imjasonh ready for another look, I made the following changes:
|
6232343
to
374637e
Compare
- run the image digest exporter after each step - move the index path to the task definition instead of the resource since the user needs to know this at the time of creating the task so it can be used as part of the steps scripting if needed - rename indexpath to outputimagepath - add example yaml - refactor image exporter code and add more unit tests Signed-off-by: Nader Ziada <nziada@pivotal.io>
- run the image digest exporter after each step - move the index path to the task definition instead of the resource since the user needs to know this at the time of creating the task so it can be used as part of the steps scripting if needed - rename indexpath to outputimagepath - add example yaml - refactor image exporter code and add more unit tests Signed-off-by: Nader Ziada <nziada@pivotal.io>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a bunch of miscellaneous comments, generally looking great tho and the approach is solid imo!
/approve
/meow space
In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
- run the image digest exporter after each step - move the index path to the task definition instead of the resource since the user needs to know this at the time of creating the task so it can be used as part of the steps scripting if needed - rename indexpath to outputimagepath - add example yaml - refactor image exporter code and add more unit tests Signed-off-by: Nader Ziada <nziada@pivotal.io>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bit more feedback! Interface looks great, just wondering about /tools/output-image
.
I looked at the tests in a bit more detail, wondering if we can break up the AddOutputImageDigestExporter
function a bit.
ii, err := layout.ImageIndexFromPath(imageResource.IndexPath) | ||
if err != nil { | ||
// if this image doesn't have a builder that supports index.josn file, | ||
// then it will be skipped |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bumping this! :)
pkg/reconciler/v1alpha1/taskrun/resources/image_exporter_test.go
Outdated
Show resolved
Hide resolved
Args: []string{"-images", fmt.Sprintf("[{\"name\":\"source-image-1\",\"type\":\"image\",\"url\":\"gcr.io/some-image-1\",\"digest\":\"\",\"OutputImageDir\":\"%s\"}]", currentDir)}, | ||
}}, | ||
}, { | ||
desc: "image resource in task with multiple steps", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm trying to understand the difference between the two cases in this test and it seems like:
- both have a resource that is used as an input AND and output
- one has 1 step, the other has 2
I think there might be some more cases we'd want to test, like:
- output resource only
- when the
OutputImageDir
isn't set
This got me wondering if there is a way we could make the AddOutputImageDigestExporter
function more focused so it would be a bit easier to tell what needed to be tested, and the test could be shorter: what if the function was divided up like this:
- A function that can return all (if any) output image resources from a Task
- A function that sets the
OutputImageDir
as needed - A function that adds the imageDigestExporterContainer
?
(I don't mind if you want to do that in a follow-up PR instead!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
when the outputImageDir
is not set has a test in the task defaults since it get set there and output resource only don't would make any difference
for the refactor, makes sense, but I'd prefer if we do it in a follow up PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the refactor, makes sense, but I'd prefer if we do it in a follow up PR
kk!
Left a few comments! Not sure about using Also would like to see |
@bobcatfish i’ll work on these last few comments this week. Thanks :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good 😻
Few nits and one questions in addition to @bobcatfish comments
{ | ||
"mediaType": "application/vnd.oci.image.index.v1+json", | ||
"size": 314, | ||
"digest": "sha256:05f95b26ed10668b7183c1e2da98610e91372fa9f510046d4ce5812addad86b5" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think buildah
does, or we could use skopeo
to fetch an image and write it in oci
format
skopeo copy docker://busybox:latest oci:busybox_ocilayout:latest
But it can be done in a follow-up too 😉
// Resource Value stuff | ||
// +optional | ||
// Path to the index.json file for output container images | ||
OutputImageDir string `json:"outputImageDir"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to not re-use TargetPath
for the output folder ? (might have been already discussed 🙇♂️)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't know, didn't think about it 🤷🏼♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asking that as this field is only gonna be useful for one type of resources and I feel it would make sense to re-use TargetPath
.
@bobcatfish @abayer wdyt ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might bit a little confusing because it will have different meanings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might bit a little confusing because it will have different meanings
Yeah I am 50/50 on that. It's close (as it is a "target" path), but user "may" think it's related to the image reference (although this is not where we define that one so…). I'm not sure how confusing it can be 😅 #dont-know-what-i-am-talking-about 😹
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oooo yeah this is a good idea - I'm really tempted to re-use targetPath
here too 🤔but also I'm torn because overloading it may be confusing. Since we're alpha (famous last words) I'm thinking go ahead with OutputImageDir
for now and see how it goes?
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: bobcatfish, nader-ziada, vdemeester The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
- This features requires the builder used to build the image to export an oci standard layout file `index.json` https://github.com/opencontainers/image-spec/blob/master/image-layout.md - If the `index.json` file is not present, the digest will not be exposed in the taskRun - add a field in the image resource to indicate the location of the index.json file -> `indexpath` - add a field in the taskRun status to include the image name and digest -> `resourcesResult` - add a container step to collect the digest from all the files - the taskRun controller will collect the output from the image-digest-exporter container and update the taskRun status
- run the image digest exporter after each step - move the index path to the task definition instead of the resource since the user needs to know this at the time of creating the task so it can be used as part of the steps scripting if needed - rename indexpath to outputimagepath - add example yaml - refactor image exporter code and add more unit tests Signed-off-by: Nader Ziada <nziada@pivotal.io>
- rename field to OutputImageDir instead of OutputImagePath - fixed documentation typos
- fix some docs and comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work, thank you! I look forward to having this feature merge in.
The only thing that concerns me a bit on this is using the container log to transport data, but that's definitely not a show-stopper, it may be something we can improve upon in future.
return nil | ||
} | ||
|
||
// UpdateTaskRunStatusWithResourceResult if there an update to the outout image resource, add to taskrun status result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there is an update to the output
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bumping this - might merge anyway tho cuz it's been a long road and this PR is otherwise in pretty great shape - maybe @nader-ziada can fix in a follow up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can do a followup PR on that one
if err != nil { | ||
logger.Errorf("Error getting output from image-digest-exporter for %s/%s: %s", taskRun.Name, taskRun.Namespace, err) | ||
} | ||
err = resources.UpdateTaskRunStatusWithResourceResult(taskRun, logContent) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been trying to find an alternative to using the log file to share data, so that we could keep the log file to log things. The best idea I could come up with so far is to use the imagedigestreporter
to update the TaskRun via patch and store the image digest there.
Did you consider any other alternative yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a doc sent out a while back: and this PR was based on the feedback I got.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i know what you mean @afrittoli ! it seems a bit odd but it also seems like the best option at the moment - but fortunately since this is an implementation detail, I feel like we're safe to go ahead with this and if we come across a better idea we can change it later :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your patience @nader-ziada , looking great! 😻
A couple minor comments but I don't think there's anything that should stop us from merging - let's do it!
Thanks for adding this excellent new feature :D
/lgtm
/meow space
ii, err := layout.ImageIndexFromPath(imageResource.IndexPath) | ||
if err != nil { | ||
// if this image doesn't have a builder that supports index.josn file, | ||
// then it will be skipped |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the controller could be aware of that error and not try to parse if it sees the error?
The `/builder/` namespace is reserved on containers for various system tools, such as the following: | ||
|
||
- The environment variable HOME is set to `/builder/home`, used by the builder tools and injected on into all of the step containers | ||
- Default location for output-images `/builder/output-images` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
// Resource Value stuff | ||
// +optional | ||
// Path to the index.json file for output container images | ||
OutputImageDir string `json:"outputImageDir"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oooo yeah this is a good idea - I'm really tempted to re-use targetPath
here too 🤔but also I'm torn because overloading it may be confusing. Since we're alpha (famous last words) I'm thinking go ahead with OutputImageDir
for now and see how it goes?
return nil | ||
} | ||
|
||
// UpdateTaskRunStatusWithResourceResult if there an update to the outout image resource, add to taskrun status result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bumping this - might merge anyway tho cuz it's been a long road and this PR is otherwise in pretty great shape - maybe @nader-ziada can fix in a follow up?
In response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
Looks like there is some new linting @dlorenc added recently that has noticed a couple things so we can't merge just yet @nader-ziada :( 😭
|
Thanks @bobcatfish, pushed a fix to the linting issues, happy to do a follow-up PR for other comments, there was already a refactor we talked about that I said I would do as a follow up :D |
Thanks @nader-ziada!! : heart: /lgtm |
- run the image digest exporter after each step - move the index path to the task definition instead of the resource since the user needs to know this at the time of creating the task so it can be used as part of the steps scripting if needed - rename indexpath to outputimagepath - add example yaml - refactor image exporter code and add more unit tests Signed-off-by: Nader Ziada <nziada@pivotal.io>
Changes
Part of #216 - once we agree on the digest part, I can add the image validation in this or another PR
an oci standard layout file
index.json
https://github.com/opencontainers/image-spec/blob/master/image-layout.md
index.json
file is not present, the digest will not beexposed in the taskRun
index.json file ->
indexpath
digest ->
resourcesResult
image-digest-exporter container and update the taskRun status
Submitter Checklist
These are the criteria that every PR should meet, please check them off as you
review them:
See the contribution guide
for more details.
Release Notes