Utiliser GPG dans WSL2

Photo by Pixabay on Pexels.com

Pourquoi utiliser GPG ? Par exemple pour signer les commits GIT. Maintenant comment faire quand on est sous Windows 10 et qu’on souhaite utiliser le sous système Linux (WSL2)?

Sous GNU/Linux, l’installation et l’utilisation avec git est très simple. Avec WSL2,… il faut un peu d’huile de coude 🙂

Je vais tâcher de décrire dans cet article les différentes manipulations nécessaires pour:

  • Importer une clé GPG existante
  • Utiliser GPG pour signer mes commits dans WSL2

Importer une clé GPG existante

Export de la clé GPG

Identifier l’ ID de la clé

Lancez la commande suivante:

gpg --export ${ID} > public.key
gpg --export-secret-key ${ID} > private.key

Import

gpg --import public.key
gpg --import private.key

Vérification

Pour vérifier que la clé est bien configurée, vous pouvez lancer la commande suivante:

gpg --list-secret-keys --keyid-format LONG   alexandre@....
sec   rsa4096/CLE_ID 2019-12-20 [SC]
      ********************
uid                [  ultime ] Alexandre <alexandre@....>
ssb   rsa4096/SUB 2019-12-20 [E]

Si la clé n’est pas reconnue comme ultime ou comme de confiance, il faudra l’éditer:

gpg --edit-key CLE_ID
Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)
  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu
Your decision? 

Si vous ne voulez pas trop vous compliquer, je vous conseille de répondre 5.

Configuration GPG pour WSL2

Avant de configurer l’agent GPG, vous pouvez vous référer à cet article pour configurer GIT et GPG. La configuration est équivalente.

Ensuite, créez le fichier ~/.gnupg/gpg.conf avec le contenu suivant:

# Uncomment within config (or add this line)
# This tells gpg to use the gpg-agent
use-agent
# Set the default key
default-key CLE_ID

Puis créez le fichier ~/.gnupg/gpg-agent.conf avec le contenu ci-dessous:

default-cache-ttl 34560000
max-cache-ttl 34560000
pinentry-program /usr/bin/pinentry-curses

Le cache ici est défini en secondes. Il est mis ici à 400 jours.

Ce dernier fichier fait référence au programme pinentry. Vous pouvez vérifier sa présence grâce à la commande:

ls /usr/bin/pinentry-curses 

Si vous ne l’avez pas, vous pouvez l’installer grâce à la commande suivante:

sudo apt install pinentry-curses

Maintenant, on peut configurer l’environnement BASH en modifiant le fichier ~/.bashrc

# enable GPG signing
export GPG_TTY=$(tty)
if [ ! -f ~/.gnupg/S.gpg-agent ]; then
    eval $( gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf )
fi
export GPG_AGENT_INFO=${HOME}/.gnupg/S.gpg-agent:0:1

Redémarrez ensuite WSL2 pour que ça soit pris en compte.

