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

Move copyfile function to client-go & remove all ocpath related code #503

Merged
merged 1 commit into from Jul 24, 2018

Conversation

surajnarwade
Copy link
Contributor

Resolves #443

This PR will remove dependency of oc binary for copyfiles function which copies file to component while odo push

@surajnarwade surajnarwade added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. Required by Prow. label Jun 4, 2018
@mik-dass
Copy link
Contributor

mik-dass commented Jun 4, 2018

Works but if I am inside a directory not containing the war file, then push fails

[mdas@localhost odo]$ ./odo update wildly --binary "~/Downloads/sample (1).war"
The component wildly was updated successfully
[mdas@localhost odo]$ ./odo push
Pushing changes to component: wildly
stat /home/mdas/go/src/github.com/redhat-developer/odo/~/Downloads/sample (1).war: no such file or directory

@surajnarwade surajnarwade force-pushed the copy-go branch 2 times, most recently from c587bc1 to 8c972d8 Compare June 7, 2018 05:01
@surajnarwade
Copy link
Contributor Author

@mik-dass , check once again, your path seems to be messed up

/home/mdas/go/src/github.com/redhat-developer/odo/~/Downloads/sample (1).war

@mik-dass
Copy link
Contributor

mik-dass commented Jun 7, 2018

@surajnarwade Yeah sorry my bad, the problem was the ~ is not working in the "", so I guess the user will have to write the full path in that case

Copy link
Contributor

@mik-dass mik-dass left a comment

Choose a reason for hiding this comment

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

It's working for me though just the comments have to be removed

data *string
format string
}
//func getOcBinary() (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.

@surajnarwade Are these comments required?

// RsyncPath copies local directory to directory in running Pod.
func (c *Client) RsyncPath(localPath string, targetPodName string, targetPath string) (string, error) {
log.Debugf("Syncing %s to pod %s:%s", localPath, targetPodName, targetPath)
//// RsyncPath copies local directory to directory in running Pod.
Copy link
Contributor

Choose a reason for hiding this comment

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

@surajnarwade Are these comments required too?

})
}
}
//func TestGetOcBinary(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

@surajnarwade And here also, are they required?

@surajnarwade surajnarwade force-pushed the copy-go branch 2 times, most recently from 8bef6c8 to 36da172 Compare June 8, 2018 05:11
@surajnarwade surajnarwade changed the title [WIP]Move copyfiles function to client-go Move copyfile function to client-go & remove all ocpath related code Jun 8, 2018
@surajnarwade surajnarwade removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. Required by Prow. label Jun 8, 2018
@surajnarwade surajnarwade requested review from cdrage and kadel June 8, 2018 05:32
Copy link
Contributor

@mik-dass mik-dass left a comment

Choose a reason for hiding this comment

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

works for me, LGTM :)

@kadel kadel added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. Required by Prow. label Jun 8, 2018
servicecatalogclienset "github.com/kubernetes-incubator/service-catalog/pkg/client/clientset_generated/clientset/typed/servicecatalog/v1beta1"
appsv1 "github.com/openshift/api/apps/v1"
buildv1 "github.com/openshift/api/build/v1"
imagev1 "github.com/openshift/api/image/v1"
Copy link
Member

Choose a reason for hiding this comment

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

why have you grouped everything together?
api objects an clients were separated to make logical groups that are easier to search in

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it wasn't me :(
it was my stupid IDE and auto go imports
corrected to original one

@kadel
Copy link
Member

kadel commented Jun 8, 2018

When I run odo watch or odo push after I change something in the files, I'm seeing

E0608 18:53:10.537466   89235 v2.go:163] io: read/write on closed pipe

@kadel
Copy link
Member

kadel commented Jun 8, 2018

It looks like that when running odo watch it pushes content of the whole directory instead of just changed files.

@kadel
Copy link
Member

kadel commented Jun 8, 2018

When my repository contains bigger file (100M) it fails

▶ odo -v push
DEBU[0000] Trying to connect to server 192.168.99.100:8443 - %!v(MISSING)
DEBU[0000] Server https://192.168.99.100:8443 is up
DEBU[0000] isLoggedIn err:  <nil>
 output: "developer"
