Beispiel #1
0
    def test_create_session_failures(self, tmpdir, auth_type, auth_args,
                                     error_type, should_recover, attempts):
        url = 'https://example.com'
        if auth_args.get('ssl_certs_dir', None) == 'value':
            auth_args['ssl_certs_dir'] = str(tmpdir)

        session = flexmock(_value="test_value")
        (flexmock(koji_util.koji).should_receive('ClientSession').with_args(
            url, opts={
                'krb_rdns': False
            }).and_return(session))

        flexmock(time).should_receive('sleep').and_return(None)

        if should_recover:
            (session.should_receive(auth_type).and_raise(error_type).and_raise(
                error_type).and_return(True))
            test_session = create_koji_session(url, auth_args)
            assert test_session._wrapped_session == session
            assert test_session._value == "test_value"
        else:
            session.should_receive(auth_type).and_raise(error_type).times(
                attempts)
            with pytest.raises(error_type):
                create_koji_session(url, auth_args)
Beispiel #2
0
    def test_fail_authenticated_session(self, tmpdir, ssl_session):
        url = 'https://example.com'
        args = {}

        session = flexmock()
        if ssl_session:
            args['ssl_certs_dir'] = str(tmpdir)
            session.should_receive('ssl_login').once().and_return(False)
        else:
            session.should_receive('krb_login').once().and_return(False)

        (flexmock(koji_util.koji).should_receive('ClientSession').with_args(
            url, opts={'krb_rdns': False}).and_return(session))
        with pytest.raises(RuntimeError):
            create_koji_session(url, args)
Beispiel #3
0
    def run(self):
        base_image = self.workflow.builder.base_image
        if base_image.namespace != 'koji' or base_image.repo != 'image-build':
            self.log.info('Base image not supported: %s', base_image)
            return

        image_build_conf = base_image.tag
        if not image_build_conf or image_build_conf == 'latest':
            image_build_conf = 'image-build.conf'

        self.session = create_koji_session(self.koji_hub, self.koji_auth_info)

        task_id, filesystem_regex = self.build_filesystem(image_build_conf)

        task = TaskWatcher(self.session, task_id, self.poll_interval)
        task.wait()
        if task.failed():
            try:
                # Koji may re-raise the error that caused task to fail
                task_result = self.session.getTaskResult(task_id)
            except Exception as exc:
                task_result = repr(exc)
            raise RuntimeError('image task, {}, failed: {}'.format(
                task_id, task_result))

        filesystem = self.download_filesystem(task_id, filesystem_regex)

        new_base_image = self.import_base_image(filesystem)
        self.workflow.builder.set_base_image(new_base_image)
        defer_removal(self.workflow, new_base_image)

        return {
            'base-image-id': new_base_image,
            'filesystem-koji-task-id': task_id,
        }
    def __init__(self, tasker, workflow, koji_hub, koji_ssl_certs_dir=None,
                 poll_interval=DEFAULT_POLL_INTERVAL, poll_timeout=DEFAULT_POLL_TIMEOUT):
        """
        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param koji_hub: str, koji hub (xmlrpc)
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
                                   used when Koji's identity certificate is not trusted
        :param poll_interval: int, seconds between polling for Koji build
        :param poll_timeout: int, max amount of seconds to wait for Koji build
        """
        super(KojiParentPlugin, self).__init__(tasker, workflow)

        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.koji_session = create_koji_session(koji_hub, koji_auth_info)

        self.poll_interval = poll_interval
        self.poll_timeout = poll_timeout

        self._parent_image_nvr = None
        self._parent_image_build = None
        self._poll_start = None
