Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FIXED JENKINS-37824] Adding job property-related functionality
More specifically, added "jobProperties", "parameters" and "triggers"
section and related functionality.

This required some fairly complex logic for translating something like
"buildDiscarder(logRotator(numToKeepStr:'1'))" in the config into
something that can do what we need at runtime. Hooray complexity!
  • Loading branch information
abayer committed Oct 5, 2016
1 parent 366510a commit f533ef9
Show file tree
Hide file tree
Showing 39 changed files with 2,021 additions and 50 deletions.
7 changes: 6 additions & 1 deletion pom.xml
Expand Up @@ -104,7 +104,12 @@
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>2.15</version>
<version>2.18</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
Expand Down
Expand Up @@ -22,31 +22,30 @@
* THE SOFTWARE.
*/

package org.jenkinsci.plugins.pipeline.modeldefinition;

package org.jenkinsci.plugins.pipeline.modeldefinition

import com.google.common.cache.CacheBuilder
import com.google.common.cache.CacheLoader
import com.google.common.cache.LoadingCache;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import hudson.ExtensionList
import hudson.model.Describable
import hudson.model.Descriptor
import hudson.triggers.TriggerDescriptor
import org.jenkinsci.plugins.pipeline.modeldefinition.actions.ExecutionModelAction
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTArgumentList
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTBranch
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTKey
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTNamedArgumentList
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTPipelineDef
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTPositionalArgumentList
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTSingleArgument
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStage
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStages
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTStep
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTTreeStep
import org.jenkinsci.plugins.pipeline.modeldefinition.ast.ModelASTValue
import org.jenkinsci.plugins.pipeline.modeldefinition.model.NestedModel
import org.jenkinsci.plugins.pipeline.modeldefinition.model.StepBlockWithOtherArgs
import org.jenkinsci.plugins.pipeline.modeldefinition.model.MethodsToList
import org.jenkinsci.plugins.pipeline.modeldefinition.parser.Converter
import org.jenkinsci.plugins.scriptsecurity.sandbox.whitelists.Whitelisted
import org.jenkinsci.plugins.structs.SymbolLookup
import org.jenkinsci.plugins.structs.describable.UninstantiatedDescribable
import org.jenkinsci.plugins.workflow.cps.CpsScript
import org.jenkinsci.plugins.workflow.job.WorkflowRun

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.util.concurrent.TimeUnit;

