annotate sat/plugins/plugin_misc_app_manager.py @ 3877:00212260f659

plugin XEP-0420: Implementation of Stanza Content Encryption: Includes implementation of XEP-0082 (XMPP date and time profiles) and tests for both new plugins. Everything is type checked, linted, format checked and unit tested. Adds new dependency xmlschema. fix 377
author Syndace <me@syndace.dev>
date Tue, 23 Aug 2022 12:04:11 +0200
parents d66a8453b02b
children 402d31527af4
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3372
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
1 #!/usr/bin/env python3
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
2
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
3 # SàT plugin to manage external applications
3479
be6d91572633 date update
Goffi <goffi@goffi.org>
parents: 3417
diff changeset
4 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
3372
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
5
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
6 # This program is free software: you can redistribute it and/or modify
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
7 # it under the terms of the GNU Affero General Public License as published by
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
8 # the Free Software Foundation, either version 3 of the License, or
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
9 # (at your option) any later version.
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
10
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
11 # This program is distributed in the hope that it will be useful,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
14 # GNU Affero General Public License for more details.
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
15
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
16 # You should have received a copy of the GNU Affero General Public License
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
18
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
19 from pathlib import Path
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
20 from typing import Optional, List
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
21 from functools import partial, reduce
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
22 import tempfile
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
23 import secrets
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
24 import string
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
25 import shortuuid
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
26 from twisted.internet import defer
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from twisted.python.procutils import which
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
28 from sat.core.i18n import _
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
29 from sat.core import exceptions
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
30 from sat.core.constants import Const as C
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
31 from sat.core.log import getLogger
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
32 from sat.tools.common import data_format
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
33 from sat.tools.common import async_process
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
34
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
35 log = getLogger(__name__)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
36
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
37 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
38 import yaml
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
39 except ImportError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
40 raise exceptions.MissingModule(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
41 'Missing module PyYAML, please download/install it. You can use '
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
42 '"pip install pyyaml"'
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
43 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
44
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
45 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
46 from yaml import CLoader as Loader, CDumper as Dumper
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
47 except ImportError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
48 log.warning(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
49 "Can't use LibYAML binding (is libyaml installed?), pure Python version will be "
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
50 "used, but it is slower"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
51 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
52 from yaml import Loader, Dumper
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
53
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
54 from yaml.constructor import ConstructorError
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
55
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
56
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
57 PLUGIN_INFO = {
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
58 C.PI_NAME: "Applications Manager",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
59 C.PI_IMPORT_NAME: "APP_MANAGER",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
60 C.PI_TYPE: C.PLUG_TYPE_MISC,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
61 C.PI_MODES: C.PLUG_MODE_BOTH,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
62 C.PI_MAIN: "AppManager",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
63 C.PI_HANDLER: "no",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
64 C.PI_DESCRIPTION: _(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
65 """Applications Manager
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
66
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
67 Manage external applications using packagers, OS virtualization/containers or other
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
68 software management tools.
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
69 """),
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
70 }
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
71
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
72 APP_FILE_PREFIX = "sat_app_"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
73
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
74
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
75 class AppManager:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
76 load = partial(yaml.load, Loader=Loader)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
77 dump = partial(yaml.dump, Dumper=Dumper)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
78
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
79 def __init__(self, host):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
80 log.info(_("plugin Applications Manager initialization"))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
81 self.host = host
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
82 self._managers = {}
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
83 self._apps = {}
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
84 self._started = {}
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
85 # instance id to app data map
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
86 self._instances = {}
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
87 host.bridge.addMethod(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
88 "applicationsList",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
89 ".plugin",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
90 in_sign="as",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
91 out_sign="as",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
92 method=self.list_applications,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
93 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
94 host.bridge.addMethod(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
95 "applicationStart",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
96 ".plugin",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
97 in_sign="ss",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
98 out_sign="",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
99 method=self._start,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
100 async_=True,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
101 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
102 host.bridge.addMethod(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
103 "applicationStop",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
104 ".plugin",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
105 in_sign="sss",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
106 out_sign="",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
107 method=self._stop,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
108 async_=True,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
109 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
110 host.bridge.addMethod(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
111 "applicationExposedGet",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
112 ".plugin",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
113 in_sign="sss",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
114 out_sign="s",
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
115 method=self._getExposed,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
116 async_=True,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
117 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
118 yaml.add_constructor(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
119 "!sat_conf", self._sat_conf_constr, Loader=Loader)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
120 yaml.add_constructor(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
121 "!sat_generate_pwd", self._sat_generate_pwd_constr, Loader=Loader)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
122 yaml.add_constructor(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
123 "!sat_param", self._sat_param_constr, Loader=Loader)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
124
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
125 def unload(self):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
126 log.debug("unloading applications manager")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
127 for instances in self._started.values():
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
128 for instance in instances:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
129 data = instance['data']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
130 if not data['single_instance']:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
131 log.debug(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
132 f"cleaning temporary directory at {data['_instance_dir_path']}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
133 data['_instance_dir_obj'].cleanup()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
134
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
135 def _sat_conf_constr(self, loader, node):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
136 """Get a value from SàT configuration
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
137
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
138 A list is expected with either "name" of a config parameter, a one or more of
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
139 those parameters:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
140 - section
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
141 - name
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
142 - default value
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
143 - filter
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
144 filter can be:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
145 - "first": get the first item of the value
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
146 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
147 config_data = loader.construct_sequence(node)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
148 if len(config_data) == 1:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
149 section, name, default, filter_ = "", config_data[0], None, None
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
150 if len(config_data) == 2:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
151 (section, name), default, filter_ = config_data, None, None
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
152 elif len(config_data) == 3:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
153 (section, name, default), filter_ = config_data, None
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
154 elif len(config_data) == 4:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
155 section, name, default, filter_ = config_data
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
156 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
157 raise ValueError(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
158 f"invalid !sat_conf value ({config_data!r}), a list of 1 to 4 items is "
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
159 "expected"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
160 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
161
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
162 value = self.host.memory.getConfig(section, name, default)
3564
2c9e95796371 plugin app manager: "public_url" must NOT have a schema
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
163 # FIXME: "public_url" is used only here and doesn't take multi-sites into account
2c9e95796371 plugin app manager: "public_url" must NOT have a schema
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
164 if name == "public_url" and (not value or value.startswith('http')):
3372
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
165 if not value:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
166 log.warning(_(
3564
2c9e95796371 plugin app manager: "public_url" must NOT have a schema
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
167 'No value found for "public_url", using "example.org" for '
2c9e95796371 plugin app manager: "public_url" must NOT have a schema
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
168 'now, please set the proper value in libervia.conf'))
3372
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
169 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
170 log.warning(_(
3564
2c9e95796371 plugin app manager: "public_url" must NOT have a schema
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
171 'invalid value for "public_url" ({value}), it musts not start with '
2c9e95796371 plugin app manager: "public_url" must NOT have a schema
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
172 'schema ("http"), ignoring it and using "example.org" '
2c9e95796371 plugin app manager: "public_url" must NOT have a schema
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
173 'instead')
3372
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
174 .format(value=value))
3564
2c9e95796371 plugin app manager: "public_url" must NOT have a schema
Goffi <goffi@goffi.org>
parents: 3479
diff changeset
175 value = "example.org"
3372
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
176
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
177 if filter_ is None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
178 pass
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
179 elif filter_ == 'first':
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
180 value = value[0]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
181 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
182 raise ValueError(f"unmanaged filter: {filter_}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
183
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
184 return value
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
185
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
186 def _sat_generate_pwd_constr(self, loader, node):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
187 alphabet = string.ascii_letters + string.digits
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
188 return ''.join(secrets.choice(alphabet) for i in range(30))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
189
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
190 def _sat_param_constr(self, loader, node):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
191 """Get a parameter specified when starting the application
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
192
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
193 The value can be either the name of the parameter to get, or a list as
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
194 [name, default_value]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
195 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
196 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
197 name, default = loader.construct_sequence(node)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
198 except ConstructorError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
199 name, default = loader.construct_scalar(node), None
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
200 return self._params.get(name, default)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
201
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
202 def register(self, manager):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
203 name = manager.name
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
204 if name in self._managers:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
205 raise exceptions.ConflictError(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
206 f"There is already a manager with the name {name}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
207 self._managers[manager.name] = manager
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
208 if hasattr(manager, "discover_path"):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
209 self.discover(manager.discover_path, manager)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
210
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
211 def getManager(self, app_data: dict) -> object:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
212 """Get manager instance needed for this app
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
213
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
214 @raise exceptions.DataError: something is wrong with the type
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
215 @raise exceptions.NotFound: manager is not registered
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
216 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
217 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
218 app_type = app_data["type"]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
219 except KeyError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
220 raise exceptions.DataError(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
221 "app file doesn't have the mandatory \"type\" key"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
222 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
223 if not isinstance(app_type, str):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
224 raise exceptions.DataError(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
225 f"invalid app data type: {app_type!r}"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
226 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
227 app_type = app_type.strip()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
228 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
229 return self._managers[app_type]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
230 except KeyError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
231 raise exceptions.NotFound(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
232 f"No manager found to manage app of type {app_type!r}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
233
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
234 def getAppData(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
235 self,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
236 id_type: Optional[str],
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
237 identifier: str
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
238 ) -> dict:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
239 """Retrieve instance's app_data from identifier
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
240
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
241 @param id_type: type of the identifier, can be:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
242 - "name": identifier is a canonical application name
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
243 the first found instance of this application is returned
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
244 - "instance": identifier is an instance id
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
245 @param identifier: identifier according to id_type
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
246 @return: instance application data
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
247 @raise exceptions.NotFound: no instance with this id can be found
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
248 @raise ValueError: id_type is invalid
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
249 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
250 if not id_type:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
251 id_type = 'name'
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
252 if id_type == 'name':
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
253 identifier = identifier.lower().strip()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
254 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
255 return next(iter(self._started[identifier]))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
256 except (KeyError, StopIteration):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
257 raise exceptions.NotFound(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
258 f"No instance of {identifier!r} is currently running"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
259 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
260 elif id_type == 'instance':
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
261 instance_id = identifier
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
262 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
263 return self._instances[instance_id]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
264 except KeyError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
265 raise exceptions.NotFound(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
266 f"There is no application instance running with id {instance_id!r}"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
267 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
268 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
269 raise ValueError(f"invalid id_type: {id_type!r}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
270
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
271 def discover(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
272 self,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
273 dir_path: Path,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
274 manager: Optional = None
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
275 ) -> None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
276 for file_path in dir_path.glob(f"{APP_FILE_PREFIX}*.yaml"):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
277 if manager is None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
278 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
279 app_data = self.parse(file_path)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
280 manager = self.getManager(app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
281 except (exceptions.DataError, exceptions.NotFound) as e:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
282 log.warning(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
283 f"Can't parse {file_path}, skipping: {e}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
284 app_name = file_path.stem[len(APP_FILE_PREFIX):].strip().lower()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
285 if not app_name:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
286 log.warning(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
287 f"invalid app file name at {file_path}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
288 continue
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
289 app_dict = self._apps.setdefault(app_name, {})
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
290 manager_set = app_dict.setdefault(manager, set())
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
291 manager_set.add(file_path)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
292 log.debug(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
293 f"{app_name!r} {manager.name} application found"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
294 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
295
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
296 def parse(self, file_path: Path, params: Optional[dict] = None) -> dict:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
297 """Parse SàT application file
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
298
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
299 @param params: parameters for running this instance
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
300 @raise exceptions.DataError: something is wrong in the file
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
301 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
302 if params is None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
303 params = {}
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
304 with file_path.open() as f:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
305 # we set parameters to be used only with this instance
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
306 # no async method must used between this assignation and `load`
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
307 self._params = params
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
308 app_data = self.load(f)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
309 self._params = None
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
310 if "name" not in app_data:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
311 # note that we don't use lower() here as we want human readable name and
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
312 # uppercase may be set on purpose
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
313 app_data['name'] = file_path.stem[len(APP_FILE_PREFIX):].strip()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
314 single_instance = app_data.setdefault("single_instance", True)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
315 if not isinstance(single_instance, bool):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
316 raise ValueError(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
317 f'"single_instance" must be a boolean, but it is {type(single_instance)}'
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
318 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
319 return app_data
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
320
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
321 def list_applications(self, filters: Optional[List[str]]) -> List[str]:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
322 """List available application
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
323
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
324 @param filters: only show applications matching those filters.
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
325 using None will list all known applications
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
326 a filter can be:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
327 - available: applications available locally
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
328 - running: only show launched applications
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
329 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
330 if not filters:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
331 return list(self.apps)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
332 found = set()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
333 for filter_ in filters:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
334 if filter_ == "available":
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
335 found.update(self._apps)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
336 elif filter_ == "running":
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
337 found.update(self._started)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
338 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
339 raise ValueError(f"Unknown filter: {filter_}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
340 return list(found)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
341
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
342 def _start(self, app_name, extra):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
343 extra = data_format.deserialise(extra)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
344 return defer.ensureDeferred(self.start(str(app_name), extra))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
345
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
346 async def start(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
347 self,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
348 app_name: str,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
349 extra: Optional[dict] = None,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
350 ) -> None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
351 # FIXME: for now we use the first app manager available for the requested app_name
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
352 # TODO: implement running multiple instance of the same app if some metadata
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
353 # to be defined in app_data allows explicitly it.
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
354 app_name = app_name.lower().strip()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
355 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
356 app_file_path = next(iter(next(iter(self._apps[app_name].values()))))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
357 except KeyError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
358 raise exceptions.NotFound(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
359 f"No application found with the name {app_name!r}"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
360 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
361 started_data = self._started.setdefault(app_name, [])
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
362 app_data = self.parse(app_file_path, extra)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
363 app_data['_file_path'] = app_file_path
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
364 app_data['_name_canonical'] = app_name
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
365 single_instance = app_data['single_instance']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
366 if single_instance:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
367 if started_data:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
368 log.info(f"{app_name!r} is already started")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
369 return
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
370 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
371 cache_path = self.host.memory.getCachePath(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
372 PLUGIN_INFO[C.PI_IMPORT_NAME], app_name
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
373 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
374 cache_path.mkdir(0o700, parents=True, exist_ok=True)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
375 app_data['_instance_dir_path'] = cache_path
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
376 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
377 dest_dir_obj = tempfile.TemporaryDirectory(prefix="sat_app_")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
378 app_data['_instance_dir_obj'] = dest_dir_obj
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
379 app_data['_instance_dir_path'] = Path(dest_dir_obj.name)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
380 instance_id = app_data['_instance_id'] = shortuuid.uuid()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
381 manager = self.getManager(app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
382 app_data['_manager'] = manager
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
383 started_data.append(app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
384 self._instances[instance_id] = app_data
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
385
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
386 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
387 start = manager.start
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
388 except AttributeError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
389 raise exceptions.InternalError(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
390 f"{manager.name} doesn't have the mandatory \"start\" method"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
391 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
392 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
393 await start(app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
394 log.info(f"{app_name!r} started")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
395
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
396 def _stop(self, identifier, id_type, extra):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
397 extra = data_format.deserialise(extra)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
398 return defer.ensureDeferred(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
399 self.stop(str(identifier), str(id_type) or None, extra))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
400
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
401 async def stop(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
402 self,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
403 identifier: str,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
404 id_type: Optional[str] = None,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
405 extra: Optional[dict] = None,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
406 ) -> None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
407 if extra is None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
408 extra = {}
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
409
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
410 app_data = self.getAppData(id_type, identifier)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
411
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
412 log.info(f"stopping {app_data['name']!r}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
413
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
414 app_name = app_data['_name_canonical']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
415 instance_id = app_data['_instance_id']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
416 manager = app_data['_manager']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
417
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
418 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
419 stop = manager.stop
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
420 except AttributeError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
421 raise exceptions.InternalError(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
422 f"{manager.name} doesn't have the mandatory \"stop\" method"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
423 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
424 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
425 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
426 await stop(app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
427 except Exception as e:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
428 log.warning(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
429 f"Instance {instance_id} of application {app_name} can't be stopped "
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
430 f"properly: {e}"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
431 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
432 return
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
433
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
434 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
435 del self._instances[instance_id]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
436 except KeyError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
437 log.error(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
438 f"INTERNAL ERROR: {instance_id!r} is not present in self._instances")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
439
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
440 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
441 self._started[app_name].remove(app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
442 except ValueError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
443 log.error(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
444 "INTERNAL ERROR: there is no app data in self._started with id "
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
445 f"{instance_id!r}"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
446 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
447
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
448 log.info(f"{app_name!r} stopped")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
449
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
450 def _getExposed(self, identifier, id_type, extra):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
451 extra = data_format.deserialise(extra)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
452 d = defer.ensureDeferred(self.getExposed(identifier, id_type, extra))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
453 d.addCallback(lambda d: data_format.serialise(d))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
454 return d
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
455
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
456 def getValueFromPath(self, app_data: dict, path: List[str]) -> any:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
457 """Retrieve a value set in the data from it path
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
458
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
459 @param path: list of key to use in app_data to retrieve the value
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
460 @return: found value
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
461 @raise NotFound: the value can't be found
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
462 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
463
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
464 async def getExposed(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
465 self,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
466 identifier: str,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
467 id_type: Optional[str] = None,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
468 extra: Optional[dict] = None,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
469 ) -> dict:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
470 """Get data exposed by the application
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
471
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
472 The manager's "computeExpose" method will be called if it exists. It can be used
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
473 to handle manager specific conventions.
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
474 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
475 app_data = self.getAppData(id_type, identifier)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
476 if app_data.get('_exposed_computed', False):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
477 return app_data['expose']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
478 if extra is None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
479 extra = {}
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
480 expose = app_data.setdefault("expose", {})
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
481 if "passwords" in expose:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
482 passwords = expose['passwords']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
483 for name, value in list(passwords.items()):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
484 if isinstance(value, list):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
485 # if we have a list, is the sequence of keys leading to the value
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
486 # to expose. We use "reduce" to retrieve the desired value
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
487 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
488 passwords[name] = reduce(lambda l, k: l[k], value, app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
489 except Exception as e:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
490 log.warning(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
491 f"Can't retrieve exposed value for password {name!r}: {e}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
492 del passwords[name]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
493
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
494 url_prefix = expose.get("url_prefix")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
495 if isinstance(url_prefix, list):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
496 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
497 expose["url_prefix"] = reduce(lambda l, k: l[k], url_prefix, app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
498 except Exception as e:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
499 log.warning(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
500 f"Can't retrieve exposed value for url_prefix: {e}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
501 del expose["url_prefix"]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
502
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
503 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
504 computeExpose = app_data['_manager'].computeExpose
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
505 except AttributeError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
506 pass
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
507 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
508 await computeExpose(app_data)
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
509
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
510 app_data['_exposed_computed'] = True
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
511 return expose
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
512
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
513 async def _doPrepare(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
514 self,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
515 app_data: dict,
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
516 ) -> None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
517 name = app_data['name']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
518 dest_path = app_data['_instance_dir_path']
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
519 if next(dest_path.iterdir(), None) != None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
520 log.debug(f"There is already a prepared dir at {dest_path}, nothing to do")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
521 return
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
522 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
523 prepare = app_data['prepare'].copy()
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
524 except KeyError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
525 prepare = {}
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
526
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
527 if not prepare:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
528 log.debug("Nothing to prepare for {name!r}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
529 return
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
530
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
531 for action, value in list(prepare.items()):
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
532 log.debug(f"[{name}] [prepare] running {action!r} action")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
533 if action == "git":
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
534 try:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
535 git_path = which('git')[0]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
536 except IndexError:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
537 raise exceptions.NotFound(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
538 "Can't find \"git\" executable, {name} can't be started without it"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
539 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
540 await async_process.run(git_path, "clone", value, str(dest_path))
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
541 log.debug(f"{value!r} git repository cloned at {dest_path}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
542 else:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
543 raise NotImplementedError(
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
544 f"{action!r} is not managed, can't start {name}"
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
545 )
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
546 del prepare[action]
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
547
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
548 if prepare:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
549 raise exceptions.InternalError('"prepare" should be empty')
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
550
3565
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
551 async def _doCreateFiles(
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
552 self,
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
553 app_data: dict,
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
554 ) -> None:
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
555 dest_path = app_data['_instance_dir_path']
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
556 files = app_data.get('files')
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
557 if not files:
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
558 return
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
559 if not isinstance(files, dict):
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
560 raise ValueError('"files" must be a dictionary')
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
561 for filename, data in files.items():
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
562 path = dest_path / filename
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
563 if path.is_file():
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
564 log.info(f"{path} already exists, skipping")
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
565 with path.open("w") as f:
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
566 f.write(data.get("content", ""))
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
567 log.debug(f"{path} created")
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
568
3372
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
569 async def startCommon(self, app_data: dict) -> None:
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
570 """Method running common action when starting a manager
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
571
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
572 It should be called by managers in "start" method.
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
573 """
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
574 log.info(f"starting {app_data['name']!r}")
5d926c7b0d99 plugin app manager: first draft:
Goffi <goffi@goffi.org>
parents:
diff changeset
575 await self._doPrepare(app_data)
3565
d66a8453b02b plugin app manager: add a way to create files:
Goffi <goffi@goffi.org>
parents: 3564
diff changeset
576 await self._doCreateFiles(app_data)