Esempio n. 1
0
    def setUp(self):
        super(PluginsTest, self).setUp()
        self.plugins = Plugins()

        self.fakes.fs.add(paths.PLUGINS)
        os.makedirs(paths.PLUGINS)
        self.fakes.users.add("jenkins", 123)
        self.fakes.groups.add("jenkins", 123)
        self.fakes.juju.config["plugins-site"] = "http://x/"
        self.fakes.processes.wget.locations["http://x/plugin.hpi"] = b"data"
    def changed(self):
        """Install optional plugins."""
        # extension subordinates may request the principle service install
        # specified jenkins plugins
        log("Installing required plugins as requested by jenkins-extension "
            "subordinate.")
        plugins = Plugins()
        plugins.install(relation_get("required_plugins"))

        api = Api()
        api.wait()  # Wait for the service to be fully up
Esempio n. 3
0
    def changed(self):
        """Install optional plugins."""
        # extension subordinates may request the principle service install
        # specified jenkins plugins
        log("Installing required plugins as requested by jenkins-extension "
            "subordinate.")
        plugins = Plugins()
        plugins.install(relation_get("required_plugins"))

        api = Api()
        api.wait()  # Wait for the service to be fully up
Esempio n. 4
0
def configure_plugins():
    if get_state("extension.connected"):
        # We've been driven by an extension, let it take control over
        # plugin.
        log("External relation detected - skip configuring plugins")
        return
    status_set("maintenance", "Configuring plugins")
    remove_state("jenkins.configured.plugins")
    plugins = Plugins()
    plugins.install(config("plugins"))
    api = Api()
    api.wait()  # Wait for the service to be fully up
    set_state("jenkins.configured.plugins")
Esempio n. 5
0
 def test_using_json_from_plugin_site(self, mock_restart_jenkins):
     """
     If the configured plugin-site has an update-center.json file,
     it should be used instead of the default one.
     """
     self.plugins = Plugins()
     orig_plugins_site = hookenv.config()["plugins-site"]
     try:
         hookenv.config(
         )["plugins-site"] = "https://updates.jenkins.io/stable/"
         self.plugins = Plugins()
     finally:
         hookenv.config()["plugins-site"] = orig_plugins_site
Esempio n. 6
0
def configure_plugins():
    if get_state("extension.connected"):
        # We've been driven by an extension, let it take control over
        # plugin.
        log("External relation detected - skip configuring plugins")
        return
    status_set("maintenance", "Configuring plugins")
    remove_state("jenkins.configured.plugins")
    plugins = Plugins()
    plugins.install(config("plugins"))
    api = Api()
    api.wait()  # Wait for the service to be fully up
    set_state("jenkins.configured.plugins")
Esempio n. 7
0
def update_plugins():
    last_update = unitdata.kv().get("jenkins.plugins.last_update")
    if last_update is None:
        unitdata.kv().set("jenkins.plugins.last_update", 0)
        last_update = 0
    # Only try to update plugins when the interval configured has passed
    update_interval = time.time() - (config("plugins-auto-update-interval") * 60)
    if (last_update < update_interval):
        status_set("maintenance", "Updating plugins")
        plugins = Plugins()
        plugins.update(config("plugins"))
        api = Api()
        api.wait()  # Wait for the service to be fully up
    unitdata.kv().set("jenkins.plugins.last_update", time.time())
Esempio n. 8
0
    def setUp(self):
        super(PluginsTest, self).setUp()
        self.plugins = Plugins()

        self.fakes.fs.add(paths.PLUGINS)
        os.makedirs(paths.PLUGINS)
        self.fakes.users.add("jenkins", 123)
        self.fakes.groups.add("jenkins", 123)
        self.fakes.juju.config["plugins-site"] = "http://x/"
        self.fakes.processes.wget.locations["http://x/plugin.hpi"] = b"data"
    def joined(self):
        """Indicate the relation is connected and install required plugins."""
        log("Installing and configuring gearman-plugin for Zuul communication")
        # zuul relation requires we install the required plugins and set the
        # address of the remote zuul/gearman service in the plugin setting.
        plugins = Plugins()
        plugins.install(PLUGINS)
        self.set_state("{relation_name}.connected")

        # Generate plugin config with address of remote unit.
        zuul_host = relation_get("private-address")
        zuul_config = ZUUL_CONFIG.format(zuul_host).encode("utf-8")
        write_file(
            GERMAN_PLUGIN, zuul_config, owner="jenkins", group="nogroup")

        # Restart jenkins so changes will take efect.
        service_restart("jenkins")

        # Trigger the extension hook to update it with zuul relation data, if
        # it's coded to do so.
        hooks = Hooks()
        hooks.execute(["extension-relation-joined"])
Esempio n. 10
0
    def joined(self):
        """Indicate the relation is connected and install required plugins."""
        log("Installing and configuring gearman-plugin for Zuul communication")
        # zuul relation requires we install the required plugins and set the
        # address of the remote zuul/gearman service in the plugin setting.
        plugins = Plugins()
        plugins.install(PLUGINS)
        self.set_state("{relation_name}.connected")

        # Generate plugin config with address of remote unit.
        zuul_host = relation_get("private-address")
        zuul_config = ZUUL_CONFIG.format(zuul_host).encode("utf-8")
        write_file(GERMAN_PLUGIN,
                   zuul_config,
                   owner="jenkins",
                   group="nogroup")

        # Restart jenkins so changes will take efect.
        service_restart("jenkins")

        # Trigger the extension hook to update it with zuul relation data, if
        # it's coded to do so.
        hooks = Hooks()
        hooks.execute(["extension-relation-joined"])
Esempio n. 11
0
def update_plugins():
    last_update = unitdata.kv().get("jenkins.plugins.last_update")
    if last_update is None:
        unitdata.kv().set("jenkins.plugins.last_update", 0)
        last_update = 0
    # Only try to update plugins when the interval configured has passed
    update_interval = time.time() - (config("plugins-auto-update-interval") *
                                     60)
    if (last_update < update_interval):
        status_set("maintenance", "Updating plugins")
        remove_state("jenkins.updated.plugins")
        plugins = Plugins()
        plugins.update(config("plugins"))
        api = Api()
        api.wait()  # Wait for the service to be fully up
        # Restart jenkins if any plugin got updated
        last_restart = unitdata.kv().get("jenkins.last_restart") or 0
        last_plugin_update_time = (
            unitdata.kv().get("jenkins.plugins.last_plugin_update_time") or 0)
        if (last_restart < last_plugin_update_time):
            restart()
        unitdata.kv().set("jenkins.plugins.last_restart", time.time())
        set_state("jenkins.updated.plugins")
    unitdata.kv().set("jenkins.plugins.last_update", time.time())
Esempio n. 12
0
class PluginsTest(CharmTest):
    def setUp(self):
        super(PluginsTest, self).setUp()
        self.plugins = Plugins()

        self.fakes.fs.add(paths.PLUGINS)
        os.makedirs(paths.PLUGINS)
        self.fakes.users.add("jenkins", 123)
        self.fakes.groups.add("jenkins", 123)
        self.fakes.juju.config["plugins-site"] = "http://x/"
        self.fakes.processes.wget.locations["http://x/plugin.hpi"] = b"data"

    def test_install(self):
        """
        The given plugins are downloaded from the Jenkins site.
        """
        self.plugins.install("plugin")
        self.assertEqual(["stop", "start"],
                         self.fakes.processes.systemctl.actions["jenkins"])
        plugin_path = os.path.join(paths.PLUGINS, "plugin.hpi")
        self.assertThat(plugin_path, FileContains("data"))

    def test_install_no_certificate_check(self):
        """
        If plugins-check-certificate is set to 'no', the plugins site
        certificate won't be validated.
        """
        self.fakes.juju.config["plugins-check-certificate"] = "no"
        self.plugins.install("plugin")
        self.assertIn("--no-check-certificate",
                      self.fakes.processes.procs[-4].args)

    def test_install_dont_remove_unlisted(self):
        """
        If remove-unlisted-plugins is set to 'yes', then unlisted plugins
        are removed from disk.
        """
        self.fakes.juju.config["remove-unlisted-plugins"] = "yes"
        unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
        with open(unlisted_plugin, "w"):
            pass
        self.plugins.install("plugin")
        self.assertThat(unlisted_plugin, Not(PathExists()))

    def test_install_do_remove_unlisted(self):
        """
        If remove-unlisted-plugins is set to 'no', then unlisted plugins
        will be left on disk.
        """
        unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
        with open(unlisted_plugin, "w"):
            pass
        self.plugins.install("plugin")
        self.assertThat(unlisted_plugin, PathExists())

    def test_install_skip_non_file_unlisted(self):
        """
        If an unlisted plugin is not actually a file, it's just skipped and
        doesn't get removed.
        """
        self.fakes.juju.config["remove-unlisted-plugins"] = "yes"
        unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
        os.mkdir(unlisted_plugin)
        self.plugins.install("plugin")
        self.assertThat(unlisted_plugin, PathExists())

    def test_install_already_installed(self):
        """
        If a plugin is already installed, it doesn't get downloaded.
        """
        self.fakes.juju.config["remove-unlisted-plugins"] = "yes"
        plugin_path = os.path.join(paths.PLUGINS, "plugin.hpi")
        with open(plugin_path, "w"):
            pass
        self.plugins.install("plugin")
        commands = [proc.args[0] for proc in self.fakes.processes.procs]
        self.assertNotIn("wget", commands)
