1 .. -*- coding: utf-8 -*- |
1 Mise en place d'un environnement de développement Erudi |
|
2 ======================================================= |
|
3 |
|
4 .. toctree:: |
|
5 :maxdepth: 1 |
|
6 |
|
7 sect_mercurial.txt |
|
8 sect_installation.txt |
|
9 sect_cubicweb-ctl.txt |
2 |
10 |
3 |
11 |
4 Migration |
|
5 ========= |
|
6 |
12 |
7 Une des idées de base d'Erudi est la création incrémentale d'application, et |
13 Création d'un composant |
8 pour cela de nombreuses actions sont fournies afin de facilement faire évoluer |
14 ----------------------- |
9 une application et tout particulièrement le modèle de données manipulé sans |
15 Commençons par créer un squelette qui nous servira de base au développement de |
10 perdre les données des instances existantes. |
16 notre composant ou application :: |
11 |
17 |
12 La version courante d'un modèle d'application est données dans le fichier |
18 cd ~/hg |
13 `__pkginfo__.py` sous forme d'un tuple de 3 entiers. |
19 erudi-ctl newtemplate moncomposant |
|
20 # répondre aux questions |
|
21 hg init moncomposant |
|
22 cd moncomposant |
|
23 hg add . |
|
24 hg ci |
|
25 |
|
26 A partir de là si tout va bien, votre composant devrait être affiché par |
|
27 `erudi-ctl list` dans la section *Available components*, si ce n'est pas le cas |
|
28 revoir la section `Configuration de l'environnement`_. |
|
29 |
|
30 Pour utiliser un composant, il faut le mentionner dans la variable |
|
31 __use__ du fichier __pkginfo__ de l'application. Cette variable |
|
32 contrôle à la fois le packaging de l'application (dépendances gérées |
|
33 par les utilitaires système comme les outils APT) et les composants |
|
34 effectivement utilisables lors de la création de la base |
|
35 (import_erschema('Moncomposant') ne fonctionne pas sinon). |
|
36 |
|
37 Création d'une instance de développement |
|
38 ---------------------------------------- |
|
39 |
|
40 Maintenant que nous avons notre squelette de modèle, on peut en créer une |
|
41 instance afin de voir ce que tout ça donne dans un simple navigateur web. |
|
42 Nous allons utiliser une configuration `all-in-one` afin de simplifier les |
|
43 choses :: |
|
44 |
|
45 erudi-ctl create -c all-in-one moncomposant moninstance |
|
46 |
|
47 Une série de questions vont être posées, la réponse par défaut est généralement |
|
48 suffisante. Vous pourrez de toute façon modifier la configuration par la suite |
|
49 en éditant les fichiers générés. Lorsqu'un login/mot de passe d'accès au sgbd |
|
50 vous est demandé, il est recommandé d'utilisé l'utilisateur créé lors de la |
|
51 `Configuration Postgres`_. |
|
52 |
|
53 Il est important de distinguer ici l'utilisateur utilisé pour accéder au sgbd, |
|
54 et l'utilisateur utilisé pour s'authentifier dans l'application erudi. Lorsque |
|
55 l'application erudi démarre, elle utilise le login/mot de passe sgdb pour |
|
56 récupérer le schéma et gérer les transactions bas-niveau. En revanche, lorsque |
|
57 `erudi-ctl create` vous demande un login/mot de passe `manager` pour erudi, il |
|
58 s'agit d'un utilisateur qui sera créé dans l'application `erudi` pour pouvoir |
|
59 s'y connecter dans un premier temps et l'administrer. Il sera par la suite possible |
|
60 de créer des utilisateurs différents pour l'application. |
|
61 |
|
62 A l'issue de cette commande, la définition de votre instance se trouve dans |
|
63 *~/etc/erudi.d/moninstance/*. Pour la lancer, il suffit de taper :: |
|
64 |
|
65 erudi-ctl start -D moninstance |
|
66 |
|
67 L'option `-D` indique le *debug mode* : l'instance ne passe pas en mode serveur |
|
68 et ne se déconnecte pas du terminal, ce qui simplifie le dépannage en cas de non |
|
69 démarrage de l'instance. Vous pouvez ensuite allez voir ce que ça donne en |
|
70 pointant votre navigateur sur l'url `http://localhost:8080` (le n° de port |
|
71 dépend de votre configuration). Pour vous authentifier vous pouvez utiliser le |
|
72 login/mot de passe administrateur que vous avez spécifié lors de la création de |
|
73 l'instance. |
|
74 |
|
75 Pour arrêter l'instance, un Ctrl-C dans la fenêtre où vous l'avez lancé |
|
76 suffit. Si l'option `-D` a été omise, il faut taper :: |
|
77 |
|
78 erudi-ctl stop moninstance |
|
79 |
|
80 Voilà, tout est en place pour démarrer le développement du modèle... |
14 |
81 |
15 |
82 |
16 Gestion des scripts de migrations |
83 Utilisation de erudi-liveserver |
17 --------------------------------- |
84 ------------------------------- |
18 Les scripts des migrations doivent être placés dans le répertoire `migration` de |
|
19 l'application, et nommé de la manière suivante : |
|
20 |
85 |
21 :: |
86 Afin de tester rapidement un nouveau composant, on peut également |
|
87 utiliser le script `erudi-liveserver` qui permet de créer une |
|
88 application en mémoire (utilisant une base de données SQLite par |
|
89 défaut) et la rendre accessible via un serveur web:: |
22 |
90 |
23 <n° de version X.Y.Z>[_<description>]_<mode>.py |
91 erudi-liveserver moncomposant |
24 |
92 |
25 dans lequel : |
93 ou bien, pour utiliser une base de données existante (SQLite ou postgres):: |
26 |
94 |
27 * X.Y.Z correspond au n° de version du modèle vers lequel le script permet de |
95 erudi-liveserver -s monfichier_sources moncomposant |
28 migrer, |
|
29 |
96 |
30 * le *mode* (entre le dernier "_" et l'extension ".py") indique à quelle partie |
|
31 de l'application (serveur RQL, serveur web) le script s'applique en cas |
|
32 d'installation distribuée. Il peut valoir : |
|
33 |
|
34 * `common`, s'applique aussi bien sur le serveur RQL que sur le serveur web, |
|
35 et met à jour des fichiers sur le disque (migration de fichier de |
|
36 configuration par exemple). |
|
37 |
|
38 * `web`, s'applique uniquement sur le serveur web, et met à jour des fichiers |
|
39 sur le disque |
|
40 |
|
41 * `repository`, s'applique uniquement sur le serveur RQL, et met à jour des |
|
42 fichiers sur le disque |
|
43 |
|
44 * `Any`, s'applique uniquement sur le serveur RQL, et met à jour des |
|
45 données en base (migrations de schéma et de données par ex.) |
|
46 |
|
47 |
|
48 Toujours dans le répertoire `migration`, le fichier spécial `depends.map` permet |
|
49 d'indiquer que pour migrer vers une version spécifique du modèle, il faut tout |
|
50 d'abord avoir migrer vers une version données de erudi. Ce fichier peut contenir |
|
51 des commentaires (lignes commençant par un "#"), et une dépendance est notée sur |
|
52 une ligne de la manière suivante : :: |
|
53 |
|
54 <n° de version du modèle X.Y.Z> : <n° de version erudi X.Y.Z> |
|
55 |
|
56 Par exemple :: |
|
57 |
|
58 0.12.0: 2.26.0 |
|
59 0.13.0: 2.27.0 |
|
60 # 0.14 works with 2.27 <= erudi <= 2.28 at least |
|
61 0.15.0: 2.28.0 |
|
62 |
|
63 |
|
64 Contexte de base |
|
65 ---------------- |
|
66 Les identifiants suivants sont préféfinis dans les scripts de migration : |
|
67 |
|
68 * `config`, configuration de l'instance |
|
69 |
|
70 * `interactive_mode`, booléen indiquant si le script est éxécuté en mode |
|
71 interactif ou non |
|
72 |
|
73 * `appltemplversion`, version du modèle d'application de l'instance |
|
74 |
|
75 * `applerudiversion`, version erudi de l'instance |
|
76 |
|
77 * `templversion`, version du modéle d'application installée |
|
78 |
|
79 * `erudiversion`, version erudi installée |
|
80 |
|
81 * `confirm(question)`, fonction posant une question et retournant vrai si |
|
82 l'utilisateur a répondu oui, faux sinon (retourne toujours vrai en mode non |
|
83 interactif) |
|
84 |
|
85 * `_`, fonction équivalente à `unicode` permettant de marquer des chaines à |
|
86 internationaliser dans les scripts de migration |
|
87 |
|
88 Dans les scripts "repository", les identifiants suivant sont également définis : |
|
89 |
|
90 * `checkpoint`, demande confirmant et effectue un "commit" au point d'appel |
|
91 |
|
92 * `repo_schema`, schéma persistent de l'instance (i.e. schéma de l'instance en |
|
93 cours de migration) |
|
94 |
|
95 * `newschema`, schéma installé sur le système de fichier (i.e. schéma de la |
|
96 version à jour du modèle et de erudi) |
|
97 |
|
98 * `sqlcursor`, un curseur SQL pour les très rares cas où il est réellement |
|
99 nécessaire ou avantageux de passer par du sql |
|
100 |
|
101 * `repo`, l'objet repository |
|
102 |
|
103 |
|
104 Migration de schéma |
|
105 ------------------- |
|
106 Les fonctions de migration de schéma suivantes sont disponibles dans les scripts |
|
107 "repository" : |
|
108 |
|
109 * `add_attribute(etype, attrname, attrtype=None, commit=True)`, ajoute un |
|
110 nouvel attribut à un type d'entité existante. Si le type de celui-ci n'est pas |
|
111 spécifié il est extrait du schéma à jour. |
|
112 |
|
113 * `drop_attribute(etype, attrname, commit=True)`, supprime un |
|
114 attribut à un type d'entité existante. |
|
115 |
|
116 * `rename_attribute(etype, oldname, newname, commit=True)`, renomme un attribut |
|
117 |
|
118 * `add_entity_type(etype, auto=True, commit=True)`, ajoute un nouveau type |
|
119 d'entité. Si `auto` est vrai, toutes les relations utilisant ce type d'entité |
|
120 et ayant un type d'entité connu à l'autre extrémité vont également être |
|
121 ajoutées. |
|
122 |
|
123 * `drop_entity_type(etype, commit=True)`, supprime un type d'entité et toutes |
|
124 les relations l'utilisant. |
|
125 |
|
126 * `rename_entity_type(oldname, newname, commit=True)`, renomme un type d'entité |
|
127 |
|
128 * `add_relation_type(rtype, addrdef=True, commit=True)`, ajoute un nouveau type |
|
129 de relation. Si `addrdef` est vrai, toutes les définitions de relation de ce |
|
130 type seront également ajoutées. |
|
131 |
|
132 * `drop_relation_type(rtype, commit=True)`, supprime un type de relation et |
|
133 toutes les définitions de ce type. |
|
134 |
|
135 * `rename_relation(oldname, newname, commit=True)`, renomme une relation. |
|
136 |
|
137 * `add_relation_definition(subjtype, rtype, objtype, commit=True)`, ajoute une |
|
138 définition de relation. |
|
139 |
|
140 * `drop_relation_definition(subjtype, rtype, objtype, commit=True)`, supprime |
|
141 une définition de relation. |
|
142 |
|
143 * `synchronize_permissions(ertype, commit=True)`, synchronise les permissions |
|
144 d'un type d'entité ou de relation |
|
145 |
|
146 * `synchronize_rschema(rtype, commit=True)`, synchronise les propriétés et |
|
147 permissions d'un type de relation. |
|
148 |
|
149 * `synchronize_eschema(etype, commit=True)`, synchronise les propriétés et |
|
150 permissions d'un type d'entité. |
|
151 |
|
152 * `synchronize_schema(commit=True)`, synchronise le schéma persistent avec le |
|
153 schéma à jour (mais sans ajouter ni supprimer de nouveaux types d'entités ou |
|
154 de relations ni de définitions de relation). |
|
155 |
|
156 * `change_relation_props(subjtype, rtype, objtype, commit=True, **kwargs)`, change |
|
157 les propriétés d'une definition de relation en utilisant les arguments nommés |
|
158 pour les propriétés à changer. |
|
159 |
|
160 * `set_widget(etype, rtype, widget, commit=True)`, change le widget à utiliser |
|
161 pour la relation <rtype> du type d'entité <etype> |
|
162 |
|
163 * `set_size_constraint(etype, rtype, size, commit=True)`, change la contrainte |
|
164 de taille pour la relation <rtype> du type d'entité <etype> |
|
165 |
|
166 |
|
167 Migration de données |
|
168 -------------------- |
|
169 Les fonctions de migration de données suivantes sont disponibles dans les scripts |
|
170 "repository" : |
|
171 |
|
172 * `rql(rql, kwargs=None, cachekey=None, ask_confirm=True)`, éxécute une |
|
173 requête rql arbitraire, d'interrogation ou de modification. Un objet result |
|
174 set est retourné. |
|
175 |
|
176 * `add_entity(etype, *args, **kwargs)`, ajoute une nouvelle entité du type |
|
177 données. La valeur des attributs et relations est spécifiée en utilisant les |
|
178 arguments nommés et positionnels. |
|
179 |
|
180 |
|
181 Création de workflow |
|
182 -------------------- |
|
183 Les fonctions de création de workflow suivantes sont disponibles dans les scripts |
|
184 "repository" : |
|
185 |
|
186 * `add_state(name, stateof, initial=False, commit=False, **kwargs)`, ajoute un |
|
187 nouvel état de workflow |
|
188 |
|
189 * `add_transition(name, transitionof, fromstates, tostate, requiredgroups=(), commit=False, **kwargs)`, |
|
190 ajoute une nouvelle transtion de workflow |
|
191 |
|
192 Migration de configuration |
|
193 -------------------------- |
|
194 Les fonctions de migration de configuration suivantes sont disponibles dans tout |
|
195 les scripts : |
|
196 |
|
197 * `option_renamed(oldname, newname)`, indique qu'une option a été renommée |
|
198 |
|
199 * `option_group_change(option, oldgroup, newgroup)`, indique qu'une option a |
|
200 changé de groupe |
|
201 |
|
202 * `option_added(oldname, newname)`, indique qu'une option a été ajoutée |
|
203 |
|
204 * `option_removed(oldname, newname)`, indique qu'une option a été supprimée |
|
205 |
|
206 |
|
207 Autres fonctions de migration |
|
208 ----------------------------- |
|
209 Ces fonctions ne sont utilisés que pour des opérations de bas niveau |
|
210 irréalisables autrement ou pour réparer des bases cassées lors de session |
|
211 interactive. Elles sont disponibles dans les scripts "repository". |
|
212 |
|
213 * `sqlexec(sql, args=None, ask_confirm=True)`, éxécute une requête sql |
|
214 arbitraire, à n'utiliser |
|
215 |
|
216 * `add_entity_type_table(etype, commit=True)` |
|
217 * `add_relation_type_table(rtype, commit=True)` |
|
218 * `uninline_relation(rtype, commit=True)` |
|