def get_running_builds(server: Jenkins):
    # running_builds = []
    # get all running builds so we know if a duplicate job is already running
    running_builds = server.get_running_builds()
    queued_builds = server.get_queue_info()

    builds_with_params = []

    for build in queued_builds:
        if "task" in build and "name" in build["task"]:
            try:
                parameters = parameters_from_actions(build["actions"])
                builds_with_params.append({
                    "name": build["task"]["name"],
                    "parameters": parameters
                })
            except Exception:
                traceback.print_exc()

    for build in running_builds:
        try:
            parameters = parameters_for_job(server, build['name'],
                                            build['number'])
            builds_with_params.append({
                "name": build['name'],
                "number": build['number'],
                "parameters": parameters
            })
        except Exception:
            traceback.print_exc()

    return builds_with_params
Esempio n. 2
0
class JenkinsBot(BotPlugin):
    """JenkinsBot is an Err plugin to manage Jenkins CI jobs from your chat platform like Slack."""
    def __init__(self, bot):
        self.jenkins = Jenkins(JENKINS_URL, JENKINS_USERNAME, JENKINS_PASSWORD)
        super().__init__(bot)

    @botcmd(split_args_with=None)
    def jenkins_build(self, msg, args):
        """Build the job specified by jobName. You can add params!"""

        # Params are passed like "key1=value1 key2=value2"
        params = {}
        try:
            for arg in args[1:]:
                params[arg.split('=', 1)[0]] = arg.split('=', 1)[1]
        except IndexError:
            return "I don't like that params! Try with this format: key1=value1 key2=value2..."

        try:
            self.jenkins.build_job(args[0].strip(), params)
        except NotFoundException:
            return "Sorry, I can't find the job. Typo maybe?"

        return ' '.join([
            "The job", args[0].strip(),
            "has been sent to the queue to be built."
        ])

    @botcmd
    def jenkins_cancel(self, msg, args):
        """Cancel a job in the queue by jobId."""

        try:
            self.jenkins.cancel_queue(args.strip())
        except NotFoundException:
            return "Sorry, I can't find the job. Maybe the ID does not exist."

        return "Job canceled from the queue."

    @botcmd
    def jenkins_list(self, msg, args):
        """List Jenkins jobs. You can filter with strings."""

        self.send(msg.to, "I'm getting the jobs list from Jenkins...")

        search_term = args.strip().lower()
        jobs = [
            job for job in self.jenkins.get_jobs()
            if search_term.lower() in job['name'].lower()
        ]

        return self.format_jobs(jobs)

    @botcmd
    def jenkins_describe(self, msg, args):
        """Describe the job specified by jobName."""

        try:
            job = self.jenkins.get_job_info(args.strip())
        except NotFoundException:
            return "Sorry, I can't find the job. Typo maybe?"

        return ''.join([
            'Name: ', job['name'], '\n', 'URL: ', job['url'], '\n',
            'Description: ',
            'None' if job['description'] is None else job['description'], '\n',
            'Next Build Number: ',
            str('None'
                if job['nextBuildNumber'] is None else job['nextBuildNumber']),
            '\n', 'Last Successful Build Number: ',
            str('None' if job['lastBuild'] is None else job['lastBuild']
                ['number']), '\n', 'Last Successful Build URL: ',
            'None' if job['lastBuild'] is None else job['lastBuild']['url'],
            '\n'
        ])

    @botcmd
    def jenkins_running(self, msg, args):
        """List running jobs."""

        self.send(msg.to, "I will ask for the current running builds list!")

        jobs = self.jenkins.get_running_builds()

        return self.format_running_jobs(jobs)

    @botcmd(split_args_with=None)
    def jenkins_stop(self, msg, args):
        """Stop the building job specified by jobName and jobNumber."""

        try:
            int(args[1].strip())
        except ValueError:
            return "You have to specify the jobNumber: \"!jenkins stop <jobName> <jobNumber>"

        try:
            self.jenkins.stop_build(args[0].strip(), int(args[1].strip()))
        except NotFoundException:
            return "Sorry, I can't find the job. Typo maybe?"

        return ' '.join(["The job", args[0].strip(), "has been stopped."])

    @botcmd
    def jenkins_queue(self, msg, args):
        """List jobs in queue."""

        self.send(msg.to, "Getting the job queue...")

        jobs = self.jenkins.get_queue_info()

        return self.format_queue_jobs(jobs)

    def format_jobs(self, jobs):
        """Format jobs list"""

        if len(jobs) == 0:
            return "I haven't found any job."

        max_length = max([len(job['name']) for job in jobs])
        return '\n'.join([
            '%s (%s)' % (job['name'].ljust(max_length), job['url'])
            for job in jobs
        ]).strip()

    def format_queue_jobs(self, jobs):
        """Format queue jobs list"""

        if len(jobs) == 0:
            return "It seems that there is not jobs in queue."

        return '\n'.join([
            '%s - %s (%s)' %
            (str(job['id']), job['task']['name'], job['task']['url'])
            for job in jobs
        ]).strip()

    def format_running_jobs(self, jobs):
        """Format running jobs list"""

        if len(jobs) == 0:
            return "There is no running jobs!"

        return '\n'.join([
            '%s - %s (%s) - %s' %
            (str(job['number']), job['name'], job['url'], job['executor'])
            for job in jobs
        ]).strip()
class JenkinsNotifier(BotPlugin):
    """JenkinsBot is an Err plugin to manage Jenkins CI jobs from your chat platform like Slack."""

    status = {'blue':'SUCCESS', 'blue_anime':'IN PROGRESS','red': 'FAILED', 'red_anime': 'IN PROGRESS', 'disabled':   'DISABLED', 'aborted':'ABORTED', 'notbuilt': 'NOTBUILT', 'yellow': 'UNSTABLE'}
    failedjobsstring = " "


    def __init__(self, bot, name):
        self.jenkins = Jenkins(JENKINS_URL, JENKINS_USERNAME, JENKINS_TOKEN)
        super().__init__(bot, name) 


    @botcmd(split_args_with=None)
    def jn_build(self, msg, args):
        """Build the job specified by jobName. You can add params!"""

        # Params are passed like "key1=value1 key2=value2"
        params = {}
        #try:
        #    for arg in args[1:]:
        #        params[arg.split('=', 1)[0]] = arg.split('=', 1)[1]
        #except IndexError:
        #    return "I don'G like that params! Try with this format: key1=value1 key2=value2..."
        jobName = ''.join([args[0],' ',args[1]]) #TODO handle jobname with spaces in it, space is cosidered argument splitter  
        try:
            self.jenkins.build_job(jobName, params)
        except NotFoundException:
            return ' '.join(["Sorry, I can't find the job. Typo maybe?"," ARGS=",jobName])

        return ' '.join(["The job", args[0].strip(), "has been sent to the queue to be built."])


    @botcmd
    def jn_cancel(self, msg, args):
        """Cancel a job in the queue by jobId."""

        try:
            self.jenkins.cancel_queue(args.strip())
        except NotFoundException:
            return "Sorry, I can't find the job. Maybe the ID does not exist."

        return "Job canceled from the queue."


    @botcmd
    def jn_list(self, msg, args):
        """List Jenkins jobs. You can filter with strings."""

        self.send(msg.to, "I'm getting the jobs list from Jenkins...")

        search_term = args.strip().lower()
        jobs = [job for job in self.jenkins.get_jobs()
                if search_term.lower() in job['name'].lower()]

        return self.format_jobs(jobs)


    @botcmd
    def jn_status(self, msg, args):
        """List Jenkins jobs with their current status."""

        self.send(msg.to, "I'm getting the jobs with status Jenkins...")

        search_term = args.strip().lower()
        jobs = [job for job in self.jenkins.get_jobs()
                if search_term.lower() in job['fullname'].lower()]

        return self.format_job_status(jobs)




    @botcmd
    def jn_describe(self, msg, args):
        """Describe the job specified by jobName."""

        try:
            job = self.jenkins.get_job_info(args.strip())
        except NotFoundException:
            return "Sorry, I can't find the job. Typo maybe?"

        return ''.join([
            'Name: ', job['name'], '\n',
            'URL: ', job['url'], '\n',
            'Description: ', 'None' if job['description'] is None else job['description'], '\n',
            'Next Build Number: ',
            str('None' if job['nextBuildNumber'] is None else job['nextBuildNumber']), '\n',
            'Last Successful Build Number: ',
            str('None' if job['lastBuild'] is None else job['lastBuild']['number']), '\n',
            'Last Successful Build URL: ',
            'None' if job['lastBuild'] is None else job['lastBuild']['url'], '\n'
        ])


    @botcmd
    def jn_running(self, msg, args):
        """List running jobs."""

        self.send(msg.to, "I will ask for the current running builds list!")

        jobs = self.jenkins.get_running_builds()

        return self.format_running_jobs(jobs)


    @botcmd(split_args_with=None)
    def jn_stop(self, msg, args):
        """Stop the building job specified by jobName and jobNumber."""

        try:
            int(args[1].strip())
        except ValueError:
            return "You have to specify the jobNumber: \"!jenkins stop <jobName> <jobNumber>"

        try:
            self.jenkins.stop_build(args[0].strip(), int(args[1].strip()))
        except NotFoundException:
            return "Sorry, I can't find the job. Typo maybe?"

        return ' '.join(["The job", args[0].strip(), "has been stopped."])


    @botcmd
    def jn_queue(self, msg, args):
        """List jobs in queue."""

        self.send(msg.to, "Getting the job queue...")

        jobs = self.jenkins.get_queue_info()

        return self.format_queue_jobs(jobs)


    @botcmd
    def jn_msgtimer(self, msg, args):
        """Sends messages at fix intervals."""
        yield "Starting timer"
        self.start_poller(5, self.my_callback)
        self.send(msg.to,
        "Boo! Bet you weren't expecting me, were you?", 
        )


    def my_callback(self):
        self.log.info('I am called every 5sec')
        self.send(self.build_identifier("#errbottestchannel"), "I am called every 5sec", )

    @botcmd 
    def jn_failed(self, msg, args):

        """List Jenkins jobs with failed status."""
        self.send(msg.to, "I'm getting the failed jobs ...")
        failedJobs = []
        search_term = args.strip().lower()
        jobs = [job for job in self.jenkins.get_jobs()
                if search_term.lower() in job['fullname'].lower()]
        for job in jobs:
            if self.status[job['color']] == 'FAILED':
               failedJobs.append(job)
        return self.format_job_status(failedJobs)