A la première utilisation de GPG ( par ex. lors d’un commit, vous aurez une interface Ncurses qui apparaîtra dans votre prompt WSL2. Vous aurez à renseigner le mot de passe de votre clé.

Installer Ubuntu 20.04 LTS sur un DELL Inspiron 13 5000

Les confinements se suivent et se ressemblent. Me voilà à installer Ubuntu sur un nouvel ordinateur.
A l’instar de l’ancien laptop que j’ai acheté pour mon aînée, j’ai acheté un DELL pour ma deuxième fille.
J’ai opté pour un DELL Inspiron 5301.


A l’instar de mon autre laptop, je j’ai pas pris de risques. J’ai opté pour un DELL qui est pleinement compatible avec Ubuntu. Oui j’aurai pu installer un ordinateur avec Ubuntu pré-installé, mais je n’ai pas eu le temps de faire un choix « serein ».


Configuration du BIOS

Voila les paramètres que j’ai appliqué:

Dans le menu "Storage" puis "SATA Operation": vous devez sélectionner AHCI au lieu de RAID.
Dans le menu "Change boot mode settings >UEFI Boot Mode" , vous devez désactiver le Secure Boot.

Une fois réalisé, vous pouvez redémarrer en appuyant sur la touche F12. Si vous n’arrivez pas à revenir sur le BIOS pour indiquer de booter sur votre clé USB, vous obtiendrez un écran d’erreur Windows dû à la configuration AHCI. Personnellement, en redémarrant une ou deux fois, j’ai obtenu un écran de démarrage avancé qui m’a permis de sélectionner le périphérique (ma clé USB) sur lequel démarrer.

Maintenant vous pouvez accéder à l’installeur Ubuntu et profiter.

Installation

J’ai eu plusieurs fois des popup « erreur rencontré ». Ce n’était pas bloquant. J’ai continué.

Tout s’est déroulé sans encombre. Le matériel est très bien reconnu.

Les seuls logiciels que j’ai installé sont pour l’instant : VLC, Minecraft ( obligatoire dans la famille ) et Chromium.

Music Scores As Code

Derrière ce nom pompeux qui peut effrayer, je vais essayer d’expliquer dans cet article comment on peut versionner facilement ses partitions et les publier sur le web.

En cherchant comment mettre de la documentation technique avec des diagrammes PlantUml dans des repos GITLAB et générés avec des pipelines, je me suis mis dans la tête de faire la même chose avec des partitions 🙂

Depuis plusieurs années, j’utilise lilypond pour créer mes partitions. C’est un peu difficile de s’y mettre, mais une fois la syntaxe assimilée, la saisie d’une partition est beaucoup plus efficace. Le rendu des partitions est vraiment optimisé.
Si vous voulez plus de détails sur le pourquoi du comment je vous conseille cette page.

Vous trouverez des exemples sur le site.

J’ai donc eu l’idée de:

  • Stocker ces partitions sur un repo github (jusque là rien d’exceptionnel)
  • Générer automatiquement les partitions au format PDF, PNG et MIDI via une github action (ça commence à devenir intéressant…)
  • Les publier avec les github pages (tant qu’à faire 🙂)

Stockage

Pourquoi stocker dans un référentiel de sources tel que Github ? Pour les non informaticiens : les partitions sont stockées au format texte.

\version "2.12.1"

\header {
  title="Try a little tenderness"
  composer="Harry Woods, Jimmy Campbell & Reg Connely"
  subtitle = "Commitments Version"
  %poet = "Poete"
  instrument = "Piano"
  editor = "L'éditeur"
  %meter=\markup {\bold {"Remarque sur le rhythme"}}
  style = "Soul"
  maintainer = "Alexandre Touret"
  maintainerEmail = "alexandre.touret@free.fr"
  maintainerWeb = "http://blog.touret.info"     
  lastupdated = ""
  source = "Music room"
  footer = "Footer"
  copyright =\markup {\fontsize #-1.5
 "Delivered by A TOURET"}
}
upper=
\relative c'{
  \clef treble
  \time 4/4
  \tempo 4=176
  \key g \major
  
  d'2 (b4 e
  d2 b4 a 
  g2 g2 
  <e g,>2) <fis, c' d> 
  \bar "||"

GIT et GITHUB permettent de versionner facilement et pouvoir faire facilement un retour arrière en cas d’erreur.
Aussi, GITHUB offre des fonctionnalités « sociales » et collaboratives qui facilitent la revue des modifications ( en cas de travail à plusieurs ).
Bref, ça offre la sécurité d’une sauvegarde et la possibilité d’un retour arrière en cas d’erreur.

Générer les partitions avec une github action

Les github actions sont des outils permettant:

GitHub Actions makes it easy to automate all your software workflows, now with world-class CI/CD. Build, test, and deploy your code right from GitHub. Make code reviews, branch management, and issue triaging work the way you want.

J’ai donc décidé de créer un workflow qui permet de générer les partitions au format lilypond.

J’ai mis à disposition le code sur github sous licence GNU GPLv3. Elle est utilisable telle quelle.

Pour créer l’action, il faut créer un fichier action.yml à la racine du repo. Voici le contenu

name: 'Lilypond Generator'
description: 'Run Lilypond tool with the given set of arguments to generate music sheets'
author: '@alexandre-touret'

inputs:
  args:
    description: 'Arguments for Lilyponid'
    required: true
    default: '-h'

