From 82d80e7a4bbf732a6087a3fbe0d663ce1bb72bc2 Mon Sep 17 00:00:00 2001 From: Luis Toledo Date: Mon, 8 Oct 2018 16:44:05 -0300 Subject: [PATCH] - Adding storage access example for script plugin - Adding logfilter example for java plugin --- README.md | 1 + .../JavaPluginTemplateGenerator.groovy | 2 +- .../logfilter/Plugin.java.template | 83 ++++++++++++++++++ .../logfilter/PluginSpec.groovy.template | 45 ++++++++++ .../java-plugin/logfilter/README.md.template | 4 + .../logfilter/build.gradle.template | 42 +++++++++ .../templates/java-plugin/logfilter/icon.png | Bin 0 -> 1704 bytes .../logfilter/java-plugin.structure | 6 ++ .../filecopier/plugin.yaml.template | 20 ++++- .../plugin.yaml.template | 38 +++++++- .../nodeexecutor/plugin.yaml.template | 20 ++++- .../workflow/plugin.yaml.template | 20 ++++- .../JavaPluginTemplateGeneratorTest.groovy | 16 ++++ 13 files changed, 292 insertions(+), 5 deletions(-) create mode 100644 src/main/resources/templates/java-plugin/logfilter/Plugin.java.template create mode 100644 src/main/resources/templates/java-plugin/logfilter/PluginSpec.groovy.template create mode 100644 src/main/resources/templates/java-plugin/logfilter/README.md.template create mode 100644 src/main/resources/templates/java-plugin/logfilter/build.gradle.template create mode 100644 src/main/resources/templates/java-plugin/logfilter/icon.png create mode 100644 src/main/resources/templates/java-plugin/logfilter/java-plugin.structure diff --git a/README.md b/README.md index 0d6541a..6442bd0 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ Java Plugins: * Notification * WorkflowStep * WorkflowNodeStep +* LogFilter Script Plugins: * ResourceModelSource diff --git a/src/main/groovy/com/rundeck/plugin/generator/JavaPluginTemplateGenerator.groovy b/src/main/groovy/com/rundeck/plugin/generator/JavaPluginTemplateGenerator.groovy index e9f3cb2..e672886 100644 --- a/src/main/groovy/com/rundeck/plugin/generator/JavaPluginTemplateGenerator.groovy +++ b/src/main/groovy/com/rundeck/plugin/generator/JavaPluginTemplateGenerator.groovy @@ -24,7 +24,7 @@ class JavaPluginTemplateGenerator extends AbstractTemplateGenerator { private static final String TEMPLATE_BASE = "templates/java-plugin/" private static final String JAVA_STRUCTURE = "java-plugin.structure" - private static final List ALLOWED_TEMPLATES = ["ResourceModelSource","Notification","WorkflowStep","WorkflowNodeStep"] + private static final List ALLOWED_TEMPLATES = ["ResourceModelSource","Notification","WorkflowStep","WorkflowNodeStep","LogFilter"] @Override Map makeTemplateProperties(final String pluginName, final String providedService) { diff --git a/src/main/resources/templates/java-plugin/logfilter/Plugin.java.template b/src/main/resources/templates/java-plugin/logfilter/Plugin.java.template new file mode 100644 index 0000000..3fbb49f --- /dev/null +++ b/src/main/resources/templates/java-plugin/logfilter/Plugin.java.template @@ -0,0 +1,83 @@ +package com.plugin.${javaPluginClass.toLowerCase()}; + +import com.dtolabs.rundeck.core.logging.LogEventControl; +import com.dtolabs.rundeck.core.logging.LogLevel; +import com.dtolabs.rundeck.core.logging.PluginLoggingContext; +import com.dtolabs.rundeck.core.plugins.Plugin; +import com.dtolabs.rundeck.plugins.descriptions.PluginDescription; +import com.dtolabs.rundeck.plugins.descriptions.PluginProperty; +import com.dtolabs.rundeck.plugins.descriptions.SelectLabels; +import com.dtolabs.rundeck.plugins.descriptions.SelectValues; +import com.dtolabs.rundeck.plugins.logging.LogFilterPlugin; +import java.util.HashMap; +import java.util.Map; + +@Plugin(service="LogFilter",name="${sanitizedPluginName}") +@PluginDescription(title="${pluginName}", description="My plugin description") +public class ${javaPluginClass} implements LogFilterPlugin{ + + @PluginProperty(name = "example header",title = "Example String",description = "Example description") + private String header; + + @PluginProperty( + title = "Data type", + description = "Select datatype output", + required = false + ) + @SelectValues( + values = {"text/plain", "text/html"}, + freeSelect = true + ) + @SelectLabels(values = {"TEXT", "HTML"}) + String datatype = null; + + + private boolean started = false; + private StringBuilder buffer; + + @Override + public void init(final PluginLoggingContext context) { + started = true; + buffer = new StringBuilder(); + + if(datatype.equals("text/html")){ + buffer.append(""); + buffer.append(""); + } + } + + @Override + public void handleEvent(final PluginLoggingContext context, final LogEventControl event) { + if(event.getEventType().equals("log") && event.getLoglevel().equals(LogLevel.NORMAL) ){ + + if(datatype.equals("text/html")){ + buffer.append(""); + }else{ + buffer.append("[").append(header).append("] ").append(event.getMessage()).append("\\n"); + } + + event.setLoglevel(LogLevel.DEBUG); + } + } + + @Override + public void complete(final PluginLoggingContext context) { + if (started && datatype!=null && buffer.length()>0) { + + if(datatype.equals("text/html")){ + buffer.append("
Log Output
").append("[").append(header).append("] ").append(event.getMessage()).append("
"); + } + + Map type = new HashMap<>(); + type.put("content-data-type", datatype); + + + context.log( + 2, + buffer.toString(), + type + ); + + } + } +} \ No newline at end of file diff --git a/src/main/resources/templates/java-plugin/logfilter/PluginSpec.groovy.template b/src/main/resources/templates/java-plugin/logfilter/PluginSpec.groovy.template new file mode 100644 index 0000000..cb2e5f5 --- /dev/null +++ b/src/main/resources/templates/java-plugin/logfilter/PluginSpec.groovy.template @@ -0,0 +1,45 @@ +package com.plugin.${javaPluginClass.toLowerCase()} + +import com.dtolabs.rundeck.core.dispatcher.ContextView +import com.dtolabs.rundeck.core.execution.workflow.DataOutput +import com.dtolabs.rundeck.core.logging.LogEventControl +import com.dtolabs.rundeck.core.logging.LogLevel +import com.dtolabs.rundeck.core.logging.PluginLoggingContext +import spock.lang.Specification + +class ${javaPluginClass}Spec extends Specification { + + def "test preset type "() { + given: + def plugin = new ${javaPluginClass}() + plugin.datatype = datatype + plugin.header = "test" + def sharedoutput = new DataOutput(ContextView.global()) + def context = Mock(PluginLoggingContext) { + getOutputContext() >> sharedoutput + } + def events = [] + lines.each { line -> + events << Mock(LogEventControl) { + getMessage() >> line + getEventType() >> 'log' + getLoglevel() >> LogLevel.NORMAL + } + } + when: + plugin.init(context) + events.each { + plugin.handleEvent(context, it) + } + plugin.complete(context) + + then: + 1 * context.log(2, output, meta) + + where: + datatype | lines | output | meta + 'text/plain' | ['1,2,3', '---', 'a,b,c'] | '[test] 1,2,3\\n[test] ---\\n[test] a,b,c\\n' | ['content-data-type': 'text/plain'] + 'text/html' | ['1,2,3', '---', 'a,b,c'] | "
Log Output
[test] 1,2,3
[test] ---
[test] a,b,c
" | ['content-data-type': 'text/html'] + } + +} \ No newline at end of file diff --git a/src/main/resources/templates/java-plugin/logfilter/README.md.template b/src/main/resources/templates/java-plugin/logfilter/README.md.template new file mode 100644 index 0000000..a03f19d --- /dev/null +++ b/src/main/resources/templates/java-plugin/logfilter/README.md.template @@ -0,0 +1,4 @@ +# ${pluginName} Rundeck Plugin + +This is a log filter plugin. + diff --git a/src/main/resources/templates/java-plugin/logfilter/build.gradle.template b/src/main/resources/templates/java-plugin/logfilter/build.gradle.template new file mode 100644 index 0000000..b304aa9 --- /dev/null +++ b/src/main/resources/templates/java-plugin/logfilter/build.gradle.template @@ -0,0 +1,42 @@ +version = '0.1.0' +defaultTasks 'clean','build' +apply plugin: 'java' +apply plugin: 'groovy' +apply plugin: 'idea' +sourceCompatibility = 1.8 +ext.rundeckPluginVersion= '2.0' +ext.rundeckVersion= '${rundeckVersion}' + + +repositories { + mavenLocal() + mavenCentral() +} + +dependencies { + compile 'org.rundeck:rundeck-core:3.0.1+' + + testCompile 'junit:junit:4.12' + testCompile "org.codehaus.groovy:groovy-all:2.4.15" + testCompile "org.spockframework:spock-core:1.0-groovy-2.4" +} + +ext.pluginClassNames='com.plugin.${sanitizedPluginName}.${javaPluginClass}' +jar { + manifest { + attributes 'Rundeck-Plugin-Classnames': pluginClassNames + attributes 'Rundeck-Plugin-File-Version': version + attributes 'Rundeck-Plugin-Name': '${pluginName}' + attributes 'Rundeck-Plugin-Description': 'Provide a short description of your plugin here.' + attributes 'Rundeck-Plugin-Rundeck-Compatibility-Version': '3.x' + attributes 'Rundeck-Plugin-Tags': 'java,notification' + attributes 'Rundeck-Plugin-Version': rundeckPluginVersion, 'Rundeck-Plugin-Archive': 'true' + } + from("rundeck-verb-artifact.yaml") { + into("") + } +} + +task wrapper(type: Wrapper) { + gradleVersion = '4.4.1' +} diff --git a/src/main/resources/templates/java-plugin/logfilter/icon.png b/src/main/resources/templates/java-plugin/logfilter/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7aaf7e86c71a6ef5ccce85c9a7a081da744f16b8 GIT binary patch literal 1704 zcmV;Z23PrsP);EK~!jg?U{c}Rb?2*Kj&WVy>hRYAA0Y?UzDgIVEC&{4Z>DR zx=?;pD;s8-qaRaO7R8)pxwUDFTGL!<)@DoRudxV_(zRN-OoTZHk~dOpq^O`GAY8cT z^v5j-N=s{JusyACsb+NE9hFQACAqKixtUB$hFsLyXc*CW`0_d{Sx_L^X5~MiLjygiu8-USV5P zLS!VK<_JruHWQ{_>?4r}c?cOv)7Es;xRSZlGsJ9|zeElvc%6enwx)%&VP`Q}1O}*) zevxm;r&7}{B<$Z1%O-9QMX0~TJCrkv)2cQh5n@3hWdOTlI|0qsB_u+g=aA-%nZY{J zd5_yvZA=T9zv7N{E9VK4I^G6~)hpX9){X1dd-*b;N=~77y$4 zanOTPu)D3rOON1O8x}H@4kGE&?bk&ZT>`W%gzI{dGbALID;#DEF|-+R*F-Z;rjXBN z1_}G<-Xm_hDB+U<6Coq9h-}Ufsmo875DN+)vu{9a#(GjIW1Mb3T|$beU_L+SCK1Kg z+|0||ZOB(x$Wp3U$#;fGL~tG#3&|BerLKpNS30M8mr_FnB9M{DBZo#J49CzElE?*$ z*@>NiVG=E@Bc0C~V=9KK5Dy)cu!AT%O_8YK0CBuVy6HHobz~yv*uoUkBx?AO$wF^{ zS}=9_@Na@@YKkYJK(9V&dYW zd;bpvWQvRHSi1C6JRT?0rj4Mc#{4ZxUS0|tHq0hBcNd2a{cI?P>WbKG!S59{HRtj9 zno$(U$w^}S_8dcG{UI&wW;`Az6DQteIEGLi$;{kAeEddIQZ^F^$jqJ{XPD6Kwj*7) zw^ytvCpC2&@4tVv&vU!oirp^u@kh9fTCEa^iNOmqzrSxynKNe$SFaZG_S^UMKC7%; zMr-R!xZQRv7Kws_nY6SN(Arwal`Ah%U7gR>tA)&+JC+w-n90F|i^$DQ;;pwbXlpB^ zsw$t3j@4YdwweP677-Pt-U$n}@wK(jV6$1VS|t<(wr;KJ^SjMvVenu(k&%wxXI`%h zx7&dvNvv6O7i-tfA`pH$=xLkJZb}O>1;BwiSJUIrRuNkk` z#Xa|oX5G5GS-!ly-!TfUh@wDSo1eP6i#+#S1qB6Ph`0g4l`JewLzWe0%=mx_6E-ty zR1p_0wA0fg-(cU_8GLQtyY~d~@f%4`{|JD4?^RD{p%qC^-o&X>mxTxaXN(>ljl*H3 zq2V$|j{E|^rAwXc-(OE&UjN@&N=r`yaQbwR*X6RS@`U6%==Yh8hzO>Z)haP$NH~h3 z(Ae0DEGxvsxbb?O07w!{ojMFz?!OlQ9#c`o>UBtj{Pfc$Ah_ute|!>q_B@2kWkXSd zsj_EJEe?m3W5=GNs3?Q#>U@%t#BbU~pqg5Nz>PV4J!DzI=WC(3xQ?u>@od|+00{0Y ziv^rc8_SlJ5FQ>zW@bWfC(zXuz~QjoFys9#fYw-4d##L&F+@Z-C@b^P-rn~LXV|d8 zq^8DFUw?_Js(Wbr{D58r>^h}-Sx{kx&z3SnUuva`q2+S)}$MZGa0p@7?M=j6%dcsx!v zZ1|R=N6(U$7R$<&(`jz*VEFJi>F(BEc`f`c-S4VZGg!ZVcAuux?+=ijy_2%CA49_N yx3%%Hv60N1Hx7@-NmElBB_$_0cP?~SO1}d1V%O)$wH#Xj0000build.gradle +README.md.template->README.md +icon.png->src/main/resources/resources/icon.png +Plugin.java.template->src/main/java/com/plugin/${javaPluginClass.toLowerCase()}/${javaPluginClass}.java +PluginSpec.groovy.template->src/test/groovy/com/plugin/${javaPluginClass.toLowerCase()}/${javaPluginClass}Spec.groovy + diff --git a/src/main/resources/templates/script-plugin/filecopier/plugin.yaml.template b/src/main/resources/templates/script-plugin/filecopier/plugin.yaml.template index 58e31ac..86d3cb1 100644 --- a/src/main/resources/templates/script-plugin/filecopier/plugin.yaml.template +++ b/src/main/resources/templates/script-plugin/filecopier/plugin.yaml.template @@ -40,4 +40,22 @@ providers: description: 'Just echo what would be done' default: true renderingOptions: - groupName: 'Config' \ No newline at end of file + groupName: 'Config' + - type: String + name: storageprivatekey + title: Storage Private Key + description: Access to storage private key example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-key-type=private" + - type: String + name: storagepassword + title: Storage Password + description: Access to storage password example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-data-type=password" \ No newline at end of file diff --git a/src/main/resources/templates/script-plugin/nodeexecutor-filecopier/plugin.yaml.template b/src/main/resources/templates/script-plugin/nodeexecutor-filecopier/plugin.yaml.template index 82e8b18..92ecd48 100644 --- a/src/main/resources/templates/script-plugin/nodeexecutor-filecopier/plugin.yaml.template +++ b/src/main/resources/templates/script-plugin/nodeexecutor-filecopier/plugin.yaml.template @@ -41,6 +41,24 @@ providers: default: true renderingOptions: groupName: 'Config' + - type: String + name: storageprivatekey + title: Storage Private Key + description: Access to storage private key example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-key-type=private" + - type: String + name: storagepassword + title: Storage Password + description: Access to storage password example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-data-type=password" - name: ${sanitizedPluginName}-FileCopier service: FileCopier title: ${pluginName} @@ -70,4 +88,22 @@ providers: description: 'Just echo what would be done' default: true renderingOptions: - groupName: 'Config' \ No newline at end of file + groupName: 'Config' + - type: String + name: storageprivatekey + title: Storage Private Key + description: Access to storage private key example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-key-type=private" + - type: String + name: storagepassword + title: Storage Password + description: Access to storage password example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-data-type=password" \ No newline at end of file diff --git a/src/main/resources/templates/script-plugin/nodeexecutor/plugin.yaml.template b/src/main/resources/templates/script-plugin/nodeexecutor/plugin.yaml.template index b383b93..7e85361 100644 --- a/src/main/resources/templates/script-plugin/nodeexecutor/plugin.yaml.template +++ b/src/main/resources/templates/script-plugin/nodeexecutor/plugin.yaml.template @@ -40,4 +40,22 @@ providers: description: 'Just echo what would be done' default: true renderingOptions: - groupName: 'Config' \ No newline at end of file + groupName: 'Config' + - type: String + name: storageprivatekey + title: Storage Private Key + description: Access to storage private key example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-key-type=private" + - type: String + name: storagepassword + title: Storage Password + description: Access to storage password example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-data-type=password" \ No newline at end of file diff --git a/src/main/resources/templates/script-plugin/workflow/plugin.yaml.template b/src/main/resources/templates/script-plugin/workflow/plugin.yaml.template index a24545e..462c299 100644 --- a/src/main/resources/templates/script-plugin/workflow/plugin.yaml.template +++ b/src/main/resources/templates/script-plugin/workflow/plugin.yaml.template @@ -44,4 +44,22 @@ providers: title: Debug? description: 'Write debug messages to stderr' renderingOptions: - groupName: 'Config' \ No newline at end of file + groupName: 'Config' + - type: String + name: storageprivatekey + title: Storage Private Key + description: Access to storage private key example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-key-type=private" + - type: String + name: storagepassword + title: Storage Password + description: Access to storage password example + renderingOptions: + selectionAccessor: "STORAGE_PATH" + valueConversion: "STORAGE_PATH_AUTOMATIC_READ" + storage-path-root: "keys" + storage-file-meta-filter: "Rundeck-data-type=password" \ No newline at end of file diff --git a/src/test/groovy/com/rundeck/plugin/generator/JavaPluginTemplateGeneratorTest.groovy b/src/test/groovy/com/rundeck/plugin/generator/JavaPluginTemplateGeneratorTest.groovy index fcaa77a..f169c6d 100644 --- a/src/test/groovy/com/rundeck/plugin/generator/JavaPluginTemplateGeneratorTest.groovy +++ b/src/test/groovy/com/rundeck/plugin/generator/JavaPluginTemplateGeneratorTest.groovy @@ -85,4 +85,20 @@ class JavaPluginTemplateGeneratorTest extends Specification { new File(tmpDir,"/my-workflownodestep-plugin/src/test/groovy/com/plugin/myworkflownodestepplugin/MyWorkflownodestepPluginSpec.groovy").exists() } + def "Create Logfilter Template"() { + when: + File tmpDir = File.createTempDir() + JavaPluginTemplateGenerator generator = new JavaPluginTemplateGenerator() + generator.createTemplate("My LogFilter Plugin","LogFilter",tmpDir.absolutePath) + int compileResult = TestUtils.buildGradle(new File(tmpDir,"my-logfilter-plugin")) + + then: + compileResult == 0 + new File(tmpDir,"/my-logfilter-plugin/build.gradle").exists() + new File(tmpDir,"/my-logfilter-plugin/src/main/resources/resources/icon.png").exists() + new File(tmpDir,"/my-logfilter-plugin/README.md").exists() + new File(tmpDir,"/my-logfilter-plugin/src/main/java/com/plugin/mylogfilterplugin/MyLogfilterPlugin.java").exists() + new File(tmpDir,"/my-logfilter-plugin/src/test/groovy/com/plugin/mylogfilterplugin/MyLogfilterPluginSpec.groovy").exists() + } + }