# SUPPORT FUNCTIONS START HERE

    def format_jobs(self, jobs):
        """Format jobs list"""

        if len(jobs) == 0:
            return "I haven't found any job."

        max_length = max([len(job['name']) for job in jobs])
        return '\n'.join(['%s (%s)' % (job['name'].ljust(max_length),
                                       job['url']) for job in jobs]).strip()


    def format_queue_jobs(self, jobs):
        """Format queue jobs list"""

        if len(jobs) == 0:
            return "It seems that there is not jobs in queue."

        return '\n'.join(['%s - %s (%s)' % (str(job['id']),
                                            job['task']['name'],
                                            job['task']['url']) for job in jobs]).strip()


    def format_running_jobs(self, jobs):
        """Format running jobs list"""

        if len(jobs) == 0:
            return "There is no running jobs!"

        return '\n'.join(['%s - %s (%s) - %s' % (str(job['number']),
                                                 job['name'],
                                                 job['url'],
                                                 job['executor']) for job in jobs]).strip()

    @botcmd
    def jn_queue(self, msg, args):
        """List jobs in queue."""

        self.send(msg.to, "Getting the job queue...")

        jobs = self.jenkins.get_queue_info()

        return self.format_queue_jobs(jobs)


    def format_jobs(self, jobs):
        """Format jobs list"""

        if len(jobs) == 0:
            return "I haven't found any job."

        max_length = max([len(job['name']) for job in jobs])
        return '\n'.join(['%s (%s)' % (job['name'].ljust(max_length),
                                       job['url']) for job in jobs]).strip()


    def format_queue_jobs(self, jobs):
        """Format queue jobs list"""

        if len(jobs) == 0:
            return "It seems that there is not jobs in queue."

        return '\n'.join(['%s - %s (%s)' % (str(job['id']),
                                            job['task']['name'],
                                            job['task']['url']) for job in jobs]).strip()


    def format_running_jobs(self, jobs):
        """Format running jobs list"""

        if len(jobs) == 0:
            return "There is no running jobs!"

        return '\n'.join(['%s - %s (%s) - %s' % (str(job['number']),
                                                 job['name'],
                                                 job['url'],
                                                 job['executor']) for job in jobs]).strip()

    def format_job_status(self, jobs):
        """Format job status"""

        if len(jobs) == 0:
            return "there are no jobs to return"
        return '\n'.join(['%s (%s)' % (job['fullname'], self.status[job['color']]) for job in jobs]).strip()
Esempio n. 4
0
def main():
    module_args = {
        'api': {
            'type': 'str',
            'required': False
        },
        'wait_for': {
            'type':    'str',
            'required': False,
        },
    }

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    result = { 
        'changed' :False,
    }

    # format: <github-user>:<github-token>
    auth_file = path.join(Path.home(), ".jenkins/auth")
    with open(auth_file) as af:
        auth = [line.strip() for line in af if not line.strip().startswith("#")]
    github_user, github_token = auth[0].split(":")

    # jenkins server name
    instance = environ['INSTANCE']
    workspace = environ['WORKSPACE']
    domain = environ['DOMAIN']
    server_name = f'https://jenkins-{instance}.{workspace}.{domain}'

    server = Jenkins(server_name, username=github_user, password=github_token, timeout=10)

    if module.params['api']:
        info, _ = inspect_server(server, result)

        if module.params['api'] == "/quietDown":
            if info['quietingDown'] == True:
                module.exit_json(**result)  # Already quiesced
            if not module.check_mode:
                server.quiet_down()
            result['changed'] = True
            module.exit_json(**result)
    elif module.params['wait_for']:
        if module.params['wait_for'] == 'normal_operation':
            info = {}
            try:
                info, _ = inspect_server(server, result)
            except:
                pass

            if 'mode' in info and info['mode'] == "NORMAL":
                serverAPI = jenkinsapi.jenkins.Jenkins(server_name, username=github_user, password=github_token, timeout=10, useCrumb=True)
                if serverAPI.is_quieting_down:
                    serverAPI.cancel_quiet_down()
                    result['changed'] = True
                module.exit_json(**result)  # Already operating normally
            if server.wait_for_normal_op(NORMAL_TIMEOUT):
                result['changed'] = True
                module.exit_json(**result)  # Successfully waited
            else:  # Waiting failed
                module.fail_json(msg=f'Timeout waiting for server transition to NORMAL operation mode ({NORMAL_TIMEOUT}s)', **result)
        elif module.params['wait_for'] == 'running_jobs':
            info, _ = inspect_server(server, result)

            running_builds = server.get_running_builds()
            if len(running_builds) == 0:
                module.exit_json(**result)  # No jobs running
            else:
                result['changed'] = True
                if not module.check_mode:
                    _start = time()
                    while time() < _start + RUNNING_JOBS_TIMEOUT:
                        running_builds = server.get_running_builds()
                        if len(running_builds) == 0:
                            module.exit_json(**result)  # Successfully waited for running jobs to end
            # Jobs still running, fail
            module.fail_json(msg=f'Timeout waiting for running jobs to complete ({RUNNING_JOBS_TIMEOUT}s)', **result)