runs:
    using: 'docker'
    image: 'Dockerfile'
    args:
      - ${{ inputs.args }}

branding:
  icon: 'underline'
  color: 'blue'

Vous aurez compris que ce fichier fait référence à une image Docker. Cette dernière n’est ni plus ni moins qu’une Debian avec lilypond d’installé.

Pour l’utiliser dans un repo github, on peut créer une action qui l’utilise. Voici un exemple:

jobs:
  build_sheets:
    runs-on: ubuntu-latest
    env:
        LILYPOND_FILES: "*.ly"
    steps:
      - name: Checkout Source 
        uses: actions/checkout@v1
      - name: Get changed files
        id: getfile
        run: |
          echo "::set-output name=files::$(find ${{github.workspace}} -name "${{ env.LILYPOND_FILES }}" -printf "%P\n" | xargs)"
      - name: LILYPOND files considered echo output
        run: |
          echo ${{ steps.getfile.outputs.files }}
      - name: Generate PDF music sheets
        uses: alexandre-touret/lilypond-github-action@master
        with:
            args: -V -f --pdf ${{ steps.getfile.outputs.files }}

A la dernière ligne on peut passer les arguments nécessaires à lilypond.

Publication

La c’est l’étape la plus facile :). Il suffit d’activer les github pages et de commiter et pusher les partitions générées

 - name: Push Local Changes
        run: |
          git config --local user.email "${{ secrets.GIT_USERNAME }}"
          git config --local user.name "${{ secrets.GIT_EMAIL }}"
          git add .
          git commit -m "Add changes" -a
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}

Il suffit de créer une page index.md à la racine et d’ajouter des liens vers les partitions générées ( dans mon cas, ça se passe dans le répertoire /docs ).
Vous pouvez trouver un exemple ici.

Conclusion

Voila comment on peut générer un site avec des partitions crées avec Lilypond.
Vous trouverez les différents liens ci-dessous. Peut être que je publierai cette action sur le marketplace une fois que j’aurai publié une documentation digne de ce nom :).

Améliorer le temps de démarrage de Debian 10

Mon PC Lenovo a un SSD. Le temps de démarrage est actuellement de 11 sec. Ça commence à faire pas mal… J’ai eu donc envie de me pencher sur l’optimisation du démarrage ( encore une fois) . Voici comment gagner (facilement) quelques secondes au démarrage.

Tout d’abord, vous devez analyser les services qui prennent du temps au démarrage. Vous pouvez le faire avec cette commande:

systemd-analyze plot > plot.svg

J’ai obtenu le graphique suivant:

Configuration GRUB

La première manipulation à réaliser est de désactiver le timeout de GRUB. Pour celà, vous pouvez modifier la variable GRUB_TIMEOUT dans le fichier /etc/default/grub:

GRUB_TIMEOUT=0

Ensuite, vous devez mettre à jour la configuration GRUB en exécutant cette commande:

sudo update-grub2

Au prochain reboot, vous ne verrez plus le menu GRUB.

Configuration NetworkManager

Dans mon cas, le service NetworkManager-wait-online.service prenait près de 9 secondes. Après avoir lu plusieurs billets et rapports de bug, je me suis aperçu que je pouvais le désactiver au boot. Vous pouvez le faire en lançant la commande suivante

sudo systemctl disable NetworkManager-wait-online.service

Configuration Apt

Un autre service qui prenait pas mal de temps était apt-daily.timer qui vérifiait au boot qu’il y avait des mises à jour de l’OS. Après quelques recherches, j’ ai vu qu’on pouvait soit le désactiver ( ce qui n’est pas recommandé pour les mises à jour de sécurité ) soit décaler la recherche. J’ai choisi cette solution. Vous devez donc exécuter la commande suivante:

sudo systemctl edit apt-daily.timer

Et renseigner le contenu suivant:

[Timer]
OnBootSec=15min
OnUnitActiveSec=1d
AccuracySec=1h
RandomizedDelaySec=30min

Ce service sera donc lancé 15 minutes après le boot. Ce qui est largement suffisant.

[EDIT] Vous pouvez appliquer la même configuration pour le service apt-daily-upgrade en exécutant la commande:

