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

Running oc with Proc to avoid command expansion #176

Merged
merged 1 commit into from
Sep 14, 2018

Conversation

vfreex
Copy link
Contributor

@vfreex vfreex commented Sep 4, 2018

This PR reimplements the mechanism to run oc command on a slave. It fixes https://bugzilla.redhat.com/show_bug.cgi?id=1625518

Why this is needed

We met issues when using pipeline syntax with Jenkins Client Plugin. When an option passed to a Selector contains spaces or special characters (like #, ;, etc), they are mistakenly explained by shell rather than passed to the oc process.

The current implementation

When using OpenShift Pipeline DSL, oc process is started with DurableTask,
which is designed to run a bash script or batch script on a slave.
This is not ideal because when the command arguments include special characters
(like whitespaces, #, !, ;), it's hard to escape them correctly.

The new implementation

The new implementation uses standard Jenkins API to start a oc process
on a slave. stdout and stderr outputs are piped to Jenkins master
so that polling is not needed.

@openshift-ci-robot openshift-ci-robot added the size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. label Sep 4, 2018
@openshift-ci-robot openshift-ci-robot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Sep 4, 2018
@bparees
Copy link
Contributor

bparees commented Sep 4, 2018

/ok-to-test

@openshift-ci-robot openshift-ci-robot removed the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label Sep 4, 2018
@vfreex
Copy link
Contributor Author

vfreex commented Sep 5, 2018

I believe the test failure is a problem of the test suite: To run oc rsh some-pod ps ax, the DSL should be written as

openshift.rsh("some-pod", "ps", "ax")

not

openshift.rsh("some-pod", "ps ax")

The latter should be interpreted as running an executable named ps ax without any arguments.

@bparees
Copy link
Contributor

bparees commented Sep 5, 2018

I believe the test failure is a problem of the test suite: To run oc rsh some-pod ps ax, the DSL should be written as

if the test was passing as it was, then people may have written pipelines expecting that behavior as well, so changing/breaking it is not an option.

@vfreex
Copy link
Contributor Author

vfreex commented Sep 5, 2018

@bparees Right, that could break things.
But it seems to be that treating a string as a whole parameter without splitting at spaces is more reasonable, because oc rsh takes the arguments as executable argument1 argument2 ... rather than interpret them with a shell.

A practical use case is to pass environment variables with values containing spaces and special bash characters (like ;, #, $).
For example, suppose there's a Java application which accepts a 'JAVA_OPTS' environment variable to override jvm options, and we want to set it to '-Xms256m -Xmx2048m'.
Then we can run:
openshift.set('env', 'pod/mypod', 'JAVA_OPTS=-Xms256m -Xmx2048m').

@bparees
Copy link
Contributor

bparees commented Sep 5, 2018

But it seems to be that treating a string as a whole parameter without splitting at spaces is more reasonable, because oc rsh takes the arguments as executable argument1 argument2 ... rather than interpret them with a shell.

I don't disagree, but i also don't want to break existing users, so I think we need to think about the best way to introduce this change..we may have to introduce a flag so people are opting into the new behavior.

@vfreex
Copy link
Contributor Author

vfreex commented Sep 6, 2018

@bparees Thanks for the explanation. I'll also think about the best way to make this change.

@vfreex
Copy link
Contributor Author

vfreex commented Sep 7, 2018

@bparees Following are my thoughts to make the change compatible:

  1. Introduce a switch on the configuration page. Users can make their choices on spiting arguments on spaces or not. By default, the option is set to split on spaces, but a warning message will show during build.
    2.Except that, we will not handle any other special characters. DurableTask will no longer be used to avoid potential shell injection.

What do you think?

@bparees
Copy link
Contributor

bparees commented Sep 7, 2018

What do you think?

it sounds ok to me, but let's wait for @gabemontero to come back on monday and see if he has any other ideas/thoughts that could avoid having to have a top level config field for this.

@vfreex
Copy link
Contributor Author

vfreex commented Sep 7, 2018

@bparees Thanks. I'll adding an option to see if this change can pass all tests.

@vfreex vfreex force-pushed the fix-oc-expansion branch 2 times, most recently from a5fe218 to b4a5cba Compare September 7, 2018 05:17
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 10, 2018
@gabemontero
Copy link
Contributor

So on situation related to the second commit ... the precise failure may have provided some context and reminders of prior history for me (I can't find it now), but I suspect that the grouping of "ps aux" may have stemmed from groovy shortcomings and OpenShiftDSL method signature shortcomings that arose as a result.

For example, private Map buildCommonArgs(Object overb, List verbArgs, Object[] ouserArgsArray, Object... ooverrideArgs)

I vaguely recall groovy confusing the ouserArgsArray and ooverideArgs array.

Assuming my recollections are on the right path, I'd be curious if @vfreex could examine the arg array in https://github.com/openshift/jenkins-client-plugin/blob/master/src/main/resources/com/openshift/jenkins/plugins/OpenShiftDSL.groovy#L908-L914 and entries in the array along spaces, and create a new array with the extra entries, and get the "ps aux" scenario to pass.

If so, I'd say we could punt on the config opt in stuff.

If this is not the right track, then I'll need a repro of the failure with the relevant logs, etc.

Generally speaking, I really like @vfreex 's change here, and getting off Durable Task.

That said, my initial thought is not get this into 3.11, it is too late, and target this for 4.0, where it gets a full release worth of soaking with our upstream users. But we can discuss that in parallel as needed.

@vfreex
Copy link
Contributor Author

vfreex commented Sep 11, 2018

@gabemontero Thanks for your comment. I examined the Groovy code and it seems to me the caller passes arguments to buildCommonArgs correctly, and the entries in ouserArgsArray are containing spaces as the user input.

Personally I don't expect the behavior of spiting arguments by spaces to become a long-term solution, otherwise it will be impossible to pass arguments including spaces unless introducing escape characters, which will increase the complexity. For example, to create a file named my test file.txt inside a pod, openshift.exec('my-pod', 'touch', my test file.txt') will create 3 files my test and file.txt and there is no way to escape.

@vfreex
Copy link
Contributor Author

vfreex commented Sep 13, 2018

@gabemontero Thanks for digging out. I'll take a look soon.

@vfreex
Copy link
Contributor Author

vfreex commented Sep 13, 2018

@gabemontero
Regarding to the error when verbose is enable, it seems to me the ProcStarter.readStderr() method doesn't work correctly as https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/Proc.java#L114 described.

What readStderr does is just setting reverseStderr to true, resulting in the err parameter passed to LocalProc is set to LocalProc.SELFPUMP_OUTPUT (
https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/Launcher.java#L934), otherwise err parameter will be set to null. But the construct of LocalProc will set the redirectError parameter of ProcessBuilder to true in both cases (https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/Proc.java#L219).

I'll file a bug report to Jenkins. At the same time, a workaround for this PR should be used. Options like:

  1. providing a custom OutputStream via ProcStarter.stderr(errStream) to avoid using readStderr()
  2. Directly use ProcessBuilder with launcher.getChannel().call().

@openshift openshift deleted a comment from TomSchmitz Sep 13, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 13, 2018
@gabemontero
Copy link
Contributor

sounds good on all points @vfreex - we'll await your next update

@vfreex
Copy link
Contributor Author

vfreex commented Sep 14, 2018

@gabemontero Hi, I've updated the PR. The new change uses Proc.LocalProc to directly create a process on the node where filePath is located, and pipe the stdout and stderr to the Jenkins master.
Please take another look. Thank you!

@vfreex vfreex force-pushed the fix-oc-expansion branch 2 times, most recently from a817ca5 to 9457ab3 Compare September 14, 2018 17:41
This PR reimplements the mechanism to run `oc` command on a slave.

When using OpenShift Pipeline DSL, `oc` process is started with `DurableTask`,
which is designed to run a bash script or batch script on a slave.
This is not ideal because when the command arguments include special characters
(like whitespaces, `#`, `!`, `;`), it's hard to escape them correctly.

The new implementation uses standard Jenkins API to start a `oc` process
on a slave. `stdout` and `stderr` outputs are piped to Jenkins master
so that polling is not needed.
@vfreex vfreex changed the title Running oc with Launcher to avoid command explansion Running oc with Proc to avoid command expansion Sep 14, 2018
@openshift openshift deleted a comment from TomSchmitz Sep 14, 2018
@gabemontero
Copy link
Contributor

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Sep 14, 2018
@openshift-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: gabemontero, vfreex

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Sep 14, 2018
@openshift-merge-robot openshift-merge-robot merged commit 54d37d6 into openshift:master Sep 14, 2018
@gabemontero
Copy link
Contributor

verified the verbose fix locally ... thanks again @vfreex

I'll initiate a new version shortly and update here and in the bugzilla

To remind on an earlier comment, given the depth of change, for now at least, we'll only pull into v4 of our openshift jenkins images. As time progresses and we get some traction with the upstream community, we can reassess updating older releases.

gabemontero pushed a commit to jenkinsci/openshift-client-plugin that referenced this pull request Sep 14, 2018
Running `oc` with Proc to avoid command expansion
@openshift openshift deleted a comment from TomSchmitz Sep 14, 2018
@gabemontero
Copy link
Contributor

v1.0.17 of the client plugin as been initiated at the jenkins update center

@openshift openshift deleted a comment from TomSchmitz Dec 12, 2018
@openshift openshift deleted a comment from TomSchmitz Dec 12, 2018
@gabemontero
Copy link
Contributor

Hey @vfreex ... fyi, turns out the switch from ProcStarter to Proc.LocalProc has broken the sidecar container scenario with the k8s plugin.

See https://bugzilla.redhat.com/show_bug.cgi?id=1657208

The oc command is getting executed in the jnlp default container using the alpine image, where of course it is not present.

The sidecar scenario works with the version of this plugin (the last being v1.0.16) that leveraged the jenkins Launcher to invoke oc.

As a shot in the dark, I did pick up your jenkinsci/kubernetes-plugin#377 by bumping the k8s plugin to 1.12.9, but it had no effect.

I've started considering the option 1) you noted in #176 (comment) as a means to both solve the verbose logging issue as well as re-engage the k8s plugin container decorator to get the command running in the right container.

If you have a sec and recall any issues if and when you tried that, please let me know.

thanks

@gabemontero
Copy link
Contributor

my prototype seems to be working ... hope to have a PR up soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants