14
from jenkinsapi.jenkins import Jenkins
15
from jenkinsapi.custom_exceptions import JenkinsAPIException
17
log = logging.getLogger(__name__)
20
class FailedToStart(Exception):
24
class TimeOut(Exception):
28
class StreamThread(threading.Thread):
30
def __init__(self, name, q, stream, fn_log):
31
threading.Thread.__init__(self)
38
log.info("Starting %s", self.name)
41
line = self.stream.readline()
43
self.fn_log(line.rstrip())
44
self.q.put((self.name, line))
47
self.q.put((self.name, None))
50
class JenkinsLancher(object):
55
JENKINS_WAR_URL = "http://mirrors.jenkins-ci.org/war/latest/jenkins.war"
57
def __init__(self, war_path, plugin_urls=None):
58
self.war_path = war_path
59
self.war_directory, self.war_filename = os.path.split(self.war_path)
60
self.jenkins_home = tempfile.mkdtemp(prefix='jenkins-home-')
61
self.jenkins_process = None
62
self.q = Queue.Queue()
63
self.plugin_urls = plugin_urls or []
64
self.http_port = random.randint(9000, 10000)
67
os.chdir(self.war_directory)
68
if os.path.exists(self.war_path):
69
log.info("We already have the War file...")
71
log.info("Redownloading Jenkins")
72
subprocess.check_call('./get-jenkins-war.sh')
74
def update_config(self):
75
config_dest = os.path.join(self.jenkins_home, 'config.xml')
76
config_dest_file = open(config_dest, 'w')
77
config_source = pkg_resources.resource_string('jenkinsapi_tests.systests', 'config.xml')
78
config_dest_file.write(config_source.encode('UTF-8'))
80
def install_plugins(self):
81
for i, url in enumerate(self.plugin_urls):
82
self.install_plugin(url, i)
84
def install_plugin(self, hpi_url, i):
85
plugin_dir = os.path.join(self.jenkins_home, 'plugins')
86
if not os.path.exists(plugin_dir):
89
log.info("Downloading %s", hpi_url)
90
log.info("Plugins will be installed in '%s'" % plugin_dir)
91
# FIXME: This is kinda ugly but works
92
filename = "plugin_%s.hpi" % i
93
plugin_path = os.path.join(plugin_dir, filename)
94
with open(plugin_path, 'wb') as h:
95
request = requests.get(hpi_url)
96
h.write(request.content)
99
log.info("Shutting down jenkins.")
100
self.jenkins_process.terminate()
101
self.jenkins_process.wait()
102
shutil.rmtree(self.jenkins_home)
104
def block_until_jenkins_ready(self, timeout):
105
start_time = datetime.datetime.now()
106
timeout_time = start_time + datetime.timedelta(seconds=timeout)
110
Jenkins('http://localhost:8080')
111
log.info('Jenkins is finally ready for use.')
112
except JenkinsAPIException:
113
log.info('Jenkins is not yet ready...')
114
if datetime.datetime.now() > timeout_time:
115
raise TimeOut('Took too long for Jenkins to become ready...')
118
def start(self, timeout=60):
121
self.install_plugins()
123
os.environ['JENKINS_HOME'] = self.jenkins_home
124
os.chdir(self.war_directory)
126
jenkins_command = ['java', '-jar', self.war_filename,
127
'--httpPort=%d' % self.http_port]
129
log.info("About to start Jenkins...")
130
log.info("%s> %s", os.getcwd(), " ".join(jenkins_command))
131
self.jenkins_process = subprocess.Popen(
132
jenkins_command, stdin=subprocess.PIPE,
133
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
136
StreamThread('out', self.q, self.jenkins_process.stdout, log.info),
137
StreamThread('err', self.q, self.jenkins_process.stderr, log.warn)
146
streamName, line = self.q.get(block=True, timeout=timeout)
148
log.warn("Input ended unexpectedly")
152
if 'Failed to initialize Jenkins' in line:
153
raise FailedToStart(line)
155
if 'Invalid or corrupt jarfile' in line:
156
raise FailedToStart(line)
158
if 'is fully up and running' in line:
162
log.warn('Stream %s has terminated', streamName)
164
self.block_until_jenkins_ready(timeout)
167
if __name__ == '__main__':
168
logging.basicConfig()
169
logging.getLogger('').setLevel(logging.INFO)
174
'/home/sal/workspace/jenkinsapi/src/jenkinsapi_tests/systests/jenkins.war'
177
log.info("Jenkins was launched...")
181
log.info("...now to shut it down!")