heremaps / gradle-jenkins-jobdsl-plugin

A plugin for Gradle to manage Jenkins Job DSL projects.
https://plugins.gradle.org/plugin/com.here.jobdsl
Apache License 2.0
53 stars 9 forks source link

Proposal: be able to send script parameters via execution of dslGenerateXml task #96

Closed michelzanini closed 6 years ago

michelzanini commented 6 years ago

Hi,

I would like to propose a feature, that if you agree being useful, I could create a PR with the changes for you.

When running dslGenerateXml gradle task, I need to send some sensitive parameters to my script, like username and password. When I am running scripts from Jenkins, I can do something like this:

jobDsl targets: 'src/jobdsl/*.groovy', removedJobAction: 'DELETE', removedViewAction: 'DELETE', additionalClasspath: 'build/classes/groovy/main', additionalParameters: [username: 'someUser', password: 'somePassword' ]

Job DSL lets me send "additionalParameters" which them I can access them as variables in my Groovy script. This works well for me as I can send user / pass coming from Jenkins credentials and keep them private.

However, for development purposes I also want to be able to run dslGenerateXml gradle task, but be able to have the variables available. In the end, what I need is running something like this:

./gradlew dslGenerateXml --username=someUser --password=somePassword

And those variables appearing on the script that is run. I had some look at the source code and I think this can be done by changing the GenerateXmlRunner class here:

new FilteringJenkinsJobManagement(filter, System.out, [:], workspace, failOnMissingPlugin)

Right now a JobManagement is created with [:] (empty additional parameters). If we can map the Gradle parameters somehow, parse them and adding them in place of [:], this would work very nicely for me.

If you like this proposal them I could implement this as a PR.

Let me know, Thanks.

michelzanini commented 6 years ago

@mnonnenmacher

mnonnenmacher commented 6 years ago

This sounds like a great idea, a PR would be very welcome. Please note that I won't be able to review before July 23rd. Thanks!

michelzanini commented 6 years ago

I found a way that what I need can be accomplished without any need to create a PR.

This is what I have done:

On build.gradle:

jobdsl {
  configuration = [
    username: project.properties['username'],
    password: project.properties['password']
  ]
}

This allows for sending the parameters when running the task as follows:

./gradlew -Pusername=someUser -Ppassword= somePassword dslGenerateXml

Then on the Groovy script:

import com.example.SeedJob
import com.here.gradle.plugins.jobdsl.util.DslConfig

def usernameParameter = binding.hasVariable('username') ? username : DslConfig.get('username')
def passwordParameter = binding.hasVariable('password') ? password : DslConfig.get('password')

SeedJob seedJob = new SeedJob()
seedJob.execute(usernameParameter, passwordParameter)

You can see I first attempt to obtain the value from binding, then from DslConfig. When running dslGenerateXml from the command line, the variable will be stored in DslConfig. But, when running from Jenkinsfile jobDsl the variable will be on binding. I am giving priority to find it on binding first, so then from Jenkinsfile I can do this:

stage('Generate XML') {
      steps {
        withCredentials([usernamePassword(credentialsId: 'my-credentials', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
          sh "./gradlew -username=$USERNAME -Pcredentials=$PASSWORD dslGenerateXml"
        }
      }
    }

    stage('Run DSL scripts') {
      steps {
        withCredentials([usernamePassword(credentialsId: 'my-credentials', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
          jobDsl targets: 'src/jobdsl/*.groovy',
              additionalClasspath: 'build/classes/groovy/main',
              additionalParameters: [
                  username: "$USERNAME",
                  password: "$PASSWORD"
              ]
        }
      }
}

With that both styles can send parameters, either by running dslGenerateXml on Gradle or running the Job DSL command.

Since this is a OK solution I will close this ticket.

Then only thing I can see could be done to improve in the plugin is to merge DslConfig.configuration and DslConfig.serverConfiguration map keys, where serverConfiguration takes priority and send this resulting map to:

new FilteringJenkinsJobManagement(filter, System.out, DslConfig.mergedConfigurationMap(), workspace, failOnMissingPlugin)

That way the jobdsl.configuration variables would also be on binding then the Groovy script can just use them without the if/else.

But I wont create a PR for this as it does not does too much improvement, I will leave it to you.

Thanks.

mnonnenmacher commented 6 years ago

@michelzanini Thanks for sharing your solution! I will check your proposed improvements for one of the next releases.