Beispiel #5
0
    def __init__(self,
                 tasker,
                 workflow,
                 hub,
                 target=None,
                 koji_ssl_certs_dir=None):
        """
        constructor

        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param hub: string, koji hub (xmlrpc)
        :param target: unused - backwards compatibility
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
            Note that this plugin requires koji_ssl_certs_dir set if Koji
            certificate is not trusted by CA bundle.
        """
        # call parent constructor
        super(BumpReleasePlugin, self).__init__(tasker, workflow)
        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.xmlrpc = create_koji_session(hub, koji_auth_info)
    def run(self):
        dockerfile = DockerfileParser(self.workflow.builder.df_path)

        image_name = ImageName.parse(dockerfile.baseimage)
        if image_name.namespace != 'koji' or image_name.repo != 'image-build' :
            self.log.info('Base image not supported: %s', dockerfile.baseimage)
            return
        image_build_conf = image_name.tag or 'image-build.conf'

        self.session = create_koji_session(self.koji_hub, self.koji_auth_info)

        task_id, filesystem_regex = self.build_filesystem(image_build_conf)

        task = TaskWatcher(self.session, task_id, self.poll_interval)
        task.wait()
        if task.failed():
            raise RuntimeError('Create filesystem task failed: {}'
                               .format(task_id))

        filesystem = self.download_filesystem(task_id, filesystem_regex)

        base_image = self.import_base_image(filesystem)
        dockerfile.baseimage = base_image

        return base_image
    def test_create_simple_session(self):
        url = 'https://koji-hub-url.com'
        session = flexmock()

        (flexmock(koji_util.koji).should_receive('ClientSession').with_args(
            url).and_return(session))
        assert create_koji_session(url) == session
    def __init__(self,
                 tasker,
                 workflow,
                 hub,
                 target=None,
                 koji_ssl_certs_dir=None,
                 append=False):
        """
        constructor

        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param hub: string, koji hub (xmlrpc)
        :param target: unused - backwards compatibility
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
            Note that this plugin requires koji_ssl_certs_dir set if Koji
            certificate is not trusted by CA bundle.
        :param append: if True, the release will be obtained by appending a
            '.' and a unique integer to the release label in the dockerfile.
        """
        # call parent constructor
        super(BumpReleasePlugin, self).__init__(tasker, workflow)
        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.xmlrpc = create_koji_session(hub, koji_auth_info)

        self.append = append
    def __init__(self,
                 tasker,
                 workflow,
                 koji_parent_build,
                 koji_hub,
                 koji_ssl_certs_dir=None):
        """
        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param koji_parent_build: str, either Koji build ID or Koji build NVR
        :param koji_hub: str, koji hub (xmlrpc)
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
                                   used when Koji's identity certificate is not trusted
        """
        super(InjectParentImage, self).__init__(tasker, workflow)

        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.koji_session = create_koji_session(koji_hub, koji_auth_info)

        try:
            self.koji_parent_build = int(koji_parent_build)
        except ValueError:
            self.koji_parent_build = koji_parent_build

        self._koji_parent_build_info = None
        self._repositories = None
        self._new_parent_image = None
    def run(self):
        base_image = self.workflow.builder.base_image
        if base_image.namespace != 'koji' or base_image.repo != 'image-build':
            self.log.info('Base image not supported: %s', base_image)
            return

        image_build_conf = base_image.tag
        if not image_build_conf or image_build_conf == 'latest':
            image_build_conf = 'image-build.conf'

        self.session = create_koji_session(self.koji_hub, self.koji_auth_info)

        task_id, filesystem_regex = self.build_filesystem(image_build_conf)

        task = TaskWatcher(self.session, task_id, self.poll_interval)
        task.wait()
        if task.failed():
            raise RuntimeError(
                'Create filesystem task failed: {}'.format(task_id))

        filesystem = self.download_filesystem(task_id, filesystem_regex)

        new_base_image = self.import_base_image(filesystem)
        self.workflow.builder.set_base_image(new_base_image)
        defer_removal(self.workflow, new_base_image)

        return {
            'base-image-id': new_base_image,
            'filesystem-koji-task-id': task_id,
        }
    def __init__(self, tasker, workflow, koji_parent_build, koji_hub, koji_ssl_certs_dir=None):
        """
        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param koji_parent_build: str, either Koji build ID or Koji build NVR
        :param koji_hub: str, koji hub (xmlrpc)
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
                                   used when Koji's identity certificate is not trusted
        """
        super(InjectParentImage, self).__init__(tasker, workflow)

        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.koji_session = create_koji_session(koji_hub, koji_auth_info)

        try:
            self.koji_parent_build = int(koji_parent_build)
        except ValueError:
            self.koji_parent_build = koji_parent_build

        self._koji_parent_build_info = None
        self._repositories = None
        self._new_parent_image = None
    def __init__(self,
                 tasker,
                 workflow,
                 koji_hub,
                 koji_ssl_certs_dir=None,
                 poll_interval=DEFAULT_POLL_INTERVAL,
                 poll_timeout=DEFAULT_POLL_TIMEOUT):
        """
        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param koji_hub: str, koji hub (xmlrpc)
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
                                   used when Koji's identity certificate is not trusted
        :param poll_interval: int, seconds between polling for Koji build
        :param poll_timeout: int, max amount of seconds to wait for Koji build
        """
        super(KojiParentPlugin, self).__init__(tasker, workflow)

        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.koji_session = create_koji_session(koji_hub, koji_auth_info)

        self.poll_interval = poll_interval
        self.poll_timeout = poll_timeout

        self._parent_image_nvr = None
        self._parent_image_build = None
        self._poll_start = None
    def test_create_simple_session(self):
        url = 'https://koji-hub-url.com'
        session = flexmock()

        (flexmock(koji_util.koji)
            .should_receive('ClientSession').with_args(url).and_return(session))
        assert create_koji_session(url) == session