sudo systemctl edit apt-daily-upgrade.timer

Ensuite, vous pouvez recharger la configuration en exécutant cette commande:

sudo systemctl daemon-reload

Résultats

Après ces quelques manipulations qui peuvent prendre 5 minutes grand maximum, j’ai réussi à optimiser le boot en réduisant le démarrage à 5 secondes!

Vous pourrez trouver le détail ci-dessous:

Répéter avec JjazzLab tout seul dans son garage

Avec les contraintes liées au confinement, les répétitions se font de plus en plus rares. Pour ne pas perdre la main, il y a quelques logiciels qui permettent de jouer d’un instrument et d’ improviser tout en ayant une bande son en fond musical.

Il y a plusieurs logiciels payants/propriétaires sur différentes plateformes:

J’ai découvert ce dernier récemment en naviguant sur le site Linux Mao. Il a l’avantage d’être gratuit (le moteur est sous licence LGPL 3.0, pas le logiciel en tant que tel), de fonctionner sous GNU/LINUX, d’ offrir un son pas mal du tout et de permettre la configuration de la dynamique au fur et à mesure du morceau.

Je vais expliquer comment l’installer sur Debian.

Configuration Midi

Activation des périphériques virtuels MIDI

Créer un fichier /etc/modules.load.d/midi.conf avec le contenu suivant:

snd-virmidi

Ensuite créer le fichier /etc/modprobe.d/midi.conf avec le contenu suivant:

options snd-virmidi midi_devs=1

Logiquement à ce stade, lors du prochain reboot, vous aurez un périphérique virtuel MIDI activé. En attendant vous pouvez lancer la commande suivante

$ sudo modprobe snd-virmidi midi_devs=1

Synthétiser du MIDI

Pour faire fonctionner ce logiciel, il faut installer une banque de son ( au format SF2) et un logiciel permettant de l’utiliser pour synthétiser du MIDI.
La banque de son recommandée est disponible via ce lien. Téléchargez là et copiez la dans un répertoire accessible.

Pour le second, il vous faudra installer fluidsynth. Voic les quelques commandes à lancer:

$ sudo apt install fluid-synth qsynth

Petite vérification…

Avant d’ aller plus loin dans la configuration de fluidsynth, vous pouvez vous assurer que tout est OK en récupérant un fichier MIDI et en lançant la commande suivante:

$ fluidsynth -a pulseaudio -m alsa_seq -l -i /opt/JJazzLab-2.0-Linux/JJazzLab-SoundFont.sf2  MIDI_sample.mid

Normalement vous devriez avoir du son.

Configurer fluidsynth

Lancez qsynth et cliquez sur le bouton « configuration »

Vous trouverez ci-dessous la configuration que j’ai appliqué. Elle diffère légèrement de celle présentée dans la documentation.

Pensez à redémarrer fluidsynth après application de ces nouveaux paramètres.

Configurer aconnect

Disclaimer: La c’est la partie la plus obscure…

Il faut maintenant « brancher » la sortie du synthétiseur virtuel MIDI à fluidsynth pour que le son MIDI soit interprété par ce dernier à travers sa banque de son. Ce n’est pas intuitif, je vous avais prévenu …
Je ne vous parle pas de la pseudo interface graphique à aconnect. La ligne de console est plus parlante ( c’est pour dire ) .

Exécutez la commande suivante:

$ aconnect -lo                                            
client 14: 'Midi Through' [type=noyau]
    0 'Midi Through Port-0'
client 24: 'Virtual Raw MIDI 2-0' [type=noyau,card=2]
    0 'VirMIDI 2-0     '
client 128: 'FLUID Synth (JJLAB)' [type=utilisateur,pid=17838]
    0 'Synth input port (JJLAB:0)'

Dans mon cas, je vais avoir à connecter le client 24:0 au synthétiseur 128:0 grâce à la commande :

$ aconnect 24:0 128:0

Maintenant, si on relance la commande aconnect -lo on obtient le résultat suivant:

client 14: 'Midi Through' [type=noyau]
    0 'Midi Through Port-0'
client 24: 'Virtual Raw MIDI 2-0' [type=noyau,card=2]
    0 'VirMIDI 2-0     '
	Connexion À: 128:0
client 128: 'FLUID Synth (JJLAB)' [type=utilisateur,pid=17838]
    0 'Synth input port (JJLAB:0)'
	Connecté Depuis: 24:0

Attention, cette commande devra être lancée ( ainsi que fluidsynth) avant chaque démarrage de jjazzlab.

Installation de Jjazzlab

Téléchargez les binaires sur ce site, puis décompressez l’archive dans le répertoire /opt par ex.

Vous devez également installer java

$ sudo apt install openjdk-11-jdk

Ensuite, vous devez créer le fichier ~/.local/share/applications/jjazzlab.desktop avec le contenu suivant:

[Desktop Entry]
Type=Application
Name=JJazzLab
GenericName=JJazzLab
Icon=
Exec="/opt/JJazzLab-2.0-Linux/bin/jjazzlab"
Terminal=false
Categories=Audio;Music;Player;AudioVideo;

Maintenant vous pouvez directement démarrer JJazzlab via le menu.

Configuration

Une fois jjazzlab démarré, vous devez aller dans le menu « Tools>Options » et sélectionnez les valeurs suivantes:

Ouvrez un fichier example (ex. sunny )

Cliquez sur le menu décrit par un clavier

Puis configurez comme suit:

Maintenant vous pouvez télécharger les standards fournis sur le site et improviser dessus 🙂

Erreur 139 à l’exécution d’un container docker

Voici un rapide article sur un problème rencontré récemment. Lors de l’exécution d’un container docker, j’ai eu une erreur SIGSEGV 139. Un crash avec aucune log.

Bref que du bonheur 🙂



Avant d’aller plus loin voici mon environnement:

Après quelques recherches, je me suis rendu compte qu’on pouvait reproduire ce comportement en exécutant cette commande:

docker run -it gcc:4.8.5

Une des raisons trouvées serait un problème de compatibilité avec le noyau 4.8.5 (oui ça remonte…).
Une solution est d’activer l’émulation vsyscall.


Voici la configuration à effectuer:
Dans le fichier /etc/default/grub, ajouter la ligne suivante:

GRUB_CMDLINE_LINUX_DEFAULT="quiet vsyscall=emulate"

Puis lancer les commandes suivantes:

$ sudo update-grub 
$ sudo reboot

Maintenant le container devrait pouvoir s’exécuter correctement.

Installer Ubuntu 18.04 LTS sur un Dell Inspiron 14-3493

Suite aux premières annonces de distanciation sociale ( avant que le confinement soit effectif ) j’ai acheté en catastrophe un PC portable. Les critères étaient : 8Go de RAM, un disque SSD … et la compatibilité GNU/LINUX :).

N’ayant pas trop de temps pour chercher la bonne affaire ( technologique et financière ), j’ ai acheté un Dell Inspiron 14-3493.



Je n’ai pas pris trop de risques. Bien que livré avec Windows 10, ce modèle est déjà certifié compatible Ubuntu.
L’installation d’Ubuntu se passe très bien. C’est plié en moins de 30mn. Du coup, je ne la détaillerai pas dans cet article – si vous êtes intéressé, vous pouvez consulter cet article. Pour les pré-requis, c’est une autre paire de manches …

Voilà les différentes actions que j’ai réalisé au préalable

Redémarrer l’ordinateur et accéder au BIOS

Là, j’ai un peu galéré pour accéder au BIOS. La seule manipulation que j’ai trouvé et de lancer le menu « Démarrage avancé » puis sélectionner « Utiliser un périphérique ».

Vous pouvez donc sélectionner le disque dur. Au boot en appuyant sur la touche F12 et/ou F2, vous pouvez accéder au BIOS.

Configuration du BIOS

Voila les paramètres que j’ai appliqué:

Dans le menu "SATA Operation": vous devez sélectionner AHCI au lieu de RAID.
Dans le menu "Change boot mode settings >UEFI Boot Mode" , vous devez désactiver le Secure Boot.

Une fois réalisé, vous pouvez redémarrer en appuyant sur la touche F2 et/ou F12. Si vous n’arrivez pas à revenir sur le BIOS pour indiquer de booter sur votre clé USB, vous obtiendrez un écran d’erreur Windows dû à la configuration AHCI. Personnellement, en redémarrant une ou deux fois, j’ai obtenu un écran de démarrage avancé qui m’a permis de sélectionner le périphérique (ma clé USB) sur lequel démarrer.

Maintenant vous pouvez accéder à l’installeur Ubuntu et profiter 🙂

Après l’installation

Je n’ai rien fait de particulier si ce n’est configurer le trackpad. Pour cela, j’ai installé gnome-tweaks. Mis à part ça, tout fonctionne très bien!

Passer votre application Java8 en Java11

Java 8 est encore largement utilisé dans les entreprises aujourd’hui. Il y a même certains frameworks qui n’ont pas encore sauté le pas.
Je vais essayer d’exposer dans cette article les étapes à réaliser pour migrer (simplement) votre application JAVA8 en JAVA 11.

Dans cet article, je prendrai comme postulat que l’application se construit avec Maven.

Pré-requis

Tout d’abord vérifiez votre environnement d’exécution cible! Faites un tour du coté de la documentation et regardez le support de JAVA.

Si vous utilisez des FRAMEWORKS qui utilisent des FAT JARS, faites de même (ex. pour spring boot, utilisez au moins la version 2.1.X).

Ensuite, vous aurez sans doute à mettre à jour maven ou gradle. Préférez les dernières versions.

Configuration maven

Les trois plugins à mettre à jour obligatoirement sont :

Maven compiler plugin

<plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
          <release>11</release>
          <encoding>UTF-8</encoding>
        </configuration>
      </plugin>

maven surefire / failsafe plugin

Pour ces deux plugins, ajouter la configuration suivante:

 <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.2</version>
        <configuration>
        [...]
          <argLine>--illegal-access=permit</argLine>
          [...]
        </configuration>
      </plugin>

Mise à jour des librairies

Bon,la il n’y a pas de magie. Vous devez mettre à jour toutes vos librairies. Mis à part si vous utilisez des librairies exotiques, la plupart supportent JAVA 11 maintenant.

C’est une bonne opportunité de faire le ménage dans vos fichiers pom.xml 🙂

APIS supprimées du JDK

Si vous faites du XML, SOAP ou que vous utilisiez l’API activation, vous devez désormais embarquer ces librairies. Le JDK ne les inclut plus par défaut.

Par exemple:

 <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

Modularisation avec JIGSAW

Bon là … je vous déconseille de partir directement sur la modularisation, surtout si vous migrez une application existante. Bien que la modularité puisse aider à réduire vos images docker en construisant vos propres JRE et d’améliorer la sécurité, elle apporte son lot de complexité.
Bref pour la majorité des applications, je vous déconseille de l’intégrer.

Conclusion

Avec toutes ces manipulations, vous devriez pouvoir porter vos applications sur JAVA11. Il y aura sans doute quelques bugs. Personnellement, j’en ai eu avec CGLIB vs Spring AOP sur une classe instrumentée avec un constructeur privé. Sur ce coup j’ai contourné ce problème ( je vous laisse deviner comment 🙂 ).

Partager des variables entre scénarios gatling

Je suis en train de mettre en œuvre des tests de performance avec Gatling. Un des principaux outils libres de tests de performance.

J’ai eu récemment à résoudre un « petit » soucis : je souhaitai partager des variables entre plusieurs scénarios. Il existe pas mal de solutions sur stackoverflow. J’ai condensé certaines d’entre elles pour les adapter à mon besoin.
Ces variables sont issues de exécution d’une seule requête et sont automatiquement injectées dans les scénarios suivants. Ce mécanisme permet par exemple de récupérer un jeton d’un serveur d’identification et de l’injecter pour le scénario que l’on souhaite tester.

Pour ce faire, il faut ajouter une variable de type LinkedBlockingDeque et injecter le contenu choisi via la session

 val holder = new LinkedBlockingDeque[String]() 
...
val firstScenario = scenario("First Simulation")
		.exec(http("first scenario")
			.post("/base/url1")
			.check(jsonPath("$.my_variable").find.saveAs("variable")))
		.exec(session => {
            holder.offerLast(session("variable").as[String])
            session}       
        );

