Example #1
0
def resolve(vague_name, repository_path, default_series):
    """Get a Charm and associated identifying information

    :param str vague_name: a lazily specified charm name, suitable for use with
        :meth:`CharmURL.infer`

    :param repository_path: where on the local filesystem to find a repository
        (only currently meaningful when `charm_name` is specified with
        `"local:"`)
    :type repository_path: str or None

    :param str default_series: the Ubuntu series to insert when `charm_name` is
        inadequately specified.

    :return: a tuple of a :class:`juju.charm.url.CharmURL` and a
        :class:`juju.charm.base.CharmBase` subclass, which together contain
        both the charm's data and all information necessary to specify its
        source.
    """
    url = CharmURL.infer(vague_name, default_series)
    if url.collection.schema == "local":
        repo = LocalCharmRepository(repository_path)
    elif url.collection.schema == "cs":
        repo = RemoteCharmRepository("https://store.juju.ubuntu.com")
    return repo, url
Example #2
0
    def test_agent_upgrade_bad_unit_state(self):
        """The an upgrade fails if the unit is in a bad state."""
        self.agent.set_watch_enabled(False)
        yield self.agent.startService()

        # Upload a new version of the unit's charm
        repository = self.increment_charm(self.charm)
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)

        # Mark the unit for upgrade, with an invalid state.
        yield self.states["service"].set_charm_id(charm_state.id)
        yield self.states["unit"].set_upgrade_flag()
        yield self.agent.workflow.set_state("start_error")

        output = self.capture_logging("unit.upgrade", level=logging.DEBUG)

        # Do the upgrade
        upgrade = CharmUpgradeOperation(self.agent)
        value = yield upgrade.run()

        # Verify the upgrade.
        self.assertIdentical(value, False)
        self.assertIn("Unit not in an upgradeable state: start_error",
                      output.getvalue())
        self.assertIdentical(
            (yield self.states["unit"].get_upgrade_flag()),
            False)
Example #3
0
    def test_agent_force_upgrade_bad_unit_state(self):
        """The upgrade runs if forced and the unit is in a bad state."""
        # Upload a new version of the unit's charm
        repository = self.increment_charm(self.charm)
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)
        old_charm_id = yield self.states["unit"].get_charm_id()

        output = self.capture_logging("juju.agents.unit", level=logging.DEBUG)

        self.agent.set_watch_enabled(True)
        yield self.agent.startService()

        # Mark the unit for upgrade, with an invalid state.
        with (yield self.agent.workflow.lock()):
            yield self.agent.workflow.fire_transition("error_configure")
        yield self.states["service"].set_charm_id(charm_state.id)
        yield self.states["unit"].set_upgrade_flag(force=True)

        # Its hard to watch something with no hooks and no state changes.
        yield self.sleep(0.1)

        self.assertIdentical(
            (yield self.states["unit"].get_upgrade_flag()), False)
        self.assertIn("Forced upgrade complete", output.getvalue())
        self.assertEquals(
            (yield self.states["unit"].get_charm_id()), "local:series/mysql-2")
        self.assertEquals(old_charm_id, "local:series/dummy-1")
Example #4
0
    def test_agent_upgrade_bad_unit_state(self):
        """The upgrade fails if the unit is in a bad state."""
        # Upload a new version of the unit's charm
        repository = self.increment_charm(self.charm)
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)
        old_charm_id = yield self.states["unit"].get_charm_id()

        log_written = self.wait_for_log(
            "juju.agents.unit",
            "Cannot upgrade: unit is in non-started state configure_error. "
            "Reissue upgrade command to try again.")
        self.agent.set_watch_enabled(True)
        yield self.agent.startService()

        # Mark the unit for upgrade, with an invalid state.
        with (yield self.agent.workflow.lock()):
            yield self.agent.workflow.fire_transition("error_configure")
        yield self.states["service"].set_charm_id(charm_state.id)
        yield self.states["unit"].set_upgrade_flag()
        yield log_written

        self.assertIdentical(
            (yield self.states["unit"].get_upgrade_flag()), False)
        self.assertEquals(
            (yield self.states["unit"].get_charm_id()), old_charm_id)