Esempio n. 13
0
class PluginsTest(CharmTest):
    def setUp(self):
        super(PluginsTest, self).setUp()
        self.plugins = Plugins()

        self.fakes.fs.add(paths.PLUGINS)
        os.makedirs(paths.PLUGINS)
        self.fakes.users.add("jenkins", 123)
        self.fakes.groups.add("jenkins", 123)
        self.orig_plugins_site = hookenv.config()["plugins-site"]
        hookenv.config()["plugins-site"] = "http://x/"
        self.fakes.processes.wget.locations["http://x/plugin.hpi"] = b"data"

    def tearDown(self):
        super(PluginsTest, self).tearDown()
        hookenv.config()["plugins-site"] = self.orig_plugins_site

    def test_install(self):
        """
        The given plugins are downloaded from the Jenkins site.
        """
        self.plugins.install("plugin")
        self.assertEqual(["stop", "start"],
                         self.fakes.processes.systemctl.actions["jenkins"])
        plugin_path = os.path.join(paths.PLUGINS, "plugin.hpi")
        self.assertThat(plugin_path, FileContains("data"))

    def test_install_no_certificate_check(self):
        """
        If plugins-check-certificate is set to 'no', the plugins site
        certificate won't be validated.
        """
        orig_plugins_check_certificate = hookenv.config(
        )["plugins-check-certificate"]
        try:
            hookenv.config()["plugins-check-certificate"] = "no"
            self.plugins.install("plugin")
            commands = [proc.args[0] for proc in self.fakes.processes.procs]
            self.assertIn("--no-check-certificate",
                          self.fakes.processes.procs[-4].args)
        finally:
            hookenv.config(
            )["plugins-check-certificate"] = orig_plugins_check_certificate

    def test_install_dont_remove_unlisted(self):
        """
        If remove-unlisted-plugins is set to 'yes', then unlisted plugins
        are removed from disk.
        """
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
            with open(unlisted_plugin, "w"):
                pass
            self.plugins.install("plugin")
            self.assertThat(unlisted_plugin, Not(PathExists()))
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    def test_install_do_remove_unlisted(self):
        """
        If remove-unlisted-plugins is set to 'no', then unlisted plugins
        will be left on disk.
        """
        unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
        with open(unlisted_plugin, "w"):
            pass
        self.plugins.install("plugin")
        self.assertThat(unlisted_plugin, PathExists())

    def test_install_skip_non_file_unlisted(self):
        """
        If an unlisted plugin is not actually a file, it's just skipped and
        doesn't get removed.
        """
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
            os.mkdir(unlisted_plugin)
            self.plugins.install("plugin")
            self.assertThat(unlisted_plugin, PathExists())
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    def test_install_already_installed(self):
        """
        If a plugin is already installed, it doesn't get downloaded.
        """
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            hookenv.config()["plugins-force-reinstall"] = False
            hookenv.config()["plugins-auto-update"] = False
            plugin_path = os.path.join(paths.PLUGINS, "plugin.hpi")
            with open(plugin_path, "w"):
                pass
            self.plugins.install("plugin")
            commands = [proc.args[0] for proc in self.fakes.processes.procs]
            self.assertNotIn("wget", commands)
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    def test_install_bad_plugin(self):
        """
        If plugin can't be downloaded we expect error message in the logs
        """
        def broken_download(*args, **kwargs):
            raise Exception("error")

        self.plugins._install_plugin = broken_download
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            plugin_path = os.path.join(paths.PLUGINS, "bad_plugin.hpi")
            with open(plugin_path, "w"):
                pass
            self.assertRaises(Exception, self.plugins.install, "bad_plugin")
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    def test_install_force_reinstall(self):
        """
        If a plugin is already installed and plugin-force-reinstall is yes it
        should get downloaded.
        """
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            hookenv.config()["plugins-force-reinstall"] = True
            plugin_path = os.path.join(paths.PLUGINS, "plugin.hpi")
            with open(plugin_path, "w"):
                pass
            self.plugins.install("plugin")
            commands = [proc.args[0] for proc in self.fakes.processes.procs]
            self.assertIn("wget", commands)
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    def test_update(self):
        """
        The given plugins are downloaded from the Jenkins site if newer
        versions are available
        """
        hookenv.config()["plugins-auto-update"] = True
        plugin_path = os.path.join(paths.PLUGINS, "plugin.hpi")
        with open(plugin_path, "w"):
            pass
        self.plugins.update("plugin")
        commands = [proc.args[0] for proc in self.fakes.processes.procs]
        self.assertIn("wget", commands)

    def test_update_bad_plugin(self):
        """
        If plugin can't be downloaded we expect error message in the logs
        """
        def broken_download(*args, **kwargs):
            raise Exception("error")

        self.plugins._install_plugin = broken_download
        plugin_path = os.path.join(paths.PLUGINS, "bad_plugin.hpi")
        with open(plugin_path, "w"):
            pass
        self.assertRaises(Exception, self.plugins.update, "bad_plugin")