Beispiel #14
0
    def __init__(self,
                 tasker,
                 workflow,
                 target,
                 hub,
                 root,
                 proxy=None,
                 koji_ssl_certs_dir=None):
        """
        constructor

        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param target: string, koji target to use as a source
        :param hub: string, koji hub (xmlrpc)
        :param root: string, koji root (storage)
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
            Note that this plugin requires koji_ssl_certs_dir set if Koji
            certificate is not trusted by CA bundle.
        """
        # call parent constructor
        super(KojiPlugin, self).__init__(tasker, workflow)
        self.target = target
        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.xmlrpc = create_koji_session(hub, koji_auth_info)
        self.pathinfo = koji.PathInfo(topdir=root)
        self.proxy = proxy
Beispiel #15
0
    def test_create_simple_session(self):
        url = 'https://example.com'
        session = flexmock()

        (flexmock(koji_util.koji).should_receive('ClientSession').with_args(
            url, opts={'krb_rdns': False}).and_return(session))
        assert create_koji_session(url)._wrapped_session == session
    def test_create_authenticated_session(self):
        url = 'https://koji-hub-url.com'
        session = flexmock()
        session.should_receive('krb_login').once().and_return(True)

        (flexmock(koji_util.koji)
            .should_receive('ClientSession').with_args(url).and_return(session))
        assert create_koji_session(url, {}) == session
    def test_create_authenticated_session(self):
        url = 'https://koji-hub-url.com'
        session = flexmock()
        session.should_receive('krb_login').once().and_return(True)

        (flexmock(koji_util.koji).should_receive('ClientSession').with_args(
            url).and_return(session))
        assert create_koji_session(url, {}) == session
Beispiel #18
0
    def koji_session(self):
        if not self._koji_session:
            koji_auth_info = None
            if self.koji_ssl_certs_dir:
                koji_auth_info = {
                    'ssl_certs_dir': self.koji_ssl_certs_dir,
                }
            self._koji_session = create_koji_session(self.koji_hub, koji_auth_info)

        return self._koji_session
Beispiel #19
0
    def __init__(self, tasker, workflow, hub, target=None):
        """
        constructor

        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param hub: string, koji hub (xmlrpc)
        :param target: unused - backwards compatibility
        """
        # call parent constructor
        super(BumpReleasePlugin, self).__init__(tasker, workflow)
        self.xmlrpc = create_koji_session(hub)
Beispiel #20
0
    def run(self):
        self.session = create_koji_session(self.koji_info['hub'], self.koji_info.get('auth'))

        nvr_requests = self.read_nvr_requests()
        url_requests = self.read_url_requests()

        download_queue = (self.process_by_nvr(nvr_requests) +
                          self.process_by_url(url_requests))

        self.download_files(download_queue)

        # TODO: Return a list of files for koji metadata
        return download_queue
def get_koji_session(workflow, fallback):
    config = get_koji(workflow, fallback)

    from atomic_reactor.koji_util import create_koji_session

    auth_info = {
        "proxyuser": config['auth'].get('proxyuser'),
        "ssl_certs_dir": config['auth'].get('ssl_certs_dir'),
        "krb_principal": config['auth'].get('krb_principal'),
        "krb_keytab": config['auth'].get('krb_keytab_path')
    }

    return create_koji_session(config['hub_url'], auth_info)
Beispiel #22
0
    def login(self):
        """
        Log in to koji

        :return: koji.ClientSession instance, logged in
        """
        auth_info = {
            "proxyuser": self.koji_proxy_user,
            "ssl_certs_dir": self.koji_ssl_certs,
            "krb_principal": self.koji_principal,
            "krb_keytab": self.koji_keytab
        }
        return create_koji_session(self.kojihub, auth_info)
    def login(self):
        """
        Log in to koji

        :return: koji.ClientSession instance, logged in
        """
        auth_info = {
            "proxyuser": self.koji_proxy_user,
            "ssl_certs_dir": self.koji_ssl_certs,
            "krb_principal": self.koji_principal,
            "krb_keytab": self.koji_keytab
        }
        return create_koji_session(self.kojihub, auth_info)