Example #5
0
    def test_charm_upgrade(self):
        """
        'juju charm-upgrade <service_name>' will schedule
        a charm for upgrade.
        """
        repository = self.increment_charm(self.charm)

        mock_environment = self.mocker.patch(Environment)
        mock_environment.get_machine_provider()
        self.mocker.result(self.provider)

        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()
        main(["upgrade-charm", "--repository", repository.path, "mysql"])
        yield finished

        # Verify the service has a new charm reference
        charm_id = yield self.service_state1.get_charm_id()
        self.assertEqual(charm_id, "local:series/mysql-2")

        # Verify the provider storage has been updated
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        storage = self.provider.get_file_storage()
        try:
            yield storage.get(
                "local_3a_series_2f_mysql-2_3a_%s" % charm.get_sha256())
        except FileNotFound:
            self.fail("New charm not uploaded")

        # Verify the upgrade flag on the service units.
        upgrade_flag = yield self.service_unit1.get_upgrade_flag()
        self.assertTrue(upgrade_flag)
Example #6
0
 def assert_charm_upgraded(self, expect_upgraded):
     charm_id = yield self.states["unit"].get_charm_id()
     self.assertEquals(charm_id == self.expected_upgrade, expect_upgraded)
     if expect_upgraded:
         expect_revision = CharmURL.parse(self.expected_upgrade).revision
         charm = CharmDirectory(os.path.join(self.unit_directory, "charm"))
         self.assertEquals(charm.get_revision(), expect_revision)
Example #7
0
    def test_agent_upgrade_bad_unit_state(self):
        """The an upgrade fails if the unit is in a bad state."""
        self.agent.set_watch_enabled(False)
        yield self.agent.startService()

        # Upload a new version of the unit's charm
        repository = self.increment_charm(self.charm)
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)

        # Mark the unit for upgrade, with an invalid state.
        yield self.states["service"].set_charm_id(charm_state.id)
        yield self.states["unit"].set_upgrade_flag()
        yield self.agent.workflow.set_state("start_error")

        output = self.capture_logging("unit.upgrade", level=logging.DEBUG)

        # Do the upgrade
        upgrade = CharmUpgradeOperation(self.agent)
        value = yield upgrade.run()

        # Verify the upgrade.
        self.assertIdentical(value, False)
        self.assertIn("Unit not in an upgradeable state: start_error",
                      output.getvalue())
        self.assertIdentical((yield self.states["unit"].get_upgrade_flag()),
                             False)
