Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Added URL support for --from-file command line flag #726

Merged
merged 24 commits into from May 16, 2018
Merged

Added URL support for --from-file command line flag #726

merged 24 commits into from May 16, 2018

Conversation

tkeech1
Copy link
Contributor

@tkeech1 tkeech1 commented May 1, 2018

Issue Ref: Issue 705

Description:

This PR adds support for URLs in the --from-file command line flag which allows the user to specify a a raw code file or zip file when calling function deploy or function update. For example:

function deploy foo --runtime python2.7 --from-file https://raw.githubusercontent.com/<USER>/<REPO>/<BRANCH>/<FILE> --handler test.foobar

Thanks.

TODOs:

  • Ready to review
  • Automated Tests
  • Docs

Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

Hi @tkeech1, thank you for sending a PR for this!

I would suggest a different approach here. Instead of downloading the file with the CLI and setting the function content in the field Function it would be better to:

  • Set the content type to url.
  • Set the function content to the URL given by the user.
  • In the provision container (see the method getProvisionContainer in k8sutil.go), if the content type is an url, download the file with curl and decode or unzip it if the content type isurl+base64 or url+zip.

That way we avoid the limitation of 1MB that the CRD object has and we fix as well #655.

Another couple of small suggestions:

  • You can still download the file in the CLI as well to obtain the sha256.
  • We don't need to support URLs pointing to a Zip file from the CLI in the first PR, we can assume that --from-url will point to a plain text file for the moment.

Let us know if you need any help with that.

if err != nil {
logrus.Fatal(err)
}

file, err := cmd.Flags().GetString("from-file")
Copy link
Contributor

Choose a reason for hiding this comment

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

we would need to throw an error if --from-url and --from-file are both set

Copy link
Contributor

Choose a reason for hiding this comment

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

did you miss this comment? (not sure if it has been answered elsewhere). Actually, thinking about it, it would be better to support that the flag --from-file supports to specify an URL. That is more similar to kubectl that allows you to do kubectl create -f https://... we can parse the path and discover if it is an URL.

@@ -120,6 +121,16 @@ func getFileSha256(file string) (string, error) {
return "sha256:" + checksum, err
}

func getHTTPSha256(bytes []byte) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this can be called getSha256, there is nothing specific about HTTP here

@tkeech1
Copy link
Contributor Author

tkeech1 commented May 2, 2018

Hi @andresmgot,
Thanks for the feedback. I'll try to make the changes you've suggested.

@gkarthiks
Copy link

Hi @tkeech1 , I have one more question. If the URL is say the gitlab or github URL, which needs an authentication, how are we handling the authentication?

Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

Great! thank you for applying the changes. I see that the CI is working now. Can you add an integration test to check that the feature is working in a real environment?

For doing so you need to add, in the examples/Makefile, a couple of tasks:

get-python-url:
    kubeless function deploy get-python --runtime python2.7 --handler helloget.foo --from-file https://raw.githubusercontent.com/kubeless/kubeless/v1.0.0-alpha.1/examples/python/helloget.py

get-python-url-verify:
    kubeless function call get-python |egrep hello.world

And then enable the test in the bats file tests/integration-tests.bats

@test "Deploy functions to evaluate" {
  deploy_function get-python
  ...
+ deploy_function get-python-url
  ...
}
...
+@test "Test function: get-python-url" {
+  verify_function get-python-url
+  kubeless_function_delete get-python-url
+}

