-
Notifications
You must be signed in to change notification settings - Fork 370
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
Adds --manifest-url flag to allow plugin installation from remote manifests #350
Adds --manifest-url flag to allow plugin installation from remote manifests #350
Conversation
This comment has been minimized.
This comment has been minimized.
51dadcc
to
3da3c54
Compare
This comment has been minimized.
This comment has been minimized.
/assign @soltysh |
86ca432
to
c34fd2e
Compare
c34fd2e
to
f708231
Compare
This proposal was previously discussed & denied, I believe. |
Oh, I couldn't find any such discussion on Github. This PR downloads the yaml file from the URL and stores it in a temporary location. After download, it transfers the control to I couldn't think of any potential drawbacks. In fact, I see this as an advantage for developers/users. May I know the reason behind denying this idea? |
I also tried to find but couldn't. Now I'm thinking if it was a private discussion with @corneliusweig. The main reasoning was a about a few points:
Since this has came up multiple times by now, we might be open to it. /unassign @soltysh |
Hi @rewanth1997, the issue @ahmetb mentioned is #193. I think the main reason against the However, even plugin devs do stumble over this |
I wasn't aware of the I just checked the The idea of throwing a custom error to use curl seems good but building a generic regex expression for URL is very tough. Limiting this just to |
@rewanth1997 Implementing the URL parser is not necessary. Go already has that built in. See https://github.com/kubernetes-sigs/krew/pull/302/files if _, err := url.ParseRequestURI(word); err == nil {
return true
} |
@corneliusweig I don't think this will work for our use case.
"/home/rewanth/kubectl-fields/deploy/krew/plugin.yaml" gets detected as URI but we are looking for URL.
Output
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: rewanth1997 The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
@corneliusweig I added an additional check to check for |
Good find! I'll consider adding the same logic in the other PR. Can you also add some tests for this behavior? Otherwise this looks good. Thanks! |
I validated the module independently with different protocols like SMB, FTP, HTTP, etc. I believe these checks are good enough for integration. Please let me know if something else needs to be done.
Output
Goplayground link to run tests: https://play.golang.org/p/xUN0SHp1c9t |
@corneliusweig have we settled on --manifest vs --manifest-url? |
Uses random port instead of hard-coded port. Closes http response object
All the tests are successful on my local system. Just to confirm, I forked my current working repository (https://github.com/rewanth1997/krew/tree/manifest-url) into my test account (https://github.com/testinguser883/krew/tree/manifest-url) and the build is successful there also (https://travis-ci.org/testinguser883/krew/builds/622366453). I'm not sure why travis is failing here. I made all the suggested changes expect I added the abstraction layer, removed hard-coded port number, closed response object after use and fixed a few linter bugs as well. Please review the latest code. |
@rewanth1997 I think you need to rebase your current branch on top of
I guess you will have to resolve a few merge conflicts. |
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.
Ok, this looks much better now. Left a few more comments, but that should be easy to do.
eec4072
to
0609ed9
Compare
@corneliusweig All recommended changes updated. |
@corneliusweig Even the mutually exclusive condition is fixed in the latest commit. All tests are passed locally. Please let me know if any further changes are required. |
The tests are failing with a very unusual error. |
t.Helper() | ||
|
||
server := httptest.NewUnstartedServer(http.FileServer(http.Dir("testdata"))) | ||
|
||
listener, err := net.Listen("tcp", "127.0.0.1:0") | ||
if err != nil { | ||
t.Fatalf("trouble starting local server") | ||
} | ||
server.Listener = listener | ||
server.Start() | ||
return server, server.URL |
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.
You can probably just do this:
httptest.NewServer(..)
return server.URL, server.Close
it does everything you want, and then you can embed it to the test because it's 2 lines.
func TestKrewInstall_EmptyManifestURL(t *testing.T) { | ||
skipShort(t) | ||
|
||
server, baseURL := startLocalServer(t) | ||
defer server.Close() | ||
|
||
test, cleanup := NewTest(t) | ||
defer cleanup() | ||
|
||
err := test.Krew("install", | ||
"--manifest-url", baseURL+emtpyManifestURI).Run() | ||
if err == nil { | ||
t.Errorf("expected install to fail but was successful") | ||
} | ||
} |
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.
what does this really test?
our validation method? aren't those already covered with unit tests?
func TestKrewInstall_InvalidManifestURL(t *testing.T) { | ||
skipShort(t) | ||
|
||
server, baseURL := startLocalServer(t) | ||
defer server.Close() | ||
|
||
test, cleanup := NewTest(t) | ||
defer cleanup() | ||
|
||
err := test.Krew("install", | ||
"--manifest-url", baseURL+invalidManifestURI).Run() | ||
if err == nil { | ||
t.Errorf("expected install to fail but was successful") | ||
} | ||
} |
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.
what does this really test?
our validation method? aren't those already covered with unit tests?
// GetPlugin is an abstraction layer for manifest and manifest-url handlers and returns plugin object | ||
func GetPlugin(manifest string, manifestURL string) (index.Plugin, error) { | ||
if manifest != "" { | ||
return indexscanner.ReadPluginFile(manifest) | ||
} | ||
|
||
return readRemotePluginManifest(manifestURL) | ||
} |
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.
This isn't really a good way to do things.
We could do this at the call site, now you just embedded the decisionmaking here, and it doesn't have unit tests.
func readRemotePluginManifest(url string) (index.Plugin, error) { | ||
resp, err := http.Get(url) | ||
if err != nil { | ||
return index.Plugin{}, errors.Wrapf(err, "Error downloading manifest from %q", url) | ||
} | ||
defer resp.Body.Close() | ||
|
||
plugin, err := indexscanner.DecodePluginFile(resp.Body) | ||
if err != nil { | ||
return index.Plugin{}, errors.Wrapf(err, "Error decoding manifest from %q", url) | ||
} | ||
|
||
return plugin, nil | ||
} |
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.
this doesn't have unit tests :)
would be good to unit-test this, rather than trying to test /empty.yaml /invalid.yaml etc.
@@ -0,0 +1,49 @@ | |||
// Copyright 2019 The Kubernetes Authors. |
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.
this cmd/ package does nearly nothing noteworthy that requires creating a new package for. especially because cmd/ directory directly has "tool" names (krew, generate-plugin-list, ...) this doesn't fit here.
I think this PR has showed us fundamentally how we should approach accepting patches to krew codebase. To me, minimalism is key, and ideally we should not require ~200 lines of new code to add one flag like this. I'll be preparing a PR that does the same thing. I think some issues in the PR stems from the fact that our indexscanner API isn't the best it could be. Let's see how much new code it'll end up in. |
@@ -81,8 +85,8 @@ Remarks: | |||
return errors.New("must specify either specify either plugin names (via positional arguments or STDIN), or --manifest; not both") |
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.
you missed this part. this ought to also factor in --manifest-url.
/hold |
Yes, even I'm not sure why? This branch is building successfully without any errors It would be great if you can point out why the build is failing here (maybe it's because this branch is not synced with the current master repo?) |
Yeah, most likely you’ll need to rebase. |
Yeah, sure. We will work on your PR. I will try to give inputs to the best of my knowledge. @corneliusweig @ahmetb Thanks for considering my idea, being so patient and reviewing my PR. |
Hey @rewanth1997, sorry that your PR doesn't make it into krew's codebase. Don't be upset though. The final draft was already much more mature than the initial one, so you probably could learn a lot by doing it. For your future work, you should focus on testing your code. You can learn a lot from looking at @ahmetb's version :) /close |
@corneliusweig: Closed this PR. 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. |
This feature addition lets the user/developer to install a krew plugin directly from the source URL instead of manually downloading the plugin file.
Problem statement
Install kubectl plugin from config file
Current approach
Proposed approach
This new feature addition will download the plugin from the URL to a temporary location and then installs the plugin from that temporary fie using the regular
manifest
method.Please review the feature request. I'm happy to make the necessary changes if any.
Regards,
Rewanth