#!/bin/groovy
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

// Template Jenkins Declarative Pipeline script to run Test w/ RF HW

// Location of the python executor node shall be in the same subnet as the others servers
def pythonExecutor = params.pythonExecutor

// Location of the test XML file to be run
def testXMLFile = params.pythonTestXmlFile
def mainPythonAllXmlFiles = ""
def buildStageStatus = true

// Name of the test stage
def testStageName = params.pipelineTestStageName

def lockResources = []
if (params.LockResources != null && params.LockResources.trim().length() > 0)
  params.LockResources.trim().split(",").each{lockResources += [resource: it.trim()]}

// Global Parameters. Normally they should be populated when the master job
// triggers the slave job with parameters
def eNB_Repository
def eNB_Branch
def eNB_CommitID
def eNB_AllowMergeRequestProcess
def eNB_TargetBranch

//Status fed to the database
def StatusForDb = ""


pipeline {
  agent {label pythonExecutor}
  options {
    ansiColor('xterm')
    lock(extra: lockResources)
  }
  stages {
    stage("Build Init") {
      steps {
        // update the build name and description
        buildName "${params.eNB_MR}"
        buildDescription "Branch : ${params.eNB_Branch}"
      }
    }
    stage ("Verify Parameters") {
      steps {
        script {
          echo '\u2705 \u001B[32mVerify Parameters\u001B[0m'
          def allParametersPresent = true

          // It is already to late to check it
          if (params.pythonExecutor != null) {
            echo "eNB CI executor node  :   ${pythonExecutor}"
          }
          // If not present picking a default Stage Name
          if (params.pipelineTestStageName == null) {
            // picking default
            testStageName = 'Template Test Stage'
          }

          if (params.LockResources == null) {
            echo "no LockResources given"
            allParametersPresent = false
          }
          // 1st eNB parameters
          if (params.eNB_IPAddress == null) {
            allParametersPresent = false
          }
          if (params.eNB_SourceCodePath == null) {
            allParametersPresent = false
          }
          if (params.eNB_Credentials == null) {
            allParametersPresent = false
          }
          // 2nd eNB parameters
          if (params.eNB1_IPAddress == null) {
            allParametersPresent = false
          }
          if (params.eNB1_SourceCodePath == null) {
            allParametersPresent = false
          }
          if (params.eNB1_Credentials == null) {
            allParametersPresent = false
          }
          // 3rd eNB parameters
          if (params.eNB2_IPAddress == null) {
            allParametersPresent = false
          }
          if (params.eNB2_SourceCodePath == null) {
            allParametersPresent = false
          }
          if (params.eNB2_Credentials == null) {
            allParametersPresent = false
          }
          if (params.UE_IPAddress == null) {
              allParametersPresent = false
          }
          if (params.UE_SourceCodePath == null) {
              allParametersPresent = false
          }
          if (params.UE_Credentials == null) {
              allParametersPresent = false
          }          
          // the following 4 parameters should be pushed by the master trigger
          // if not present, take the job GIT variables (used for developing)
          if (params.eNB_Repository == null) {
            eNB_Repository = env.GIT_URL
          } else {
            eNB_Repository = params.eNB_Repository
          }
          echo "eNB_Repository        :   ${eNB_Repository}"
          if (params.eNB_Branch == null) {
            eNB_Branch = env.GIT_BRANCH
          } else {
            eNB_Branch = params.eNB_Branch
          }
          echo "eNB_Branch            :   ${eNB_Branch}"
          if (params.eNB_CommitID == null) {
            eNB_CommitID = env.GIT_COMMIT
          } else {
            eNB_CommitID = params.eNB_CommitID
          }
          echo "eNB_CommitID          :   ${eNB_CommitID}"
          if (params.eNB_mergeRequest!= null) {
            eNB_AllowMergeRequestProcess = params.eNB_mergeRequest
            if (eNB_AllowMergeRequestProcess) {
              if (params.eNB_TargetBranch != null) {
                eNB_TargetBranch = params.eNB_TargetBranch
              } else {
                eNB_TargetBranch = 'develop'
              }
              echo "eNB_TargetBranch      :   ${eNB_TargetBranch}"
            }
          }

          if (params.EPC_IPAddress == null) {
            allParametersPresent = false
          }
          if (params.EPC_Type == null) {
            allParametersPresent = false
          }
          if (params.EPC_SourceCodePath == null) {
            allParametersPresent = false
          }
          if (params.EPC_Credentials == null) {
            allParametersPresent = false
          }

          if (allParametersPresent) {
            echo "All parameters are present"
            if (eNB_AllowMergeRequestProcess) {
              sh "git fetch"
              sh "./ci-scripts/doGitLabMerge.sh --src-branch ${eNB_Branch} --src-commit ${eNB_CommitID} --target-branch ${eNB_TargetBranch} --target-commit latest"
            } else {
              sh "git fetch"
              sh "git checkout -f ${eNB_CommitID}"
            }
          } else {
            echo "Some parameters are missing"
            sh "./ci-scripts/fail.sh"
          }
        }
      }
    }
    stage ("Build and Test") {
      steps {
        script {
          dir ('ci-scripts') {
            echo "\u2705 \u001B[32m${testStageName}\u001B[0m"
            // If not present picking a default XML file
            if (params.pythonTestXmlFile == null) {
              // picking default
              testXMLFile = 'xml_files/enb_usrpB210_band7_50PRB.xml'
              echo "Test XML file(default):   ${testXMLFile}"
              mainPythonAllXmlFiles += "--XMLTestFile=" + testXMLFile + " "
            } else {
              String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
              for (xmlFile in myXmlTestSuite) {
                if (fileExists(xmlFile)) {
                  mainPythonAllXmlFiles += "--XMLTestFile=" + xmlFile + " "
                  echo "Test XML file     :   ${xmlFile}"
                }
              }
            }
            withCredentials([
              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password'],
              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB1_Credentials}", usernameVariable: 'eNB1_Username', passwordVariable: 'eNB1_Password'],
              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB2_Credentials}", usernameVariable: 'eNB2_Username', passwordVariable: 'eNB2_Password'],
              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password'],
              [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
            ]) {
              sh "python3 main.py --mode=InitiateHtml --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} ${mainPythonAllXmlFiles}"
              String[] myXmlTestSuite = testXMLFile.split("\\r?\\n")
              for (xmlFile in myXmlTestSuite) {
                if (fileExists(xmlFile)) {
                  try {
                   timeout (time: 60, unit: 'MINUTES') {
                    sh "python3 main.py --mode=TesteNB --ranRepository=${eNB_Repository} --ranBranch=${eNB_Branch} --ranCommitID=${eNB_CommitID} --ranAllowMerge=${eNB_AllowMergeRequestProcess} --ranTargetBranch=${eNB_TargetBranch} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath} --eNB1IPAddress=${params.eNB1_IPAddress} --eNB1UserName=${eNB1_Username} --eNB1Password=${eNB1_Password} --eNB1SourceCodePath=${params.eNB1_SourceCodePath} --eNB2IPAddress=${params.eNB2_IPAddress} --eNB2UserName=${eNB2_Username} --eNB2Password=${eNB2_Password} --eNB2SourceCodePath=${params.eNB2_SourceCodePath} --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath} --EPCIPAddress=${params.EPC_IPAddress} --EPCType=${params.EPC_Type} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --XMLTestFile=${xmlFile}"
                   }
                  } catch (Exception e) {
                    currentBuild.result = 'FAILURE'
                    buildStageStatus = false
                  }
                }
              }
              sh "python3 main.py --mode=FinalizeHtml --finalStatus=${buildStageStatus} --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password}"
            }
          }
        }
      }
    }
    stage('Log Collection') {
      parallel {
        stage('Log Collection (eNB - Build)') {
          steps {
            withCredentials([
               [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
            ]) {
              echo '\u2705 \u001B[32mLog Collection (eNB - Build)\u001B[0m'
              sh "python3 ci-scripts/main.py --mode=LogCollectBuild --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}"

              echo '\u2705 \u001B[32mLog Transfer (eNB - Build)\u001B[0m'
              sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true"
            }
            script {
              if(fileExists("build.log.${env.BUILD_ID}.zip")) {
                archiveArtifacts "build.log.${env.BUILD_ID}.zip"
              }
            }
          }
        }
        stage('Log Collection (OAI UE - Build)') {
            steps {
                echo '\u2705 \u001B[32mLog Collection (OAI UE - Build)\u001B[0m'
                withCredentials([
                    [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
                ]) {
                    sh "python3 ci-scripts/main.py --mode=LogCollectBuild --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath}"

                    echo '\u2705 \u001B[32mLog Transfer (UE - Build)\u001B[0m'
                    sh "sshpass -p \'${UE_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${UE_Username}@${params.UE_IPAddress}:${UE_SourceCodePath}/cmake_targets/build.log.zip ./build.log.${env.BUILD_ID}.zip || true"
                  }
                  script {
                      if(fileExists("build.log.${env.BUILD_ID}.zip")) {
                          archiveArtifacts "build.log.${env.BUILD_ID}.zip"
                      }
                  }
            }
        }
        stage('Log Collection (eNB - Run)') {
          steps {
            withCredentials([
               [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.eNB_Credentials}", usernameVariable: 'eNB_Username', passwordVariable: 'eNB_Password']
            ]) {
              echo '\u2705 \u001B[32mLog Collection (eNB - Run)\u001B[0m'
              sh "python3 ci-scripts/main.py --mode=LogCollecteNB --eNBIPAddress=${params.eNB_IPAddress} --eNBUserName=${eNB_Username} --eNBPassword=${eNB_Password} --eNBSourceCodePath=${params.eNB_SourceCodePath}"

              echo '\u2705 \u001B[32mLog Transfer (eNB - Run)\u001B[0m'
              sh "sshpass -p \'${eNB_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${eNB_Username}@${params.eNB_IPAddress}:${eNB_SourceCodePath}/cmake_targets/enb.log.zip ./enb.log.${env.BUILD_ID}.zip || true"
            }
            script {
              if(fileExists("enb.log.${env.BUILD_ID}.zip")) {
                archiveArtifacts "enb.log.${env.BUILD_ID}.zip"
              }
            }
          }
        }
        stage('Log Collection (OAI UE - Run)') {
            steps {
                withCredentials([
                    [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.UE_Credentials}", usernameVariable: 'UE_Username', passwordVariable: 'UE_Password']
                ]) {
                    echo '\u2705 \u001B[32mLog Collection (OAI UE - Run)\u001B[0m'
                    sh "python3 ci-scripts/main.py --mode=LogCollectOAIUE --UEIPAddress=${params.UE_IPAddress} --UEUserName=${UE_Username} --UEPassword=${UE_Password} --UESourceCodePath=${params.UE_SourceCodePath}"

                    echo '\u2705 \u001B[32mLog Transfer (OAI UE - Run)\u001B[0m'
                    sh "sshpass -p \'${UE_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${UE_Username}@${params.UE_IPAddress}:${UE_SourceCodePath}/cmake_targets/ue.log.zip ./ue.log.${env.BUILD_ID}.zip || true"
                  }
                  script {
                      if(fileExists("ue.log.${env.BUILD_ID}.zip")) {
                            archiveArtifacts "ue.log.${env.BUILD_ID}.zip"
                      }
                  }
            }
        }
        stage('Log Collection (CN)') {
          // Bypassing this stage if EPC server is not defined
          when {
            expression { params.EPC_IPAddress != "none" }
          }
          steps {
            script {
              withCredentials([
                   [$class: 'UsernamePasswordMultiBinding', credentialsId: "${params.EPC_Credentials}", usernameVariable: 'EPC_Username', passwordVariable: 'EPC_Password']
              ]) {
                echo '\u2705 \u001B[32mLog Collection (HSS)\u001B[0m'
                sh "python3 ci-scripts/main.py --mode=LogCollectHSS --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --EPCType=${params.EPC_Type}"
                if (params.EPC_Type != 'OAICN5G') {
                  sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/hss.log.zip ./hss.log.${env.BUILD_ID}.zip || true"
                }
                echo '\u2705 \u001B[32mLog Collection (MME or AMF)\u001B[0m'
                sh "python3 ci-scripts/main.py --mode=LogCollectMME --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --EPCType=${params.EPC_Type}"
                if (params.EPC_Type == 'OAICN5G') {
                  sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/mme.log.zip ./amf.log.${env.BUILD_ID}.zip || true"
                } else {
                  sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/mme.log.zip ./mme.log.${env.BUILD_ID}.zip || true"
                }
                echo '\u2705 \u001B[32mLog Collection (SPGW or SMF/UPF)\u001B[0m'
                sh "python3 ci-scripts/main.py --mode=LogCollectSPGW --EPCIPAddress=${params.EPC_IPAddress} --EPCUserName=${EPC_Username} --EPCPassword=${EPC_Password} --EPCSourceCodePath=${params.EPC_SourceCodePath} --EPCType=${params.EPC_Type}"
                if (params.EPC_Type == 'OAICN5G') {
                  sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/spgw.log.zip ./smf-upf.log.${env.BUILD_ID}.zip || true"
                } else {
                  sh "sshpass -p \'${EPC_Password}\' scp -o 'StrictHostKeyChecking no' -o 'ConnectTimeout 10' ${EPC_Username}@${params.EPC_IPAddress}:${EPC_SourceCodePath}/scripts/spgw.log.zip ./spgw.log.${env.BUILD_ID}.zip || true"
                }
              }
              if(fileExists("hss.log.${env.BUILD_ID}.zip")) {
                archiveArtifacts "hss.log.${env.BUILD_ID}.zip"
              }
              if(fileExists("mme.log.${env.BUILD_ID}.zip")) {
                archiveArtifacts "mme.log.${env.BUILD_ID}.zip"
              }
              if(fileExists("spgw.log.${env.BUILD_ID}.zip")) {
                archiveArtifacts "spgw.log.${env.BUILD_ID}.zip"
              }
              if(fileExists("amf.log.${env.BUILD_ID}.zip")) {
                archiveArtifacts "amf.log.${env.BUILD_ID}.zip"
              }
              if(fileExists("smf-upf.log.${env.BUILD_ID}.zip")) {
                archiveArtifacts "smf-upf.log.${env.BUILD_ID}.zip"
              }
              echo '\u2705 \u001B[32mLog Collection for CoreNetwork Done!\u001B[0m'
            }
          }
        }
      }
    }
  }

  post {
    always {
      script {
        if(fileExists("ci-scripts/test_results.html")) {
          sh "mv ci-scripts/test_results.html test_results-${JOB_NAME}.html"
          sh "sed -i -e 's#TEMPLATE_JOB_NAME#${JOB_NAME}#' -e 's@build #TEMPLATE_BUILD_ID@build #${BUILD_ID}@' -e 's#Build-ID: TEMPLATE_BUILD_ID#Build-ID: <a href=\"${BUILD_URL}\">${BUILD_ID}</a>#' -e 's#TEMPLATE_STAGE_NAME#${testStageName}#' test_results-${JOB_NAME}.html"
          archiveArtifacts "test_results-${JOB_NAME}.html"
        }
        if (params.pipelineZipsConsoleLog != null) {
          if (params.pipelineZipsConsoleLog) {
            echo "Archiving Jenkins console log"
            sh "wget --no-check-certificate --no-proxy ${env.JENKINS_URL}/job/${env.JOB_NAME}/${env.BUILD_ID}/consoleText -O consoleText.log || true"
            sh "zip -m consoleText.log.${env.BUILD_ID}.zip consoleText.log || true"
            if(fileExists("consoleText.log.${env.BUILD_ID}.zip")) {
              archiveArtifacts "consoleText.log.${env.BUILD_ID}.zip"
            }
          }
        }
      }
    }
  }
}