Esempio n. 14
0
class PluginsTest(CharmTest):
    def setUp(self):
        super(PluginsTest, self).setUp()
        self.plugins = Plugins()

        self.fakes.fs.add(paths.PLUGINS)
        os.makedirs(paths.PLUGINS)
        self.fakes.users.add("jenkins", 123)
        self.fakes.groups.add("jenkins", 123)
        self.orig_plugins_site = hookenv.config()["plugins-site"]
        self.fakes.processes.wget.locations["http://x/plugin.hpi"] = b"data"

    def tearDown(self):
        super(PluginsTest, self).tearDown()
        hookenv.config()["plugins-site"] = self.orig_plugins_site

    def test_remove_plugin(self, mock_restart_jenkins):
        """
        The given plugin file is removed from disk.
        """
        plugin_name = "plugin"
        plugin_path = os.path.join(paths.PLUGINS,
                                   "{}-1.jpi".format(plugin_name))
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            with open(plugin_path, "w"):
                pass
            # When using a non-existent path it returns None
            self.assertIsNone(self.plugins._remove_plugin(plugin_name))
            self.plugins._remove_plugin(plugin_path)
            self.assertThat(plugin_path, Not(PathExists()))
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    @mock.patch("charms.layer.jenkins.api.Api.get_plugin_version")
    def test_install(self, mock_get_plugin_version, mock_restart_jenkins):
        """
        The given plugins are downloaded from the Jenkins site.
        """
        mock_get_plugin_version.return_value = False
        plugin_name = "ansicolor"
        installed_plugin = ""
        installed_plugin.join(self.plugins.install(plugin_name))
        plugin_path = os.path.join(paths.PLUGINS, installed_plugin)
        self.assertTrue(os.path.exists(plugin_path),
                        msg="Plugin not installed in the proper directory")

        mock_restart_jenkins.assert_called_with()

    @mock.patch("charms.layer.jenkins.api.Api.get_plugin_version")
    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    def test_install_raises_error(self, mock_get_plugins_to_install,
                                  mock_get_plugin_version,
                                  mock_restart_jenkins):
        """
        When install fails it should log and raise an error
        """
        def failed_install(*args, **kwargs):
            raise Exception()

        plugin_name = "bad_plugin"
        mock_get_plugins_to_install.return_value = {plugin_name}
        mock_get_plugin_version.return_value = False
        self.plugins._install_plugins = failed_install

        self.assertRaises(Exception, self.plugins.install, plugin_name)
        self.assertEqual(
            "INFO: Plugin installation failed, check logs for details",
            self.fakes.juju.log[-1])
        mock_restart_jenkins.assert_not_called()

    @mock.patch("test_plugins.Plugins._install_plugins")
    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    def test_install_do_remove_unlisted(self, mock_get_plugins_to_install,
                                        mock_install_plugins,
                                        mock_restart_jenkins):
        """
        If remove-unlisted-plugins is set to 'yes', then unlisted plugins
        are removed from disk.
        """
        plugin_name = "plugin"
        plugin_path = os.path.join(paths.PLUGINS,
                                   "{}-1.jpi".format(plugin_name))
        mock_get_plugins_to_install.return_value = {plugin_name}
        mock_install_plugins.return_value = {plugin_path}
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.jpi")
            with open(unlisted_plugin, "w"):
                pass
            self.plugins.install(plugin_name)
            self.assertThat(unlisted_plugin, Not(PathExists()))

        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    @mock.patch("test_plugins.Plugins._remove_plugin")
    @mock.patch("test_plugins.Plugins._install_plugins")
    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    def test_install_dont_remove_unlisted(self, mock_get_plugins_to_install,
                                          mock_install_plugins,
                                          mock_remove_plugin,
                                          mock_restart_jenkins):
        """
        If remove-unlisted-plugins is set to 'no', then unlisted plugins
        will be left on disk.
        """
        plugin_name = "plugin"
        plugin_path = os.path.join(paths.PLUGINS,
                                   "{}-1.jpi".format(plugin_name))
        mock_get_plugins_to_install.return_value = {plugin_name}
        mock_install_plugins.return_value = {plugin_path}
        unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.jpi")
        unlisted_plugin_path = "{}{}".format(
            self.fakes.fs.root.path, os.path.join(paths.PLUGINS,
                                                  "unlisted.jpi"))
        with open(unlisted_plugin, "w"):
            pass
        self.plugins.install(plugin_name)
        self.assertEqual(
            "INFO: Unlisted plugins: ({}) Not removed. Set "
            "remove-unlisted-plugins to 'yes' to clear them "
            "away.".format(unlisted_plugin_path), self.fakes.juju.log[-1])
        mock_remove_plugin.assert_not_called()

    @mock.patch("test_plugins.Plugins._install_plugins")
    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    def test_install_skip_non_file_unlisted(self, mock_get_plugins_to_install,
                                            mock_install_plugins,
                                            mock_restart_jenkins):
        """
        If an unlisted plugin is not actually a file, it's just skipped and
        doesn't get removed.
        """
        mock_get_plugins_to_install.return_value = {"plugin"}
        mock_install_plugins.return_value = {
            os.path.join(paths.PLUGINS, "plugin.jpi")
        }
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
            os.mkdir(unlisted_plugin)
            self.plugins.install("plugin")
            self.assertThat(unlisted_plugin, PathExists())
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    @mock.patch("test_plugins.Plugins._download_plugin")
    @mock.patch("test_plugins.Plugins._get_latest_version")
    @mock.patch("charms.layer.jenkins.api.Api.get_plugin_version")
    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    def test_install_already_installed(self, mock_get_plugins_to_install,
                                       mock_get_latest_version,
                                       mock_get_plugin_version,
                                       mock_download_plugin,
                                       mock_restart_jenkins):
        """
        If a plugin is already installed, it doesn't get downloaded.
        """
        plugin_name = "plugin"
        mock_get_plugins_to_install.return_value = {plugin_name}
        mock_get_plugin_version.return_value = "1"
        mock_get_latest_version.return_value = "1"
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            hookenv.config()["plugins-auto-update"] = False
            self.plugins.install(plugin_name)
            mock_download_plugin.assert_not_called()
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    def test_install_bad_plugin(self, mock_restart_jenkins):
        """
        If plugin can't be downloaded we expect error message in the logs
        """
        orig_remove_unlisted_plugins = hookenv.config(
        )["remove-unlisted-plugins"]
        try:
            hookenv.config()["remove-unlisted-plugins"] = "yes"
            plugin_path = os.path.join(paths.PLUGINS, "bad_plugin.hpi")
            with open(plugin_path, "w"):
                pass
            self.assertRaises(Exception, self.plugins.install, "bad_plugin")
        finally:
            hookenv.config(
            )["remove-unlisted-plugins"] = orig_remove_unlisted_plugins

    @mock.patch("test_plugins.Plugins._download_plugin")
    @mock.patch("test_plugins.Plugins._get_latest_version")
    @mock.patch("charms.layer.jenkins.api.Api.get_plugin_version")
    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    def test_install_fail(self, mock_get_plugins_to_install,
                          mock_get_plugin_version, mock_get_latest_version,
                          mock_download_plugin, mock_restart_jenkins):
        """If a plugin is already installed, it doesn't get downloaded."""
        plugin_name = "plugin"
        mock_get_plugins_to_install.return_value = {plugin_name}
        mock_get_plugin_version.return_value = False
        mock_get_latest_version.return_value = "1"
        mock_download_plugin.return_value = False
        hookenv.config()["remove-unlisted-plugins"] = "yes"
        self.plugins.install(plugin_name)
        self.assertEqual("INFO: Failed to download plugin",
                         self.fakes.juju.log[-1])

    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    @mock.patch("charms.layer.jenkins.api.Api.get_plugin_version")
    @mock.patch("test_plugins.Plugins._get_latest_version")
    @mock.patch("test_plugins.Plugins._download_plugin")
    def test_update(self, mock_download_plugin, mock_get_latest_version,
                    mock_get_plugin_version, mock_get_plugins_to_install,
                    mock_restart_jenkins):
        """
        The given plugins are installed from the Jenkins site if newer
        versions are available
        """
        plugin_name = "plugin"
        mock_get_plugins_to_install.return_value = {plugin_name}
        mock_get_plugin_version.return_value = "1"
        mock_get_latest_version.return_value = "1.1"
        orig_plugins_auto_update = hookenv.config()["plugins-auto-update"]
        try:
            hookenv.config()["plugins-auto-update"] = True
            self.plugins.update(plugin_name)
            mock_download_plugin.assert_called_with(plugin_name, mock.ANY)
            mock_restart_jenkins.assert_called_with()
        finally:
            hookenv.config()["plugins-auto-update"] = orig_plugins_auto_update

    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    @mock.patch("charms.layer.jenkins.api.Api.get_plugin_version")
    @mock.patch("test_plugins.Plugins._get_latest_version")
    @mock.patch("test_plugins.Plugins._download_plugin")
    def test_dont_update(self, mock_download_plugin, mock_get_latest_version,
                         mock_get_plugin_version, mock_get_plugins_to_install,
                         mock_restart_jenkins):
        """
        No plugins are reinstalled if not necessary.
        """
        plugin_name = "plugin"
        mock_get_plugins_to_install.return_value = {plugin_name}
        mock_get_plugin_version.return_value = "1"
        mock_get_latest_version.return_value = "1"
        orig_plugins_auto_update = hookenv.config()["plugins-auto-update"]
        try:
            hookenv.config()["plugins-auto-update"] = True
            self.plugins.update(plugin_name)
            mock_download_plugin.assert_not_called()
            self.assertEqual("INFO: No plugins updated",
                             self.fakes.juju.log[-1])

        finally:
            hookenv.config()["plugins-auto-update"] = orig_plugins_auto_update

    @mock.patch("charms.layer.jenkins.api.Api.get_plugin_version")
    @mock.patch("test_plugins.Plugins._get_plugins_to_install")
    def test_update_raises_error(self, mock_get_plugins_to_install,
                                 mock_get_plugin_version,
                                 mock_restart_jenkins):
        """
        When install fails it should log and raise an error
        """
        def failed_install(*args, **kwargs):
            raise Exception()

        plugin_name = "bad_plugin"
        mock_get_plugins_to_install.return_value = {plugin_name}
        mock_get_plugin_version.return_value = False
        self.plugins._install_plugins = failed_install

        self.assertRaises(Exception, self.plugins.update, plugin_name)
        self.assertEqual("INFO: Plugin update failed, check logs for details",
                         self.fakes.juju.log[-1])
        mock_restart_jenkins.assert_not_called()

    def test_update_bad_plugin(self, mock_restart_jenkins):
        """
        If plugin can't be downloaded we expect error message in the logs
        """
        def broken_download(*args, **kwargs):
            raise Exception("error")

        self.plugins._install_plugin = broken_download
        plugin_path = os.path.join(paths.PLUGINS, "bad_plugin.hpi")
        with open(plugin_path, "w"):
            pass
        self.assertRaises(Exception, self.plugins.update, "bad_plugin")

    def test_using_json_from_plugin_site(self, mock_restart_jenkins):
        """
        If the configured plugin-site has an update-center.json file,
        it should be used instead of the default one.
        """
        self.plugins = Plugins()
        orig_plugins_site = hookenv.config()["plugins-site"]
        try:
            hookenv.config(
            )["plugins-site"] = "https://updates.jenkins.io/stable/"
            self.plugins = Plugins()
        finally:
            hookenv.config()["plugins-site"] = orig_plugins_site

    def test_broken_json_from_plugin_site(self, mock_restart_jenkins):
        """
        If the configured plugin-site has no update-center.json file,
        it should error.
        """
        orig_plugins_site = hookenv.config()["plugins-site"]
        try:
            hookenv.config(
            )["plugins-site"] = "https://updates.jenkins.io/not-valid/"
            self.assertRaises(Exception, Plugins)
        finally:
            hookenv.config()["plugins-site"] = orig_plugins_site