DEBU[0000] No component name passed, assuming current component
Pushing changes to component: python
DEBU[0000] Getting BuildConfig: python
DEBU[0000] Source for component python is file:///Users/tomas/tmp/odo-examples/blog-django-py (local)
DEBU[0000] Waiting for deploymentconfig=python pod
DEBU[0000] Status of python-1-hv54p pod is Running
DEBU[0000] Pod python-1-hv54p is running.
DEBU[0000] Copying file /Users/tomas/tmp/odo-examples/blog-django-py/ to pod python-1-hv54p:/opt/app-root/src
E0608 19:19:36.436075   96528 v2.go:163] io: read/write on closed pipe
DEBU[0002] Error:
unable push files to pod: error while streaming command: command terminated with exit code 2
failed to push component: python

@surajnarwade surajnarwade removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. Required by Prow. label Jun 11, 2018
@surajnarwade
Copy link
Contributor Author

surajnarwade commented Jun 11, 2018

For more than 100M file,

  • error is coming from fsnotify
error watching filesystem for changes: fsnotify queue overflow 
Error while trying to watch /home/snarwade/odo-example/nodejs-ex

Reference:

ABOUT PUSHING the content of WHOLE DIRECTORY

oc rsync has 3 stratergies: rsync, rsync-daemon, or tar

according to documentation,

The tar copy method does not provide the same functionality as rsync. For example, rsync creates the destination directory if it does not exist and will only send files that are different between the source and the destination.

To avoid rsync, I tried to use Tar here, make sense ?

@kadel , can you please give me link of python example that you are trying ?

@kadel
Copy link
Member

kadel commented Jun 11, 2018

ABOUT PUSHING the content of WHOLE DIRECTORY

We can avoid that, just modify watch so it doesn't push the whole directory, but just a single file that has changed, even better tar all the files that changed in the watch loop

For more than 100M file,
large files are working with old implementation

the error

unable push files to pod: error while streaming command: command terminated with exit code 2

is not from fsnotify library but it looks like it is from the tar command in pod

@kadel
Copy link
Member

kadel commented Jun 11, 2018

Hmm, it looks like the 100M problem is away. I can't reproduce it anymore.

@surajnarwade surajnarwade force-pushed the copy-go branch 2 times, most recently from 1deedf6 to 28c3a6c Compare June 13, 2018 06:34
//watchTar
for _, fileName := range changedFiles {
if checkFileExist(fileName) {
fmt.Println("sending file", fileName)
Copy link
Member

Choose a reason for hiding this comment

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

this probably shouldn't print to stdout. Also, the message is confusing it is not actually sending a file, or is it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh that was my debug line :P

func (c *Client) RsyncPath(localPath string, targetPodName string, targetPath string) (string, error) {
log.Debugf("Syncing %s to pod %s:%s", localPath, targetPodName, targetPath)
// CopyFile copies single local file to the directory in running Pod.
func (c *Client) CopyFile(asFile bool, localFile string, targetPodName string, targetPath string, changedFiles []string) error {
Copy link
Member

Choose a reason for hiding this comment

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

We need a comment explaining what the parameters are and fix names.
for example localFile doesn't have to be always a file, it can be a path to a directory when asFiles is false.
changedFiles is also not a good name.
What happens when I set both localFile and changedFiles?

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'll add comments, you can't set both localFile & changedFiles at once, changedFiles will only set if we are using odo watch

}

// watchTar will be used to tar files using odo watch
func watchTar(tw *taro.Writer, fileName string, destFile string) error {
Copy link
Member

Choose a reason for hiding this comment

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

watchTar it looks like you are watching tars :-)
Isn't this function just adding a single file to the taro.Writer?

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 :|

@@ -1,15 +1,17 @@
package occlient

import (
taro "archive/tar"
Copy link
Member

Choose a reason for hiding this comment

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

why is this taro and not just tar?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

because there is conflict of name tar, we are using tar from S2I as well,
https://github.com/surajnarwade/ocdev/blob/28c3a6c56db39ad593a0cc79b099eea9d1d24535/pkg/occlient/occlient.go#L24

Copy link
Member

@kadel kadel left a comment

Choose a reason for hiding this comment

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

It is broken for binary components!!!

When you try to push on a binary component it looks like it is pushing the whole directory.

We need to fix tests first!!!
This should be caught by tests!

@@ -166,13 +166,14 @@ func GetCurrent(client *occlient.Client, applicationName string, projectName str

// PushLocal push local code to the cluster and trigger build there.
// asFile indicates if it is a binary component or not
Copy link
Member

Choose a reason for hiding this comment

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

this needs to be updated

// We need to make sure that there is a '/' at the end, otherwise rsync will sync files to wrong directory
path = fmt.Sprintf("%s/", path)
}
//if !asFile {
Copy link
Member

Choose a reason for hiding this comment

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

can we delete 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.

yep :|

cmd/push.go Outdated
if sourceType == "binary" {
asFile = true
var path string
if sourceType == "local" {
Copy link
Member

Choose a reason for hiding this comment

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

this looks odd, what will happen with path when sourceType is binary?

Copy link
Member

Choose a reason for hiding this comment

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

shouldn't we call PushLocal where the last argument is slice with one file and that is the binary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

that was my stupid mistake :( and was breaking the binary thing

"--exclude", ".git",
"--no-perms",
// CopyFile copies localFile to the directory in running Pod.
// if asFile is true, localFile will be file otherwise it is path to a directory
Copy link
Member

Choose a reason for hiding this comment

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

needs to be updated

// if asFile is true, localFile will be file otherwise it is path to a directory
// copyFiles is list of changed files captured during `odo watch`
// localFile is ignored if copyFiles is set
func (c *Client) CopyFile(localFile string, targetPodName string, targetPath string, copyFiles []string) error {
Copy link
Member

Choose a reason for hiding this comment

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

localFile should be named localPath as it will indicate that we want to copy the whole directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it can be binary as well, so I kept localFile only

Copy link
Member

Choose a reason for hiding this comment

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

no, first argument should always be a directory. If single file copy is required the last argument should be used

if len(copyFiles) != 0 {
log.Debugf("Copying files %s to pod %s:%s", copyFiles, targetPodName, targetPath)
} else {
log.Debugf("Copying file %s to pod %s:%s", localFile, targetPodName, targetPath)
Copy link
Member

Choose a reason for hiding this comment

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

this should say that it is copying directory not files

@kadel
Copy link
Member

kadel commented Jun 27, 2018

@surajnarwade I tried those commands and they are working for me

Are you sure @mik-dass? Can you please try it again for binary components?

@surajnarwade surajnarwade force-pushed the copy-go branch 2 times, most recently from 417b6f6 to ee14e02 Compare June 29, 2018 12:29
@surajnarwade
Copy link
Contributor Author

@kadel , there was my stupid mistake, Now binary components also works :)

@@ -46,7 +46,7 @@ var watchCmd = &cobra.Command{
componentName = args[0]
}

sourceType, sourcePath, err := component.GetComponentSource(client, componentName, applicationName, projectName)
_, sourcePath, err := component.GetComponentSource(client, componentName, applicationName, projectName)
Copy link
Member

Choose a reason for hiding this comment

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

why are we no longer retrieving the sourceType?

log.Debugf("isLoggedIn err: %#v \n output: %#v", err, string(output))
// isLoggedIn checks whether user is logged in or not and returns boolean output
func (c *Client) isLoggedIn() bool {
output, err := c.userClient.Users().Get("~", metav1.GetOptions{})
Copy link
Member

Choose a reason for hiding this comment

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

What's the purpose of the constant "~"? May have to add a comment here (since I don't understand either)

Copy link
Member

Choose a reason for hiding this comment

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

Home maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it gives us current user

dest := targetPath + "/" + path.Base(localPath)
reader, writer := io.Pipe()

go func() {
Copy link
Member

Choose a reason for hiding this comment

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

Add comment here. This section creates a go routine that creates the tar in the background, correct? Should we add input / any debug information here / progress bar?

defer writer.Close()
err := makeTar(localPath, dest, writer, copyFiles)
if err != nil {
os.Exit(-1)
Copy link
Member

Choose a reason for hiding this comment

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

Exists with -1... shouldn't we add an error out here / error message?

}
return nil
Copy link
Member

Choose a reason for hiding this comment

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

I don't see a sync check, for this function, should we wait until the go routine is finished before proceeding?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

@cdrage go routine is writing to Pipe via writer. ExecCMDInContainer is then streaming it to the command's stdin via reader. There is no need to sync anything. ExecCMDInContainer waits for the command to finish, the command will finish only after it receives all the data to stdin.

var cmdArr []string

if len(copyFiles) != 0 || string(localPath[len(localPath)-1]) == "/" {
cmdArr = []string{"tar", "xf", "-", "-C", targetPath, "--strip", "1"}
Copy link
Member

Choose a reason for hiding this comment

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

we're using tar commands here from the OS. even though it's unlikely, the OS may not have tar (windows users, maybe Mac), could we use the tar library that you imported instead

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this tar command runs inside container, so we don't need to worry about it, we are already using tar library here

return true
}

// makeTar function is copied from https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/cmd/cp.go#L309
Copy link
Member

Choose a reason for hiding this comment

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

lgtm

func (c *Client) CopyFile(localFile string, targetPodName string, targetPath string) (string, error) {
log.Debugf("Copying file %s to pod %s:%s", localFile, targetPodName, targetPath)
// Tar will be used to tar files using odo watch
func tar(tw *taro.Writer, fileName string, destFile string) error {
Copy link
Member

Choose a reason for hiding this comment

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

is this function also copied from somewhere else?

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 Author

Choose a reason for hiding this comment

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

Updated with reference link

Copy link
Member

@kadel kadel left a comment

Choose a reason for hiding this comment

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

during odo watch on binary component I get following message:

DEBU[0009] Copying directory [/Users/tomas/tmp/odo-examples/backend/target/ROOT.war] to pod wildfly-app-1-qfnn5:/opt/app-root/src
Please wait, building component....

It should say "Copying files" not "directory"

Plus it didn't work correctly for some reason.
New war file wasn't used. Component continued to use the old one. Only after I run odo push the new war file was actually used.
Copy either didn't happen during odo watch or it was copied to the wrong place.

@kadel
Copy link
Member

kadel commented Jul 12, 2018

When doing push on the local component:

[0000] Source for component wildfly is file:///Users/tomas/tmp/odo-examples/backend (local)
DEBU[0000] Waiting for deploymentconfig=wildfly-app pod
DEBU[0000] Status of wildfly-app-1-2gnw7 pod is Running
DEBU[0000] Pod wildfly-app-1-2gnw7 is running.
DEBU[0000] Copying directory [] to pod wildfly-app-1-2gnw7:/opt/app-root/src

empty [] looks weird, something is wrong there

// copyFiles is list of changed files captured during `odo watch`
// localFile is ignored if copyFiles is set
func (c *Client) CopyFile(localPath string, targetPodName string, targetPath string, copyFiles []string) error {
if len(copyFiles) != 0 || string(localPath[len(localPath)-1]) == "/" {
Copy link
Member

Choose a reason for hiding this comment

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

why is it checking if there is / at the end?

@surajnarwade
Copy link
Contributor Author

@kadel , I tried to refactor as per your suggestions. But that's not working since it will need path variable as well since we have to define filename in tar header.

SO I made couple changes in the code and it seems that everything working fine in all 4 scenarios:

  • --local while odo push

  • --binary while odo push

  • --local while odo watch

  • --binary while odo watch

Examples used:

@surajnarwade surajnarwade force-pushed the copy-go branch 3 times, most recently from 844ddf3 to 2c3e544 Compare July 17, 2018 14:56
@surajnarwade
Copy link
Contributor Author

@kadel @cdrage modified as per changes, code and logic is pretty straight forward (thanks to @kadel ) now.
Please review :)

Copy link
Member

@kadel kadel left a comment

Choose a reason for hiding this comment

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

Comments need to be more descriptive.
Code looks good.

@@ -165,14 +165,10 @@ func GetCurrent(client *occlient.Client, applicationName string, projectName str
}

// PushLocal push local code to the cluster and trigger build there.
// asFile indicates if it is a binary component or not
func PushLocal(client *occlient.Client, componentName string, applicationName string, path string, asFile bool, out io.Writer) error {
// files is list of changed files captured during `odo watch` or binary file
Copy link
Member

Choose a reason for hiding this comment

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

The comment should also describe what path is, and how it relates to files

func (c *Client) RsyncPath(localPath string, targetPodName string, targetPath string) (string, error) {
log.Debugf("Syncing %s to pod %s:%s", localPath, targetPodName, targetPath)
// CopyFile copies localPath directory or list of files in copyFiles list to the directory in running Pod.
// copyFiles is list of changed files captured during `odo watch` as well as binary file path
Copy link
Member

Choose a reason for hiding this comment

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

The comment should also describe how localPath relates to copyFiles. This is really important and not obvious.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added :0

}
return nil
Copy link
Member

Choose a reason for hiding this comment

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

@cdrage go routine is writing to Pipe via writer. ExecCMDInContainer is then streaming it to the command's stdin via reader. There is no need to sync anything. ExecCMDInContainer waits for the command to finish, the command will finish only after it receives all the data to stdin.

Copy link
Member

@cdrage cdrage left a comment

Choose a reason for hiding this comment

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

Other than @kadel 's comment, code LGTM and testing works.

Resolves redhat-developer#443

This PR will remove dependency of oc binary for `copyfiles` function which copies file to component while `odo push`
@surajnarwade
Copy link
Contributor Author

@kadel @cdrage Update with comments

@cdrage
Copy link
Member

cdrage commented Jul 24, 2018

LGTM.

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.

None yet

4 participants