@@ -433,6 +433,10 @@ func getProvisionContainer(function, checksum, fileName, handler, contentType, r
decodedFile := "/tmp/func.decoded"
prepareCommand = appendToCommand(prepareCommand, fmt.Sprintf("base64 -d < %s > %s", originFile, decodedFile))
originFile = decodedFile
} else if strings.Contains(contentType, "url") {
fromURLFile := "/tmp/func.fromurl"
prepareCommand = appendToCommand(prepareCommand, fmt.Sprintf("curl %s --silent --output %s", function, fromURLFile))
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets add -L to follow redirects

if err != nil {
logrus.Fatal(err)
}

file, err := cmd.Flags().GetString("from-file")
Copy link
Contributor

Choose a reason for hiding this comment

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

did you miss this comment? (not sure if it has been answered elsewhere). Actually, thinking about it, it would be better to support that the flag --from-file supports to specify an URL. That is more similar to kubectl that allows you to do kubectl create -f https://... we can parse the path and discover if it is an URL.

if !strings.HasPrefix(c.Args[0], "curl https://raw.githubusercontent.com/test/test/test/test.py --silent --output /tmp/func.fromurl") {
t.Errorf("Unexpected command: %s", c.Args[0])
}

Copy link
Contributor

Choose a reason for hiding this comment

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

can you add another unit test that checks that if the type is url+zip it downloads and unzip the file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @andresmgot,
Can you add a .zip file that can be used for integration testing to examples/nodejs/? My local integration tests use https://github.com/tkeech1/kubelessfunction/blob/master/nodejs/helloFunctions.zip but I would like to update the tests to download the zip file from the kubeless repo to avoid creating a dependency on my repo. Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's okay to have it there for the moment, just upload the file with this PR. We can modify the URL after this PR gets merged.

@andresmgot
Copy link
Contributor

Hi @tkeech1 , I have one more question. If the URL is say the gitlab or github URL, which needs an authentication, how are we handling the authentication?

Let's track that in a different Issue/PR.

Also, we need to support URLs for the flag --dependencies as well. It would be weird to allow remote files for the function code but no for its dependencies.

@tkeech1
Copy link
Contributor Author

tkeech1 commented May 8, 2018

Hi @andresmgot,
I like the idea of supporting URLs directly in the --from-file flag. I'll also add URL support for --dependencies and include the other changes you mentioned. Thanks.

* pv for kafka

* Update README.md

Fix some typos and links
@andresmgot andresmgot mentioned this pull request May 8, 2018
2 tasks
@andresmgot andresmgot mentioned this pull request May 15, 2018
Copy link
Contributor

@andresmgot andresmgot left a comment

Choose a reason for hiding this comment

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

This is great, thank you for working on this! I just made a few minor comments now.

It also seems that you need to update the unit tests in function_test.go. Once you fix that and apply the changes we can merge this PR.

Also can you update the docs at docs/advanced-function-deployment.md? There is a small description of the supported content types.

}
function.Spec.FunctionContentType = "url"
// strip any query params to determine if the file is a zip
if path.Ext(strings.Split(functionURL.String(), "?")[0]) == ".zip" {
Copy link
Contributor

Choose a reason for hiding this comment

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

I would move the check if strings.Index(file, "http://") and if path.Ext(strings.Split(functionURL.String(), "?")[0]) == ".zip" to the function getContentType of the function.go file so the same function always returns the full contentType

} else {
function.Spec.Function = base64.StdEncoding.EncodeToString(functionBytes)
}
function.Spec.Checksum, err = getFileSha256(file)
Copy link
Contributor

Choose a reason for hiding this comment

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

I would create another function here that given a content type it returns the content and its checksum:

func parseContent(content, type) (string, string, error)

that function would read a file in case the type is text do the base64 in case it is a zip or download the file in case it is an URL. That way you can reuse it for the dependencies file.

if !strings.HasPrefix(c.Args[0], "curl https://raw.githubusercontent.com/test/test/test/test.py --silent --output /tmp/func.fromurl") {
t.Errorf("Unexpected command: %s", c.Args[0])
}

Copy link
Contributor

Choose a reason for hiding this comment

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

It's okay to have it there for the moment, just upload the file with this PR. We can modify the URL after this PR gets merged.

get-python-url-deps:
kubeless function deploy get-python-url-deps --runtime python2.7 --handler helloget.foo --from-file https://raw.githubusercontent.com/kubeless/kubeless/v1.0.0-alpha.1/examples/python/hellowithdeps.py --dependencies https://raw.githubusercontent.com/kubeless/kubeless/v1.0.0-alpha.1/examples/python/requirements.txt

get-python-url-deps-verify:
Copy link
Contributor

Choose a reason for hiding this comment

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

This is very complete but these kind of tests take a long time to be executed in the CI. Can you merge get-python-url, get-python-url-filedep and get-python-url-deps in just one test? Basically having just get-python-url-deps since that one covers the previous two.

@andresmgot
Copy link
Contributor

Thank you for addressing all the comments! We can merge this now.

@andresmgot andresmgot merged commit a650c4c into vmware-archive:master May 16, 2018
@andresmgot andresmgot changed the title Added --from-url command line flag Added URL support for --from-file command line flag May 16, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants