// upgradeCharm upgrades the charm for the given service to the given charm id. // If the service is already deployed using the given charm id, do nothing. // This function returns an error if the existing charm and the target one are // incompatible, meaning an upgrade from one to the other is not allowed. func upgradeCharm(client *api.Client, log deploymentLogger, service, id string) error { existing, err := client.ServiceGetCharmURL(service) if err != nil { return errors.Annotatef(err, "cannot retrieve info for service %q", service) } if existing.String() == id { log.Infof("reusing service %s (charm: %s)", service, id) return nil } url, err := charm.ParseURL(id) if err != nil { return errors.Annotatef(err, "cannot parse charm URL %q", id) } if url.WithRevision(-1).Path() != existing.WithRevision(-1).Path() { return errors.Errorf("bundle charm %q is incompatible with existing charm %q", id, existing) } if err := client.ServiceSetCharm(service, id, false); err != nil { return errors.Annotatef(err, "cannot upgrade charm to %q", id) } log.Infof("upgraded charm for existing service %s (from %s to %s)", service, existing, id) return nil }