def get_koji_session(workflow, fallback):
    config = get_koji(workflow, fallback)

    from atomic_reactor.koji_util import create_koji_session

    auth_info = {
        "proxyuser": config['auth'].get('proxyuser'),
        "ssl_certs_dir": config['auth'].get('ssl_certs_dir'),
        "krb_principal": config['auth'].get('krb_principal'),
        "krb_keytab": config['auth'].get('krb_keytab_path')
    }

    return create_koji_session(config['hub_url'], auth_info)
Beispiel #25
0
    def test_create_authenticated_session(self, tmpdir, ssl_session):
        url = 'https://example.com'
        args = {}

        session = flexmock()
        if ssl_session:
            args['ssl_certs_dir'] = str(tmpdir)
            session.should_receive('ssl_login').once().and_return(True)
        else:
            session.should_receive('krb_login').once().and_return(True)

        (flexmock(koji_util.koji).should_receive('ClientSession').with_args(
            url, opts={'krb_rdns': False}).and_return(session))
        assert create_koji_session(url, args)._wrapped_session == session
    def login(self):
        """
        Log in to koji

        :return: koji.ClientSession instance, logged in
        """

        # krbV python library throws an error if these are unicode
        auth_info = {
            "proxyuser": self.koji_proxy_user,
            "ssl_certs_dir": self.koji_ssl_certs,
            "krb_principal": str(self.koji_principal),
            "krb_keytab": str(self.koji_keytab)
        }
        return create_koji_session(str(self.kojihub), auth_info)
    def login(self):
        """
        Log in to koji

        :return: koji.ClientSession instance, logged in
        """

        # krbV python library throws an error if these are unicode
        auth_info = {
            "proxyuser": self.koji_proxy_user,
            "ssl_certs_dir": self.koji_ssl_certs,
            "krb_principal": str(self.koji_principal),
            "krb_keytab": str(self.koji_keytab)
        }
        return create_koji_session(str(self.kojihub), auth_info)
Beispiel #28
0
    def run(self):
        """
        Run the plugin.
        """
        if self.workflow.build_process_failed:
            self.log.info('Build failed, skipping koji tagging')
            return

        build_id = self.workflow.exit_results.get(KojiPromotePlugin.key)
        if not build_id:
            self.log.info('No koji build from %s', KojiPromotePlugin.key)
            return

        session = create_koji_session(self.kojihub, self.koji_auth)
        build_tag = tag_koji_build(session, build_id, self.target,
                                   poll_interval=self.poll_interval)

        return build_tag
    def run(self):
        """
        Run the plugin.
        """
        if self.workflow.build_process_failed:
            self.log.info('Build failed, skipping koji tagging')
            return

        build_id = self.workflow.exit_results.get(KojiImportPlugin.key)
        if not build_id:
            build_id = self.workflow.exit_results.get(KojiPromotePlugin.key)
            if not build_id:
                self.log.info('No koji build from %s or %s', KojiImportPlugin.key,
                              KojiPromotePlugin.key)
                return

        session = create_koji_session(self.kojihub, self.koji_auth)
        build_tag = tag_koji_build(session, build_id, self.target,
                                   poll_interval=self.poll_interval)

        return build_tag
    def run(self):
        base_image = self.workflow.builder.base_image
        if base_image.namespace != 'koji' or base_image.repo != 'image-build':
            self.log.info('Base image not supported: %s', base_image)
            return

        image_build_conf = base_image.tag
        if not image_build_conf or image_build_conf == 'latest':
            image_build_conf = 'image-build.conf'

        self.session = create_koji_session(self.koji_hub, self.koji_auth_info)

        task_id, filesystem_regex = self.run_image_task(image_build_conf)

        new_base_image = None
        if not self.is_orchestrator:
            new_base_image = self.stream_filesystem(task_id, filesystem_regex)

        return {
            'base-image-id': new_base_image,
            'filesystem-koji-task-id': task_id,
        }
Beispiel #31
0
    def run(self):
        base_image = self.workflow.builder.base_image
        if base_image.namespace != 'koji' or base_image.repo != 'image-build':
            self.log.info('Base image not supported: %s', base_image)
            return

        image_build_conf = base_image.tag
        if not image_build_conf or image_build_conf == 'latest':
            image_build_conf = 'image-build.conf'

        self.session = create_koji_session(self.koji_hub, self.koji_auth_info)

        task_id, filesystem_regex = self.run_image_task(image_build_conf)

        new_base_image = None
        if not self.is_orchestrator:
            new_base_image = self.stream_filesystem(task_id, filesystem_regex)

        return {
            'base-image-id': new_base_image,
            'filesystem-koji-task-id': task_id,
        }
    def __init__(self, tasker, workflow, hub, target=None, koji_ssl_certs_dir=None, append=False):
        """
        constructor

        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param hub: string, koji hub (xmlrpc)
        :param target: unused - backwards compatibility
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
            Note that this plugin requires koji_ssl_certs_dir set if Koji
            certificate is not trusted by CA bundle.
        :param append: if True, the release will be obtained by appending a
            '.' and a unique integer to the release label in the dockerfile.
        """
        # call parent constructor
        super(BumpReleasePlugin, self).__init__(tasker, workflow)
        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.xmlrpc = create_koji_session(hub, koji_auth_info)

        self.append = append