Example #8
0
def resolve(vague_name, repository_path, default_series):
    """Get a Charm and associated identifying information

    :param str vague_name: a lazily specified charm name, suitable for use with
        :meth:`CharmURL.infer`

    :param repository_path: where on the local filesystem to find a repository
        (only currently meaningful when `charm_name` is specified with
        `"local:"`)
    :type repository_path: str or None

    :param str default_series: the Ubuntu series to insert when `charm_name` is
        inadequately specified.

    :return: a tuple of a :class:`juju.charm.url.CharmURL` and a
        :class:`juju.charm.base.CharmBase` subclass, which together contain
        both the charm's data and all information necessary to specify its
        source.
    """
    url = CharmURL.infer(vague_name, default_series)
    if url.collection.schema == "local":
        repo = LocalCharmRepository(repository_path)
    elif url.collection.schema == "cs":
        repo = RemoteCharmRepository("https://store.juju.ubuntu.com")
    return repo, url
    def test_apply_new_charm_defaults(self):
        finished = self.setup_cli_reactor()
        self.setup_exit(0)
        self.mocker.replay()

        # Add a charm and its service.
        metadata = {"name": "haiku",
                    "summary": "its short",
                    "description": "but with cadence"}
        repository = self.add_charm(
            metadata=metadata,
            revision=1,
            config={
                "options": {
                    "foo": {"type": "string",
                            "default": "foo-default",
                            "description": "Foo"},
                    "bar": {"type": "string",
                            "default": "bar-default",
                            "description": "Bar"},
                    }
                })

        charm_dir = yield repository.find(CharmURL.parse("local:series/haiku"))
        service_state = yield self.add_service_from_charm(
            "haiku", charm_dir=charm_dir)

        # Update a config value
        config = yield service_state.get_config()
        config["foo"] = "abc"
        yield config.write()

        # Upgrade the charm
        repository = self.add_charm(
            metadata=metadata,
            revision=2,
            config={
                "options": {
                    "foo": {"type": "string",
                            "default": "foo-default",
                            "description": "Foo"},
                    "bar": {"type": "string",
                            "default": "bar-default",
                            "description": "Bar"},
                    "dca": {"type": "string",
                            "default": "default-dca",
                            "description": "Airport"},
                    }
                })

        main(["upgrade-charm", "--repository", repository.path, "haiku"])

        yield finished

        config = yield service_state.get_config()
        self.assertEqual(
            config,
            {"foo": "abc", "dca": "default-dca", "bar": "bar-default"})
Example #10
0
    def assert_latest_error(self, dns_name, url_str, err_type, message):
        self.mocker.replay()
        repo = self.repo(dns_name)
        d = self.assertFailure(repo.latest(CharmURL.parse(url_str)), err_type)

        def verify(error):
            self.assertEquals(str(error), message)
        d.addCallback(verify)
        return d
Example #11
0
    def assert_find_uncached(self, dns_name, url_str, info_url, find_url):
        self.mock_charm_info(info_url, succeed(self.charm_info(url_str, 1)))
        self.mock_download(find_url)
        self.mocker.replay()

        repo = self.repo(dns_name)
        charm = yield repo.find(CharmURL.parse(url_str))
        self.assertEquals(charm.get_sha256(), self.sha256)
        self.assertEquals(charm.path, self.cache_location(url_str, 1))
        self.assertEquals(os.listdir(self.download_path), [])
Example #12
0
    def assert_find_uncached(self, dns_name, url_str, info_url, find_url):
        self.mock_charm_info(info_url, succeed(self.charm_info(url_str, 1)))
        self.mock_download(find_url)
        self.mocker.replay()

        repo = self.repo(dns_name)
        charm = yield repo.find(CharmURL.parse(url_str))
        self.assertEquals(charm.get_sha256(), self.sha256)
        self.assertEquals(charm.path, self.cache_location(url_str, 1))
        self.assertEquals(os.listdir(self.download_path), [])
Example #13
0
    def ready_upgrade(self, bad_hook):
        repository = self.increment_charm(self.charm)
        hooks_dir = os.path.join(repository.path, "series", "mysql", "hooks")
        self.write_exit_hook(
            "upgrade-charm", int(bad_hook), hooks_dir=hooks_dir)

        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)
        yield self.states["service"].set_charm_id(charm_state.id)
        self.expected_upgrade = charm_state.id
Example #14
0
    def assert_latest_error(self, dns_name, url_str, err_type, message):
        self.mocker.replay()
        repo = self.repo(dns_name)
        d = self.assertFailure(repo.latest(CharmURL.parse(url_str)), err_type)

        def verify(error):
            self.assertEquals(str(error), message)

        d.addCallback(verify)
        return d
Example #15
0
    def mark_charm_upgrade(self):
        # Create a new version of the charm
        repository = self.increment_charm(self.charm)

        # Upload the new charm version
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)

        # Mark the unit for upgrade
        yield self.states["service"].set_charm_id(charm_state.id)
        yield self.states["unit"].set_upgrade_flag()
Example #16
0
    def mark_charm_upgrade(self):
        # Create a new version of the charm
        repository = self.increment_charm(self.charm)

        # Upload the new charm version
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)

        # Mark the unit for upgrade
        yield self.states["service"].set_charm_id(charm_state.id)
        yield self.states["unit"].set_upgrade_flag()
Example #17
0
    def assert_find_cached(self, dns_name, url_str, info_url):
        os.makedirs(self.cache_path)
        cache_location = self.cache_location(url_str, 1)
        shutil.copy(self.charm.as_bundle().path, cache_location)

        self.mock_charm_info(info_url, succeed(self.charm_info(url_str, 1)))
        self.mocker.replay()

        repo = self.repo(dns_name)
        charm = yield repo.find(CharmURL.parse(url_str))
        self.assertEquals(charm.get_sha256(), self.sha256)
        self.assertEquals(charm.path, cache_location)
Example #18
0
    def assert_find_cached(self, dns_name, url_str, info_url):
        os.makedirs(self.cache_path)
        cache_location = self.cache_location(url_str, 1)
        shutil.copy(self.charm.as_bundle().path, cache_location)

        self.mock_charm_info(info_url, succeed(self.charm_info(url_str, 1)))
        self.mocker.replay()

        repo = self.repo(dns_name)
        charm = yield repo.find(CharmURL.parse(url_str))
        self.assertEquals(charm.get_sha256(), self.sha256)
        self.assertEquals(charm.path, cache_location)
Example #19
0
    def test_latest_store_warning(self):
        self.mock_charm_info(
            "https://anoth.er/charm-info?charms=cs%3Aseries/name",
            succeed(self.charm_info(
                "cs:series/name", 1, warnings=["eww", "yuck"])))
        self.mocker.replay()

        repo = self.repo("https://anoth.er")
        log = self.capture_logging("juju.charm")
        revision = yield repo.latest(CharmURL.parse("cs:series/name-1"))
        self.assertIn("eww", log.getvalue())
        self.assertIn("yuck", log.getvalue())
        self.assertEquals(revision, 1)
Example #20
0
    def test_latest_store_warning(self):
        self.mock_charm_info(
            "https://anoth.er/charm-info?charms=cs%3Aseries/name",
            succeed(
                self.charm_info("cs:series/name", 1, warnings=["eww",
                                                               "yuck"])))
        self.mocker.replay()

        repo = self.repo("https://anoth.er")
        log = self.capture_logging("juju.charm")
        revision = yield repo.latest(CharmURL.parse("cs:series/name-1"))
        self.assertIn("eww", log.getvalue())
        self.assertIn("yuck", log.getvalue())
        self.assertEquals(revision, 1)
Example #21
0
    def test_find_info_store_warning(self):
        self.mock_charm_info(
            "https://anoth.er/charm-info?charms=cs%3Aseries/name-1",
            succeed(self.charm_info(
                "cs:series/name-1", 1, warnings=["omg", "halp"])))
        self.mock_download("https://anoth.er/charm/series/name-1")
        self.mocker.replay()

        repo = self.repo("https://anoth.er")
        log = self.capture_logging("juju.charm")
        charm = yield repo.find(CharmURL.parse("cs:series/name-1"))
        self.assertIn("omg", log.getvalue())
        self.assertIn("halp", log.getvalue())
        self.assertEquals(charm.get_sha256(), self.sha256)
Example #22
0
    def test_revision(self):
        url1 = CharmURL.parse("cs:foo/bar")
        error = self.assertRaises(CharmURLError, url1.assert_revision)
        self.assertEquals(
            str(error), "Bad charm URL 'cs:foo/bar': expected a revision")

        url2 = url1.with_revision(0)
        url1.collection.schema = "local" # change url1, verify deep copied
        url2.assert_revision()
        self.assertEquals(str(url2), "cs:foo/bar-0")

        url3 = url2.with_revision(999)
        url3.assert_revision()
        self.assertEquals(str(url3), "cs:foo/bar-999")