// TODO: Prune like mad once we have step-in-groovy and don't need these static whitelisted wrapper methods.
/**
Expand Down Expand Up @@ -126,6 +125,33 @@ public class Utils {

}

@Whitelisted
public static Class<Describable> getMethodstoListType(Class c) {
Class retClass
c.genericInterfaces.each { Type t ->
if (t instanceof ParameterizedType) {
if (t.rawType.equals(MethodsToList.class)) {
retClass = t.actualTypeArguments.first()
}
}
}

return retClass
}
/*
@Whitelisted
public static Class<Describable> getMethodsToListDescribable(Class c) {
Class<Describable> returnClass
if (c instanceof MethodsToList) {
c.genericInterfaces.each { Type t ->
if (t instanceof ParameterizedType) {
if (t.rawType)
}
}
}
}
*/
/**
* Simple wrapper for isInstance to avoid whitelisting issues.
*
Expand Down Expand Up @@ -180,4 +206,58 @@ public class Utils {
}


@Whitelisted
static Map<String,Object> mapForDescribable(UninstantiatedDescribable ud) {
Map<String,Object> args = [:]

ud.arguments.each { k, v ->
if (k == UninstantiatedDescribable.ANONYMOUS_KEY &&
(v instanceof List || v instanceof Object[]) &&
v[0] instanceof Map) {
args.putAll((Map) v[0])
} else if (v instanceof UninstantiatedDescribable) {
args.putAll(mapForDescribable((UninstantiatedDescribable)v))
} else {
args[k] = v
}
}
if (ud.klass != null) {
args['$class'] = ud.klass
} else {
Descriptor d = SymbolLookup.get().findDescriptor(Object.class, ud.symbol)
if (d != null) {
args['$class'] = d.clazz.simpleName
}
}

return args
}

static generateTypeCache(Class<? extends Descriptor> type, List<String> excludedSymbols = []) {
return CacheBuilder.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(new CacheLoader<Object, Map<String, String>>() {
@Override
Map<String, String> load(Object key) throws Exception {
return populateTypeCache(type, excludedSymbols)
}
})
}

private static Map<String,String> populateTypeCache(Class<? extends Descriptor> type, List<String> excludedSymbols = []) {
Map<String,String> knownTypes = [:]

ExtensionList.lookup(type).each { t ->
Set<String> symbolValue = SymbolLookup.getSymbolValue(t)
if (!symbolValue.isEmpty() && !symbolValue.any { excludedSymbols.contains(it) }) {
knownTypes.put(symbolValue.iterator().next(), t.clazz.getName())
}

// Add the class name mapping even if we also found the symbol, for backwards compatibility reasons.
knownTypes.put(t.clazz.getName(), t.clazz.getName())
}

return knownTypes
}

}
@@ -0,0 +1,39 @@
/*
* The MIT License
*
* Copyright (c) 2016, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/


package org.jenkinsci.plugins.pipeline.modeldefinition.ast

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

@ToString(includeSuper = true, includeSuperProperties = true)
@EqualsAndHashCode(callSuper = true)
@SuppressFBWarnings(value="SE_NO_SERIALVERSIONID")
public class ModelASTBuildParameter extends ModelASTMethodCallFromArguments {
ModelASTBuildParameter(Object sourceLocation) {
super(sourceLocation)
}
}
@@ -0,0 +1,73 @@
/*
* The MIT License
*
* Copyright (c) 2016, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package org.jenkinsci.plugins.pipeline.modeldefinition.ast

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import net.sf.json.JSONArray
import net.sf.json.JSONObject
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidator

@ToString(includeSuper = true, includeSuperProperties = true)
@EqualsAndHashCode(callSuper = true)
@SuppressFBWarnings(value="SE_NO_SERIALVERSIONID")
public final class ModelASTBuildParameters extends ModelASTElement {
List<ModelASTBuildParameter> parameters = []

public ModelASTBuildParameters(Object sourceLocation) {
super(sourceLocation)
}

@Override
public JSONObject toJSON() {
JSONArray a = new JSONArray()
parameters.each { s ->
a.add(s.toJSON())
}

return new JSONObject()
.accumulate("parameters",a)
}

@Override
public void validate(ModelValidator validator) {
validator.validateElement(this)
parameters.each { s ->
s?.validate(validator)
}
}

@Override
public String toGroovy() {
return "parameters {\n${parameters.collect { it.toGroovy() }.join("\n") }\n"
}

@Override
public void removeSourceLocation() {
super.removeSourceLocation()
parameters.each { it.removeSourceLocation() }
}
}
Expand Up @@ -82,3 +82,4 @@ public abstract class ModelASTElement {
}

}

@@ -0,0 +1,73 @@
/*
* The MIT License
*
* Copyright (c) 2016, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package org.jenkinsci.plugins.pipeline.modeldefinition.ast

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString
import net.sf.json.JSONArray
import net.sf.json.JSONObject
import org.jenkinsci.plugins.pipeline.modeldefinition.validator.ModelValidator

@ToString(includeSuper = true, includeSuperProperties = true)
@EqualsAndHashCode(callSuper = true)
@SuppressFBWarnings(value="SE_NO_SERIALVERSIONID")
public final class ModelASTJobProperties extends ModelASTElement {
List<ModelASTJobProperty> properties = []

public ModelASTJobProperties(Object sourceLocation) {
super(sourceLocation)
}

@Override
public JSONObject toJSON() {
JSONArray a = new JSONArray()
properties.each { s ->
a.add(s.toJSON())
}

return new JSONObject()
.accumulate("properties",a)
}

@Override
public void validate(ModelValidator validator) {
validator.validateElement(this)
properties.each { s ->
s?.validate(validator)
}
}

@Override
public String toGroovy() {
return "jobProperties {\n${properties.collect { it.toGroovy() }.join("\n") }\n"
}

@Override
public void removeSourceLocation() {
super.removeSourceLocation()
properties.each { it.removeSourceLocation() }
}
}
@@ -0,0 +1,39 @@
/*
* The MIT License
*
* Copyright (c) 2016, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/


package org.jenkinsci.plugins.pipeline.modeldefinition.ast

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings
import groovy.transform.EqualsAndHashCode
import groovy.transform.ToString

@ToString(includeSuper = true, includeSuperProperties = true)
@EqualsAndHashCode(callSuper = true)
@SuppressFBWarnings(value="SE_NO_SERIALVERSIONID")
public class ModelASTJobProperty extends ModelASTMethodCallFromArguments {
ModelASTJobProperty(Object sourceLocation) {
super(sourceLocation)
}
}

0 comments on commit f533ef9

Please sign in to comment.