Maintenant on peut l’utiliser dans un autre scénario comme feeder:

val secondScenario = scenario("Second Simulation")
		.feed(sharedDataFeeder)

Voici l’exemple complet

class RecordedSimulation extends Simulation {
val httpProtocol = http
.baseUrl("https://mabaseurl")
.inferHtmlResources()
.acceptHeader("*/*")
.acceptEncodingHeader("gzip, deflate")
.connectionHeader("close")
.userAgentHeader("PostmanRuntime/7.17.1")
/* randomized data information */
var feeder = Iterator.continually(Map("somedata" -> (Random.alphanumeric.take(20).mkString)))
/* ------------------------------------- */
val holder = new LinkedBlockingDeque[String]()
/* Enables to store and fetch the oauth access token */
var sharedDataFeeder= Iterator.continually(Map("variable" -> holder.takeFirst()))
/* ------------------------------------- */
val firstScenario = scenario("First Simulation")
.exec(http("first scenario")
.post("/base/url1")
.check(jsonPath("$.my_variable").find.saveAs("variable")))
.exec(session => {
holder.offerLast(session("variable").as[String])
session}
);
val secondScenario = scenario("Second Simulation")
.feed(feeder)
.feed(sharedDataFeeder)
.repeat(1){
exec(http("url1")
.post("/url1")
.headers(Map("my_header" -> "Bearer ${variable}","Content-Type" -> "application/json"))
.body(ElFileBody("recordedsimulation/anonymized_data.json")));
}
setUp(firstScenario.inject(atOnceUsers(1)),secondScenario.inject(constantConcurrentUsers(10) during (10 minutes),
rampConcurrentUsers(10) to (20) during (10 minutes))
.protocols(httpProtocol));
}


En espérant que cela puisse aider à certain.e.s d’entre vous 🙂

Programmmation par aspect avec Spring AOP

Une fois n’est pas coutume, voici un article qui reprend des basiques de la programmation. J’aborde une stack JAVA, mais c’est applicable à d’autres langages.

Il existe une fonctionnalité très intéressante dans Spring (et dans J(akarta)EE) que l’on oublie assez souvent : l’AOP ou encore la programmation par aspect. Cette manière de programmer permet notamment de séparer le code fonctionnel et technique.
Si vous faites du JAVA, vous utilisez déjà l’AOP. En effet, quand vous faites une insertion en base via JPA dans un EJB ou un bean annoté @Transactional, une transaction est initiée au début de la méthode et fermée à la fin.

Avec Spring et notamment dans Spring boot, voici comment initier l’AOP.

Configuration maven

Ajouter le starter AOP:

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

Activation des aspects

Dans la configuration ci-dessous, je prendrai comme exemple le logging des méthodes ( un log en début de méthode et un log en fin ). 

La définition des aspects se fait dans des classes annotées par @Configuration.

@Configuration
@Aspect
@ConditionalOnProperty(name = "debug.enabled", havingValue = "true")
public class DebuggingConfiguration {

private static final Logger LOGGER = LoggerFactory.getLogger(DebuggingConfiguration.class);
private static final String WITHIN_MY_PACKAGE = "within(my.package..*)";

/**
* Log before execution
*
* @param joinPoint the current method
*/
@Before(WITHIN_MY_PACKAGE)
public void logBeforeExecution(JoinPoint joinPoint) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Beginning of method : [{}]", joinPoint.getSignature().getName());
}
}

/**
* Log after execution
*
* @param joinPoint the current method
*/
@After(WITHIN_MY_PACKAGE)
public void logAfterExecution(JoinPoint joinPoint) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("End of method : [{}]", joinPoint.getSignature().getName());
}
}
}

L’utilisation de l’ annotation @ConditionalOnProperty me permet d’activer cette classe de configuration seulement si la propriété debug.enabled est initialisée à true.

Les annotations @Before et @After indiquent à Spring AOP quand exécuter ces méthodes ou sur quelles méthodes. Dans mon cas, quand les méthodes appelées sont définies dans les classes d’un package défini.

Pour plus de détails sur la syntaxe et les possibilités, vous pouvez vous référer à la documentation.