Initial revision.

This commit is contained in:
Julien Palard 2022-11-18 15:36:16 +01:00
commit 3c20ed2657
Signed by: mdk
GPG Key ID: 0EFC1AC1006886F8
6 changed files with 316 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
output/

35
Makefile Normal file
View File

@ -0,0 +1,35 @@
SRCS := $(sort $(wildcard *.md))
DEST := $(notdir $(PWD))
.PHONY: static
static: output/index.html
cp -a static/ output/
%.html: %.md
sed 's/#!//e;' $< | mdtoreveal /dev/stdin --output $@
output/index.md: $(SRCS)
mkdir -p output
cat $(SRCS) > output/index.md
.PHONY: publish
publish: static
rsync -vah --delete output/ mdk@mdk.fr:/var/www/mdk.fr/$DEST/
.PHONY: clean
clean:
rm -fr output
.PHONY: entr
entr:
ls -1 *.md | entr $(MAKE) static
.PHONY: serve
serve: static
python3 -m http.server -d output/
.PHONY: test
test:
if [ -f test.py ]; then \
python test.py *.md; \
fi

280
slides.md Normal file
View File

@ -0,0 +1,280 @@
# HackInScience
<!-- .slide: data-background="static/background.jpg" -->
<br/>
<b>Julien Palard</b>
<tt>CPython core dev</tt>
# C'est historique.
Tu ne peux pas dire qu'HackInScience n'est pas né en 2014, parce que c'est historique.
## Enseigner le Python
J'ai l'habitude.
Mais à des groupes de ~6 pendant ~3 jours.
## C'est green
![Ruby Rhod](static/ruby-rhod.jpg)
## Enseigner le Python
Un jour on m'a proposé un groupe de 50 pendant 7 jours.
## C'est pas green
![Ruby Rhod étranglé](static/pas-green.jpg)
## Mais on est devs
Alors on a automatisé tout ce qui pouvait l'être.
::: notes
Pour passer du temps avec ceux qui en ont besoin.
# HackInScience.org
C'est un petit Django, avec un peu de celery.
::: notes
Pour répartir les corrections sur des machines qui ne font que ça.
## Démo en prod !
https://hackinscience.org
::: notes
Faire un tour côté teams, et un tour côté admin aussi !
## C'est moche !
J'ai dit que j'étais dev, pas dev front, toute aide est la bienvenue.
::: notes c'est du bootstrap.
## Je veux voir le code !
La première version fonctionnelle : 181 lignes de Python.
Ça devrait loger dans quelques slides ;)
::: notes
Aujourd'hui c'est 2700 lignes de code…
## Django models
```python
class Exercise(models.Model):
title = models.CharField(max_length=255)
check = models.TextField()
wording = models.TextField()
```
::: notes
Si vous connaissez déjà Django, concentrez-vous sur le contenu.
## Django models
Un modèle Django c'est pas just pour l'ORM, ça aide à générer :
- des migrations de DB ;
- l'interface d'admin ;
- les formulaires ;
- les vues ;
- l'API ;
- l'autocomplétion dans l'IDE .
- les requêtes SQL (l'ORM).
::: notes
Un modèle permet au code de connaître de la structure de la base de donnée. Il n'est plus aveugle. C'est bien.
## Django view
```python
class ExerciseListView(LoginRequiredMixin, ListView):
model = Exercise
template_name = "hkis/exercises.html"
```
::: notes
Vous saviez que la MRO de Python garanti un héritage de gauche à droite ?
Ici il est garanti que les méthodes surchargées par `LoginRequiredMixin`
sont exécutées avant celles de `ListView`.
## Django view
```python
class ExerciseView(LoginRequiredMixin, DetailView):
model = Exercise
template_name = "hkis/exercise.html"
```
## Une petite API
```python
class ExerciseSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Exercise
fields = '__all__'
class ExerciseViewSet(viewsets.ModelViewSet):
queryset = Exercise.objects.all()
serializer_class = ExerciseSerializer
router = routers.DefaultRouter()
router.register('exercises', ExerciseViewSet)
```
::: notes
Pourquoi un "Router" ? Parce que derrière cette ViewSet il y a plein
de vues !
Démo time !
## Une interface d'admin
```python
from django.contrib import admin
from website.models import Answer, Exercise
admin.site.register(Answer)
admin.site.register(Exercise)
```
::: notes
Démo time !
# C'est utilisé ?
Je n'ai pas de « pisteur », mais j'ai une DB.
En octobre 2022 : 730 personnes ont résolu 10_780 exercices
La moulinette a corrigé près de 50k rendus.
::: notes
Google Analytics c'est illégal. Mais je sais écrire du SQL.
Aucun tracker, aucune pub, aucun asset externe.
10k c'est peu ou beaucoup, je ne sais pas.
## Ça tient la charge ?
Les exercices sont corrigés en environ 200ms,
Deux serveurs se répartissent le travail (et ils s'ennuient).
Les boucles infinies sont interrompues après 20s.
::: notes
Il est très facile d'ajouter un serveur de correction au besoin.
# Côté sécu
Le code de chaque exercice est exécuté côté serveur, c'est un challenge niveau sécurité.
::: notes
Python est réputé pour ne pas être sandboxable, du moins pas depuis l'intérieur de l'interpréteur.
## Namespaces Linux + seccomp + rlimit
Les exercices sont exécutés dans des environements très restreints.
## seccomp
`seccomp` (*secure computing*) c'est un outil du kernel Linux pour
limiter les appels systèmes que peuvent faire les programmes.
## rlimit
`rlimit` (*resource limit*) c'est un moyen de limiter les resources utilisées par un programme.
On limite par exemple à 20s de CPU, 2000 threads, 100 fichiers ouverts, 1GB de RAM, ….
## namespaces
C'est aussi une fonctionalité du kernel Linux, elle permet de faire
croire à un processus qu'il a une ressource « juste pour lui ».
## C'est compliqué
Configurer setccomp, rlimit, les namespaces, la vie et le reste
correctement, c'est pas simple.
Nous on utilise [firejail](https://github.com/netblue30/firejail).
## C'est simple
Un petit appercu de comment on lance firejail :
```python
FIREJAIL_OPTIONS = [
"--net=none",
"--shell=none",
"--x11=none",
"--private-dev",
"--private-tmp",
"--caps.drop=all",
"--nonewprivs",
"--nosound",
"--no3d",
"--noroot",
"--seccomp",
...
```
::: notes
C'est rassurant écrit comme ça, mais on sait que rien n'est parfait…
# La rédaction d'exercices
## Via l'interface d'admin
## Via un repo git
# L'hébergement d'instances locales
# L'API
# L'AFPy
La PyConFr
# Gandi
# Questions
- Mastodon : [@mdk@mamot.fr](https://mamot.fr/@mdk)
- XMPP : mdk@chapril.org
- HTTP : https://mdk.fr
- SMTP : julien@python.org
- Whatsapp : HAHAHA jamais.

BIN
static/background.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
static/pas-green.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
static/ruby-rhod.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB