82 lines
3.9 KiB
Python
82 lines
3.9 KiB
Python
# -*- coding: utf-8 -*-
|
||
import json
|
||
|
||
import requests
|
||
from requests.auth import HTTPBasicAuth
|
||
|
||
from const import JENKINS_BASE_URL, JENKINS_DEFAULT_JOB, JENKINS_TOKEN, JENKINS_USER
|
||
from logger import logger
|
||
|
||
|
||
class JenkinsRequest(object):
|
||
def __init__(self, jenkins_url=None, username=None, password=None):
|
||
if jenkins_url:
|
||
self.base_url = jenkins_url.rstrip('/')
|
||
use_username = username or JENKINS_USER or 'jenkins'
|
||
use_password = password or JENKINS_TOKEN or 'jenkins'
|
||
self.auth = HTTPBasicAuth(use_username, use_password)
|
||
else:
|
||
self.base_url = JENKINS_BASE_URL.rstrip('/')
|
||
self.auth = HTTPBasicAuth(JENKINS_USER, JENKINS_TOKEN) if JENKINS_USER and JENKINS_TOKEN else None
|
||
self.session = requests.Session()
|
||
self.session.auth = self.auth
|
||
logger.info(f'Jenkins配置: base_url={self.base_url}, username={use_username if jenkins_url else JENKINS_USER}')
|
||
|
||
def get_crumb(self):
|
||
if not self.base_url:
|
||
return {}
|
||
|
||
crumb_url = f'{self.base_url}/crumbIssuer/api/json'
|
||
try:
|
||
response = self.session.get(crumb_url, timeout=30)
|
||
if response.status_code != 200:
|
||
logger.warning(f'获取Jenkins crumb失败:status={response.status_code}')
|
||
return {}
|
||
crumb_data = response.json()
|
||
if crumb_data.get('crumbRequestField') and crumb_data.get('crumb'):
|
||
logger.info(f'成功获取Jenkins crumb: {crumb_data["crumbRequestField"]}')
|
||
return {crumb_data['crumbRequestField']: crumb_data['crumb']}
|
||
except Exception as err:
|
||
logger.warning(f'获取Jenkins crumb失败:{err}')
|
||
return {}
|
||
|
||
def build_with_parameters(self, params, job_name=None):
|
||
job_name = job_name or JENKINS_DEFAULT_JOB
|
||
if not self.base_url or not job_name:
|
||
return False, 'Jenkins配置不完整', {}
|
||
|
||
url = f'{self.base_url}/job/{job_name}/buildWithParameters'
|
||
headers = self.get_crumb()
|
||
headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
|
||
|
||
logger.info(f'Jenkins构建请求: url={url}, params={json.dumps(params, ensure_ascii=False)}')
|
||
|
||
try:
|
||
response = self.session.post(url, data=params, headers=headers, timeout=60)
|
||
if response.status_code not in (200, 201, 202):
|
||
logger.error(f'Jenkins触发失败:status={response.status_code}, body={response.text[:500]}')
|
||
|
||
if response.status_code == 403 and 'crumb' in response.text:
|
||
logger.info('Crumb失效,尝试重新获取并重试...')
|
||
headers = self.get_crumb()
|
||
headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
|
||
response = self.session.post(url, data=params, headers=headers, timeout=60)
|
||
|
||
if response.status_code not in (200, 201, 202):
|
||
logger.error(f'Jenkins触发失败(重试后):status={response.status_code}')
|
||
return False, f'Jenkins触发失败:{response.status_code}', {}
|
||
|
||
location = response.headers.get('Location', '')
|
||
queue_id = None
|
||
if '/queue/item/' in location:
|
||
try:
|
||
queue_id = int(location.rstrip('/').split('/')[-1])
|
||
except Exception:
|
||
queue_id = None
|
||
|
||
logger.info(f'Jenkins构建成功:queue_id={queue_id}, location={location}')
|
||
return True, '', {'job_name': job_name, 'queue_id': queue_id, 'location': location}
|
||
|
||
except Exception as err:
|
||
logger.error(f'Jenkins请求异常:{err}, params={json.dumps(params, ensure_ascii=False)}')
|
||
return False, str(err), {} |