Example #23
0
    def test_revision(self):
        url1 = CharmURL.parse("cs:foo/bar")
        error = self.assertRaises(CharmURLError, url1.assert_revision)
        self.assertEquals(str(error),
                          "Bad charm URL 'cs:foo/bar': expected a revision")

        url2 = url1.with_revision(0)
        url1.collection.schema = "local"  # change url1, verify deep copied
        url2.assert_revision()
        self.assertEquals(str(url2), "cs:foo/bar-0")

        url3 = url2.with_revision(999)
        url3.assert_revision()
        self.assertEquals(str(url3), "cs:foo/bar-999")
Example #24
0
    def test_find_info_store_warning(self):
        self.mock_charm_info(
            "https://anoth.er/charm-info?charms=cs%3Aseries/name-1",
            succeed(
                self.charm_info("cs:series/name-1",
                                1,
                                warnings=["omg", "halp"])))
        self.mock_download("https://anoth.er/charm/series/name-1")
        self.mocker.replay()

        repo = self.repo("https://anoth.er")
        log = self.capture_logging("juju.charm")
        charm = yield repo.find(CharmURL.parse("cs:series/name-1"))
        self.assertIn("omg", log.getvalue())
        self.assertIn("halp", log.getvalue())
        self.assertEquals(charm.get_sha256(), self.sha256)
Example #25
0
    def __init__(self, client, charm_id, charm_data):
        self._client = client
        self._charm_url = CharmURL.parse(charm_id)
        self._charm_url.assert_revision()

        self._metadata = MetaData()
        self._metadata.parse_serialization_data(charm_data["metadata"])

        self._config = ConfigOptions()
        self._config.parse(charm_data["config"])

        # Just a health check:
        assert self._metadata.name == self.name

        self._sha256 = charm_data["sha256"]

        self._bundle_url = charm_data.get("url")
Example #26
0
    def __init__(self, client, charm_id, charm_data):
        self._client = client
        self._charm_url = CharmURL.parse(charm_id)
        self._charm_url.assert_revision()

        self._metadata = MetaData()
        self._metadata.parse_serialization_data(charm_data["metadata"])

        self._config = ConfigOptions()
        self._config.parse(charm_data["config"])

        # Just a health check:
        assert self._metadata.name == self.name

        self._sha256 = charm_data["sha256"]

        self._bundle_url = charm_data.get("url")
Example #27
0
    def test_deploy_upgrade_remote(self):
        """The upgrade option is invalid with a remote charm."""
        repo = self.mocker.mock(RemoteCharmRepository)
        repo.type
        self.mocker.result("store")
        resolve = self.mocker.replace("juju.control.deploy.resolve")
        resolve("cs:sample", None, "series")
        self.mocker.result((repo, CharmURL.infer("cs:sample", "series")))
        repo.find(MATCH(lambda x: isinstance(x, CharmURL)))
        self.mocker.result(CharmDirectory(self.sample_dir1))
        self.mocker.replay()

        environment = self.config.get("firstenv")
        error = yield self.assertFailure(deploy.deploy(
            self.config, environment, None, "cs:sample",
            "myblog", logging.getLogger("deploy"), [], upgrade=True),
            CharmError)
        self.assertIn("Only local directory charms can be upgraded on deploy",
                      str(error))
