-
Notifications
You must be signed in to change notification settings - Fork 163
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-42091] Add JSON steps #22
Changes from all commits
e55530e
ff194ee
43a0bea
cf048f5
2dc5eb6
37f396f
3b916c8
faf7586
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* | ||
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2016 Nikolas Falco | ||
* | ||
* 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.utility.steps.json; | ||
|
||
import org.apache.commons.lang.StringUtils; | ||
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl; | ||
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl; | ||
import org.jenkinsci.plugins.workflow.steps.Step; | ||
import org.kohsuke.stapler.DataBoundConstructor; | ||
import org.kohsuke.stapler.DataBoundSetter; | ||
import org.kohsuke.stapler.StaplerRequest; | ||
|
||
import hudson.Extension; | ||
import hudson.Util; | ||
import net.sf.json.JSONObject; | ||
|
||
/** | ||
* Reads a JSON file from the workspace. | ||
* | ||
* @author Nikolas Falco | ||
*/ | ||
public class ReadJSONStep extends AbstractStepImpl { | ||
|
||
private String file; | ||
private String text; | ||
|
||
@DataBoundConstructor | ||
public ReadJSONStep() { | ||
} | ||
|
||
/** | ||
* The path to a file in the workspace to read JSON content from. | ||
* | ||
* @return the file path | ||
*/ | ||
public String getFile() { | ||
return file; | ||
} | ||
|
||
/** | ||
* The path to a file in the workspace to read JSON content from. | ||
* | ||
* @param file the path to file in the workspace | ||
*/ | ||
@DataBoundSetter | ||
public void setFile(String file) { | ||
this.file = Util.fixEmpty(file); | ||
} | ||
|
||
/** | ||
* A String containing JSON formatted data. | ||
* | ||
* @return text to parse | ||
*/ | ||
public String getText() { | ||
return text; | ||
} | ||
|
||
/** | ||
* A String containing JSON formatted data. | ||
* | ||
* @param text to parse | ||
*/ | ||
@DataBoundSetter | ||
public void setText(String text) { | ||
this.text = Util.fixEmpty(text); | ||
} | ||
|
||
@Extension | ||
public static class DescriptorImpl extends AbstractStepDescriptorImpl { | ||
|
||
public DescriptorImpl() { | ||
super(ReadJSONStepExecution.class); | ||
} | ||
|
||
@Override | ||
public String getFunctionName() { | ||
return "readJSON"; | ||
} | ||
|
||
@Override | ||
public String getDisplayName() { | ||
return Messages.ReadJSONStep_DescriptorImpl_displayName(); | ||
} | ||
|
||
@Override | ||
public Step newInstance(StaplerRequest req, JSONObject formData) throws FormException { | ||
String file = formData.getString("file"); | ||
String text = formData.getString("text"); | ||
if (StringUtils.isNotBlank(file) && StringUtils.isNotBlank(text)) { | ||
// seems that FormException is not handled correctly, it is not shown at all client side | ||
throw new FormException(Messages.ReadJSONStepExecution_tooManyArguments(getFunctionName()), "text"); | ||
} | ||
|
||
return super.newInstance(req, formData); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2016 Nikolas Falco | ||
* | ||
* 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.utility.steps.json; | ||
|
||
import static org.apache.commons.lang.StringUtils.isBlank; | ||
import static org.apache.commons.lang.StringUtils.isNotBlank; | ||
import java.io.FileNotFoundException; | ||
import java.io.InputStream; | ||
import javax.inject.Inject; | ||
|
||
import org.apache.commons.io.IOUtils; | ||
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution; | ||
import org.jenkinsci.plugins.workflow.steps.StepContextParameter; | ||
|
||
import hudson.FilePath; | ||
import net.sf.json.JSON; | ||
import net.sf.json.JSONSerializer; | ||
|
||
/** | ||
* Execution of {@link ReadJSONStep}. | ||
* | ||
* @author Nikolas Falco | ||
*/ | ||
public class ReadJSONStepExecution extends AbstractSynchronousNonBlockingStepExecution<JSON> { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
@StepContextParameter | ||
private transient FilePath ws; | ||
|
||
@Inject | ||
private transient ReadJSONStep step; | ||
|
||
@Override | ||
protected JSON run() throws Exception { | ||
String fName = step.getDescriptor().getFunctionName(); | ||
if (isNotBlank(step.getFile()) && isNotBlank(step.getText())) { | ||
throw new IllegalArgumentException(Messages.ReadJSONStepExecution_tooManyArguments(fName)); | ||
} | ||
if (isBlank(step.getFile()) && isBlank(step.getText())) { | ||
throw new IllegalArgumentException(Messages.ReadJSONStepExecution_missingRequiredArgument(fName)); | ||
} | ||
|
||
JSON json = null; | ||
if (!isBlank(step.getFile())) { | ||
FilePath f = ws.child(step.getFile()); | ||
if (f.exists() && !f.isDirectory()) { | ||
try (InputStream is = f.read()) { | ||
json = JSONSerializer.toJSON(IOUtils.toString(is)); | ||
} | ||
} else if (f.isDirectory()) { | ||
throw new IllegalArgumentException(Messages.JSONStepExecution_fileIsDirectory(f.getRemote())); | ||
} else if (!f.exists()) { | ||
throw new FileNotFoundException(Messages.JSONStepExecution_fileNotFound(f.getRemote())); | ||
} | ||
} | ||
if (!isBlank(step.getText())) { | ||
json = JSONSerializer.toJSON(step.getText().trim()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||
} | ||
|
||
return json; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2016 Nikolas Falco | ||
* | ||
* 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.utility.steps.json; | ||
|
||
import org.jenkinsci.plugins.workflow.steps.AbstractStepDescriptorImpl; | ||
import org.jenkinsci.plugins.workflow.steps.AbstractStepImpl; | ||
import org.kohsuke.stapler.DataBoundConstructor; | ||
import hudson.Extension; | ||
import hudson.Util; | ||
import net.sf.json.JSON; | ||
|
||
/** | ||
* Writes a {@link JSON} object to file in the current working directory. | ||
* | ||
* @author Nikolas Falco | ||
*/ | ||
public class WriteJSONStep extends AbstractStepImpl { | ||
|
||
private final String file; | ||
private final JSON json; | ||
|
||
@DataBoundConstructor | ||
public WriteJSONStep(String file, JSON json) { | ||
this.file = Util.fixNull(file); | ||
this.json = json; | ||
} | ||
|
||
/** | ||
* Returns the name of the file to write. | ||
* | ||
* @return the file name | ||
*/ | ||
public String getFile() { | ||
return file; | ||
} | ||
|
||
/** | ||
* Return the JSON object to save. | ||
* | ||
* @return a {@link JSON} object | ||
*/ | ||
public JSON getJson() { | ||
return json; | ||
} | ||
|
||
@Extension | ||
public static class DescriptorImpl extends AbstractStepDescriptorImpl { | ||
|
||
public DescriptorImpl() { | ||
super(WriteJSONStepExecution.class); | ||
} | ||
|
||
@Override | ||
public String getFunctionName() { | ||
return "writeJSON"; | ||
} | ||
|
||
@Override | ||
public String getDisplayName() { | ||
return Messages.WriteJSONStep_DescriptorImpl_displayName(); | ||
} | ||
|
||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
* The MIT License (MIT) | ||
* | ||
* Copyright (c) 2016 Nikolas Falco | ||
* | ||
* 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.utility.steps.json; | ||
|
||
import java.io.FileNotFoundException; | ||
import java.io.OutputStreamWriter; | ||
|
||
import javax.inject.Inject; | ||
|
||
import org.apache.commons.lang.StringUtils; | ||
import org.jenkinsci.plugins.workflow.steps.AbstractSynchronousNonBlockingStepExecution; | ||
import org.jenkinsci.plugins.workflow.steps.StepContextParameter; | ||
|
||
import hudson.FilePath; | ||
|
||
/** | ||
* Execution of {@link WriteJSONStep}. | ||
* | ||
* @author Nikolas Falco | ||
*/ | ||
public class WriteJSONStepExecution extends AbstractSynchronousNonBlockingStepExecution<Void> { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
@StepContextParameter | ||
private transient FilePath ws; | ||
|
||
@Inject | ||
private transient WriteJSONStep step; | ||
|
||
@Override | ||
protected Void run() throws Exception { | ||
if (step.getJson() == null) { | ||
throw new IllegalArgumentException(Messages.WriteJSONStepExecution_missingJSON(step.getDescriptor().getFunctionName())); | ||
} | ||
if (StringUtils.isBlank(step.getFile())) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you do require both arguments to be set they should both be in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. right, I miss due I've add json later. |
||
throw new IllegalArgumentException(Messages.WriteJSONStepExecution_missingFile(step.getDescriptor().getFunctionName())); | ||
} | ||
|
||
FilePath path = ws.child(step.getFile()); | ||
if (path.isDirectory()) { | ||
throw new FileNotFoundException(Messages.JSONStepExecution_fileIsDirectory(path.getRemote())); | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps a nice thing to do would be to warn if you are overwriting an existing file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typicall scenario of writeJSON is read json file and manipulate its data, add other data and update the same file (like maven step does). I could add a boolean property override to step, but this could be a show stopper in case devops change the pipeline and/or developer would provide a base JSON file to be enhance with writeJSON step, etc etc. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
try (OutputStreamWriter writer = new OutputStreamWriter(path.write())) { | ||
step.getJson().write(writer); | ||
} | ||
return null; | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can return the object here directly, since you don't seem to try to do any override (even if your help text below at times indicates you do)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could but personally I do not like too much exit point, when is possible I prefer this way
SonarQube open a violation when >= 5 return in a method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, it's just that this behaves a bit differently then from what is stated, if both file and text is set (which is blocked in
newInstance
but can happen by other means) it would read the file and then overwrite the val with what is in text. Nothing wrong with that, just that the code doesn't fully reflect what is expected.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If both fields are set an IllegalArgumentException will be throw at the begin of this method