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

[JENKINS-26535] added support for parameterized parameter types #52

Closed
wants to merge 3 commits into from
Closed

[JENKINS-26535] added support for parameterized parameter types #52

wants to merge 3 commits into from

Conversation

daspilker
Copy link
Member

Follow up of https://groups.google.com/forum/#!msg/jenkinsci-dev/-XVFCCiE4Bs

This fixed the issue mentioned on the mailing list, but does probably not work for all cases and might not fix JENKINS-26535 completely.

return new ArrayType(type, of(Types.getTypeArgument(Types.getBaseClass(type,Collection.class), 0, Object.class)));
}
Class<?> c = Types.erasure(type);
// Assume it is a nested object of some sort.
Copy link
Member

Choose a reason for hiding this comment

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

Most of this is actually reindentation, making the diff look a lot bigger than it actually is. Had to apply the WS ignore setting in GitHub to see it.

if (Types.isSubClassOf(type, Collection.class)) {
return new ArrayType(type, of(Types.getTypeArgument(Types.getBaseClass(type,Collection.class), 0, Object.class)));
}
throw new UnsupportedOperationException("do not know how to categorize attributes of type " + type);
Copy link
Member

Choose a reason for hiding this comment

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

This seems to have been removed and I am not sure why. Where is the fallback?

Copy link
Member

Choose a reason for hiding this comment

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

I guess it is just not necessary any more and whatever sanity-checking was needed is already done in DescribableModel?

Copy link
Member Author

Choose a reason for hiding this comment

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

The fallback became unreachable, so I removed it. I was surprised that no unit tests failed. There is not much sanity-checking in DescribableModel or DescribableParameter.

I thought about limiting support for Homo/HeterogeneousObjectType to Describable types and keeping the fallback, but that triggered a test failure in DescribableModelTest#recursion since Recursion is not a Describable. I'm not sure if that is on purpose.

@daspilker
Copy link
Member Author

I pushed some tests for the problems that have been mentioned in the description of JENKINS-26535. So I'm pretty confident that this fixes JENKINS-26535.

I also ran the Job DSL tests successfully with a snapshot build.

jetersen
jetersen previously approved these changes Aug 29, 2019
@baymac
Copy link
Member

baymac commented Sep 6, 2019

@daspilker @jglick Is it ready for release?

…/DescribableModelTest.java

Co-Authored-By: Joseph Petersen <josephp90@gmail.com>
@jetersen
Copy link
Member

jetersen commented Oct 17, 2019

@abayer @dwnusbaum @jglick 👋 we have a test case that confirms that JENKINS-26535 is resolved 👍

Would be great with a release!

@jetersen
Copy link
Member

@car-roll this is still a blocker, can this be added to fix this very old bug

@jetersen
Copy link
Member

ping @car-roll @jglick 😓

@jglick
Copy link
Member

jglick commented Nov 26, 2019

I do not maintain this plugin, do not ask me.

@jetersen
Copy link
Member

You reviewed the code so maybe the maintainer is waiting for your approval? 😅

Copy link
Contributor

@car-roll car-roll left a comment

Choose a reason for hiding this comment

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

Code-wise everything looks fine to me, but I'm not familiar enough with this part of the code to give an approval. I will defer to @dwnusbaum or @abayer

Also, apologies for the late reply 😢 I had meant to comment on this earlier.

Copy link
Member

@dwnusbaum dwnusbaum left a comment

Choose a reason for hiding this comment

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

The code seems ok to me. I don't feel like I really understand the implications, and I'm not aware of the original intent behind this code to know if there is any reason to not do this (for example, I think that previously, parameters of type Map were not supported in some cases based on some testing I did with ParallelStep, but I retested with this PR, and now they appear to be supported. Is that a problem? 🤷‍♂).

I also ran workflow-cps's tests against this change and didn't see any regressions. Are there any other plugins whose tests should be run against the change?

@jglick
Copy link
Member

jglick commented Dec 5, 2019

parameters of type Map were not supported in some cases

Because Map is not a legal databinding type. The only compound types supported are arrays or Lists whose element type is assignable to Describable.

@jglick
Copy link
Member

jglick commented Dec 5, 2019

The basic description is in

* The arguments may be primitives (as wrappers) or {@link String}s if that is their declared type.
* {@link Character}s, {@link Enum}s, and {@link URL}s may be represented by {@link String}s.
* Other object types may be passed in “raw” as well, but JSON-like structures are encouraged instead.
* Specifically a {@link List} may be used to represent any list- or array-valued argument.
though this likely needs to be expanded and clarified some.

@dwnusbaum
Copy link
Member

dwnusbaum commented Dec 5, 2019

Because Map is not a legal databinding type. The only compound types supported are arrays or Lists whose element type is assignable to Describable.

@jglick Ok, well with this PR in its current state, they are supported (at least as constructor parameters). I guess this is related to the old fallback that throws an UnsupportedOperationException no longer being reachable as you noted in #52 (comment).

@jetersen
Copy link
Member

👋 This is still blocking would be great to have a release 🙏

Copy link
Member

@oleg-nenashev oleg-nenashev left a comment

Choose a reason for hiding this comment

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

I think it is good to go. Thanks a lot @daspilker !

@oleg-nenashev
Copy link
Member

Apparently I am listed as a plugin maintainer. I would be interested to cut the release if @jglick and @dwnusbaum are satisfied by the current state

@jglick
Copy link
Member

jglick commented Jan 4, 2020

I would leave it to @dwnusbaum.

Copy link
Member

@dwnusbaum dwnusbaum left a comment

Choose a reason for hiding this comment

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

@oleg-nenashev My understanding of this PR is that in addition to fixing the things described in JENKINS-26535 that we want to fix, it allows some other things that we do not want to allow. For example, in master, DescribableModel does not support this class:

public class MapParameter {
    @DataBoundConstructor
    public MapParameter(Map<String, String> data) { }
}

This test (copy it into DescribableModelTest if you want to try it yourself (make sure that MapParameter is marked as static if it is an inner class)), which passes against master, shows what happens if you try to use DescribableModel with MapParameter today:

@Test
public void mapParameter() throws Exception {
    schema(MapParameter.class, "MapParameter(data: java.lang.UnsupportedOperationException: do not know how to categorize attributes of type java.util.Map<java.lang.String, java.lang.String>)");
}

That test no longer passes when run against this PR, because now, DescribableModel supports Map parameters. Here is the passing version of the test when using this PR:

@Test
public void mapParameter() throws Exception {
    schema(MapParameter.class, "MapParameter(data: Map{})");
}

I think this change in behavior would be the same for any class with type parameters, not just Map.

@jglick's comment here leads me to believe that this is a bad thing, but I do not totally understand the implications. I don't think it would cause any regressions, but I'm not really sure how it would affect existing use cases of DescribableModel.

As @daspilker noted here, one seemingly reasonable way to disallow these types breaks an existing test (DescribableModelTest#recursion), so it is unclear what should be done.

To recap, I think we need answers to these questions before we can merge this PR:

  1. Does the fact that the MapParameter class is now supported by DescribableModel represent a problem with this PR that needs to be fixed before it is merged?
  2. Should DescribableModelTest#recursion pass as-is, or does master have a bug and Recursion should need to implement Describable for the test to pass?
    • If the latter, what are the implications of fixing the code so that that test fails? Does any existing code rely on that behavior?

@darxriggs
Copy link

It looks like this pull request is stuck. I therefore like to ask who could follow up on it?

jansohn referenced this pull request in jenkinsci/bitbucket-branch-source-plugin Feb 27, 2020
Now all traits consistently have a @symbol annotation.

This improves configuration with JobDSL. Otherwise there is
a clash e.g. with the github-branch-source-plugin.
@timja
Copy link
Member

timja commented Apr 25, 2020

Hi @dwnusbaum, just taking a bit of a look at this,

The test case you suggested doesn't appear to be passing anymore on master,

java.lang.ArrayIndexOutOfBoundsException: 1
	at org.jenkinsci.plugins.structs.describable.DescribableModel.<init>(DescribableModel.java:160)
	at org.jenkinsci.plugins.structs.describable.DescribableModelTest.schema(DescribableModelTest.java:925)
	at org.jenkinsci.plugins.structs.describable.DescribableModelTest.mapParameter(DescribableModelTest.java:81)

image

Is there any chance you could update it, I would be interested in taking a look here, but not familiar with the code at all,

thanks!

@dwnusbaum
Copy link
Member

dwnusbaum commented Apr 27, 2020

@timja, sorry, the problem is just that public class MapParameter should be public static class MapParameter when you copy it into DescribableModelTest. I will update my earlier comment. FWIW, for the questions I asked in #52 (review), my answers would be:

  1. Yes, supporting types such as MapParameter is a problem. I think the fix is to do as @daspilker describes here.
  2. DescribableModelTest#recursion should not pass as-is in master. Recursion should need to implement Describable for the test to pass.
    • The implications of making DescribableModel more restrictive for HeterogeneousObjectType and HomogenousObjectType are unclear. I would run the PCT against as many plugins as possible with the proposed change to see if any existing types are affected so they can be fixed in advance. (EDIT: I randomly noticed RateLimitBranchProperty$Throttle, which looks like it would be affected by implementing a restriction like that and would need to be modified)

@jglick
Copy link
Member

jglick commented Apr 27, 2020

I cannot recall now all the reasons why I permitted non-Describable types with @DataBoundConstructor. I do not think Recursion specifically was intended to be testing that loophole, though. The one corner case I can think of is ParameterValue, which has non-Describable subtypes with @DataBoundConstructor on them, critical for example for the Pipeline build step. See hacks like parameterValueClass. Unless and until the core patch suggested in JENKINS-26093 is in the baseline, you need to retain this special case.

@zbynek
Copy link
Contributor

zbynek commented Mar 4, 2021

@jglick

Because Map is not a legal databinding type.

Is there a reason why List<String> is legal and Map<String, String> is not? What would it take to make Map legal as well?

As you can see in the step docs there are multiple steps that take Map as an argument. I was hoping the description of Map and List could be similar in the docs, but the way structs describes Lists and Maps is different (ArrrayType vs ErrorType).

@jglick
Copy link
Member

jglick commented Mar 4, 2021

Is there a reason why List<String> is legal and Map<String, String> is not?

Neither are legal. Besides atomic-ish types, only List<SomeKindOfDescribable> is legal.

@jglick
Copy link
Member

jglick commented Mar 4, 2021

there are multiple steps that take Map as an argument

And these plugins are implemented incorrectly.

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