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

Make default value cache immutable #642

Closed
wants to merge 6 commits into from

Conversation

marcusholl
Copy link
Member

The default values provided by us via resources/default_pipeline_environment.yml must not be modifiable by pipelines / pipeline steps. If these properties are modifiable we get in trouble like here: SAP-archive/jenkins-pipelines#18 and here: SAP-archive/jenkins-pipelines#16.

This is "fixing the root cause" for this type of issue. With this PR we ensure that the default values cannot be updated by pipelines / pipeline steps.

The unit tests fails until the fix(es) for the issue above are not merged. The corresponding pull requests are:

#632 (especially this one),
#631 and
#614

*
* All other Objects we expect here (... basically from parsing json) are expected to be
* immutable:
* - java.lang.String (in the unlikely case we see other CharSequences we convert to String)
Copy link
Member

Choose a reason for hiding this comment

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

What about GStringImpl? Do we need that also?

Copy link
Member Author

Choose a reason for hiding this comment

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

We do not get GStrings when parsing json files. See e.g. here.

private static def immutable(Collection _in, Collection _out) {

for(def e : _in) {
if(e in List || e in Set || e in Map) {
Copy link
Member

Choose a reason for hiding this comment

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

Do we need to support List and Set? How is this defined in yaml?

Copy link
Member Author

Choose a reason for hiding this comment

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

Set we actually do not need, I agree. It seems "out of the box" not possible to get sets when parsing json. --> Set support has been erased.

@marcusholl marcusholl added REVIEW Pull-Request needs a review bug 🐛 labels Apr 5, 2019
@@ -18,7 +31,9 @@ class DefaultValueCache implements Serializable {
}

static createInstance(Map defaultValues){
instance = new DefaultValueCache(defaultValues)
instance = new DefaultValueCache(
immutable(defaultValues)
Copy link
Member

@daniel-kurzynski daniel-kurzynski Apr 12, 2019

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Does the second example above really affect the default values?

The funny thing is that the first example is annotated with a fixme comment (Here we misuse the defaultConfiguration ...)

The point is: default values are shared over several steps. Having the defaults mutable opens a huge area for introducing bugs. These bugs are not obvious and hard to troubleshoot, as we already saw with the phantom stash in neoDeploy. I think the normal mind set when developing is "Default Values? Well, they are stable ...". But with the current approach they can be manipulated by error. See our issue with stashing and neoDeploy ... Having our ConfigMerger approach it is fully intransparent that certain mutable collections etc. comes without defensive copy from the default values.

We can discuss if we would like to continue with mutable default values. My personal opinion is: we will have less trouble if they are immutable. This change is not provided for fun or for the sake of sticking to some academical coding principles.

@OliverNocon already suggested to provide a deep defensive copy of the configuration when calling ConfigurationHelper#use(). That copy can be - of course - mutable. With that we avoid updating default values from one step so that update is visible to other steps. That would be IMO also an improvement, also reducing the risk of unplanned config updates. But again: in my personal opinion our life is less complicated if the default values are immutable. I will provide another PR creating defensive copies in ConfigurationHelper#use(./.)

Copy link
Member

Choose a reason for hiding this comment

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

I think as we can still create a new instance, I am fine with the change.

Copy link
Member

@OliverNocon OliverNocon left a comment

Choose a reason for hiding this comment

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

LGTM

@marcusholl
Copy link
Member Author

@daniel-kurzynski : regarding your comment above from April 12th. Do you think it would be possible to resolve your concerns by having a syntax like e.g. ${env:FOO} which checks the environment for FOO and replaces the value accordingly during the initialization of the default value cache? This is basically what happens inside DownloadCacheUtils for the network name.

The second occurance injects a constant from s4SdkGlobals. Would it be an issue to specify this value directly in the config file?

@marcusholl
Copy link
Member Author

Too old, maybe obsolute with upcoming go implementation

@marcusholl marcusholl closed this Jan 31, 2020
@OliverNocon OliverNocon added invalid and removed config REVIEW Pull-Request needs a review bug 🐛 labels Jan 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants