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

Feature/get build actions #29

Merged
merged 27 commits into from
Jul 26, 2018

Conversation

richabindra
Copy link
Contributor

This PR addresses Issue #28.

Copy link
Collaborator

@martinda martinda left a comment

Choose a reason for hiding this comment

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

@richabindra Thank you for this feature, looks great and useful. I have only one request at this time.


public abstract List<Cause> causes();

public abstract List<Parameter> parameters();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wonder if there is a way to make parameters a Map<String, String> instead of a plain list, it would make retrieval more natural.

Copy link
Owner

Choose a reason for hiding this comment

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

There is a way we could marshal it into something else but I'd actually rather not do so and instead hand back to the user the exact response we get from jenkins for better or worse.

Copy link
Collaborator

Choose a reason for hiding this comment

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

No problem, I am okay with that.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe I should have dismissed the review... oh well.

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, I was confused about this too whether to leave it as is or should we convert it to something more useful for the user. But, it makes sense to leave it as is.

Copy link
Owner

Choose a reason for hiding this comment

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

We're doing this mainly to keep things sane on our end with the least amount of confusion and gotchas. There are definitely good reasons to marshal this into something else but then I don't want to get into the habit of having these one-off cases where the user expects things to be a certain way and then the implementation provides something different. I'd rather hand back to the user, in AutoValue object format, exactly what was given to us by Jenkins.

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, agreed. So, just clarifying, I don't need to change anything in the PR?

Copy link
Owner

Choose a reason for hiding this comment

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

Nothing on this end though please do address @martinda comments below and then we can merge and kick a new patch release.

@cdancy cdancy added this to the v0.0.13 milestone Jul 24, 2018
Copy link
Collaborator

@martinda martinda left a comment

Choose a reason for hiding this comment

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

Probably need to support a nullable "_class". I also suggest adding a test for empty parameter values. See the details in the comments.


@Nullable
public abstract String userName();

Copy link
Collaborator

Choose a reason for hiding this comment

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

The src/test/resources/build-info-no-params.json contains a _class item some times. Should it be here?

There is a precedent in Plugins.java.

assertTrue(output.get(0).name().equals("bear"));
assertTrue(output.get(0).value().equals("true"));
assertTrue(output.get(1).name().equals("fish"));
assertTrue(output.get(1).value().equals("salmon"));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Although unlikely to break, there should be a test for an empty parameter value. Maybe Jenkins returns null instead of an empty space.

Copy link
Owner

Choose a reason for hiding this comment

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

Agreed to all of the above.

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, you are right. I'll incorporate the suggested changes in the next commit.

parameters = action.parameters();
}
}
for (Parameter parameter : parameters) {
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 intentionally added the test like this to provide an alternative to get(0) etc for getting params. I can change it if suggested otherwise.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Well, thanks for the tip, but I don't think it is necessary. In fact it makes the test slightly harder to read.

Copy link
Owner

Choose a reason for hiding this comment

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

Agreed. Makes it harder to read. Lets just use what comes OOTB and iterate over that.

Copy link
Collaborator

@martinda martinda left a comment

Choose a reason for hiding this comment

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

Is it possible to add live tests for null and empty params (providing Jenkins does return null and/or empty)? Thanks in advance.


import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import org.jclouds.javax.annotation.Nullable;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nullable is not used in this file.

@richabindra
Copy link
Contributor Author

richabindra commented Jul 25, 2018

I was trying to add the live test to check for null and empty param, but when I have a params map with a key and null value and I try to build the job using this param map, it keeps throwing me an NullPointerException on line 45 below:

if (prop.getKey() != null) {
String potentialKey = prop.getKey().trim();
if (potentialKey.length() > 0) {
builder.addFormParam(potentialKey, prop.getValue().toArray(new String[prop.getValue().size()]));

Using curl, I was able to pass 'null' values to the rest API. So, is there a way to send 'null' values as form parameters to the jobs API using jenkins-rest?

Also, I tried a workaround. In the above class i.e. BindMapsToForm.java, I locally tried adding a check before line 45 to convert any null value to an empty list. And that works since I explicitly avoid the null pointer exception during prop.getValue().toArray(...) conversion. But, this modifies the existing functionality. So, I am not sure which is the best way forward.

@cdancy
Copy link
Owner

cdancy commented Jul 25, 2018

@richabindra converting the potential null to an empty list sounds like a good idea to me.

@richabindra
Copy link
Contributor Author

@cdancy I tried posting to jenkins using CURL which allowed null values but jenkins-rest does not seem to allow null values to a parameter.
By converting null to an empty list, are we not modifying the existing functionality?

@martinda
Copy link
Collaborator

@richabindra What does the curl POST look like? How are you POSTing a null value? It is an empty string, is is the string "null"?

@richabindra
Copy link
Contributor Author

I believe it is a null value. I am doing this request:

curl -u <username:password> -X POST "http://jenkins.com/job/test-job/buildWithParameters?key1=null"

I think jenkins converts it to a string, since the parameter in build info JSON for the above build looks like this:

  .
  "actions" : [
    {
      "_class" : "hudson.model.ParametersAction",
      "parameters" : [
        {
          "_class" : "hudson.model.StringParameterValue",
          "name" : "key1",
          "value" : "null"
        }
      ]
    },
.
.
.

@martinda
Copy link
Collaborator

martinda commented Jul 25, 2018

That is not a null value, it is a string with a 4-letter value that spell the word null, but the value is not null. I am looking at ParametersDefinitionProperty.java trying to see if there is a difference between null and the empty string.

@martinda
Copy link
Collaborator

After looking at the source in Jenkins and Stapler, I have no idea. I would say convert null to the empty string is the right approach. We cannot pass "null" from the UI anyway, we can only pass an empty string, and it is exported as an empty string value when Jenkins exports parameters as environment variables.

@richabindra
Copy link
Contributor Author

@martinda - that's true. It is a string with the word null. I tried even with the url encoded value for null i.e. "%00", but jenkins build info shows it as an empty string. So, I think there is no easy way to pass null through the rest api.

I think it's a good idea to convert potential null to an empty list in jenkins-api as discussed earlier. What do you think. @cdancy @martinda

@richabindra
Copy link
Contributor Author

richabindra commented Jul 25, 2018

Just saw your comment @martinda . Totally agree with you. I'll go forward with converting null to an empty string. Thanks!

@cdancy
Copy link
Owner

cdancy commented Jul 25, 2018

Just saw your comment @martinda . Totally agree with you. I'll go forward with converting null to an empty string. Thanks!

+1


@Test(dependsOnMethods = "testBuildWithParametersOfJobForEmptyAndNullParams")
public void testGetBuildParametersOfJobForEmptyAndNullParams() {
while (api().jobInfo(null, "JobForEmptyAndNullParams").lastBuild() == null) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reason I add this check is to make sure the build has started running. If I don't add it, I am getting a null pointer exception on the next line i.e. line 357 while trying to get the parameters.

Copy link
Owner

Choose a reason for hiding this comment

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

@richabindra if you look at the QueueApiLiveTest @martinda added a few tests around queuing builds that is more intuitive at the expense of a bit more code. I would use something like as this could potentially hang forever if someone is not careful. You may have to expose the method getRunningQueueItem and potentially make it static.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure.

Copy link
Contributor Author

@richabindra richabindra Jul 26, 2018

Choose a reason for hiding this comment

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

@cdancy - So, the thing is I am not able to make the getRunningQueueItem as static because
it refers to non static api() method at line 235:

private QueueItem getRunningQueueItem(int queueId) throws InterruptedException {
int max = 10;
QueueItem queueItem = api().queueItem(queueId);

If I make api() method as static, it complains because it refers to api property of jclouds.apis class at line 264, which obviously I cannot make static.

private QueueApi api() {
return api.queueApi();
}

I tried following approaches:

  1. Calling "new QueueApiLiveTest().getRunningQueueItem(job.value())" in the test of JobsApiLiveTest, but it throws null pointer exception saying 'api' is null on line 264.

private QueueApi api() {
return api.queueApi();
}

  1. I created a static instance of the QueueApiLiveTest class in the QueueApiLiveTest constructor, and created a static method in QueueApiLiveTest that calls QueueApiLiveTestInstance.getRunningQueueItem(job.value()), then tried calling this static method in JobsApiLiveTest, still the 'api' on line 264 was null.

Possible alternatives:

  1. Duplicating getRunningQueueItem or similar logic in JobsApiLiveTest.
  2. JobsApiLiveTest extends QueueApiLiveTest.

I am not sure what's the best way possible.

Copy link
Collaborator

@martinda martinda Jul 26, 2018

Choose a reason for hiding this comment

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

@richabindra what about moving the method to the BaseJenkinsApiLiveTest class and making it protected?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@martinda - Yes, that works. I'll push the changes.

@martinda
Copy link
Collaborator

The live test fails for me, here is the relevant stacktrace:

java.lang.AssertionError: expected [true] but found [false]
	at org.testng.Assert.fail(Assert.java:93)
	at org.testng.Assert.failNotEquals(Assert.java:512)
	at org.testng.Assert.assertTrue(Assert.java:41)
	at org.testng.Assert.assertTrue(Assert.java:51)
	at com.cdancy.jenkins.rest.features.JobsApiLiveTest.testGetBuildCausesOfJob(JobsApiLiveTest.java:333)

@martinda
Copy link
Collaborator

Ah, the live test fails because my admin user is not "admin", it is "martin". When I create the admin user, the test passes. @cdancy is that a concern?

@richabindra
Copy link
Contributor Author

@martinda - ohh.. the test should be user name independent. Should I probably just check if causes list size is greater than 0?

@martinda
Copy link
Collaborator

@richabindra we're not testing for user name here, so yes the test should be independent of it. Check everything you expect the test to verify, but only that.

@richabindra
Copy link
Contributor Author

@martinda - yea, good catch. Pushed the change!

@martinda
Copy link
Collaborator

Thank you @richabindra, all the tests pass for me now. This looks good! I have no further comments.

@cdancy cdancy merged commit b7924aa into cdancy:master Jul 26, 2018
@cdancy
Copy link
Owner

cdancy commented Jul 26, 2018

@richabindra merged now. Thanks for the contribution! I'll spin up a new patch release shortly.

@cdancy
Copy link
Owner

cdancy commented Jul 26, 2018

Version 0.0.13 with this fix has been released.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants