Skip to content
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

porch: Added renderstatus to packagerevisionresources update api #3522

Merged
merged 6 commits into from
Oct 24, 2022

Conversation

droot
Copy link
Contributor

@droot droot commented Aug 31, 2022

This PR exposes kpt fn render results in the porch API (packagerevisionresources).

Note: Since API no longer returns failure on render failures, the existing tests are failing, I am looking into it but the code is good for review. The change is split in two commits to make it easier to review.

/cc @mortent @justinsb @ChristopherFry

Some follow ups:

  • rpkg push should display renderstatus
  • functionruntimes (builtin and podevaluator) should support structuredresults and fix exitCode.

@droot
Copy link
Contributor Author

droot commented Aug 31, 2022

/cc @ChristopherFry

@droot droot force-pushed the porch-surface-render-results branch from 12677e0 to 9619676 Compare October 7, 2022 18:56
@droot droot force-pushed the porch-surface-render-results branch 5 times, most recently from 20a00cf to eb83914 Compare October 19, 2022 21:13
@droot droot changed the title WIP: surface render results in packagerevisionresources api porch: Added renderstatus to packagerevisionresources update api Oct 19, 2022
@droot droot marked this pull request as ready for review October 19, 2022 21:17
Copy link
Contributor

@justinsb justinsb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good ... I vote to merge and iterate :-)

.gitignore Outdated
@@ -20,6 +20,7 @@ kpt/kpt
*.exe
*.gif
bin/
porch/cmd/porch/__debug_bin
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love this (I think I'd prefer a wildcard), but I guess it saves us from committing it by mistake :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found the wildcard ** matches any subdirectories.

Spec PackageRevisionResourcesSpec `json:"spec,omitempty"`
// Status PackageRevisionResourcesStatuc `json:"status,omitempty"`
Spec PackageRevisionResourcesSpec `json:"spec,omitempty"`
Status PackageRevisionResourcesStatus `json:"status,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure which which kind we should expose this on. I'm happy for it to start here, though my guess is that PackageRevision is the more likely long-term home.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. PackageRevision is the ultimate home.

// on a package resources.
type RenderStatus struct {
Result fnresult.ResultList `json:"result,omitempty"`
Err string `json:"err"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: json:"error" I suggest

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

applied, task, err := m.Apply(ctx, baseResources)
updatedResources, taskResult, task, err := m.Apply(ctx, baseResources)
if taskResult != nil && taskResult.Type == api.TaskTypeEval {
renderStatus = taskResult.RenderStatus
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean we only capture the last eval (i.e. the last function?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But is the goal that it should contain the output/errors from every function in the pipeline? Or do we abort the run when a function return an error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We abort the run when function returns error and if the last applied mutation was render, then we also return the renderStatus.
We can definitely extend it for all the mutations over time.

}

return result, m.task, nil
return result, nil, m.task, nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: four retvals is likely where I start to think about a struct

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

along these lines, perhaps there could be a struct that contains both Task and its TaskResult?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now returning TaskResult that contains *Task. Thanks.

Copy link
Contributor

@natasha41575 natasha41575 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, small question above

Copy link
Contributor

@mortent mortent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the merge and iterate approach, but we should be careful with the API. Probably easier to make changes in the types from the Aggregated APIserver than CRDs though.

Could we add a test of this to make sure we don't accidentally break it?

// and is returned in packageresourceresources API's status field. We continue with
// saving the non-rendered resources to avoid losing user's changes.
// and supress this err.
err = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this block? If we don't use the err variable for anything, can't we just replace it with _ in the call to applyResourceMutations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion. Done. Moved the comment above it.

// PackageRevisionResourcesStatus represents state of the rendered package resources.
type PackageRevisionResourcesStatus struct {
// RenderStatus contains the result of rendering the package resources.
RenderStatus RenderStatus `json:"renderStatus,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this only contains the result after a push right? We don't actually store the information anywhere, so a subsequent get will not contain the error? I would expect that he results from the latest run would be returned on every get. Similar to the previous comment, I would expect this to be on the PackageRevision rather than the PackageRevisionResources type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

subsequent get will not contain the error. I started with this API because this is the API that get's called when user edits a package and that's the place renderStatus is most useful. And I agree that renderStatus should be added to packagerevision's status and should also be persisted so that we get it on every get. And that can be done as a follow up incrementally.

applied, task, err := m.Apply(ctx, baseResources)
updatedResources, taskResult, task, err := m.Apply(ctx, baseResources)
if taskResult != nil && taskResult.Type == api.TaskTypeEval {
renderStatus = taskResult.RenderStatus
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But is the goal that it should contain the output/errors from every function in the pipeline? Or do we abort the run when a function return an error?

@droot droot force-pushed the porch-surface-render-results branch from 21c52aa to d424b55 Compare October 21, 2022 20:02
@droot droot force-pushed the porch-surface-render-results branch from d424b55 to c802d2f Compare October 21, 2022 23:35
Copy link
Contributor Author

@droot droot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback everyone. I have addressed all the feedback that I was planning to address in current cycle. There is definitely more follow ups but I think this is a reasonable checkpoint to get merged.

@droot droot merged commit aa38ca6 into kptdev:main Oct 24, 2022
@droot
Copy link
Contributor Author

droot commented Oct 24, 2022

Could we add a test of this to make sure we don't accidentally break it?

I enhanced the existing updateResources tests to assert the renderStatus.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants