package com.orchard

class CookbookUploader implements Serializable {

  def static berksInstall(script,berksBinary) {
    script.sh("${berksBinary} install")
  }

  def static berksUpload(script,berksBinary) {
    script.sh("${berksBinary} upload")
  }

  def static versionAndName(script) {
    def metadata = script.readFile('metadata.rb')
    def pattern = /version\s*\'(\d+\.\d+\.\d+)\'/
    def matcher = metadata  =~ pattern
    def result =  matcher[0][1]
    result
  }
  
  def static verifyEnv(script) {
    def binaries = []
    def knifeBinary = script.sh(returnStdout: true, script: "/usr/bin/which knife").trim()
    def berksBinary = script.sh(returnStdout: true, script: "/usr/bin/which berks").trim()
    def knifeBlock = script.sh(returnStdout: true, script: """
      source /var/lib/jenkins/.bash_profile
      gem list --local knife-block
    """)
    if (knifeBinary =~"knife" && berksBinary =~ "berks" && knifeBlock =~ "knife-block") {
      script.echo "Berks, Knife binaries and knife-block plugin found. Continuing..."
      binaries + knifeBinary + berksBinary
    } 
    else { 
      script.currentBuild.result = 'FAILURE'
      script.error("Berks, Knife binaries or knife-block plugin not found or executable.") 
    }
  }
  
  def static changeTrustedDir(script, server) {
    script.sh ("sed -i -e 's;/etc/chef/trusted_certs;/var/lib/jenkins/.chef/trusted_certs;g' ~/.chef/knife-${server}.rb")
  }
  
  def static checkCookbookVersion(script, name, site, newVersion) {
    def currentVersion = script.sh(returnStdout:true, script: "knife cookbook show ${name}")
    def action
    def pattern = /^\S*\s{3}(\d+\.\d+\.\d+)/
    def matcher = currentVersion  =~ pattern
    def result =  matcher[0][1]
    if (result == newVersion) {
      script.echo "Newer cookbook version was not found for ${site}! Moving on to next site..."
      action = 'skip'
    }
    else if (result < newVersion)  {
      script.echo "Newer cookbook version detected. Continuing..."
      action = 'update'     
    }
    else if (currentVersion !="0") {
      script.echo "Cookbook ${name} not found on ${site}. Continuing with initial upload..."
      action = 'upload'
    }
    action
  }

  def static uploadCookbook(script, name) {
    def binaries = verifyEnv(script)
    def cookbookVersion = versionAndName(script)
    def sites = script.sh(returnStdout: true,
      script: '''
        source /var/lib/jenkins/.bash_profile
        knife block list | grep '*' | awk '{print $2}'
      '''
    ).split("\n")
    sites.each { chefServer ->
      changeTrustedDir(script,chefServer)
      script.sh (returnStdout: false, script: """
        source /var/lib/jenkins/.bash_profile
        knife block use ${chefServer}
        knife ssl fetch
      """)
      def action
      def verifyCookbook = script.sh(returnStatus:true, script: "knife cookbook show ${name}")
      if (verifyCookbook != 0) {
        script.echo "Cookbook ${name} not found on ${chefServer}. Continuing with initial upload..."
        action = "upload"
      }
      else {
        action = checkCookbookVersion(script,name,chefServer,cookbookVersion)
      }
      if (action == "upload" || action == "update") {
        berksInstall(script,binaries[1])
        berksUpload(script,binaries[1])
        script.echo "Upload complete."
      }
      else if (action == "skip")  {
        script.echo "Nothing to do."
      }
      else {
        script.currentBuild.result = 'FAILURE'
        script.error("Could not determine next action, aborted...") 
      }
    }
  }

}
