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

feat(kustomize): support git/repo artifact in kustomize bake manifest #449

Merged
merged 12 commits into from
Oct 29, 2019

Conversation

KathrynLewis
Copy link
Contributor

This adds support for git/repo as an artifact type for a kustomize bake. This is a work in progress involving changes to other services as well, so we're leaving in the old logic (baking from a github/file artifact) until the rest of the PRs are merged.

@ezimanyi PTAL?

Copy link
Contributor

@ezimanyi ezimanyi left a comment

Choose a reason for hiding this comment

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

A few comments, but overall looks 👍 !


try {
extractArtifact(tarPath, env.resolvePath(""));
Copy link
Contributor

Choose a reason for hiding this comment

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

Currently, we're doing the following:

  • Requesting the artifact from clouddriver, then writing that InputStream to a file in artifactDownloader.downloadArtifact()
  • Opening the file as an InputStream and decompressing the archive

This would be simpler (and likely more efficient) if we directly consumed the InputStream we got back from clouddriver and decrypted from that, rather than needing the intermediate write to disk.

Perhaps we could rename ArtifactDownloader.downloadArtifact to ArtifactDownloader.downloadArtifactToFile and then have ArtifactDownloader.downloadArtifact just return an InputStream.

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 catch--changed! But I'm not sure how we want to handle an empty response body in the downloadArtifact() method. Right now, I just have it logging an error and returning null.

Copy link
Contributor

Choose a reason for hiding this comment

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

Good question! I'd suggest throwing an IOException (with the text you're currently logging) if the response body is empty. I realize that's a change from what we currently do, where we just silently don't write out the artifact to a file if there's no input, but it seems like an improvement as the error would be surfaced earlier and more clearly. (As opposed to currently where it would just manifest as a missing file somewhere downstream.)

On the topic of errors, @maggieneterval just improved the error handling in this file in #453 so that errors actually propagate back to the user (per the screen shots on that PR). So you'll probably have a minor merge conflict when you merge in her changes here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good--updated.


ArchiveEntry archiveEntry = null;
while ((archiveEntry = tarArchiveInputStream.getNextEntry()) != null) {
Path archiveEntryOutput = outputPath.resolve(archiveEntry.getName());
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this code behave if the archive entry's name references the parent directory? Could this break out of the temporary directory we're trying to extract to?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tested this out and you're right that if I force an entry to reference a parent, it does break out. Is this something that we want to support and handle in some way? Or should it be considered an error if an entry at the repo level tries to reference a parent? Because in theory, we wouldn't even have access to those files, correct?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we'd want to immediately throw an exception and abort if the entry tries to reference something outside of the repo directory. This would avoid security vulnerabilities where someone could send a specially-crafted repo artifact that unpacks on top of system files. (You're right that in theory important files shouldn't be accessible by the rosco process unless it's running as root which it shouldn't, but I still think it's better to fail fast before depending on these permissions being set correctly.)

A good example where we do this check elsewhere and fail fast is here. (That example is not in a re-usable place, but you could do something similar in the function you wrote.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep, that makes a lot of sense. 👍

@mrampton
Copy link

Linking to the PR in clouddriver which added git/repo: spinnaker/clouddriver#4049

Copy link
Contributor

@ezimanyi ezimanyi left a comment

Choose a reason for hiding this comment

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

One last comment, otherwise this is looking great!

if (response.getBody() == null) {
throw new IOException("Failure to fetch artifact: empty response");
} else {
try (InputStream inputStream = response.getBody().in()) {
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 think we'll want a try-with-resources in this function, as it's directly returning the InputStream which should remain open for the caller (whereas try-with-resources will close it).

I think what this function should do is just return response.getBody().in() after the null check. Then callers (including the below downloadArtifactToFile) should call this function as:

try (InputStream inputStream = downloadArtifact(artifact)) {
// ...use inputStream
}

That means we'll have nested try-with-resources blocks in downloadArtifactToFile but that's fine and the usual way of solving this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, that makes sense--updated. I have the catches nested as well, to preserve the logic of the error messages Maggie recently added.

Copy link
Contributor

@ezimanyi ezimanyi left a comment

Choose a reason for hiding this comment

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

Looks good, thanks!

@ethanfrogers ethanfrogers added the ready to merge Approved and ready for merge label Oct 29, 2019
@mergify mergify bot merged commit 2f92d63 into spinnaker:master Oct 29, 2019
@mergify mergify bot added the auto merged label Oct 29, 2019
@ethanfrogers ethanfrogers deleted the gitrepo-kustomize branch October 29, 2019 17:21
opsmxdemo pushed a commit to OpsMx/rosco that referenced this pull request Sep 15, 2020
…spinnaker#449)

* feat(kustomize): support git/repo artifact in kustomize bake manifest

* address code review comments

* address code review comments

* address code review comments
opsmxdemo pushed a commit to OpsMx/rosco that referenced this pull request Sep 16, 2020
…spinnaker#449)

* feat(kustomize): support git/repo artifact in kustomize bake manifest

* address code review comments

* address code review comments

* address code review comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
5 participants