Beispiel #33
0
    def __init__(self, tasker, workflow, target, hub, root, proxy=None, koji_ssl_certs_dir=None):
        """
        constructor

        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param target: string, koji target to use as a source
        :param hub: string, koji hub (xmlrpc)
        :param root: string, koji root (storage)
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
            Note that this plugin requires koji_ssl_certs_dir set if Koji
            certificate is not trusted by CA bundle.
        """
        # call parent constructor
        super(KojiPlugin, self).__init__(tasker, workflow)
        self.target = target
        koji_auth_info = None
        if koji_ssl_certs_dir:
            koji_auth_info = {
                'ssl_certs_dir': koji_ssl_certs_dir,
            }
        self.xmlrpc = create_koji_session(hub, koji_auth_info)
        self.pathinfo = koji.PathInfo(topdir=root)
        self.proxy = proxy
    def __init__(self,
                 tasker,
                 workflow,
                 smtp_host,
                 from_address,
                 send_on=(AUTO_CANCELED, AUTO_FAIL, MANUAL_SUCCESS,
                          MANUAL_FAIL),
                 url=None,
                 error_addresses=(),
                 additional_addresses=(),
                 email_domain=None,
                 koji_hub=None,
                 koji_root=None,
                 koji_proxyuser=None,
                 koji_ssl_certs_dir=None,
                 koji_krb_principal=None,
                 koji_krb_keytab=None,
                 to_koji_submitter=False,
                 to_koji_pkgowner=False):
        """
        constructor

        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param send_on: list of str, list of build states when a notification should be sent
            see 'allowed_states' constant and rules in '_should_send' function
        :param url: str, URL to OSv3 instance where the build logs are stored
        :param smtp_host: str, URL of SMTP server to use to send the message (e.g. "foo.com:25")
        :param from_address: str, the "From" of the notification email
        :param error_addresses: list of str, list of email addresses where to send an email
            if an error occurred (e.g. if we can't find out who to notify about the failed build)
        :param additional_addresses: list of str, always send a message to these email addresses
        :param email_domain: str, email domain used when email addresses cannot be fetched via
            kerberos principal
        :param koji_hub: str, koji hub (xmlrpc)
        :param koji_root: str, koji root (storage)
        :param koji_proxyuser: str, proxy user
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
        :param koji_krb_principal: str, name of Kerberos principal
        :param koji_krb_keytab: str, Kerberos keytab
        :param to_koji_submitter: bool, send a message to the koji submitter
        :param to_koji_pkgowner: bool, send messages to koji package owners
        """
        super(SendMailPlugin, self).__init__(tasker, workflow)
        self.send_on = set(send_on)
        self.url = url
        self.additional_addresses = list(additional_addresses)
        self.smtp_host = smtp_host
        self.from_address = from_address
        self.error_addresses = list(error_addresses)
        self.email_domain = email_domain
        self.koji_hub = koji_hub
        self.koji_root = koji_root
        self.koji_auth_info = {
            'proxyuser': koji_proxyuser,
            'ssl_certs_dir': koji_ssl_certs_dir,
            'krb_principal': koji_krb_principal,
            'krb_keytab': koji_krb_keytab,
        }
        self.to_koji_submitter = to_koji_submitter
        self.to_koji_pkgowner = to_koji_pkgowner
        self.submitter = self.DEFAULT_SUBMITTER

        try:
            metadata = get_build_json().get("metadata", {})
            self.koji_task_id = int(metadata['labels']['koji-task-id'])
        except Exception:
            self.log.exception("Failed to fetch koji task ID")
            self.koji_task_id = None
        else:
            self.log.info("Koji task ID: %s", self.koji_task_id)

        try:
            self.koji_build_id = self.workflow.exit_results.get(
                KojiPromotePlugin.key)
        except Exception:
            self.log.exception("Failed to fetch koji build ID")
            self.koji_build_id = None
        else:
            self.log.info("Koji build ID: %s", self.koji_build_id)

        try:
            self.session = create_koji_session(self.koji_hub,
                                               self.koji_auth_info)
        except Exception:
            self.log.exception("Failed to connect to koji")
            self.session = None
        else:
            self.log.info("Koji connection established")
    def __init__(self, tasker, workflow,
                 smtp_host, from_address,
                 send_on=(AUTO_CANCELED, AUTO_FAIL, MANUAL_SUCCESS, MANUAL_FAIL),
                 url=None,
                 error_addresses=(),
                 additional_addresses=(),
                 email_domain=None,
                 koji_hub=None,
                 koji_root=None,
                 koji_proxyuser=None,
                 koji_ssl_certs_dir=None,
                 koji_krb_principal=None,
                 koji_krb_keytab=None,
                 to_koji_submitter=False,
                 to_koji_pkgowner=False):
        """
        constructor

        :param tasker: DockerTasker instance
        :param workflow: DockerBuildWorkflow instance
        :param send_on: list of str, list of build states when a notification should be sent
            see 'allowed_states' constant and rules in '_should_send' function
        :param url: str, URL to OSv3 instance where the build logs are stored
        :param smtp_host: str, URL of SMTP server to use to send the message (e.g. "foo.com:25")
        :param from_address: str, the "From" of the notification email
        :param error_addresses: list of str, list of email addresses where to send an email
            if an error occurred (e.g. if we can't find out who to notify about the failed build)
        :param additional_addresses: list of str, always send a message to these email addresses
        :param email_domain: str, email domain used when email addresses cannot be fetched via
            kerberos principal
        :param koji_hub: str, koji hub (xmlrpc)
        :param koji_root: str, koji root (storage)
        :param koji_proxyuser: str, proxy user
        :param koji_ssl_certs_dir: str, path to "cert", "ca", and "serverca"
        :param koji_krb_principal: str, name of Kerberos principal
        :param koji_krb_keytab: str, Kerberos keytab
        :param to_koji_submitter: bool, send a message to the koji submitter
        :param to_koji_pkgowner: bool, send messages to koji package owners
        """
        super(SendMailPlugin, self).__init__(tasker, workflow)
        self.send_on = set(send_on)
        self.url = url
        self.additional_addresses = list(additional_addresses)
        self.smtp_host = smtp_host
        self.from_address = from_address
        self.error_addresses = list(error_addresses)
        self.email_domain = email_domain
        self.koji_hub = koji_hub
        # Make sure koji_root doesn't end with a slash for a prettier link
        self.koji_root = koji_root[:-1] if koji_root and koji_root[-1] == '/' else koji_root
        self.koji_auth_info = {
            'proxyuser': koji_proxyuser,
            'ssl_certs_dir': koji_ssl_certs_dir,
            'krb_principal': koji_krb_principal,
            'krb_keytab': koji_krb_keytab,
        }
        self.to_koji_submitter = to_koji_submitter
        self.to_koji_pkgowner = to_koji_pkgowner
        self.submitter = self.DEFAULT_SUBMITTER

        try:
            metadata = get_build_json().get("metadata", {})
            self.koji_task_id = int(metadata['labels']['koji-task-id'])
        except Exception:
            self.log.exception("Failed to fetch koji task ID")
            self.koji_task_id = None
        else:
            self.log.info("Koji task ID: %s", self.koji_task_id)

        self.koji_build_id = self.workflow.exit_results.get(KojiImportPlugin.key)
        if not self.koji_build_id:
            self.koji_build_id = self.workflow.exit_results.get(KojiPromotePlugin.key)
            if not self.koji_build_id:
                self.log.info("Failed to fetch koji build ID")
            else:
                self.log.info("Koji build ID: %s", self.koji_build_id)
        else:
            self.log.info("Koji build ID: %s", self.koji_build_id)

        try:
            self.session = create_koji_session(self.koji_hub, self.koji_auth_info)
        except Exception:
            self.log.exception("Failed to connect to koji")
            self.session = None
        else:
            self.log.info("Koji connection established")