I spent a lot of time fighting with various Java/Scala APIs to do HTTP connections with authentication, and many of them didn't work as I needed and/or were too complicated to use.
I also spent a lot of time trying out existing Java APIs and StackOverflow posts for how to interact with Jenkins. I discovered through trial and error that the RisingOak Jenkins API simply does not work to get a nested job.
I finally got something to work. I'm using it in this manner:
- Read contents of [jenkinsServerUrl]/job/JobName[/job/SubJobName]*/lastStableBuild/buildNumber to determine the last stable build number
- Compare to build number of known installation. If greater, ensure it's a stable trunk build (if it's the same as lastStableBuild then skip checking if stable).
- To check if a trunk build, parsing build parameter "branch" from the page [buildNumber]/injectedEnvVars under my Jenkins job sub URL
- To check if a stable build, parse the HTML of the [buildNumber] page under the Jenkins job sub URL, and check the status icon (this is brittle, but was the only/easiest way I could find).
- If not stable trunk build, decrement number until it's equal to the installed build, then stop.
- If later build found, download the archive, SFTP it up, and install it using SSH commands.
Here's the helper object that I use to make the authenticated HTTP requests:
package Helpers import java.io.InputStream import java.net.URL import Helpers.InputStreamHelper.InputStreamExtensions import org.apache.commons.codec.binary.Base64 import scala.io.Source /** * HTTP Helper methods */object HttpHelper { def download(url: String, savePath: String, user: String = null, passwordOrToken: String = null, requestProperties: Map[String, String]= Map("User-Agent"->"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)")) : Unit = { val inputStream = getInputStreamFromUrl(url, user, passwordOrToken, requestProperties) try { inputStream.downloadToFile(savePath) } finally { inputStream.close() } } def getPageContentFromUrl(url: String, user: String = null, passwordOrToken: String = null, requestProperties: Map[String, String]= Map("User-Agent"->"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)")) : String = { val inputStream = getInputStreamFromUrl(url, user, passwordOrToken, requestProperties) try { Source.fromInputStream(inputStream).getLines().mkString("\n") } finally { inputStream.close() } } def getInputStreamFromUrl(url: String, user: String = null, passwordOrToken: String = null, requestProperties: Map[String, String]= Map("User-Agent"->"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)")) : InputStream = { val connection = new URL(url).openConnection requestProperties.foreach({ case (name, value) => connection.setRequestProperty(name, value) }) if (user != null && passwordOrToken != null) { connection.setRequestProperty("Authorization", getHeader(user, passwordOrToken)) } connection.getInputStream } def encodeCredentials(username: String, password: String): String = { new String(Base64.encodeBase64String((username + ":" + password).getBytes)) } def getHeader(username: String, password: String): String = { "Basic " + encodeCredentials(username, password) } }
package Helpers import java.io.{FileOutputStream, InputStream} /** * Created by Samer Adra on 5/13/2015. */object InputStreamHelper { implicit class InputStreamExtensions(val inputStream: InputStream) { def downloadToFile(path: String): Unit = { val buffer = new Array[Byte](8 * 1024) val outStream = new FileOutputStream(path) try { var bytesRead = 0 while ({bytesRead = inputStream.read(buffer); bytesRead != -1}) { outStream.write(buffer, 0, bytesRead) } } finally { outStream.close() } } } }
No comments:
Post a Comment