mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-14 11:03:09 +02:00
ccc1c976ee
* Reorders getApiInformation, changes variables to get start time, adjusts and adds test cases * Changes the way to get apiInformation and reduces number of requests * Changes getting pipeline start time from correct env variable * Refactors getApiInformation functionality * Adds GetBuildReason() for Azure and Jenkins * Updates JobURL for ADO
232 lines
7.4 KiB
Go
232 lines
7.4 KiB
Go
package orchestrator
|
|
|
|
import (
|
|
"encoding/json"
|
|
"github.com/Jeffail/gabs/v2"
|
|
piperHttp "github.com/SAP/jenkins-library/pkg/http"
|
|
"github.com/SAP/jenkins-library/pkg/log"
|
|
"github.com/pkg/errors"
|
|
"io/ioutil"
|
|
"time"
|
|
)
|
|
|
|
type JenkinsConfigProvider struct {
|
|
client piperHttp.Client
|
|
options piperHttp.ClientOptions
|
|
apiInformation map[string]interface{}
|
|
}
|
|
|
|
// InitOrchestratorProvider initializes the Jenkins orchestrator with credentials
|
|
func (j *JenkinsConfigProvider) InitOrchestratorProvider(settings *OrchestratorSettings) {
|
|
j.client = piperHttp.Client{}
|
|
j.options = piperHttp.ClientOptions{
|
|
Username: settings.JenkinsUser,
|
|
Password: settings.JenkinsToken,
|
|
MaxRetries: 3,
|
|
TransportTimeout: time.Second * 10,
|
|
}
|
|
j.client.SetOptions(j.options)
|
|
log.Entry().Debug("Successfully initialized Jenkins config provider")
|
|
}
|
|
|
|
// OrchestratorVersion returns the orchestrator version currently running on
|
|
func (j *JenkinsConfigProvider) OrchestratorVersion() string {
|
|
return getEnv("JENKINS_VERSION", "n/a")
|
|
}
|
|
|
|
// OrchestratorType returns the orchestrator type Jenkins
|
|
func (j *JenkinsConfigProvider) OrchestratorType() string {
|
|
return "Jenkins"
|
|
}
|
|
|
|
func (j *JenkinsConfigProvider) fetchAPIInformation() {
|
|
if len(j.apiInformation) == 0 {
|
|
log.Entry().Debugf("apiInformation is empty, getting infos from API")
|
|
URL := j.GetBuildURL() + "api/json"
|
|
log.Entry().Debugf("API URL: %s", URL)
|
|
response, err := j.client.GetRequest(URL, nil, nil)
|
|
if err != nil {
|
|
log.Entry().WithError(err).Error("could not get API information from Jenkins")
|
|
j.apiInformation = map[string]interface{}{}
|
|
return
|
|
}
|
|
|
|
if response.StatusCode != 200 { //http.StatusNoContent
|
|
log.Entry().Errorf("Response-Code is %v, could not get timestamp from Jenkins. Setting timestamp to 1970.", response.StatusCode)
|
|
j.apiInformation = map[string]interface{}{}
|
|
return
|
|
}
|
|
err = piperHttp.ParseHTTPResponseBodyJSON(response, &j.apiInformation)
|
|
if err != nil {
|
|
log.Entry().WithError(err).Errorf("could not parse HTTP response body")
|
|
j.apiInformation = map[string]interface{}{}
|
|
return
|
|
}
|
|
log.Entry().Debugf("successfully retrieved apiInformation")
|
|
} else {
|
|
log.Entry().Debugf("apiInformation already set")
|
|
}
|
|
}
|
|
|
|
// GetBuildStatus returns build status of the current job
|
|
func (j *JenkinsConfigProvider) GetBuildStatus() string {
|
|
j.fetchAPIInformation()
|
|
if val, ok := j.apiInformation["result"]; ok {
|
|
// cases in ADO: succeeded, failed, canceled, none, partiallySucceeded
|
|
switch result := val; result {
|
|
case "SUCCESS":
|
|
return "SUCCESS"
|
|
case "ABORTED":
|
|
return "ABORTED"
|
|
default:
|
|
// FAILURE, NOT_BUILT
|
|
return "FAILURE"
|
|
}
|
|
}
|
|
return "FAILURE"
|
|
}
|
|
|
|
// GetLog returns the logfile from the current job as byte object
|
|
func (j *JenkinsConfigProvider) GetLog() ([]byte, error) {
|
|
URL := j.GetBuildURL() + "consoleText"
|
|
|
|
response, err := j.client.GetRequest(URL, nil, nil)
|
|
if err != nil {
|
|
return []byte{}, errors.Wrapf(err, "could not GET Jenkins log file %v", err)
|
|
} else if response.StatusCode != 200 {
|
|
log.Entry().Error("response code !=200 could not get log information from Jenkins, returning with empty log.")
|
|
return []byte{}, nil
|
|
}
|
|
logFile, err := ioutil.ReadAll(response.Body)
|
|
if err != nil {
|
|
return []byte{}, errors.Wrapf(err, "could not read Jenkins log file from request %v", err)
|
|
}
|
|
defer response.Body.Close()
|
|
return logFile, nil
|
|
}
|
|
|
|
// GetPipelineStartTime returns the pipeline start time in UTC
|
|
func (j *JenkinsConfigProvider) GetPipelineStartTime() time.Time {
|
|
URL := j.GetBuildURL() + "api/json"
|
|
response, err := j.client.GetRequest(URL, nil, nil)
|
|
if err != nil {
|
|
log.Entry().WithError(err).Errorf("could not getRequest to URL %s", URL)
|
|
return time.Time{}.UTC()
|
|
}
|
|
|
|
if response.StatusCode != 200 { //http.StatusNoContent -> also empty log!
|
|
log.Entry().Errorf("response code is %v . \n Could not get timestamp from Jenkins. Setting timestamp to 1970.", response.StatusCode)
|
|
return time.Time{}.UTC()
|
|
}
|
|
var responseInterface map[string]interface{}
|
|
err = piperHttp.ParseHTTPResponseBodyJSON(response, &responseInterface)
|
|
if err != nil {
|
|
log.Entry().WithError(err).Infof("could not parse http response, returning 1970")
|
|
return time.Time{}.UTC()
|
|
}
|
|
|
|
rawTimeStamp := responseInterface["timestamp"].(float64)
|
|
timeStamp := time.Unix(int64(rawTimeStamp)/1000, 0)
|
|
|
|
log.Entry().Debugf("Pipeline start time: %v", timeStamp.String())
|
|
defer response.Body.Close()
|
|
return timeStamp.UTC()
|
|
}
|
|
|
|
// GetJobName returns the job name of the current job e.g. foo/bar/BRANCH
|
|
func (j *JenkinsConfigProvider) GetJobName() string {
|
|
return getEnv("JOB_NAME", "n/a")
|
|
}
|
|
|
|
// GetJobURL returns the current job URL e.g. https://jaas.url/job/foo/job/bar/job/main
|
|
func (j *JenkinsConfigProvider) GetJobURL() string {
|
|
return getEnv("JOB_URL", "n/a")
|
|
}
|
|
|
|
// getJenkinsHome returns the jenkins home e.g. /var/lib/jenkins
|
|
func (j *JenkinsConfigProvider) getJenkinsHome() string {
|
|
return getEnv("JENKINS_HOME", "n/a")
|
|
}
|
|
|
|
// GetBuildID returns the build ID of the current job, e.g. 1234
|
|
func (j *JenkinsConfigProvider) GetBuildID() string {
|
|
return getEnv("BUILD_ID", "n/a")
|
|
}
|
|
|
|
// GetStageName returns the stage name the job is currently in, e.g. Promote
|
|
func (j *JenkinsConfigProvider) GetStageName() string {
|
|
return getEnv("STAGE_NAME", "n/a")
|
|
}
|
|
|
|
//GetBuildReason returns the build reason of the current build
|
|
func (j *JenkinsConfigProvider) GetBuildReason() string {
|
|
j.fetchAPIInformation()
|
|
marshal, err := json.Marshal(j.apiInformation)
|
|
if err != nil {
|
|
log.Entry().WithError(err).Debugf("could not marshal apiInformation")
|
|
return "Unknown"
|
|
}
|
|
jsonParsed, err := gabs.ParseJSON(marshal)
|
|
if err != nil {
|
|
log.Entry().WithError(err).Debugf("could not parse apiInformation")
|
|
return "Unknown"
|
|
}
|
|
for _, child := range jsonParsed.S("actions").Children() {
|
|
class := child.S("_class")
|
|
if class.String() == "\"hudson.model.CauseAction\"" {
|
|
for _, val := range child.S("causes").Children() {
|
|
subclass := val.S("_class")
|
|
if subclass.String() == "\"hudson.model.Cause$UserIdCause\"" {
|
|
return "Manual"
|
|
} else if subclass.String() == "\"hudson.triggers.TimerTrigger$TimerTriggerCause\"" {
|
|
return "Schedule"
|
|
} else {
|
|
return "Unknown"
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return "Unknown"
|
|
}
|
|
|
|
// GetBranch returns the branch name, only works with the git plugin enabled
|
|
func (j *JenkinsConfigProvider) GetBranch() string {
|
|
return getEnv("BRANCH_NAME", "n/a")
|
|
}
|
|
|
|
// GetBuildURL returns the build url, e.g. https://jaas.url/job/foo/job/bar/job/main/1234/
|
|
func (j *JenkinsConfigProvider) GetBuildURL() string {
|
|
return getEnv("BUILD_URL", "n/a")
|
|
}
|
|
|
|
// GetCommit returns the commit SHA from the current build, only works with the git plugin enabled
|
|
func (j *JenkinsConfigProvider) GetCommit() string {
|
|
return getEnv("GIT_COMMIT", "n/a")
|
|
}
|
|
|
|
// GetRepoURL returns the repo URL of the current build, only works with the git plugin enabled
|
|
func (j *JenkinsConfigProvider) GetRepoURL() string {
|
|
return getEnv("GIT_URL", "n/a")
|
|
}
|
|
|
|
// GetPullRequestConfig returns the pull request config
|
|
func (j *JenkinsConfigProvider) GetPullRequestConfig() PullRequestConfig {
|
|
return PullRequestConfig{
|
|
Branch: getEnv("CHANGE_BRANCH", "n/a"),
|
|
Base: getEnv("CHANGE_TARGET", "n/a"),
|
|
Key: getEnv("CHANGE_ID", "n/a"),
|
|
}
|
|
}
|
|
|
|
// IsPullRequest returns boolean indicating if current job is a PR
|
|
func (j *JenkinsConfigProvider) IsPullRequest() bool {
|
|
return truthy("CHANGE_ID")
|
|
}
|
|
|
|
func isJenkins() bool {
|
|
envVars := []string{"JENKINS_HOME", "JENKINS_URL"}
|
|
return areIndicatingEnvVarsSet(envVars)
|
|
}
|