annotate sat/plugins/plugin_misc_app_manager.py @ 3913:944f51f9c2b4

core (xmpp): make `send` a blocking method, fix `sendMessageData` calls: original `send` method is blocking, and it is used as such by Wokkel and thus can't be changed to an async method easily. However, an Async method is necessary to have an async trigger at the very end of the send workflow for end-to-end encryption. To workaround that, `send` is an async method which call `a_send`, an async method which actually does the sending. This way legacy method can still call `send` while `a_send` can be await otherwise. Fix calls to `sendMessageData`: the method now being an `async` one, `ensureDeferred` had to be used in some calls.
author Goffi <goffi@goffi.org>
date Sat, 24 Sep 2022 16:31:39 +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)