Merge pull request #1140 from ogayot/FR-1652
Add initial integration of Ubuntu Advantage in Subiquity
This commit is contained in:
commit
73bc16b8fb
|
@ -45,6 +45,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: false
|
||||
SnapList:
|
||||
|
|
|
@ -20,6 +20,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: false
|
||||
SnapList:
|
||||
|
|
|
@ -20,6 +20,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: true
|
||||
pwauth: false
|
||||
|
|
|
@ -64,6 +64,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: true
|
||||
pwauth: false
|
||||
|
|
|
@ -45,6 +45,8 @@ Filesystem:
|
|||
fstype: ext4
|
||||
mount: /
|
||||
- action: done
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
Identity:
|
||||
realname: Ubuntu
|
||||
username: ubuntu
|
||||
|
|
|
@ -25,6 +25,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: true
|
||||
pwauth: false
|
||||
|
|
|
@ -96,6 +96,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: false
|
||||
SnapList:
|
||||
|
|
|
@ -55,6 +55,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: false
|
||||
SnapList:
|
||||
|
|
|
@ -24,6 +24,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: true
|
||||
pwauth: false
|
||||
|
|
|
@ -28,6 +28,8 @@ Identity:
|
|||
hostname: ubuntu-server
|
||||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SSH:
|
||||
install_server: false
|
||||
SnapList:
|
||||
|
|
|
@ -22,6 +22,8 @@ Identity:
|
|||
# ubuntu
|
||||
password: '$6$wdAcoXrU039hKYPd$508Qvbe7ObUnxoj15DRCkzC3qO7edjH0VV7BPNRDYK4QR8ofJaEEF2heacn0QgD.f8pO8SNp83XNdWG6tocBM1'
|
||||
ssh-import-id: gh:mwhudson
|
||||
UbuntuAdvantage:
|
||||
token: "a1b2c3d4"
|
||||
SnapList:
|
||||
snaps:
|
||||
hello:
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
DISTRIB_ID=Ubuntu
|
||||
DISTRIB_RELEASE=20.04
|
||||
DISTRIB_CODENAME=focal
|
||||
DISTRIB_DESCRIPTION="Ubuntu 20.04 LTS"
|
|
@ -0,0 +1,4 @@
|
|||
DISTRIB_ID=Ubuntu
|
||||
DISTRIB_RELEASE=21.10
|
||||
DISTRIB_CODENAME=impish
|
||||
DISTRIB_DESCRIPTION="Ubuntu 21.10"
|
|
@ -110,6 +110,7 @@ class SubiquityClient(TuiApplication):
|
|||
"Refresh",
|
||||
"Filesystem",
|
||||
"Identity",
|
||||
"UbuntuAdvantage",
|
||||
"SSH",
|
||||
"SnapList",
|
||||
"Progress",
|
||||
|
|
|
@ -26,6 +26,7 @@ from .serial import SerialController
|
|||
from .snaplist import SnapListController
|
||||
from .source import SourceController
|
||||
from .ssh import SSHController
|
||||
from .ubuntu_advantage import UbuntuAdvantageController
|
||||
from .welcome import WelcomeController
|
||||
from .zdev import ZdevController
|
||||
|
||||
|
@ -44,6 +45,7 @@ __all__ = [
|
|||
'SnapListController',
|
||||
'SourceController',
|
||||
'SSHController',
|
||||
'UbuntuAdvantageController',
|
||||
'WelcomeController',
|
||||
'ZdevController',
|
||||
]
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
# Copyright 2021 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
""" Module that defines the client-side controller class for Ubuntu Advantage.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from subiquity.client.controller import SubiquityTuiController
|
||||
from subiquity.common.types import UbuntuAdvantageInfo
|
||||
from subiquity.ui.views.ubuntu_advantage import UbuntuAdvantageView
|
||||
|
||||
from subiquitycore.lsb_release import lsb_release
|
||||
from subiquitycore.tuicontroller import Skip
|
||||
|
||||
log = logging.getLogger("subiquity.client.controllers.ubuntu_advantage")
|
||||
|
||||
|
||||
class UbuntuAdvantageController(SubiquityTuiController):
|
||||
""" Client-side controller for Ubuntu Advantage configuration. """
|
||||
|
||||
endpoint_name = "ubuntu_advantage"
|
||||
|
||||
async def make_ui(self) -> UbuntuAdvantageView:
|
||||
""" Generate the UI, based on the data provided by the model. """
|
||||
|
||||
# TODO remove these two lines to enable this screen
|
||||
await self.endpoint.skip.POST()
|
||||
raise Skip("Hiding the screen until we can validate the token.")
|
||||
|
||||
path_lsb_release: Optional[str] = None
|
||||
if self.app.opts.dry_run:
|
||||
# In dry-run mode, always pretend to be on LTS
|
||||
path_lsb_release = "examples/lsb-release-focal"
|
||||
if "LTS" not in lsb_release(path_lsb_release)["description"]:
|
||||
await self.endpoint.skip.POST()
|
||||
raise Skip("Not running LTS version")
|
||||
|
||||
ubuntu_advantage_info = await self.endpoint.GET()
|
||||
return UbuntuAdvantageView(self, ubuntu_advantage_info.token)
|
||||
|
||||
def run_answers(self) -> None:
|
||||
if "token" in self.answers:
|
||||
self.done(self.answers["token"])
|
||||
|
||||
def cancel(self) -> None:
|
||||
self.app.prev_screen()
|
||||
|
||||
def done(self, token: str) -> None:
|
||||
log.debug("UbuntuAdvantageController.done token=%s", token)
|
||||
self.app.next_screen(
|
||||
self.endpoint.POST(UbuntuAdvantageInfo(token=token))
|
||||
)
|
|
@ -48,6 +48,7 @@ from subiquity.common.types import (
|
|||
StorageResponse,
|
||||
StorageResponseV2,
|
||||
TimeZoneInfo,
|
||||
UbuntuAdvantageInfo,
|
||||
WLANSupportInstallState,
|
||||
ZdevInfo,
|
||||
WSLConfigurationBase,
|
||||
|
@ -312,6 +313,13 @@ class API:
|
|||
def GET() -> List[str]: ...
|
||||
def POST(data: Payload[List[str]]): ...
|
||||
|
||||
class ubuntu_advantage:
|
||||
def GET() -> UbuntuAdvantageInfo: ...
|
||||
def POST(data: Payload[UbuntuAdvantageInfo]) -> None: ...
|
||||
|
||||
class skip:
|
||||
def POST() -> None: ...
|
||||
|
||||
|
||||
class LinkAction(enum.Enum):
|
||||
NEW = enum.auto()
|
||||
|
|
|
@ -389,6 +389,11 @@ class TimeZoneInfo:
|
|||
from_geoip: bool
|
||||
|
||||
|
||||
@attr.s(auto_attribs=True)
|
||||
class UbuntuAdvantageInfo:
|
||||
token: str
|
||||
|
||||
|
||||
class ShutdownMode(enum.Enum):
|
||||
REBOOT = enum.auto()
|
||||
POWEROFF = enum.auto()
|
||||
|
|
|
@ -41,6 +41,7 @@ from .snaplist import SnapListModel
|
|||
from .source import SourceModel
|
||||
from .ssh import SSHModel
|
||||
from .timezone import TimeZoneModel
|
||||
from .ubuntu_advantage import UbuntuAdvantageModel
|
||||
from .updates import UpdatesModel
|
||||
|
||||
|
||||
|
@ -143,6 +144,7 @@ class SubiquityModel:
|
|||
self.ssh = SSHModel()
|
||||
self.source = SourceModel()
|
||||
self.timezone = TimeZoneModel()
|
||||
self.ubuntu_advantage = UbuntuAdvantageModel()
|
||||
self.updates = UpdatesModel()
|
||||
self.userdata = {}
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright 2021 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import unittest
|
||||
|
||||
from subiquity.models.ubuntu_advantage import UbuntuAdvantageModel
|
||||
|
||||
|
||||
class TestUbuntuAdvantageModel(unittest.TestCase):
|
||||
def test_make_cloudconfig_(self):
|
||||
model = UbuntuAdvantageModel()
|
||||
|
||||
# Test with a token
|
||||
model.token = "0a1b2c3d4e5f6"
|
||||
expected = {
|
||||
"ubuntu_advantage": {
|
||||
"token": "0a1b2c3d4e5f6",
|
||||
}
|
||||
}
|
||||
self.assertEqual(model.make_cloudconfig(), expected)
|
||||
|
||||
# Test without token
|
||||
model.token = ""
|
||||
self.assertEqual(model.make_cloudconfig(), {})
|
||||
model.token = None
|
||||
self.assertEqual(model.make_cloudconfig(), {})
|
|
@ -0,0 +1,47 @@
|
|||
# Copyright 2021 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
""" Module that defines the model for Ubuntu Advantage configuration. """
|
||||
|
||||
import logging
|
||||
|
||||
log = logging.getLogger("subiquitycore.models.ubuntu_advantage")
|
||||
|
||||
|
||||
class UbuntuAdvantageModel:
|
||||
"""
|
||||
Model that represents the Ubuntu Advantage configuration.
|
||||
Currently, we rely only on cloud-init so we have no means to validate that
|
||||
the provided token is correct ; nor to retrieve information about the
|
||||
subscription.
|
||||
"""
|
||||
def __init__(self):
|
||||
""" Initialize the model. """
|
||||
self.token: str = ""
|
||||
|
||||
def make_cloudconfig(self) -> dict:
|
||||
"""
|
||||
Return a dictionary that will be included in cloud-init config.
|
||||
Having the token set to the empty-string disables the configuration.
|
||||
"""
|
||||
if not self.token:
|
||||
return {}
|
||||
# Both "ubuntu_advantage" and "ubuntu-advantage" keys are accepted, but
|
||||
# "ubuntu-advantage" is deprecated despite not being mentioned in the
|
||||
# documentation.
|
||||
return {
|
||||
"ubuntu_advantage": {
|
||||
"token": self.token,
|
||||
},
|
||||
}
|
|
@ -32,6 +32,7 @@ from .snaplist import SnapListController
|
|||
from .source import SourceController
|
||||
from .ssh import SSHController
|
||||
from .timezone import TimeZoneController
|
||||
from .ubuntu_advantage import UbuntuAdvantageController
|
||||
from .updates import UpdatesController
|
||||
from .userdata import UserdataController
|
||||
from .zdev import ZdevController
|
||||
|
@ -58,6 +59,7 @@ __all__ = [
|
|||
'SourceController',
|
||||
'SSHController',
|
||||
'TimeZoneController',
|
||||
'UbuntuAdvantageController',
|
||||
'UpdatesController',
|
||||
'UserdataController',
|
||||
'ZdevController',
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# Copyright 2021 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import unittest
|
||||
|
||||
from subiquity.server.controllers.ubuntu_advantage import (
|
||||
UbuntuAdvantageController,
|
||||
)
|
||||
from subiquitycore.tests.mocks import make_app
|
||||
|
||||
|
||||
class TestUbuntuAdvantageController(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.controller = UbuntuAdvantageController(make_app())
|
||||
|
||||
def test_serialize(self):
|
||||
self.controller.model.token = "1a2b3C"
|
||||
self.assertEqual(self.controller.serialize(), "1a2b3C")
|
||||
|
||||
def test_deserialize(self):
|
||||
self.controller.deserialize("1A2B3C4D")
|
||||
self.assertEqual(self.controller.model.token, "1A2B3C4D")
|
|
@ -0,0 +1,58 @@
|
|||
# Copyright 2021 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
""" Module defining the server-side controller class for Ubuntu Advantage. """
|
||||
|
||||
import logging
|
||||
|
||||
from subiquity.common.apidef import API
|
||||
from subiquity.common.types import UbuntuAdvantageInfo
|
||||
from subiquity.server.controller import SubiquityController
|
||||
|
||||
log = logging.getLogger("subiquity.server.controllers.ubuntu_advantage")
|
||||
|
||||
|
||||
class UbuntuAdvantageController(SubiquityController):
|
||||
""" Represent the server-side Ubuntu Advantage controller. """
|
||||
|
||||
endpoint = API.ubuntu_advantage
|
||||
|
||||
model_name = "ubuntu_advantage"
|
||||
|
||||
def serialize(self) -> str:
|
||||
""" Save the current state of the model so it can be loaded later.
|
||||
Currently this function is called automatically by .configured().
|
||||
"""
|
||||
return self.model.token
|
||||
|
||||
def deserialize(self, token: str) -> None:
|
||||
""" Loads the last-known state of the model. """
|
||||
self.model.token = token
|
||||
|
||||
async def GET(self) -> UbuntuAdvantageInfo:
|
||||
""" Handle a GET request coming from the client-side controller. """
|
||||
return UbuntuAdvantageInfo(token=self.model.token)
|
||||
|
||||
async def POST(self, data: UbuntuAdvantageInfo) -> None:
|
||||
""" Handle a POST request coming from the client-side controller and
|
||||
then call .configured().
|
||||
"""
|
||||
log.debug("Received POST: %s", data)
|
||||
self.model.token = data.token
|
||||
await self.configured()
|
||||
|
||||
async def skip_POST(self) -> None:
|
||||
""" When running on a non-LTS release, we want to call this so we can
|
||||
skip the screen on the client side. """
|
||||
await self.configured()
|
|
@ -204,6 +204,7 @@ POSTINSTALL_MODEL_NAMES = ModelNames({
|
|||
"packages",
|
||||
"snaplist",
|
||||
"ssh",
|
||||
"ubuntu_advantage",
|
||||
"userdata",
|
||||
},
|
||||
desktop={"timezone"})
|
||||
|
@ -242,6 +243,7 @@ class SubiquityServer(Application):
|
|||
"Zdev",
|
||||
"Source",
|
||||
"Network",
|
||||
"UbuntuAdvantage",
|
||||
"Proxy",
|
||||
"Mirror",
|
||||
"Filesystem",
|
||||
|
|
|
@ -215,6 +215,10 @@ class TestFlow(TestAPI):
|
|||
}
|
||||
await inst.post('/ssh', ssh)
|
||||
await inst.post('/snaplist', [])
|
||||
ua_params = {
|
||||
"token": "a1b2c3d4e6f7g8h9I0K1",
|
||||
}
|
||||
await inst.post('/ubuntu_advantage', ua_params)
|
||||
for state in 'RUNNING', 'POST_WAIT', 'POST_RUNNING', 'UU_RUNNING':
|
||||
await inst.get('/meta/status', cur=state)
|
||||
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
# Copyright 2021 Canonical, Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
""" Module that defines the view class for Ubuntu Advantage configuration. """
|
||||
|
||||
import logging
|
||||
import re
|
||||
|
||||
from urwid import connect_signal
|
||||
|
||||
from subiquitycore.view import BaseView
|
||||
from subiquitycore.ui.form import (
|
||||
Form,
|
||||
simple_field,
|
||||
WantsToKnowFormField,
|
||||
)
|
||||
|
||||
from subiquitycore.ui.interactive import StringEditor
|
||||
|
||||
|
||||
log = logging.getLogger('subiquity.ui.views.ubuntu_advantage')
|
||||
|
||||
ua_help = _("If you want to enroll this system using your Ubuntu Advantage "
|
||||
"subscription, enter your Ubuntu Advantage token here. "
|
||||
"Otherwise, leave this blank.")
|
||||
|
||||
|
||||
class UATokenEditor(StringEditor, WantsToKnowFormField):
|
||||
""" Represent a text-box editor for the Ubuntu Advantage Token. """
|
||||
def __init__(self):
|
||||
""" Initialize the text-field editor for UA token. """
|
||||
self.valid_char_pat = r"[a-zA-Z0-9]"
|
||||
self.error_invalid_char = _("The only characters permitted in this "
|
||||
"field are alphanumeric characters.")
|
||||
super().__init__()
|
||||
|
||||
def valid_char(self, ch: str) -> bool:
|
||||
""" Tells whether the character passed is within the range of allowed
|
||||
characters
|
||||
"""
|
||||
if len(ch) == 1 and not re.match(self.valid_char_pat, ch):
|
||||
self.bff.in_error = True
|
||||
self.bff.show_extra(("info_error", self.error_invalid_char))
|
||||
return False
|
||||
return super().valid_char(ch)
|
||||
|
||||
|
||||
class UbuntuAdvantageForm(Form):
|
||||
"""
|
||||
Represents a form requesting Ubuntu Advantage information
|
||||
"""
|
||||
cancel_label = _("Back")
|
||||
|
||||
UATokenField = simple_field(UATokenEditor)
|
||||
|
||||
token = UATokenField(_("Ubuntu Advantage token:"), help=ua_help)
|
||||
|
||||
|
||||
class UbuntuAdvantageView(BaseView):
|
||||
""" Represent the view of the Ubuntu Advantage configuration. """
|
||||
|
||||
title = _("Enable Ubuntu Advantage")
|
||||
excerpt = _("Enter your Ubuntu Advantage token if you want to enroll "
|
||||
"this system.")
|
||||
|
||||
def __init__(self, controller, token: str):
|
||||
""" Initialize the view with the default value for the token. """
|
||||
self.controller = controller
|
||||
|
||||
self.form = UbuntuAdvantageForm(initial={"token": token})
|
||||
|
||||
def on_cancel(_: UbuntuAdvantageForm):
|
||||
self.cancel()
|
||||
|
||||
connect_signal(self.form, 'submit', self.done)
|
||||
connect_signal(self.form, 'cancel', on_cancel)
|
||||
|
||||
super().__init__(self.form.as_screen(excerpt=_(self.excerpt)))
|
||||
|
||||
def done(self, form: UbuntuAdvantageForm) -> None:
|
||||
""" Called when the user presses the Done button. """
|
||||
log.debug("User input: %r", form.as_data())
|
||||
|
||||
self.controller.done(form.token.value)
|
||||
|
||||
def cancel(self) -> None:
|
||||
""" Called when the user presses the Back button. """
|
||||
self.controller.cancel()
|
Loading…
Reference in New Issue