Add channel config option
The charm uses a hardcoded channel declared in src/layer.yaml with the value 1.0/stable, this prevents users from overriding it. This became a blocker with the release of octavia-diskimage-retrofit 2.0 in the `2.0` track to support Ubuntu Noble 24.04, the snap migrated to core24[0][1] This change introduces a new configuration option that defaults to null, this will allow the charm to use the 1.0/stable channel when running on Jammy and 2.0/stable when running on Noble. Existing environments running on Jammy will see no behavior change, and no operator's intervention is needed when upgrading. [0] https://github.com/openstack-charmers/octavia-diskimage-retrofit/pull/44 [1] https://github.com/openstack-charmers/octavia-diskimage-retrofit/pull/46 Change-Id: I1ccba9de844f7900c9a8517fff4de2f8c4019871 Signed-off-by: Felipe Reyes <felipe.reyes@canonical.com> Co-Authored-by: Hemanth Nakkina <hemanth.nakkina@canonical.com> Change-Id: I1ccba9de844f7900c9a8517fff4de2f8c4019871 Signed-off-by: Hemanth Nakkina <hemanth.nakkina@canonical.com>
This commit is contained in:
co-authored by
Hemanth Nakkina
parent
93ee45ba54
commit
6671969b97
@@ -1,4 +1,9 @@
|
||||
options:
|
||||
channel:
|
||||
type: string
|
||||
default:
|
||||
description: >-
|
||||
The snap channel to install from.
|
||||
ubuntu-mirror:
|
||||
type: string
|
||||
default: ''
|
||||
|
||||
@@ -9,10 +9,6 @@ options:
|
||||
basic:
|
||||
use_venv: True
|
||||
include_system_packages: False
|
||||
snap:
|
||||
octavia-diskimage-retrofit:
|
||||
channel: 1.0/stable
|
||||
classic: true
|
||||
comment: |
|
||||
Using devmode pending resolution of snapd fuse-support issue
|
||||
https://github.com/openstack-charmers/octavia-diskimage-retrofit/issues/6
|
||||
|
||||
@@ -17,6 +17,20 @@ import charms.reactive as reactive
|
||||
import charms_openstack.bus
|
||||
import charms_openstack.charm as charm
|
||||
|
||||
from collections import defaultdict
|
||||
from charms.layer import snap
|
||||
from charms.reactive.flags import (
|
||||
set_flag,
|
||||
clear_flag,
|
||||
)
|
||||
from charmhelpers.core.hookenv import (
|
||||
config,
|
||||
log,
|
||||
)
|
||||
from charmhelpers.core.host import (
|
||||
get_distrib_codename,
|
||||
)
|
||||
|
||||
charms_openstack.bus.discover()
|
||||
|
||||
charm.use_defaults(
|
||||
@@ -26,6 +40,34 @@ charm.use_defaults(
|
||||
'upgrade-charm',
|
||||
)
|
||||
|
||||
CHANNELS = defaultdict(lambda: 'latest/edge')
|
||||
CHANNELS.update({
|
||||
'jammy': '1.0/stable',
|
||||
'noble': '2.0/stable',
|
||||
})
|
||||
|
||||
|
||||
@reactive.when_not('snap.installed.octavia-diskimage-retrofit')
|
||||
def snap_install():
|
||||
channel = config('channel')
|
||||
if not channel:
|
||||
series = get_distrib_codename()
|
||||
channel = CHANNELS[series]
|
||||
log('No snap channel configured, using default '
|
||||
'for series {}: {}'.format(series, channel),
|
||||
level="INFO")
|
||||
|
||||
if validate_snap_risk(channel):
|
||||
clear_flag('snap.channel.invalid')
|
||||
snap.install('core')
|
||||
snap.install('octavia-diskimage-retrofit',
|
||||
channel=channel,
|
||||
classic=True)
|
||||
else:
|
||||
log('Invalid snap channel risk level: {}'.format(channel),
|
||||
level="ERROR")
|
||||
set_flag('snap.channel.invalid')
|
||||
|
||||
|
||||
@reactive.when('identity-credentials.connected')
|
||||
@reactive.when_not('identity-credentials.available')
|
||||
@@ -48,3 +90,24 @@ def credentials_available():
|
||||
def retrofit_by_cron():
|
||||
with charm.provide_charm_instance() as instance:
|
||||
instance.handle_auto_retrofit()
|
||||
|
||||
|
||||
def validate_snap_risk(channel):
|
||||
"""Validate a provided snap channel's risk
|
||||
|
||||
Any prefix is ignored ('0.10' in '0.10/stable' for example).
|
||||
|
||||
:param: channel: string of the snap channel to validate
|
||||
:returns: boolean: whether provided channel is valid
|
||||
"""
|
||||
tokens = channel.split('/')
|
||||
if len(tokens) == 1:
|
||||
risk_level = tokens[0]
|
||||
else:
|
||||
# Check if track is a risk level (invalid case like 'stable/edge')
|
||||
track = tokens[0]
|
||||
risk_level = tokens[1]
|
||||
if track in ('stable', 'candidate', 'beta', 'edge'):
|
||||
return False
|
||||
|
||||
return risk_level in ('stable', 'candidate', 'beta', 'edge')
|
||||
|
||||
@@ -68,7 +68,7 @@ applications:
|
||||
path: 'streams/v1/index.sjson',
|
||||
max: 1,
|
||||
item_filters: [
|
||||
'release~(jammy)',
|
||||
'release~(noble)',
|
||||
'arch~(x86_64|amd64)',
|
||||
'ftype~(disk1.img|disk.img)'
|
||||
]
|
||||
@@ -103,8 +103,9 @@ applications:
|
||||
octavia-diskimage-retrofit:
|
||||
charm: ../../../octavia-diskimage-retrofit.charm
|
||||
options:
|
||||
retrofit-uca-pocket: antelope
|
||||
retrofit-series: jammy
|
||||
channel: 2.0/edge
|
||||
retrofit-uca-pocket: caracal
|
||||
retrofit-series: noble
|
||||
|
||||
relations:
|
||||
|
||||
|
||||
@@ -30,3 +30,11 @@ sys.modules['glanceclient'] = glanceclient
|
||||
sys.modules['keystoneauth1'] = keystoneauth1
|
||||
sys.modules['keystoneauth1.loading'] = keystoneauth1.loading
|
||||
sys.modules['keystoneauth1.session'] = keystoneauth1.session
|
||||
|
||||
# Mock out charms.layer modules
|
||||
charms_layer = mock.MagicMock()
|
||||
charms_layer_snap = mock.MagicMock()
|
||||
charms_layer_basic = mock.MagicMock()
|
||||
sys.modules['charms.layer'] = charms_layer
|
||||
sys.modules['charms.layer.snap'] = charms_layer_snap
|
||||
sys.modules['charms.layer.basic'] = charms_layer_basic
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
import reactive.octavia_diskimage_retrofit_handlers as handlers
|
||||
@@ -45,6 +46,8 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks):
|
||||
'when_not': {
|
||||
'request_credentials': (
|
||||
'identity-credentials.available',),
|
||||
'snap_install': (
|
||||
'snap.installed.octavia-diskimage-retrofit',),
|
||||
},
|
||||
}
|
||||
# test that the hooks were registered via the
|
||||
@@ -76,3 +79,27 @@ class TestOctaviaDiskimageRetrofitHandlers(test_utils.PatchHelper):
|
||||
def test_credentials_available(self):
|
||||
handlers.credentials_available()
|
||||
self.charm_instance.assess_status.assert_called_once_with()
|
||||
|
||||
|
||||
class TestValidateSnapRisk(unittest.TestCase):
|
||||
|
||||
def test_valid_risk_only(self):
|
||||
for risk in ('stable', 'candidate', 'beta', 'edge'):
|
||||
with self.subTest(risk=risk):
|
||||
self.assertTrue(handlers.validate_snap_risk(risk))
|
||||
|
||||
def test_valid_channel_with_track(self):
|
||||
self.assertTrue(handlers.validate_snap_risk('0.10/stable'))
|
||||
self.assertTrue(handlers.validate_snap_risk('latest/edge'))
|
||||
self.assertTrue(handlers.validate_snap_risk('1.0/candidate'))
|
||||
self.assertTrue(handlers.validate_snap_risk('2/beta'))
|
||||
|
||||
def test_invalid_risk_only(self):
|
||||
self.assertFalse(handlers.validate_snap_risk('invalid'))
|
||||
self.assertFalse(handlers.validate_snap_risk(''))
|
||||
self.assertFalse(handlers.validate_snap_risk('stable/edge'))
|
||||
|
||||
def test_invalid_risk_with_track(self):
|
||||
self.assertFalse(handlers.validate_snap_risk('0.10/invalid'))
|
||||
self.assertFalse(handlers.validate_snap_risk('latest/'))
|
||||
self.assertFalse(handlers.validate_snap_risk('latest/nightly'))
|
||||
|
||||
Reference in New Issue
Block a user