|
11 | 11 |
|
12 | 12 | from . import jasyncio, origin, errors |
13 | 13 | from .client import client |
| 14 | +from .errors import JujuError |
14 | 15 |
|
15 | 16 |
|
16 | 17 | async def execute_process(*cmd, log=None): |
@@ -412,7 +413,104 @@ def parse_base_arg(base): |
412 | 413 | """ |
413 | 414 | client.CharmBase() |
414 | 415 | if type(base) != str or "@" not in base: |
415 | | - raise errors.JujuError("expected base string to contain os and channel separated by '@'") |
| 416 | + raise errors.JujuError(f"expected base string to contain os and channel separated by '@', got : {base}") |
416 | 417 |
|
417 | 418 | name, channel = base.split('@') |
418 | 419 | return client.Base(name=name, channel=channel) |
| 420 | + |
| 421 | + |
| 422 | +DEFAULT_SUPPORTED_LTS = 'jammy' |
| 423 | +DEFAULT_SUPPORTED_LTS_BASE = client.Base(channel='22.04', name='ubuntu') |
| 424 | + |
| 425 | + |
| 426 | +def base_channel_from_series(track, risk, series=None): |
| 427 | + return origin.Channel(track=track, risk=risk).normalize().compute_base_channel(series=series) |
| 428 | + |
| 429 | + |
| 430 | +def get_os_from_series(series=None): |
| 431 | + if not series or series in UBUNTU_SERIES: |
| 432 | + return 'ubuntu' |
| 433 | + raise JujuError(f'os for the series {series} needs to be added') |
| 434 | + |
| 435 | + |
| 436 | +def get_base_from_origin_or_channel(origin_or_channel, series=None): |
| 437 | + channel = base_channel_from_series(origin_or_channel.track, origin_or_channel.risk, series) |
| 438 | + os_name = get_os_from_series(series) |
| 439 | + return client.Base(channel=channel, name=os_name) |
| 440 | + |
| 441 | + |
| 442 | +def series_for_charm(requested_series, supported_series): |
| 443 | + """series_for_charm takes a requested series and a list of series supported by a |
| 444 | + charm and returns the series which is relevant. |
| 445 | + If the requested series is empty, then the first supported series is used, |
| 446 | + otherwise the requested series is validated against the supported series. |
| 447 | + """ |
| 448 | + if len(supported_series) == 1 and supported_series[0] == '': |
| 449 | + raise JujuError("invalid supported series reported by charm : ['']") |
| 450 | + if len(supported_series) == 0: |
| 451 | + if requested_series == '': |
| 452 | + raise JujuError("missing series") |
| 453 | + return requested_series |
| 454 | + |
| 455 | + # use the charm default |
| 456 | + if requested_series == '': |
| 457 | + return supported_series[-1] |
| 458 | + |
| 459 | + for s in supported_series: |
| 460 | + if requested_series == s: |
| 461 | + return requested_series |
| 462 | + raise JujuError(f'requested series {requested_series} is not among the supported series {supported_series}') |
| 463 | + |
| 464 | + |
| 465 | +def user_requested(series_arg, supported_series, force): |
| 466 | + series = series_for_charm(series_arg, supported_series) |
| 467 | + if force: |
| 468 | + series = series_arg |
| 469 | + # Todo (cderici): validate the series with workload_series to see if juju is supporting that |
| 470 | + return series |
| 471 | + |
| 472 | + |
| 473 | +def series_selector(series_arg='', charm_url=None, model_config=None, supported_series=[], force=False): |
| 474 | + """ |
| 475 | + series_selector corresponds to the CharmSeries() in |
| 476 | + https://github.com/juju/juju/blob/develop/core/charm/series_selector.go |
| 477 | +
|
| 478 | + determines what series to use with a charm. |
| 479 | + Order of preference is: |
| 480 | + - user requested with --series or defined by bundle when deploying |
| 481 | + - user requested in charm's url (e.g. juju deploy jammy/ubuntu) |
| 482 | + - model default, if set, acts like --series |
| 483 | + - default from charm metadata supported series / series in url |
| 484 | + - default LTS |
| 485 | + """ |
| 486 | + |
| 487 | + # User has requested a series with --series. |
| 488 | + if series_arg: |
| 489 | + return user_requested(series_arg, supported_series, force) |
| 490 | + |
| 491 | + # User specified a series in the charm URL, e.g. |
| 492 | + # juju deploy precise/ubuntu. |
| 493 | + if charm_url and charm_url.series: |
| 494 | + return user_requested(charm_url.series, supported_series, force) |
| 495 | + |
| 496 | + # No series explicitly requested by the user. |
| 497 | + # Use model default series, if explicitly set and supported by the charm. |
| 498 | + if model_config and model_config['default-base'].value: |
| 499 | + default_base = model_config['default-base'].value |
| 500 | + base = parse_base_arg(default_base) |
| 501 | + series = base_channel_to_series(base.channel) |
| 502 | + return user_requested(series, supported_series, force) |
| 503 | + |
| 504 | + # Next fall back to the charm's list of series, filtered to what's supported |
| 505 | + # by Juju. Preserve the order of the supported series from the charm |
| 506 | + # metadata, as the order could be out of order compared to Ubuntu series |
| 507 | + # order (precise, xenial, bionic, trusty, etc). |
| 508 | + try: |
| 509 | + # TODO (cderici): restrict the supported_series with JujuSupportedSeries |
| 510 | + return user_requested('', supported_series, force) |
| 511 | + except JujuError: |
| 512 | + pass |
| 513 | + |
| 514 | + # Charm hasn't specified a default (likely due to being a local charm |
| 515 | + # deployed by path). Last chance, best we can do is default to LTS. |
| 516 | + return DEFAULT_SUPPORTED_LTS |
0 commit comments