Example #28
0
    def test_agent_upgrade_hook_failure(self):
        """An upgrade fails if the upgrade hook errors."""
        self.agent.set_watch_enabled(False)
        yield self.agent.startService()

        # Upload a new version of the unit's charm
        repository = self.increment_charm(self.charm)
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)

        # Mark the unit for upgrade
        yield self.states["service"].set_charm_id(charm_state.id)
        yield self.states["unit"].set_upgrade_flag()

        hook_done = self.wait_on_hook(
            "upgrade-charm", executor=self.agent.executor)
        self.write_hook("upgrade-charm", "#!/bin/bash\nexit 1")
        output = self.capture_logging("unit.upgrade", level=logging.DEBUG)

        # Do the upgrade
        upgrade = CharmUpgradeOperation(self.agent)
        value = yield upgrade.run()

        # Verify the failed upgrade.
        self.assertIdentical(value, False)
        self.assertIn("Invoking upgrade transition", output.getvalue())
        self.assertIn("Upgrade failed.", output.getvalue())
        yield hook_done

        # Verify state
        workflow_state = yield self.agent.workflow.get_state()
        self.assertEqual("charm_upgrade_error", workflow_state)

        # Verify new charm is in place
        new_charm = get_charm_from_path(
            os.path.join(self.agent.unit_directory, "charm"))

        self.assertEqual(
            self.charm.get_revision() + 1, new_charm.get_revision())

        # Verify upgrade flag is cleared.
        self.assertFalse((yield self.states["unit"].get_upgrade_flag()))
Example #29
0
    def test_agent_upgrade_hook_failure(self):
        """An upgrade fails if the upgrade hook errors."""
        self.agent.set_watch_enabled(False)
        yield self.agent.startService()

        # Upload a new version of the unit's charm
        repository = self.increment_charm(self.charm)
        charm = yield repository.find(CharmURL.parse("local:series/mysql"))
        charm, charm_state = yield self.publish_charm(charm.path)

        # Mark the unit for upgrade
        yield self.states["service"].set_charm_id(charm_state.id)
        yield self.states["unit"].set_upgrade_flag()

        hook_done = self.wait_on_hook("upgrade-charm",
                                      executor=self.agent.executor)
        self.write_hook("upgrade-charm", "#!/bin/bash\nexit 1")
        output = self.capture_logging("unit.upgrade", level=logging.DEBUG)

        # Do the upgrade
        upgrade = CharmUpgradeOperation(self.agent)
        value = yield upgrade.run()

        # Verify the failed upgrade.
        self.assertIdentical(value, False)
        self.assertIn("Invoking upgrade transition", output.getvalue())
        self.assertIn("Upgrade failed.", output.getvalue())
        yield hook_done

        # Verify state
        workflow_state = yield self.agent.workflow.get_state()
        self.assertEqual("charm_upgrade_error", workflow_state)

        # Verify new charm is in place
        new_charm = get_charm_from_path(
            os.path.join(self.agent.unit_directory, "charm"))

        self.assertEqual(self.charm.get_revision() + 1,
                         new_charm.get_revision())

        # Verify upgrade flag is cleared.
        self.assertFalse((yield self.states["unit"].get_upgrade_flag()))
Example #30
0
 def test_find_inappropriate_url(self):
     url = CharmURL.parse("cs:foo/bar")
     err = self.assertRaises(AssertionError, self.repository1.find, url)
     self.assertEquals(str(err), "schema mismatch")
Example #31
0
 def assert_infer(self, string, schema, user, series, name, rev):
     url = CharmURL.infer(string, "default")
     self.assert_url(url, schema, user, series, name, rev)
Example #32
0
 def assert_latest(self, dns_name, url_str, revision):
     self.mocker.replay()
     repo = self.repo(dns_name)
     result = yield repo.latest(CharmURL.parse(url_str))
     self.assertEquals(result, revision)
Example #33
0
 def assert_parse(self, string, schema, user, series, name, rev):
     url = CharmURL.parse(string)
     self.assert_url(url, schema, user, series, name, rev)
     self.assertEquals(str(url), string)
     self.assertEquals(url.path, string.split(":", 1)[1])
Example #34
0
 def charm_url(self, name):
     return CharmURL.parse("local:series/" + name)
Example #35
0
 def assert_parse(self, string, schema, user, series, name, rev):
     url = CharmURL.parse(string)
     self.assert_url(url, schema, user, series, name, rev)
     self.assertEquals(str(url), string)
     self.assertEquals(url.path, string.split(":", 1)[1])