Esempio n. 15
0
class PluginsTest(CharmTest):

    def setUp(self):
        super(PluginsTest, self).setUp()
        self.plugins = Plugins()

        self.fakes.fs.add(paths.PLUGINS)
        os.makedirs(paths.PLUGINS)
        self.fakes.users.add("jenkins", 123)
        self.fakes.groups.add("jenkins", 123)
        self.fakes.juju.config["plugins-site"] = "http://x/"
        self.fakes.processes.wget.locations["http://x/plugin.hpi"] = b"data"

    def test_install(self):
        """
        The given plugins are downloaded from the Jenkins site.
        """
        self.plugins.install("plugin")
        self.assertEqual(
            ["stop", "start"],
            self.fakes.processes.systemctl.actions["jenkins"])
        plugin_path = os.path.join(paths.PLUGINS, "plugin.hpi")
        self.assertThat(plugin_path, FileContains("data"))

    def test_install_no_certificate_check(self):
        """
        If plugins-check-certificate is set to 'no', the plugins site
        certificate won't be validated.
        """
        self.fakes.juju.config["plugins-check-certificate"] = "no"
        self.plugins.install("plugin")
        self.assertIn(
            "--no-check-certificate", self.fakes.processes.procs[-4].args)

    def test_install_dont_remove_unlisted(self):
        """
        If remove-unlisted-plugins is set to 'yes', then unlisted plugins
        are removed from disk.
        """
        self.fakes.juju.config["remove-unlisted-plugins"] = "yes"
        unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
        with open(unlisted_plugin, "w"):
            pass
        self.plugins.install("plugin")
        self.assertThat(unlisted_plugin, Not(PathExists()))

    def test_install_do_remove_unlisted(self):
        """
        If remove-unlisted-plugins is set to 'no', then unlisted plugins
        will be left on disk.
        """
        unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
        with open(unlisted_plugin, "w"):
            pass
        self.plugins.install("plugin")
        self.assertThat(unlisted_plugin, PathExists())

    def test_install_skip_non_file_unlisted(self):
        """
        If an unlisted plugin is not actually a file, it's just skipped and
        doesn't get removed.
        """
        self.fakes.juju.config["remove-unlisted-plugins"] = "yes"
        unlisted_plugin = os.path.join(paths.PLUGINS, "unlisted.hpi")
        os.mkdir(unlisted_plugin)
        self.plugins.install("plugin")
        self.assertThat(unlisted_plugin, PathExists())

    def test_install_already_installed(self):
        """
        If a plugin is already installed, it doesn't get downloaded.
        """
        self.fakes.juju.config["remove-unlisted-plugins"] = "yes"
        plugin_path = os.path.join(paths.PLUGINS, "plugin.hpi")
        with open(plugin_path, "w"):
            pass
        self.plugins.install("plugin")
        commands = [proc.args[0] for proc in self.fakes.processes.procs]
        self.assertNotIn("wget", commands)
Esempio n. 16
0
def plugins_layer():
    try:
        plugins = Plugins()
    except PluginSiteError as e:
        status_set("error", e.message)
    return plugins