Example #36
0
def upgrade_charm(
    config, environment, verbose, log, repository_path, service_name, dry_run):
    """Upgrades a service's charm.

    First determines if an upgrade is available, then updates the
    service charm reference, and marks the units as needing upgrades.
    """
    provider = environment.get_machine_provider()
    client = yield provider.connect()

    service_manager = ServiceStateManager(client)
    service_state = yield service_manager.get_service_state(service_name)
    old_charm_id = yield service_state.get_charm_id()

    old_charm_url = CharmURL.parse(old_charm_id)
    old_charm_url.assert_revision()
    repo, charm_url = resolve(
        str(old_charm_url.with_revision(None)),
        repository_path,
        environment.default_series)
    new_charm_url = charm_url.with_revision(
        (yield repo.latest(charm_url)))

    if charm_url.collection.schema == "local":
        if old_charm_url.revision >= new_charm_url.revision:
            new_revision = old_charm_url.revision + 1
            charm = yield repo.find(new_charm_url)
            if isinstance(charm, CharmDirectory):
                if dry_run:
                    log.info("%s would be set to revision %s",
                             charm.path, new_revision)
                else:
                    log.info("Setting %s to revision %s",
                             charm.path, new_revision)
                    charm.set_revision(new_revision)
                new_charm_url.revision = new_revision

    new_charm_id = str(new_charm_url)

    # Verify its newer than what's deployed
    if not new_charm_url.revision > old_charm_url.revision:
        if dry_run:
            log.info("Service already running latest charm %r", old_charm_id)
        else:
            raise NewerCharmNotFound(old_charm_id)
    elif dry_run:
        log.info("Service would be upgraded from charm %r to %r",
                 old_charm_id, new_charm_id)

    # On dry run, stop before modifying state.
    if not dry_run:
        # Publish the new charm
        storage = provider.get_file_storage()
        publisher = CharmPublisher(client, storage)
        charm = yield repo.find(new_charm_url)
        yield publisher.add_charm(new_charm_id, charm)
        result = yield publisher.publish()
        charm_state = result[0]

        # Update the service charm reference
        yield service_state.set_charm_id(charm_state.id)

    # Mark the units for upgrades
    units = yield service_state.get_all_unit_states()
    for unit in units:
        running, state = yield is_unit_running(client, unit)
        if not running:
            log.info(
                "Unit %r is not in a running state (state: %r), won't upgrade",
                unit.unit_name, state or "uninitialized")
            continue

        if not dry_run:
            yield unit.set_upgrade_flag()
Example #37
0
 def charm_url(self, name):
     return CharmURL.parse("local:series/" + name)
Example #38
0
 def test_find_inappropriate_url(self):
     url = CharmURL.parse("cs:foo/bar")
     err = self.assertRaises(AssertionError, self.repository1.find, url)
     self.assertEquals(str(err), "schema mismatch")
Example #39
0
 def assert_infer(self, string, schema, user, series, name, rev):
     url = CharmURL.infer(string, "default")
     self.assert_url(url, schema, user, series, name, rev)
Example #40
0
 def cache_location(self, url_str, revision):
     charm_url = CharmURL.parse(url_str)
     cache_key = under.quote("%s.charm" %
                             (charm_url.with_revision(revision)))
     return os.path.join(self.cache_path, cache_key)
Example #41
0
 def assert_latest(self, dns_name, url_str, revision):
     self.mocker.replay()
     repo = self.repo(dns_name)
     result = yield repo.latest(CharmURL.parse(url_str))
     self.assertEquals(result, revision)
Example #42
0
 def cache_location(self, url_str, revision):
     charm_url = CharmURL.parse(url_str)
     cache_key = under.quote(
         "%s.charm" % (charm_url.with_revision(revision)))
     return os.path.join(self.cache_path, cache_key)