Source code of my website
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

๐ŸŽ‰ : import jekyll content

+2345
+5
archetypes/default.md
··· 1 + +++ 2 + title = '{{ replace .File.ContentBaseName "-" " " | title }}' 3 + date = {{ .Date }} 4 + draft = true 5 + +++
+47
content/posts/2020-06-01-global-gitignore-file.md
··· 1 + --- 2 + created: "2020-04-16" 3 + date: "2020-06-01T00:00:00Z" 4 + language: en 5 + modified: "2022-06-17" 6 + tags: 7 + - DevOps 8 + - Git 9 + title: "Configure a Global Gitignore \U0001F648" 10 + slug: global-gitignore-file 11 + --- 12 + 13 + This short articles shows how to setup a global `.gitignore` file, to exclude files or directories for all your git repositories. 14 + 15 + This is very useful for editor files or `.env` file, and prevents accidental commits. 16 + I also added common directories for Java and NodeJS related developments (`target/` and `node_modules`), and IntelliJ IDEA files (`*.iml` and `.idea/`) 17 + 18 + Thus said, you should also always setup a `.gitignore` file in your projets, as the global file only work for you, and will not be shared with the code of your project. 19 + 20 + ## create the .gitignore file 21 + 22 + On Linux systems, the default location for a global `.gitignore` file is `~/.config/git/ignore`. 23 + 24 + Create this file if it doesn't exist, and put your content in it: 25 + 26 + ```shell 27 + # create the directory if it doesn't exists 28 + $ mkdir -p ~/.config/git 29 + 30 + # create the global ignore file 31 + $ cat <<EXCL >> ~/.config/git/ignore 32 + # global gitignore file 33 + 34 + # idea settings 35 + .idea/ 36 + *.iml 37 + 38 + # java 39 + target/ 40 + 41 + # direnv 42 + .envrc 43 + .env 44 + EXCL 45 + ``` 46 + 47 + And you are done!
+78
content/posts/2020-07-15-schedule-linux-commands.md
··· 1 + --- 2 + created: "2020-07-15" 3 + date: "2020-07-15T00:00:00Z" 4 + language: en 5 + modified: "2022-06-17" 6 + tags: 7 + - DevOps 8 + title: Schedule a linux command to run later with `at` 9 + slug: schedule-linux-commands 10 + --- 11 + 12 + As I prepare and run a lot of scripts, sometimes I need to run a script at a precise time of the day. 13 + 14 + When a script must be only run once, `cron` is not a viable solution. 15 + So I discovered the `at` scheduler 16 + 17 + You need to install it first, using `apt` as usual. 18 + 19 + ```shell 20 + $ sudo apt install at 21 + ``` 22 + 23 + ## Schedule a command to run 24 + 25 + 1. use the command `at` with a time / date 26 + 2. input the commands to run in the prompt 27 + 3. type CTRL+D to exit (^D) 28 + 29 + ```shell 30 + $ at 9AM 31 + warning: commands will be executed using /bin/sh 32 + at> cd workspaces/github/dotfiles 33 + at> git pull 34 + at> <EOT> 35 + job 1 at Sat Apr 16 09:00:00 2022 36 + ``` 37 + 38 + This example will pull a repository contents at 9 AM tomorrow ! 39 + 40 + `at` supports a lot of time specifications. 41 + 42 + Here is an extract of its man page: 43 + 44 + > At allows fairly complex time specifications, extending the POSIX.2 standard. It accepts times of the form 45 + > HH:MM to run a job at a specific time of day. (If that time is already past, the next day is assumed.) You 46 + > may also specify midnight, noon, or teatime (4pm) and you can have a time-of-day suffixed with AM or PM for 47 + > running in the morning or the evening. 48 + 49 + The commands are executed with the logged-in user account, using a `/bin/sh` shell. 50 + It will use the available env-vars of the shell when the command `at` is executed, and will `cd` into the current directory before running your scruipt. 51 + 52 + ## view scheduled commands 53 + 54 + ```shell 55 + $ atq 56 + 1 Sat Apr 16 09:00:00 2022 a jwittouck 57 + ``` 58 + 59 + ## view the details of a job 60 + 61 + ```shell 62 + $ at -c 1 63 + 64 + 65 + cd /home/jwittouck || { 66 + echo 'Execution directory inaccessible' >&2 67 + exit 1 68 + } 69 + cd workspaces/github/dotfiles 70 + git pull 71 + 72 + ``` 73 + 74 + ## delete a job 75 + 76 + ```shell 77 + $ atrm 1 78 + ```
+76
content/posts/2021-02-06-xdotool-cheatsheet.md
··· 1 + --- 2 + created: "2021-02-06" 3 + date: "2021-02-06T00:00:00Z" 4 + language: en 5 + modified: "2022-04-15" 6 + tags: 7 + - Tools 8 + title: xdotool cheatsheet 9 + slug: xdotool-cheatsheet 10 + --- 11 + 12 + I played a lot these days with xdotool, to try to automate some stuff for my Elgato Streamdeck. 13 + 14 + These are the things I try to do: 15 + 16 + * Select a window, and send a Keyboard sequence (such as CTRL+B to mute/unmute a Teams call) 17 + * Type emojis to the active window ๐Ÿ˜… 18 + * More a window around, or resize it 19 + 20 + Here are some links that I found about `xdotool`: 21 + 22 + * [Xdotool - Window Stack](https://www.linux.org/threads/xdotool-%E2%80%93-window-stack.10687/) 23 + * [Xdotool - Examples](https://www.linux.org/threads/xdotool-examples.10705/#post-36275) 24 + 25 + 26 + Below are the commands I found useful during my research. 27 + 28 + ## get window classes 29 + 30 + ``` 31 + xprop | grep 'CLASS' 32 + ``` 33 + 34 + Click on the window you want to analyse after that. 35 + 36 + More details about classes on this thread: [xdotool: what are "class" and "classname" for a window?](https://askubuntu.com/questions/1060170/xdotool-what-are-class-and-classname-for-a-window) 37 + 38 + ## find active window 39 + 40 + ``` 41 + xdotool getactivewindow 42 + ``` 43 + 44 + ## find a window by class 45 + 46 + ``` 47 + xdotool search --onlyvisible --limit 1 --class "Firefox" 48 + ``` 49 + 50 + ## focus a window 51 + 52 + ``` 53 + xdotool windowactivate 123456 54 + ``` 55 + 56 + ## send a key 57 + 58 + ``` 59 + xdotool search --onlyvisible --limit 1 --class "Firefox" key ctrl+t 60 + ``` 61 + 62 + ## send a key to firefox (by changing active window and come back) 63 + 64 + ``` 65 + ACTIVE_WINDOW=$(xdotool getactivewindow) 66 + FIREFOX_WINDOW=$(xdotool search --onlyvisible --limit 1 --class "Firefox") 67 + xdotool windowactivate $FIREFOX_WINDOW 68 + xdotool key ctrl+s 69 + xdotool windowactivate $ACTIVE_WINDOW 70 + ``` 71 + 72 + ## change a window size 73 + 74 + ``` 75 + xdotool search --onlyvisible --limit 1 --class "Firefox" windowsize 800 600 76 + ```
+101
content/posts/2021-03-26-rewrite-git-history.md
··· 1 + --- 2 + created: "2021-03-26" 3 + date: "2021-03-26T00:00:00Z" 4 + language: fr 5 + modified: "2022-04-22" 6 + tags: 7 + - DevOps 8 + - Git 9 + title: Rรฉรฉcrire une branche git 10 + slug: rewrite-git-history 11 + --- 12 + 13 + Je suis tombรฉ sur un cas oรน un fichier a รฉtรฉ ajoutรฉ dans git (commitรฉ), puis modifiรฉ par plusieurs commits successifs. 14 + 15 + Malheureusement, ce fichier contient des credentials. 16 + 17 + On va donc devoir supprimer ce fichier de tout l'historique git (oui รงa implique une rรฉรฉcriture de la sainte branche `main` ๐Ÿ˜‡). 18 + 19 + ## Trouver dans quel commit le fichier a รฉtรฉ ajoutรฉ 20 + 21 + Le fichier que je recherche s'appelle `config.json`. 22 + 23 + Je vais faire un git log, pour trouver le commit qui a ajoutรฉ ce fichier. 24 + 25 + On peut passer ร  la commande `git log` le nom du fichier ร  filtrer, ce qui nous permet d'avoir l'historique prรฉcis de ce fichier parmi tous les commits: 26 + 27 + ```shell 28 + $ git log 29 + d33736456c70ac9859da1e1f899c964db6f98cff (HEAD -> main, origin/main) ๐Ÿ”ง : update configuration 30 + 31157b8ce772c4b058d042fffef331dca87dadf5 โœจ : render button on http request 31 + 92587cbadee1063b9a9692cee014e362d99c1452 โœจ : add switch to page 32 + de63402ee023daedb4f18cc916344ac170dcfdfd โ™ป : use xdotool to write text instead of robotgo 33 + 15df7fd6e19c392dd29529b1b3b46c40961710bd โš—๏ธ : experiment with config loading 34 + 7f5f2abdfd67c588bb9c52b8c9c8dd4a6468a833 ๐Ÿ™ˆ : add binary to .gitignore 35 + dad0c5ec3d4b7334986b6aca4c483b1351cfa56a ๐Ÿ“ : add dependencies & build instructions 36 + 605e850fa4dffb49a14937400166c76b07ba817c ๐Ÿ™ˆ : add .gitignore 37 + 9a9e99a3bfd43b891bef3e2b16661d7b56dcf844 ๐Ÿ“ : add README.md 38 + 39 + ``` 40 + 41 + ```shell 42 + $ git log config.json 43 + d33736456c70ac9859da1e1f899c964db6f98cff (HEAD -> main) ๐Ÿ”ง : update configuration 44 + 15df7fd6e19c392dd29529b1b3b46c40961710bd โš—๏ธ : experiment with config loading 45 + ``` 46 + 47 + ร‡a filtre sur mon fichier, cool ! 48 + 49 + L'option `--diff-filter` permet de filtrer le log sur certaines opรฉrations, pour l'ajout (`A`), modification (`M`) ou suppression (`D`) par exemple (voir la [doc](https://git-scm.com/docs/git-log#Documentation/git-log.txt---diff-filterACDMRTUXB82308203)) 50 + 51 + ```shell 52 + $ git log --diff-filter=A config.json 53 + 15df7fd6e19c392dd29529b1b3b46c40961710bd โš—๏ธ : experiment with config loading 54 + ``` 55 + 56 + C'est mon commit `15df7f` qui a crรฉรฉ le fichier ! 57 + 58 + ## Remonter le temps 59 + 60 + Maintenant que nous avons l'hisorique de notre fichier, l'idรฉe est remonter le temps, et de rรฉรฉcrire l'ensemble des commits qui ont touchรฉ ร  ce fichier. 61 + 62 + C'est une opรฉration destructrice, qui va mettre ร  jour probablement pas mal de commits (seulement 2 dans notre exemple), donc ร  manipuler avec prรฉcaution. 63 + 64 + Pour rรฉ-รฉcrire des branches git, on utilise la commande `git filter-branch` (voir la [doc](https://git-scm.com/docs/git-filter-branch)). 65 + 66 + `git filter-branch` permet de rรฉ-รฉcrire de contenus ou des messages de commit. 67 + 68 + `git filter-branch` prend en paramรจtre un nom de branche, ou un ensemble de rรฉvisions pour lister les commits ร  parcourir, voici quelques exemples: 69 + 70 + * `HEAD` rรฉfรฉrence la branche courante (toute la branche sera parcourue) 71 + * `main` permet de jouer le filtre sur la branche main. 72 + * `HEAD~10..HEAD` permet de jouer le filtre sur les 10 derniers commits 73 + 74 + Une option m'intรฉresse pour mon cas: `--tree-filter`. 75 + Cette option permet de jouer une commande pour chaque commit de la branche, et re-commiter le rรฉsultat automatiquement, pratique ! 76 + 77 + Voici donc une commande qui permet de supprimer un fichier sur l'ensemble des commits de la branche courante: 78 + ``` 79 + $ git filter-branch --tree-filter 'rm -f config.json' HEAD 80 + ``` 81 + 82 + il est aussi possible de jouer sur toutes les branches avec l'option `--all` 83 + 84 + ``` 85 + $ git filter-branch --tree-filter 'rm -f config.json' -- --all 86 + ``` 87 + 88 + L'exรฉcution prend un peu de temps, et affiche les commits modifiรฉs : 89 + 90 + ``` 91 + Rewrite 15df7fd6e19c392dd29529b1b3b46c40961710bd (9/13) (0 seconds passed, remaining 0 predicted) rm 'config.json' 92 + Rewrite de63402ee023daedb4f18cc916344ac170dcfdfd (10/13) (0 seconds passed, remaining 0 predicted) rm 'config.json' 93 + Rewrite 92587cbadee1063b9a9692cee014e362d99c1452 (11/13) (0 seconds passed, remaining 0 predicted) rm 'config.json' 94 + Rewrite 31157b8ce772c4b058d042fffef331dca87dadf5 (12/13) (0 seconds passed, remaining 0 predicted) rm 'config.json' 95 + Rewrite d33736456c70ac9859da1e1f899c964db6f98cff (13/13) (0 seconds passed, remaining 0 predicted) rm 'config.json' 96 + 97 + Ref 'refs/heads/main' was rewritten 98 + Ref 'refs/remotes/origin/main' was rewritten 99 + ``` 100 + 101 + On a plus qu'a force push tout รงa maintenant ๐Ÿ’ช
+274
content/posts/2021-04-06-implementation-cli-elgato-keylight.md
··· 1 + --- 2 + created: "2021-04-06" 3 + date: "2021-04-06T00:00:00Z" 4 + language: fr 5 + modified: "2022-04-15" 6 + tags: 7 + - Go 8 + title: Implรฉmentation d'un CLI pour la Elgato KeyLight 9 + slug: implementation-cli-elgato-keylight 10 + --- 11 + 12 + ## Adresse IP/URL du KeyLight 13 + 14 + La KeyLight se connecte ร  votre rรฉseau WiFi. 15 + La premiรจre รฉtape consiste ร  rรฉcupรฉrer son adresse IP. 16 + 17 + La keylight rรฉpond aux requรชtes mDNS (multicast dns). 18 + 19 + C'est d'ailleurs indiquรฉ dans leur documentation: 20 + 21 + * [What Communication Protocol Is Used by Elgato Wi-Fi Products?](https://help.elgato.com/hc/en-us/articles/360060048331-What-Communication-Protocol-Is-Used-by-Elgato-Wi-Fi-Products) 22 + * [mDNS Service Strings for Elgato Devices](https://help.elgato.com/hc/en-us/articles/4413403384845-mDNS-Service-Strings-for-Elgato-Devices) 23 + 24 + Pour obtenir l'IP du keylight, il suffit donc d'emettre une requรชte DNS: 25 + 26 + ```shell 27 + dig -p 5353 PTR _elg._tcp.local @224.0.0.251 28 + 29 + ; <<>> DiG 9.16.15-Ubuntu <<>> -p 5353 PTR _elg._tcp.local @224.0.0.251 30 + ;; global options: +cmd 31 + ;; Got answer: 32 + ;; WARNING: .local is reserved for Multicast DNS 33 + ;; You are currently testing what happens when an mDNS query is leaked to DNS 34 + ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18533 35 + ;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 4 36 + 37 + ;; QUESTION SECTION: 38 + ;_elg._tcp.local. IN PTR 39 + 40 + ;; ANSWER SECTION: 41 + _elg._tcp.local. 10 IN PTR Elgato\032Key\032Light\032Air\032F3DF._elg._tcp.local. 42 + 43 + ;; ADDITIONAL SECTION: 44 + Elgato\032Key\032Light\032Air\032F3DF._elg._tcp.local. 10 IN SRV 0 0 9123 elgato-key-light-air-f3df.local. 45 + Elgato\032Key\032Light\032Air\032F3DF._elg._tcp.local. 10 IN TXT "mf=Elgato" "dt=200" "id=3C:6A:9D:16:12:45" "md=Elgato Key Light Air 20LAB9901" "pv=1.0" 46 + elgato-key-light-air-f3df.local. 10 IN A 192.168.1.11 47 + elgato-key-light-air-f3df.local. 10 IN AAAA fe80::3e6a:9dff:fe16:1245 48 + 49 + ;; Query time: 120 msec 50 + ;; SERVER: 192.168.1.11#5353(224.0.0.251) 51 + ;; WHEN: Fri Apr 15 13:55:25 CEST 2022 52 + ;; MSG SIZE rcvd: 254 53 + ``` 54 + 55 + On obtient l'URL d'accรจs au Keylight `Elgato\032Key\032Light\032Air\032F3DF._elg._tcp.local.`, son IP `192.168.1.11` ainsi que son port d'รฉcoute `9123` 56 + 57 + ## Dรฉcouverte de l'API 58 + 59 + La deuxiรจme รฉtape est de comprendre comment fonctionne l'API du KeyLight. 60 + 61 + Elle trรจs simple. 62 + 63 + Un `GET /elgato/lights` permet de rรฉcupรฉrer l'รฉtat de la KeyLight: 64 + 65 + ``` 66 + GET /elgato/lights 67 + 68 + { 69 + "numberOfLights": 1, 70 + "lights": [ 71 + { 72 + "on": 1, 73 + "brightness": 100, 74 + "temperature": 167 75 + } 76 + ] 77 + } 78 + ``` 79 + 80 + Nous avons donc 3 champs intรฉressants : 81 + * `on` indique si la KeyLight est allumรฉe (1) ou รฉteinte (0) 82 + * `brightness` indique la puissance de la luminausitรฉ (de 0 ร  100) 83 + * `temperature` indique la tempรฉrature de la lumiรจre (valeurs de 143 ร  344) pour une couleur entre 2900 et 7000 kelvin 84 + 85 + Une requรชte `PUT` permet de mettre ร  jour la KeyLight. 86 + 87 + ### Extinction de la KeyLight 88 + 89 + ``` 90 + PUT /elgato/lights 91 + 92 + { 93 + "lights": [ 94 + { 95 + "on": 0 96 + } 97 + ] 98 + } 99 + ``` 100 + 101 + ### Alumage de la KeyLight 102 + 103 + ``` 104 + PUT /elgato/lights 105 + 106 + { 107 + "lights": [ 108 + { 109 + "on": 1 110 + } 111 + ] 112 + } 113 + ``` 114 + 115 + ### Modification de la luminositรฉ 116 + 117 + ``` 118 + PUT /elgato/lights 119 + 120 + { 121 + "lights": [ 122 + { 123 + "brightness": 20 124 + } 125 + ] 126 + } 127 + ``` 128 + 129 + ### Modification de la temperature 130 + 131 + ``` 132 + PUT /elgato/lights 133 + 134 + { 135 + "lights": [ 136 + { 137 + "temperature": 200 138 + } 139 + ] 140 + } 141 + ``` 142 + 143 + ## Dรฉveloppement d'un CLI en Kotlin 144 + 145 + J'ai choisi pour m'amuser de dรฉvelopper un CLI en Kotlin, avec compilation native. 146 + 147 + Ce n'est probablement pas le setup le plus pratique, mais cela permet de mettre en place la compilation native avec GraalVM. 148 + 149 + Le CLI devra supporter les commandes suivantes : 150 + 151 + ```shell 152 + keylight on 153 + keylight off 154 + keylight brightness <X> 155 + keylight color <Y> 156 + ``` 157 + 158 + ### Installation de GraalVM 159 + 160 + L'installation de GraalVM est plutรดt simple (comme un JDK habituel). 161 + 162 + J'ai tรฉlรฉchargรฉ le `.tar.gz` sur Github ici : https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-21.0.0.2 163 + 164 + J'ai dรฉcompressรฉ le tar dans mon rรฉpertoire `/opt` 165 + 166 + J'ai aussi fait pointer ma variable `JAVA_HOME` au bon endroit : 167 + 168 + ```shell 169 + ~ > echo $JAVA_HOME 170 + /opt/graalvm-ce-java11-21.0.0.2 171 + ``` 172 + 173 + ### Crรฉation du projet 174 + 175 + Dans IntelliJ, j'ai crรฉรฉ un nouveau projet Kotlin/Maven. 176 + Je rรฉcupรจre donc un squelette de projet composรฉ d'un `pom.xml`, et d'un `main.kt`. 177 + 178 + Il n'y a plus qu'a combler les trous ! 179 + 180 + ### Configuration de la compilation native GraalVM 181 + 182 + Il faut tout d'abord installer l'outil `native-image` : 183 + 184 + ```shell 185 + /opt/graalvm-ce-java11-21.0.0.2/bin > sudo ./gu install native-image 186 + Downloading: Component catalog from www.graalvm.org 187 + Processing Component: Native Image 188 + Downloading: Component native-image: Native Image from github.com 189 + Installing new component: Native Image (org.graalvm.native-image, version 21.0.0.2) 190 + ``` 191 + 192 + (j'exรฉcute cette commande avec sudo, car mon rรฉpertoire /opt est protรฉgรฉ) 193 + 194 + Ensuite, on va utiliser le plugin maven `native-image-maven-plugin` pour produire l'image native de notre projet. 195 + On ajoute le bloc de configuration dans notre `pom.xml`: 196 + 197 + ```xml 198 + <!-- building native image with graal VM --> 199 + <plugin> 200 + <groupId>org.graalvm.nativeimage</groupId> 201 + <artifactId>native-image-maven-plugin</artifactId> 202 + <version>${graalvm.version}</version> 203 + <executions> 204 + <execution> 205 + <goals> 206 + <goal>native-image</goal> 207 + </goals> 208 + <phase>package</phase> 209 + </execution> 210 + </executions> 211 + <configuration> 212 + <imageName>keyligh</imageName> 213 + <mainClass>MainKt</mainClass> 214 + <buildArgs> 215 + --no-fallback 216 + --enable-https 217 + </buildArgs> 218 + </configuration> 219 + </plugin> 220 + ``` 221 + 222 + Les paramรจtres importants sont : 223 + * imageName : le nom du binaire produit 224 + * mainClass : le nom de la classe Java "point d'entrรฉe" de notre application. Ici, notre fichier main.kt qui contient la fonction kotlin `main` sera transformรฉ ร  la compilation en classe Java `MainKt`. 225 + * --no-fallback : permet d'empรชcher de produire un simple jar si la compilation native รฉchoue 226 + * --enable-https : permet d'activer le mode HTTPS (mรชme si on ne l'utilise pas, le client Java HTTPClient instancie le mode par dรฉfaut) 227 + 228 + La doc complรจte du plugin est ici https://www.graalvm.org/reference-manual/native-image/NativeImageMavenPlugin/ 229 + 230 + ### Implรฉmentation 231 + 232 + L'implรฉmentation du code est trรจs basique, j'ai choisi d'utiliser la librairie `jmdns` pour exรฉcuter les requรชtes mDNS depuis le CLI, et le framework `picocli` pour implรฉmenter la gestion des commandes et des paramรจtres. 233 + 234 + Le code est disponible sur Github dans le repository [juwit/keylight-cli](https://github.com/juwit/keylight-cli/). 235 + 236 + J'ai aussi configurรฉ `picocli` pour la compilation native avec un l'annotation processor `picocli-codegen`, en m'inspirant de leur documentation [Picocli on GraalVM](https://picocli.info/picocli-on-graalvm.html) : 237 + 238 + ```xml 239 + <plugin> 240 + <groupId>org.jetbrains.kotlin</groupId> 241 + <artifactId>kotlin-maven-plugin</artifactId> 242 + <version>1.4.31</version> 243 + <executions> 244 + <execution> 245 + <id>kapt</id> 246 + <goals> 247 + <goal>kapt</goal> 248 + </goals> 249 + <configuration> 250 + <sourceDirs> 251 + <sourceDir>src/main/kotlin</sourceDir> 252 + </sourceDirs> 253 + <annotationProcessorPaths> 254 + <annotationProcessorPath> 255 + <groupId>info.picocli</groupId> 256 + <artifactId>picocli-codegen</artifactId> 257 + <version>${picocli.version}</version> 258 + </annotationProcessorPath> 259 + </annotationProcessorPaths> 260 + </configuration> 261 + </execution> 262 + </executions> 263 + </plugin> 264 + ``` 265 + 266 + ### Conclusion 267 + 268 + Ce petit projet m'a permis: 269 + 270 + * d'outiller mon Keylight d'Elgato avec un CLI sous Linux (que je vais pouvoir cabler avec mon Streamdeck) 271 + * de dรฉcouvrir le protocole mDNS ! 272 + * et de tester `picocli` et la compilation native de `GraalVM` 273 + 274 + Rien de trรจs compliquรฉ, mais de bout en bout, j'y ai bien passรฉ 8 ร  10 heures. Le rรฉsultat est plutรดt cool, et je me sert du CLI presque tous les jours !
+202
content/posts/2022-06-17-direnv-pour-votre-shell.md
··· 1 + --- 2 + created: "2022-06-17" 3 + date: "2022-06-17T00:00:00Z" 4 + language: fr 5 + modified: "2022-08-05" 6 + tags: 7 + - DevOps 8 + - Shell 9 + title: direnv pour booster votre shell 10 + slug: direnv-pour-votre-shell 11 + --- 12 + 13 + # direnv pour booster votre shell 14 + ## Le problรจme 15 + Je suis le genre de dรฉveloppeur qui travaille toujours avec un terminal ouvert sur le cรดtรฉ, en plus de mon IDE. 16 + Je lance souvent des commandes `mvn` pour m'assurer que mon projet compile et que mes tests s'exรฉcutent correctement. C'est un vieux rรฉflexe qui date de l'รฉpoque oรน les IDE n'avaient qu'un support limitรฉ de *Maven*. Lancer ces commandes hors-IDE m'aide souvent ร  valider que tout fonctionnera bien dans un environnement de CI par exemple. 17 + J'ai donc parfois besoin de changer de version de *Java* en fonction du projet dans lequel je me trouve. 18 + *Maven* utilise la variable d'environnement `JAVA_HOME` pour localiser l'installation de *Java* ร  utiliser. Donc รชtre capable de charger des variables d'environnement diffรฉrentes en fonction d'un projet peut s'avรฉrer pratique. 19 + Un autre usage courant consiste ร  venir charger des clรฉ d'API ou des secrets d'accรจs cloud comme des variables `AWS_ACCESS_KEY` ou autres en fonction de mes diffรฉrents projets. 20 + ## direnv 21 + `direnv` ([lien](https://direnv.net/)) est un outil รฉcrit en go qui permet de charger des variables d'environnement dans la session courante du terminal, lorsqu'on change de rรฉpertoire en effectuant un `cd` . 22 + ### Installation 23 + `direnv` est disponible dans les dรฉpots de nombreuses distributions Linux, l'installation sur Ubuntu se fait avec les commandes habituelles, ร  savoir `apt install direnv`. 24 + L'installation pour d'autres distributions se fait ร  partir des dรฉpรดts, ou bien directement ร  partir de binaires prรฉ-compilรฉs ร  rรฉcupรฉrer sur Github dans [les releases de direnv](https://github.com/direnv/direnv/releases). 25 + ### Configuration 26 + Une fois installรฉ, il faut indiquer au shell d'appeler le binaire `direnv` ร  chaque changement de rรฉpertoire. 27 + Le shell que j'utilise au quotidien est `zsh`. Pour `zsh`, la configuration de `direnv` consiste ร  venir modifier mon fichier `~/.zshrc` pour y ajouter la ligne suivante: 28 + ```shell 29 + eval "$(direnv hook zsh)" 30 + ``` 31 + Les procรฉdures de configuration pour les autres shells sont dรฉtaillรฉes [sur le site de direnv](https://direnv.net/docs/hook.html) et sont du mรชme ordre que la procรฉdure ci-dessus. 32 + ## Utilisation basique 33 + L'utilisation de `direnv` se fait au travers d'un fichier `.envrc` ร  positionner dans le rรฉpertoire souhaitรฉ. 34 + Ce fichier peut contenir : 35 + * des commandes `export` pour dรฉclarer des variables d'environnement 36 + * des appels de fonction de la stdlib `direnv` 37 + * des appels de fonction customisรฉs 38 + * du code shell (bash) 39 + 40 + Un exemple de fichier `.envrc` dรฉposรฉ dans un rรฉpertoire `~/workspaces/demo-direnv`: 41 + ```shell 42 + export JAVA_HOME=/opt/jdk-17.0.1+12 43 + export MAVEN_HOME=/opt/apache-maven-3.8.4 44 + ``` 45 + Ce fichier dรฉclare deux variables d'environnement qui me sont utiles dans un projet Java. 46 + ร€ l'entrรฉe dans le rรฉpertoire contenant ce fichier, `direnv` va tenter de charger le fichier. Les variables d'environnement exportรฉes par le fichier seront alors chargรฉes dans la session shell courante. 47 + Au premier chargement d'un fichier, ou aprรจs une modification, `direnv` demandera une validation explicite pour autoriser le fichier. 48 + ```shell 49 + ~/workspaces > cd demo-direnv 50 + direnv: error /home/jwittouck/workspaces/demo-direnv/.envrc is blocked. Run `direnv allow` to approve its content 51 + ``` 52 + J'exรฉcute donc `direnv allow` pour autoriser le chargement de mon fichier `.envrc`: 53 + ```shell 54 + ~/workspaces/demo-direnv > direnv allow 55 + direnv: loading ~/workspaces/demo-direnv/.envrc 56 + direnv: export +JAVA_HOME +MAVEN_HOME 57 + ~/workspaces/demo-direnv > 58 + ``` 59 + `direnv` nous indique qu'il a chargรฉ notre fichier, ainsi que nos deux variables d'environnement. 60 + Nous pouvons maintenant les utiliser: 61 + ```shell 62 + ~/workspaces/demo-direnv > echo $JAVA_HOME 63 + /opt/jdk-17.0.1+12 64 + ~/workspaces/demo-direnv > echo $MAVEN_HOME 65 + /opt/apache-maven-3.8.4 66 + ``` 67 + Si on quitte le rรฉpertoire, les variables sont dรฉchargรฉes: 68 + ```shell 69 + ~/workspaces/demo-direnv > cd .. 70 + direnv: unloading 71 + ~/workspaces > echo $JAVA_HOME 72 + # rien ici ! 73 + ``` 74 + ## Modification du PATH 75 + Pour nous simplifier la vie, `direnv` propose des fonctions qui permettent de manipuler le `PATH` facilement. La fonction `PATH_add` permet d'ajouter simplement une nouvelle valeur au `PATH`. En voici un exemple dans mon fichier `.envrc` prรฉcรฉdent: 76 + ```shell 77 + export JAVA_HOME=/opt/jdk-17.0.1+12 78 + export MAVEN_HOME=/opt/apache-maven-3.8.4 79 + 80 + PATH_add $JAVA_HOME/bin 81 + PATH_add $MAVEN_HOME/bin 82 + ``` 83 + Avec cette nouvelle version de mon fichier, j'ai donc ajoutรฉ mes versions de `java` et `maven` au `PATH`. Ces ajouts seront retirรฉs ร  la sortie du rรฉpertoire: 84 + ```shell 85 + # je rentre dans mon rรฉpertoire demo-direnv 86 + ~/workspaces > cd demo-direnv 87 + direnv: loading ~/workspaces/demo-direnv/.envrc 88 + direnv: export +JAVA_HOME +MAVEN_HOME ~PATH 89 + 90 + # le $PATH a รฉtรฉ modifiรฉ 91 + ~/workspaces/demo-direnv > java --version 92 + openjdk 17.0.1 2021-10-19 93 + OpenJDK Runtime Environment Temurin-17.0.1+12 (build 17.0.1+12) 94 + OpenJDK 64-Bit Server VM Temurin-17.0.1+12 (build 17.0.1+12, mixed mode, sharing) 95 + 96 + # je sors du rรฉpertoire 97 + ~/workspaces/demo-direnv > cd .. 98 + direnv: unloading 99 + 100 + # le $PATH ne contient plus la commande java 101 + ~/workspaces > java --version 102 + zsh: command not found: java 103 + ``` 104 + Avec `direnv`, je peux donc changer de version de `java` dans mon `PATH`, simplement en changeant de rรฉpertoire. 105 + ## Utilisation avancรฉe 106 + Pour aller plus loin, `direnv` propose une librairie de fonctions qu'ils nomment *stdlib*. Ces fonctions sont listรฉes et documentรฉes dans la documentation de direnv [man/direnv-stdlib.1](https://direnv.net/man/direnv-stdlib.1.html). 107 + Voici quelques unes de ces commandes que j'utilise rรฉguliรจrement. 108 + ### [source_up](https://direnv.net/man/direnv-stdlib.1.html#codesourceup-ltfilenamegtcode) 109 + Cette commande permet d'aller chercher et exรฉcuter le premier fichier `.envrc` dans l'arborescence remontante des fichiers, ce qui permet de factoriser un peu le contenu de mes fichiers `.envrc`. 110 + Un exemple concret d'arborescence de fichiers: 111 + ```shell 112 + . 113 + โ””โ”€โ”€ workspaces 114 + ย ย  โ”œโ”€โ”€ .envrc 115 + ย ย  โ”œโ”€โ”€ projet-java-11 116 + ย ย  โ”‚ โ””โ”€โ”€ .envrc 117 + ย  โ””โ”€โ”€ projet-java-17 118 + ย  โ””โ”€โ”€ .envrc 119 + ``` 120 + Le fichier `~/workspaces/.envrc` contient les variables communes ร  mes deux projets: 121 + ```shell 122 + export MAVEN_HOME=/opt/apache-maven-3.8.4 123 + PATH_add $MAVEN_HOME/bin 124 + ``` 125 + Le fichier `~/workspaces/projet-java-11/.envrc` contient une configuration pour *Java* 11, ainsi que la commande `source_up` qui permet de charger le fichier `~/workspaces/.envrc`: 126 + ```shell 127 + source_up 128 + export JAVA_HOME=/opt/jdk-11.0.13+8 129 + PATH_add $JAVA_HOME/bin 130 + ``` 131 + Le fichier `~/workspaces/projet-java-17/.envrc` contient une configuration similaire pour *Java* 17: 132 + ```shell 133 + source_up 134 + export JAVA_HOME=/opt/jdk-17.0.1+12 135 + PATH_add $JAVA_HOME/bin 136 + ``` 137 + Avec cette utilisation, la variable `MAVEN_HOME` est disponible dans les sous-rรฉpertoires. Cette configuration permet de factoriser mes fichiers `.envrc` pour tous mes projets. 138 + ### [dotenv](https://direnv.net/man/direnv-stdlib.1.html#codedotenv-ltdotenvpathgtcode) 139 + `direnv` peut aussi scruter les fichiers `.env`, qui doivent exposer les variables d'environnement sous forme de clรฉ/valeur. Les fichiers `.env` sont moins souple car aucun script ne peut y รชtre รฉcrit. La commande `dotenv` peut nรฉanmoins aider si des `.env` existent dรฉjร  sur un projet. 140 + Voici un exemple de fichier `.env`: 141 + ```shell 142 + AWS_ACCESS_KEY_ID=xxxx-xxx-xxx-xxxx 143 + AWS_SECRET_ACCESS_KEY=xxxx-xxx-xxx-xxxx 144 + ``` 145 + Et un exemple de fichier `.envrc` qui charge le fichier `.env`: 146 + ```shell 147 + dotenv 148 + ``` 149 + Dans le cas oรน beaucoup de projets utilisent des `.env`, on peut aussi configurer `direnv` pour charger ces fichiers automatiquement, en plus des `.envrc` (qui restent chargรฉs en prioritรฉ) 150 + Cette configuration se fait dans `~/.config/direnv/direnv.toml`: 151 + ```toml 152 + [global] 153 + load_dotenv = true 154 + ``` 155 + ### [whitelist](https://direnv.net/man/direnv.toml.1.html#whitelist) 156 + Par dรฉfaut, pour chaque fichier `.envrc`, nouveau ou modifiรฉ, `direnv` affichera ce message: 157 + ```text 158 + direnv: error .envrc is blocked. Run `direnv allow` to approve its content 159 + ``` 160 + Il faut donc utiliser la commande `direnv allow` pour autoriser ces fichiers. Cela peut รชtre assez rรฉbarbatif quand cela arrive sur de nombreux projets. 161 + `direnv` fournit une configuration permettant de whitelister les fichiers et de les autoriser automatiquement. J'y ai ajoutรฉ mon rรฉpertoire de travail. Cette configuration se fait dans `~/.config/direnv/direnv.toml`: 162 + ```toml 163 + [whitelist] 164 + prefix = ["/home/jwittouck/workspaces"] 165 + ``` 166 + ### Fonction customisรฉes 167 + Pour amรฉliorer l'exemple plus haut concernant la gestion de la variable `JAVA_HOME`, il est aussi possible d'enrichir les fonctions disponibles de `direnv`. 168 + Pour cela, il faut les ajouter au fichier `~/.config/direnv/direnvrc`. 169 + Pour mon usage, j'ai crรฉรฉ cette fonction : 170 + ```shell 171 + function use_java(){ 172 + echo "Using Java version $1" 173 + export JAVA_HOME=$(find /opt -maxdepth 1 -type d -name "jdk-$1*") 174 + echo "Loading JAVA_HOME $JAVA_HOME" 175 + PATH_add $JAVA_HOME/bin 176 + } 177 + ``` 178 + Tous mes JDK sont installรฉs dans `/opt`. Cette fonction permet de trouver le JDK qui correspond au premier paramรจtre de la fonction et de positionner les variables `JAVA_HOME` et `PATH`. 179 + Elle s'utilise dans un `.envrc` de cette maniรจre: 180 + ```shell 181 + use_java 17 182 + # ou 183 + # use_java 11 184 + ``` 185 + et voici ce que loggue `direnv` ร  l'entrรฉe du rรฉpertoire : 186 + ```shell 187 + ~/workspaces > cd demo-direnv 188 + direnv: loading ~/workspaces/demo-direnv/.envrc 189 + direnv: using java 17 190 + Using Java version 17 191 + Loading JAVA_HOME /opt/jdk-17.0.1+12 192 + direnv: export +JAVA_HOME +MAVEN_HOME ~PATH 193 + ``` 194 + ## Conclusion 195 + `direnv` est un outil trรจs pratique pour manipuler les variables d'environnement. Il s'adresse avant tout ร  ceux qui passent du temps dans un shell, devs ou sysadmins. 196 + Cet article a prรฉsentรฉ principalement les usages que j'en ai pour mes projets *Java*, mais `direnv` propose aussi des fonctions pour les projets `node`, `ruby`, `python` et d'autres. 197 + C'est vite devenu un indispensable dans mes shells. 198 + ### Liens 199 + * la page d'accueil du projet sur [direnv.net](https://direnv.net/) 200 + * le repository Github du projet [direnv/direnv](https://github.com/direnv/direnv) 201 + * la documentation d'install [docs/installation](https://direnv.net/docs/installation.html) 202 + * la documentation de la stdlib [man/direnv-stdlib](https://direnv.net/man/direnv-stdlib.1.html)
+413
content/posts/2022-07-22-skaffold-et-minikube/index.md.md
··· 1 + --- 2 + created: "2022-07-22" 3 + date: "2022-07-22T00:00:00Z" 4 + language: fr 5 + modified: "2022-07-29" 6 + tags: 7 + - DevOps 8 + - Kubernetes 9 + - Skaffold 10 + - Minikube 11 + - Docker 12 + - Tutorial 13 + title: Exรฉcuter une application localement sur minikube avec skaffold 14 + slug: skaffold-et-minikube 15 + --- 16 + 17 + # Exรฉcuter une application localement sur minikube avec skaffold 18 + Lors du dรฉveloppement d'une application pour Kubernetes, le dรฉveloppeur est souvent liรฉ ร  une boucle de feedback assez longue: 19 + 1. Dรฉveloppement 20 + 2. Contruction de l'image Docker (quelques secondes/minutes) 21 + 3. Push de l'image sur un registry 22 + 4. Dรฉploiement sur Kubernetes (quelques minutes) 23 + 24 + Cette boucle est gรฉnรฉralement implรฉmentรฉe par des pipelines de CI/CD. Ces pipelines augmentent encore le temps entre le dรฉveloppement et une application dรฉmarrรฉe sur Kubernetes. Ce temps est relativement long lorsqu'on compare un cycle de dรฉveloppement local auquel un dรฉveloppeur peut รชtre habituรฉ. 25 + 26 + [`skaffold`](https://skaffold.dev), dรฉveloppรฉ par Google, est un outil open-source en license Apache, qui permet d'implรฉmenter cette boucle de dรฉveloppement sur un environnement Kubernetes local ou distant. La promesse de `skaffold` est de rendre le dรฉveloppement sur Kubernetes simple, rapide et reproductible. 27 + 28 + ![la page d'accueil de skaffold](skaffold.png) 29 + 30 + `skaffold` implรฉmente un *pipeline* qui se dรฉroule en plusieurs รฉtapes: 31 + 1. *build* : construction des images docker avec: 32 + * Docker (sur base d'un `Dockerfile`) 33 + * Buildpacks 34 + * Jib 35 + 2. *tag* de l'image docker en utilisant diffรฉrentes stratรฉgies : 36 + * l'identifiant du commit git (par dรฉfaut) 37 + * une date 38 + * des variables d'environnement 39 + * un hash des fichiers source 40 + * push de l'image sur un registry 41 + * chargement direct de l'image dans un cluster Kubernetes 42 + 3. *deploy* : dรฉploiement de l'application sur Kubernetes (local ou distant) en utilisant: 43 + * `kubectl` et des fichiers yaml 44 + * `kustomize` 45 + * `helm` 46 + 4. *tail logs & port forward* : affiche les logs de l'application et redirige un port local 47 + 5. *status check* : attend la fin du bon dรฉploiement de application 48 + 49 + `skaffold` a besoin d'un code ร  dรฉployer, ainsi qu'un accรจs ร  un cluster Kubernetes. L'accรจs au cluster se configure de la mรชme maniรจre que pour `kubectl`, ร  travers un fichier `~/.kube/config`. Pour la suite de cet article, j'utilise un cluster `minikube` que j'installe sur mon poste pour l'occasion. 50 + 51 + ## Dรฉployer un cluster minikube localement 52 + La premiรจre รฉtape consiste ร  dรฉployer un cluster `minikube` sur mon poste de dรฉveloppement. 53 + Pour ce faire, le plus pratique est de suivre les รฉtapes d'installation de l'outil dรฉtaillรฉes [dans leur documentation d'installation](https://minikube.sigs.k8s.io/docs/start/). 54 + 55 + ![installation de minikube](minikube-install.png) 56 + 57 + Voici les commandes que j'ai exรฉcutรฉ pour installer `minikube` sur mon poste Linux : 58 + ```shell 59 + $ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 60 + sudo install minikube-linux-amd64 /usr/local/bin/minikube 61 + ``` 62 + `docker` รฉtant dรฉjร  installรฉ sur mon poste, je peux tout de suite dรฉmarrer un cluster Kubernetes local avec la commande `minikube start`: 63 + ```shell 64 + $ minikube start 65 + ๐Ÿ˜„ minikube v1.24.0 on Debian bookworm/sid 66 + ๐ŸŽ‰ minikube 1.26.0 is available! Download it: https://github.com/kubernetes/minikube/releases/tag/v1.26.0 67 + ๐Ÿ’ก To disable this notice, run: 'minikube config set WantUpdateNotification false' 68 + 69 + โœจ Using the docker driver based on existing profile 70 + ๐Ÿ‘ Starting control plane node minikube in cluster minikube 71 + ๐Ÿšœ Pulling base image ... 72 + ๐Ÿ”„ Restarting existing docker container for "minikube" ... 73 + 74 + ๐Ÿงฏ Docker is nearly out of disk space, which may cause deployments to fail! (92% of capacity) 75 + ๐Ÿ’ก Suggestion: 76 + 77 + Try one or more of the following to free up space on the device: 78 + 79 + 1. Run "docker system prune" to remove unused Docker data (optionally with "-a") 80 + 2. Increase the storage allocated to Docker for Desktop by clicking on: 81 + Docker icon > Preferences > Resources > Disk Image Size 82 + 3. Run "minikube ssh -- docker system prune" if using the Docker container runtime 83 + ๐Ÿฟ Related issue: https://github.com/kubernetes/minikube/issues/9024 84 + 85 + ๐Ÿณ Preparing Kubernetes v1.22.3 on Docker 20.10.8 ... 86 + ๐Ÿ”Ž Verifying Kubernetes components... 87 + โ–ช Using image gcr.io/k8s-minikube/storage-provisioner:v5 88 + โ–ช Using image k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1 89 + โ–ช Using image k8s.gcr.io/ingress-nginx/controller:v1.0.4 90 + โ–ช Using image k8s.gcr.io/ingress-nginx/kube-webhook-certgen:v1.1.1 91 + ๐Ÿ”Ž Verifying ingress addon... 92 + ๐ŸŒŸ Enabled addons: storage-provisioner, default-storageclass, ingress 93 + ๐Ÿ„ Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default 94 + ``` 95 + Par dรฉfaut, `minikube` va gรฉnรฉrer un fichier de configuration pour `kubectl` dans `~/.kube/config`. La commande `kubectl` sera donc immรฉdiatement utilisable: 96 + ```shell 97 + $ kubectl get nodes 98 + NAME STATUS ROLES AGE VERSION 99 + minikube Ready control-plane,master 1d v1.22.3 100 + ``` 101 + Si la commande `kubectl` n'est pas installรฉe, `minikube` l'intรจgre et elle est utilisable de cette maniรจre: 102 + ```shell 103 + $ minikube kubectl get nodes 104 + NAME STATUS ROLES AGE VERSION 105 + minikube Ready control-plane,master 1d v1.22.3 106 + ``` 107 + Pour ma part, j'ai installรฉ `kubectl` avec l'outil de packaging de mon systรจme en suivant [cette procรฉdure](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-using-native-package-management). 108 + Une fois que `minikube` et `kubectl` sont installรฉs, dรฉmarrรฉs et configurรฉs, je peux passer ร  l'installation de `skaffold`. 109 + ## Installation de skaffold 110 + L'installation de `skaffold` est similaire ร  celle de `minikube` et `kubectl`. 111 + J'ai suivi la procรฉdure sur [dans leur documentation](https://skaffold.dev/docs/install/) et installรฉ la version Linux avec ces commandes: 112 + ```shell 113 + $ curl -Lo skaffold https://storage.googleapis.com/skaffold/releases/latest/skaffold-linux-amd64 && \ 114 + sudo install skaffold /usr/local/bin/ 115 + ``` 116 + `skaffold` est maintenant disponible sur mon poste: 117 + ```shell 118 + $ skaffold version 119 + v1.39.1 120 + ``` 121 + ## Configuration d'un projet 122 + `skaffold` se configure avec un fichier `skaffold.yml` ร  positionner ร  la racine de votre projet. 123 + J'ai pris pour exemple un projet Micronaut avec lequel je suis en train d'expรฉrimenter: 124 + ```shell 125 + . 126 + โ”œโ”€โ”€ micronaut-cli.yml 127 + โ”œโ”€โ”€ mvnw 128 + โ”œโ”€โ”€ mvnw.bat 129 + โ”œโ”€โ”€ pom.xml 130 + โ”œโ”€โ”€ README.md 131 + โ””โ”€โ”€ src 132 + โ””โ”€โ”€ main 133 + โ”œโ”€โ”€ java 134 + โ”‚ย ย  โ””โ”€โ”€ com 135 + โ”‚ย ย  โ””โ”€โ”€ example 136 + โ”‚ย ย  โ”œโ”€โ”€ Application.java 137 + โ”‚ย ย  โ””โ”€โ”€ pokemons 138 + โ”‚ย ย  โ”œโ”€โ”€ PokemonController.java 139 + โ”‚ย ย  โ”œโ”€โ”€ Pokemon.java 140 + โ”‚ย ย  โ”œโ”€โ”€ PokemonRepository.java 141 + โ”‚ย ย  โ””โ”€โ”€ PokemonService.java 142 + โ””โ”€โ”€ resources 143 + โ”œโ”€โ”€ application.yml 144 + โ”œโ”€โ”€ bootstrap.yml 145 + โ””โ”€โ”€ logback.xml 146 + ``` 147 + La configuration initiale du projet se fait en utilisant la commande `skaffold init` . Cette commande propose diffรฉrentes options ([documentation](https://skaffold.dev/docs/pipeline-stages/init/)) en interactif pour crรฉer son fichier de configuration. Cette รฉtape est plus simple qu'รฉcrire le fichier ร  la main. 148 + Comme je n'ai pas encore รฉcrit de fichiers manifest Kubernetes pour mon application, `skaffold` a une option pour les gรฉnรฉrer: `--generate-manifests`. 149 + 150 + La premiรจre รฉtape consiste ร  configurer la phase de *build* de l'application, ร  savoir la construction de l'image docker. Plusieurs options seront proposรฉes, en fonction de ce qui est dรฉjร  disponible dans le code : `Dockerfile`, configuration de `jib`, ou manifests Kubernetes. 151 + Mon projet Micronaut a dรฉjร  une configuration pour `jib` dans son `pom.xml`: 152 + ```xml 153 + <build> 154 + <plugins> 155 + <plugin> 156 + <groupId>com.google.cloud.tools</groupId> 157 + <artifactId>jib-maven-plugin</artifactId> 158 + <version>3.2.1</version> 159 + </plugin> 160 + </plugins> 161 + </build> 162 + ``` 163 + 164 + `skaffold init` me propose alors de paramรฉtrer ma phase de *build* avec Buildpacks ou Jib: 165 + 166 + ```shell 167 + $ skaffold init --generate-manifests 168 + ? Which builders would you like to create Kubernetes resources for? [Use arrows to move, space to select, <right> to all, <left> to none, type to filter] 169 + > [ ] Buildpacks (pom.xml) 170 + [ ] Jib Maven Plugin (com.example:demo-app-pokemon-micronaut, pom.xml) 171 + ``` 172 + Je choisis l'option *Jib* รฉtant donnรฉ que ce plugin est dรฉjร  configurรฉ pour mon application. 173 + 174 + L'รฉtape suivante propose de configurer un port ร  forwarder pour mon image Docker, je saisis le port 8080 qui est le port par dรฉfaut de mon application: 175 + ```shell 176 + ? Select port to forward for pom-xml-image (leave blank for none): 8080 177 + ``` 178 + `skaffold` me propose ensuite un manifest Kubernetes et me demande si je souhaite gรฉnรฉrer les fichiers: 179 + ```shell 180 + ? Do you want to write this configuration, along with the generated k8s manifests, to skaffold.yaml? Yes 181 + Generated manifest deployment.yaml was written 182 + Configuration skaffold.yaml was written 183 + You can now run [skaffold build] to build the artifacts 184 + or [skaffold run] to build and deploy 185 + or [skaffold dev] to enter development mode, with auto-redeploy 186 + ``` 187 + ร€ noter que si des fichiers de dรฉploiement Kubernetes sont dรฉjร  prรฉsents dans l'application, `skaffold` les dรฉtecte et les ajoute ร  sa configuration automatiquement. 188 + Le fichier `deployment.yaml` gรฉnรฉrรฉ pour Kubernetes est simple: 189 + ```yaml 190 + apiVersion: v1 191 + kind: Service 192 + metadata: 193 + name: pom-xml-image 194 + labels: 195 + app: pom-xml-image 196 + spec: 197 + ports: 198 + - port: 8080 199 + protocol: TCP 200 + clusterIP: None 201 + selector: 202 + app: pom-xml-image 203 + --- 204 + apiVersion: apps/v1 205 + kind: Deployment 206 + metadata: 207 + name: pom-xml-image 208 + labels: 209 + app: pom-xml-image 210 + spec: 211 + replicas: 1 212 + selector: 213 + matchLabels: 214 + app: pom-xml-image 215 + template: 216 + metadata: 217 + labels: 218 + app: pom-xml-image 219 + spec: 220 + containers: 221 + - name: pom-xml-image 222 + image: pom-xml-image 223 + ``` 224 + ainsi que le fichier `skaffold.yaml` 225 + ```yaml 226 + apiVersion: skaffold/v2beta29 227 + kind: Config 228 + metadata: 229 + name: demo-app-pokemon-micronaut 230 + build: 231 + artifacts: 232 + - image: pom-xml-image 233 + jib: 234 + project: com.example:demo-app-pokemon-micronaut 235 + deploy: 236 + kubectl: 237 + manifests: 238 + - deployment.yaml 239 + portForward: 240 + - resourceType: service 241 + resourceName: pom-xml-image 242 + port: 8080 243 + ``` 244 + Le fichier gรฉnรฉrรฉ contient de la configuration pour 3 รฉtapes du pipeline de `skaffold`. 245 + 246 + La phase de *build* est bien configurรฉe pour construire une image Docker en utilisant *Jib*, l'image produite sera nommรฉe `pom-xml-image`. Ce nom par dรฉfaut pourra รชtre changรฉ en modifiant ce fichier de configuration. 247 + 248 + La phase de *deploy* est configurรฉe pour dรฉployer des manifests Kubernetes, ici le fichier `deployment.yaml` qui a รฉtรฉ gรฉnรฉrรฉ par la commande `skaffold init`. Ces fichiers manifest rรฉfรฉrencent l'image `pom-xml-image` dans la partie *Deployment* du manifest. 249 + On voit donc ici comment on peut adapter cette configuration pour inclure d'autres fichiers, comme une *ConfigMap*. 250 + 251 + J'ai pris le parti de dรฉplacer les fichiers de manifest Kubernetes gรฉnรฉrรฉs dans le rรฉpertoire `src/main/Kubernetes` de mon application et de renommer l'image gรฉnรฉrรฉe. 252 + Voici la structure de mon application aprรจs ces opรฉrations: 253 + ```shell 254 + . 255 + โ”œโ”€โ”€ micronaut-cli.yml 256 + โ”œโ”€โ”€ mvnw 257 + โ”œโ”€โ”€ mvnw.bat 258 + โ”œโ”€โ”€ pom.xml 259 + โ”œโ”€โ”€ README.md 260 + โ”œโ”€โ”€ skaffold.yaml 261 + โ””โ”€โ”€ src 262 + โ””โ”€โ”€ main 263 + โ”œโ”€โ”€ java 264 + โ”‚ย ย  โ””โ”€โ”€ com 265 + โ”‚ย ย  โ””โ”€โ”€ example 266 + โ”‚ย ย  โ”œโ”€โ”€ Application.java 267 + โ”‚ย ย  โ””โ”€โ”€ pokemons 268 + โ”‚ย ย  โ”œโ”€โ”€ PokemonController.java 269 + โ”‚ย ย  โ”œโ”€โ”€ Pokemon.java 270 + โ”‚ย ย  โ”œโ”€โ”€ PokemonRepository.java 271 + โ”‚ย ย  โ””โ”€โ”€ PokemonService.java 272 + โ”œโ”€โ”€ kubernetes 273 + โ”‚ย ย  โ”œโ”€โ”€ configMap.yaml 274 + โ”‚ย ย  โ”œโ”€โ”€ deployment.yaml 275 + โ”‚ย ย  โ””โ”€โ”€ service.yaml 276 + โ””โ”€โ”€ resources 277 + โ”œโ”€โ”€ application.yml 278 + โ”œโ”€โ”€ bootstrap.yml 279 + โ””โ”€โ”€ logback.xml 280 + ``` 281 + Ainsi que le fichier `skaffold.yaml`: 282 + ```yaml 283 + apiVersion: skaffold/v2beta29 284 + kind: Config 285 + metadata: 286 + name: demo-skaffold 287 + build: 288 + artifacts: 289 + - image: demo-skaffold 290 + jib: {} 291 + deploy: 292 + kubectl: 293 + manifests: 294 + - src/main/kubernetes/*.yaml 295 + portForward: 296 + - resourceType: service 297 + resourceName: demo-skaffold 298 + port: 8080 299 + ``` 300 + ## Dรฉmarrage de mon projet 301 + Une fois les fichiers gรฉnรฉrรฉs, la commande `skaffold dev` va: 302 + * construire l'image docker en utilisant le builder *Jib* configurรฉ 303 + * dรฉposer cette image directement dans l'environnement du `minikube` 304 + * dรฉployer les fichiers de configuration Kubernetes 305 + * ouvrir un port-forward sur mon port d'รฉcoute 8080 306 + * afficher les logs de mon application dans mon shell 307 + 308 + ```shell 309 + $ skaffold dev 310 + Listing files to watch... 311 + - demo-skaffold 312 + Generating tags... 313 + - demo-skaffold -> demo-skaffold:latest 314 + Some taggers failed. Rerun with -vdebug for errors. 315 + Checking cache... 316 + - demo-skaffold: Found Locally 317 + Tags used in deployment: 318 + - demo-skaffold -> demo-skaffold:275bf648a141313e52f422d73ad69379be4f4d7c3e9e50fe3c16289da8391c33 319 + Starting deploy... 320 + - configmap/demo-skaffold created 321 + - deployment.apps/demo-skaffold created 322 + - service/demo-skaffold created 323 + Waiting for deployments to stabilize... 324 + - deployment/demo-skaffold is ready. 325 + Deployments stabilized in 2.047 seconds 326 + Port forwarding service/demo-skaffold in namespace default, remote port 8080 -> http://127.0.0.1:8080 327 + Press Ctrl+C to exit 328 + Watching for changes... 329 + [backend] __ __ _ _ 330 + [backend] | \/ (_) ___ _ __ ___ _ __ __ _ _ _| |_ 331 + [backend] | |\/| | |/ __| '__/ _ \| '_ \ / _` | | | | __| 332 + [backend] | | | | | (__| | | (_) | | | | (_| | |_| | |_ 333 + [backend] |_| |_|_|\___|_| \___/|_| |_|\__,_|\__,_|\__| 334 + [backend] Micronaut (v3.5.1) 335 + [backend] 336 + [backend] 14:15:41.202 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [k8s, cloud] 337 + [backend] 14:15:41.557 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 803ms. Server Running: http://demo-skaffold-5bfb47c8fc-cvld4:8080 338 + ``` 339 + ![](./localhost.png) 340 + 341 + En quelques minutes, mon application est dรฉmarrรฉ sur mon cluster `minikube` local. 342 + Je peux voir avec une commande `kubectl get all` que mes manifests ont bien รฉtรฉ dรฉployรฉs et que mon application tourne: 343 + ```shell 344 + $ kubectl get all 345 + NAME READY STATUS RESTARTS AGE 346 + pod/demo-skaffold-5bfb47c8fc-cvld4 1/1 Running 0 19m 347 + 348 + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 349 + service/demo-skaffold ClusterIP None <none> 8080/TCP 19m 350 + service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 1d 351 + 352 + NAME READY UP-TO-DATE AVAILABLE AGE 353 + deployment.apps/demo-skaffold 1/1 1 1 19m 354 + 355 + NAME DESIRED CURRENT READY AGE 356 + replicaset.apps/demo-skaffold-5bfb47c8fc 1 1 1 19m 357 + 358 + ``` 359 + `skaffold` est aussi capable de faire du *hot-reload* sans configuration supplรฉmentaire pour les applications buildรฉes avec *jib*. 360 + Il suffit de: 361 + * modifier le code 362 + * attendre quelques secondes que le code soit re-compilรฉ et l'application est re-dรฉmarrรฉe 363 + 364 + ```shell 365 + Watching for changes... 366 + Generating tags... 367 + - pom-xml-image -> pom-xml-image:latest 368 + Some taggers failed. Rerun with -vdebug for errors. 369 + Checking cache... 370 + - pom-xml-image: Not found. Building 371 + Starting build... 372 + Found [minikube] context, using local docker daemon. 373 + Building [pom-xml-image]... 374 + Target platforms: [linux/amd64] 375 + 376 + ... 377 + 378 + Build [pom-xml-image] succeeded 379 + Tags used in deployment: 380 + - pom-xml-image -> pom-xml-image:c6d646c3c9ba7ac130cfe23c31b2391584b4bddfce984b2cc1f1f2c711c9d509 381 + Starting deploy... 382 + Waiting for deployments to stabilize... 383 + - deployment/pom-xml-image is ready. 384 + Deployments stabilized in 1.038 second 385 + Port forwarding service/pom-xml-image in namespace default, remote port 8080 -> http://127.0.0.1:8080 386 + Watching for changes... 387 + ``` 388 + C'est particuliรจrement pratique pour tester une application localement! 389 + Si je veux arrรชter de dรฉvelopper, j'utilise la combinaison de touches *CTRL+C*, qui va stopper l'application et faire le mรฉnage sur le cluster Kubernetes: 390 + ```shell 391 + ^C 392 + Cleaning up... 393 + - configmap "demo-skaffold" deleted 394 + - deployment.apps "demo-skaffold" deleted 395 + - service "demo-skaffold" deleted 396 + ``` 397 + ## Conclusion 398 + `skaffold` permet de rendre accessible au dรฉveloppeur le dรฉploiement sur un cluster Kubernetes, local ou distant. Cet article a prรฉsentรฉ son usage sur un cluster local `minikube`, mais `skaffold` fonctionne de maniรจre indiffรฉrenciรฉe sur un cluster distant. Il permet aussi de rรฉutiliser des fichiers de configuration Kubernetes, Kustomize ou Helm existants, ce qui est trรจs pratique si l'application dispose dรฉjร  de ce type de fichiers. 399 + 400 + Le port forward est trรจs bien intรฉgrรฉ et pratique ร  l'usage (pas besoin de taper une commande `kubectl` supplรฉmentaire). 401 + 402 + La [documentation de `skaffold`](https://skaffold.dev/docs/) est trรจs complรจte et indique tous les paramรจtres que chaque phase de son pipeline accepte et fourni aussi des liens vers des tutoriaux. 403 + 404 + Enfin, `skaffold` est au coeur des plugins *Cloud Code* de Google, pour IntelliJ IDEA et VSCode pour l'exรฉcution et le dรฉploiement des application sur Kubernetes. 405 + 406 + De nombreux [exemples](https://github.com/GoogleContainerTools/skaffold/tree/main/examples) sont disponibles sur le repository Github de `skaffold`, il y en aura surement un qui correspondra ร  votre type de projet si vous voulez expรฉrimenter. 407 + 408 + ### Liens 409 + 410 + * le repository Github de [GoogleContainerTools/skaffold](https://github.com/GoogleContainerTools/skaffold) 411 + * le site web [skaffold.dev](https://skaffold.dev/) 412 + * la [documentation](https://skaffold.dev/docs/) 413 + * les [exemples de code sur Github](https://github.com/GoogleContainerTools/skaffold/tree/main/examples)
content/posts/2022-07-22-skaffold-et-minikube/localhost.png

This is a binary file and will not be displayed.

content/posts/2022-07-22-skaffold-et-minikube/minikube-install.png

This is a binary file and will not be displayed.

content/posts/2022-07-22-skaffold-et-minikube/skaffold.png

This is a binary file and will not be displayed.

content/posts/2023-02-23-mkdocs-material/create-docs-website-content-page.png

This is a binary file and will not be displayed.

content/posts/2023-02-23-mkdocs-material/create-docs-website-github-pages.png

This is a binary file and will not be displayed.

content/posts/2023-02-23-mkdocs-material/create-docs-website-preview.png

This is a binary file and will not be displayed.

content/posts/2023-02-23-mkdocs-material/create-docs-website-theme.png

This is a binary file and will not be displayed.

content/posts/2023-02-23-mkdocs-material/create-docs-website-workflow.png

This is a binary file and will not be displayed.

+414
content/posts/2023-02-23-mkdocs-material/index.md
··· 1 + --- 2 + created: "2023-02-23" 3 + date: "2023-02-23T00:00:00Z" 4 + language: fr 5 + modified: "2023-03-09" 6 + tags: 7 + - Git 8 + - Tools 9 + - Docs 10 + - Tutorial 11 + title: Crรฉer un site web de documentation statique avec MkDocs 12 + slug: mkdocs-material 13 + --- 14 + 15 + # Crรฉer un site web de documentation statique avec MkDocs 16 + 17 + Que ce soit pour un projet d'entreprise ou un projet open-source, la documentation utilisateur et technique est cruciale. 18 + Dans une documentation d'usage, les utilisateurs doivent pouvoir retrouver les instructions leur permettant d'accomplir les gestes mรฉtier de tous les jours. 19 + Pour la documentation technique, les administrateurs, opรฉrateurs et dรฉveloppeurs doivent pouvoir retrouver les opรฉrations d'installation, de mise ร  jour, ou encore de dรฉveloppement du produit. 20 + 21 + La documentation peut prendre plusieurs formes: 22 + 23 + * un document bureautique, de type LibreOffice Writer ou Microsoft Word 24 + * des pages dans un rรฉfรฉrentiel documentaire de type _wiki_, ou _Atlassian Confluence_ 25 + * un site web dรฉdiรฉ 26 + 27 + Les documents bureautique sont bien adaptรฉs ร  la documentation de procรฉdures, ou de spรฉcifications. Cependant, ils souffrent de nombreux dรฉfauts comme le manque d'archivage des modifications, une recherche compliquรฉe, un fort liant entre le format et le contenu et sont souvent portรฉs par des formats propriรฉtaires (le fameux `.docx`). 28 + 29 + Les rรฉfรฉrentiels de type _wiki_ rรฉpondent au problรจmes de recherche et d'archivage des historiques de modifications. Cependant, ils nรฉcessitent souvent une infrastructure avec une base de donnรฉes, et ont donc un coรปt d'hรฉbergement et de maintenance. 30 + 31 + Le cas du site web statique dรฉdiรฉ est le plus adaptรฉ ร  un projet open-source. Le site sera exposรฉ sur internet, aidant ร  mettre en visibilitรฉ le projet. Un site web statique nรฉcessite un hรฉbergement minimum, sans base de donnรฉes, et sera donc plus simple ร  mettre en place. 32 + 33 + # _documentation-as-Code_ 34 + 35 + Pour encourager les dรฉveloppeurs ร  rรฉdiger plus de documentation, il est intรฉressant de considรฉrer l'approche *documentation-as-code*. 36 + Cette approche s'appuie sur les process et outils de dรฉveloppement pour proposer aux dรฉveloppeurs un moyen moderne d'รฉcrire et publier leur documentation. 37 + 38 + Dans un processus de _documentation-as-code_, les dรฉveloppeurs rรฉdigent et archivent la documentation au mรชme endroit que le code source, dans un repository _git_. 39 + Cela permet de fournir une documentation plus prรฉcise, et plus ร  jour. Les mises ร  jour de documentation sont effectuรฉes en mรชme temps que les mises ร  jour du code source. 40 + 41 + Un site web de documentation pourra alors รชtre gรฉnรฉrรฉ ร  partir des documents rรฉdigรฉs par les dรฉveloppeurs. Ce site pourra รชtre publiรฉ avec des chaรฎnes d'intรฉgration continue. 42 + 43 + ## Les formats _asciidoc_ et _markdown_ 44 + 45 + En _documentation-as-code_, la documentation sera รฉcrite dans un format simple, dรฉjร  maitrisรฉ par les dรฉveloppeurs. Un des avantages principaux est que ces formats peuvent รชtre รฉditรฉs dans les IDE que les dรฉveloppeurs utilisent dรฉjร . 46 + 47 + Les deux formats les plus utilisรฉs sont l'_asciidoc_ et le _markdown_. 48 + 49 + L'intรฉrรชt d'utiliser ces formats est multiple: 50 + 51 + * le dรฉveloppeur se concentre sur la rรฉdation du contenu plutรดt que sur le formattage des donnรฉes 52 + * la documentation peut รชtre archivรฉe comme du code source, voire dans le mรชme repository que le projet 53 + * ces formats sont simples d'utilisation, mรชme pour des personnes ayant peu ou pas de connaissances techniques 54 + 55 + ## Les gรฉnรฉrateurs de sites web statiques 56 + 57 + Des fichiers _markdown_ ou _asciidoc_ sur un repository _git_ peuvent parfois รชtre suffisant. _Gitlab_ et _Github_ sont capables d'afficher des fichiers _markdown_ ou _asciidoc_ directement dans leur interface. C'est le cas par exemple des fameux `README.md` qu'on retrouve sur une majoritรฉ de projets. 58 + Cet usage peut suffire pour documenter une librairie ou un projet simple. 59 + D'autres projets, plus compliquรฉs, auront plus de pages de documentation, et des besoins de personnalisation, c'est lร  oรน un gรฉnรฉrateur de site web statique sera utile. 60 + 61 + ### _asciidoc_ et _asciidoctor_ 62 + 63 + La suite de cet article ne dรฉcrira pas comment mettre en place _asciidoc_ et _asciidoctor_, mais il รฉtait important de mentionner ces outils, qui sont utilisรฉs par de nombreux projets. 64 + 65 + _asciidoc_, couplรฉ au gรฉnรฉrateur *asciidoctor* permet directement de gรฉnรฉrer des pages _HTML_ statiques ร  partir de un ou plusieurs fichiers de documentation source. 66 + Les pages _HTML_ gรฉnรฉrรฉes peuvent alors รชtre publiรฉes directement. 67 + C'est ce qui est utilisรฉ par le framework Java *Spring* par exemple. 68 + 69 + Voici ร  titre d'exemple la [documentation gรฉnรฉrรฉe pour le framework Spring](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/) , ร  partir des documents *asciidoc* disponible sur _Github_: 70 + 71 + ![](mkdocs-spring.png) 72 + 73 + 74 + Les sources sont visibles sur le [_Github_ de _Spring_](https://github.com/spring-projects/spring-boot/tree/main/spring-boot-project/spring-boot-docs/src/docs/asciidoc). 75 + 76 + *Spring* utilise donc *asciidoctor* pour gรฉnรฉrer leur documentation dans 3 formats diffรฉrents: 77 + 78 + * un pdf complet 79 + * une page HTML complรจte (autonome) 80 + * un ensemble de pages HTMLs liรฉes entre elles 81 + 82 + ### _markdown_ et _MkDocs_ 83 + 84 + Bien qu'*asciidoctor* propose de gรฉnรฉrer plusieurs formats, d'autres gรฉnรฉrateurs compatibles Markdown existent: 85 + 86 + * [_Jekyll_](https://jekyllrb.com/), est plutรดt orientรฉ blogging 87 + * [_Hugo_](https://gohugo.io/), est orientรฉ site web gรฉnรฉraliste 88 + * [_MkDocs_](https://www.mkdocs.org/), est orientรฉ documentation 89 + 90 + Ces gรฉnรฉrateurs amรจnent une structure de site web classique, avec une navigation ร  plusieurs niveaux de menus, et souvent des champs de recherche. 91 + 92 + Parmis ces 3 solutions, _MkDocs_ est le plus orientรฉ documentation, c'est cet outil que nous allons mettre en place dans la suite de cet article. 93 + 94 + # Mise en place de _MkDocs_ 95 + 96 + Nous allons voir dans la suite de cet article: 97 + 98 + * l'installation et la configuration de _MkDocs_ 99 + * l'utilisation et la configuration d'un thรจme et sa customisation (logo, couleurs) 100 + * la rรฉdaction de quelques pages 101 + * la publication en site statique avec _Github Actions_ & _Github Pages_ 102 + 103 + # Crรฉation du projet de documentation 104 + 105 + La documentation peut รชtre crรฉรฉe comme un repository Git dรฉdiรฉ, ou comme un rรฉpertoire d'un repository existant, dans le cas d'une approche _mono-repo_ par exemple. 106 + 107 + C'est cette deuxiรจme solution que nous allons suivre. 108 + Dans un projet existant, on commence par crรฉer un rรฉpertoire `docs`: 109 + 110 + ```bash 111 + mkdir docs/ 112 + ``` 113 + 114 + La crรฉation du squelette de documentation peut se faire avec le _CLI_ (pour Command Line Interface) de _MkDocs_ et la commande [`mkdocs new`](https://www.mkdocs.org/user-guide/cli/#mkdocs-new), ou simplement en initialisant quelques fichiers ร  la main. 115 + 116 + Nous allons crรฉer l'arborescence suivante: 117 + 118 + ```text 119 + . 120 + โ”œโ”€ docs/ 121 + โ”‚ โ””โ”€ index.md 122 + โ””โ”€ mkdocs.yml 123 + ``` 124 + 125 + Le contenu de notre fichier `mkdocs.yml` minimal est le suivant: 126 + 127 + ```yaml 128 + site_name: Galactic Empire 129 + ``` 130 + 131 + Pour rรฉfรฉrence, la [documentation de _MkDocs_](https://www.mkdocs.org/user-guide/configuration/) liste les paramรจtres de configuration qui peuvent รชtre modifiรฉs dans le fichier `mkdocs.yml`. 132 + 133 + Un fichier `docs/index.md` permet de servir de page d'accueil: 134 + 135 + ```markdown 136 + # Documentation 137 + 138 + Bienvenue sur la documentation de l'Empire Galactique 139 + ``` 140 + 141 + # Dรฉmarrage de _MkDocs_ en mode preview 142 + 143 + _MkDocs_ est รฉcrit en python, et peut รชtre installรฉ en quelques commandes. La [procรฉdure d'installation](https://www.mkdocs.org/user-guide/installation/#installing-mkdocs) est simple: 144 + 145 + ```bash 146 + pip install mkdocs 147 + ``` 148 + 149 + Il existe รฉgalement des images _Docker_ dรฉdiรฉes, qui seront utiles pour l'automatisation avec _Github Actions_ ou _Gitlab CI_ pour la publication, bien que nous allons nous en passer. 150 + 151 + Le dรฉmarrage du site, en mode _preview_, se fait en une commande: 152 + 153 + ```bash 154 + $ mkdocs serve 155 + INFO - Building documentation... 156 + INFO - Cleaning site directory 157 + INFO - Documentation built in 0.15 seconds 158 + INFO - [09:32:45] Watching paths for changes: 'docs', 'mkdocs.yml' 159 + INFO - [09:32:45] Serving on http://127.0.0.1:8000/ 160 + ``` 161 + 162 + Le site web est construit, et disponible en local: 163 + 164 + ![](create-docs-website-preview.png) 165 + 166 + # Ajout d'un thรจme & customisation 167 + 168 + Le thรจme par dรฉfaut n'est pas trรจs รฉlรฉgant. 169 + Plusieurs thรจmes existent, et il est possible de crรฉer le sien, ร  condition de savoir un peu dรฉvelopper en HTML/CSS. 170 + 171 + Nรฉanmoins, un thรจme populaire est [_Material for MkDocs_](https://squidfunk.github.io/mkdocs-material) (13k stars sur _Github_). Ce thรจme propose une interface รฉpurรฉe, personnalisable, et le support d'extensions ร  _markdown_. 172 + 173 + L'installation du thรจme se fait en une ligne de commande: 174 + 175 + ```bash 176 + pip install mkdocs-material 177 + ``` 178 + 179 + Pour utiliser notre thรจme, il faut le prรฉciser dans le fichier `mkdocs.yml`: 180 + 181 + ```yaml 182 + site_name: Galactic Empire 183 + 184 + # configuration du thรจme 185 + theme: 186 + name: material 187 + ``` 188 + 189 + Nous allons maintenant un peu customiser notre thรจme. 190 + Toutes les instructions sont disponible dans la [documentation de _Material for Mkdocs_](https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/): 191 + 192 + ## Le logo 193 + 194 + Pour changer le logo, il faut indiquer quel fichier utiliser dans la configuration. 195 + Pour notre exemple, je suis allรฉ chercher un logo libre de droits sur le site web [https://pngrepo.com](https://pngrepo.com), et je l'ai positionnรฉ dans un rรฉpertoire `docs/assets` que j'ai crรฉรฉ pour l'occasion: 196 + 197 + ``` 198 + . 199 + โ”œโ”€โ”€ docs 200 + โ”‚ย ย  โ”œโ”€โ”€ assets 201 + โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ death-star.png 202 + โ”‚ย ย  โ””โ”€โ”€ index.md 203 + โ””โ”€โ”€ mkdocs.yml 204 + ``` 205 + 206 + Le logo est ensuite rรฉfรฉrencรฉ dans le fichier de configuration: 207 + 208 + ```yaml 209 + site_name: Galactic Empire project 210 + 211 + # configuration du thรจme 212 + theme: 213 + name: material 214 + logo: assets/death-star.png 215 + ``` 216 + 217 + ร€ noter que le rรฉpertoire _assets_ dรฉclarรฉ dans la configuration est bien relatif au rรฉpertoire _docs_. 218 + 219 + ## Les couleurs 220 + La configuration des couleurs passe par une dรฉclaration CSS, si on veut sortir des couleurs proposรฉes dans la palette de couleurs par dรฉfaut. 221 + Un fichier css peut surcharger l'ensemble des variables de couleurs prรฉdรฉfinies. La liste des variables est disponible dans le [fichier de dรฉfinition des couleurs](https://github.com/squidfunk/mkdocs-material/blob/master/src/assets/stylesheets/main/_colors.scss) du code source de _Material for MkDocs_. 222 + 223 + Pour surcharger les couleurs principales, il suffit donc de les re-dรฉclarer dans un fichier `.css`, de cette maniรจre: 224 + 225 + ```css 226 + :root { 227 + --md-primary-fg-color: #394A59; 228 + --md-accent-fg-color: #556567; 229 + } 230 + ``` 231 + 232 + Le fichier `.css` doit รชtre dรฉposรฉ oรน l'on souhaite. Ici, nous avons crรฉรฉ un rรฉpertoire `docs/stylesheets`: 233 + 234 + ``` 235 + . 236 + โ”œโ”€โ”€ docs 237 + โ”‚ย ย  โ”œโ”€โ”€ assets 238 + โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ death-star.png 239 + โ”‚ย ย  โ”œโ”€โ”€ index.md 240 + โ”‚ย ย  โ””โ”€โ”€ stylesheets 241 + โ”‚ย ย  โ””โ”€โ”€ galactic-empire.css 242 + โ””โ”€โ”€ mkdocs.yml 243 + ``` 244 + 245 + Enfin, le fichier `.css` doit รชtre rรฉfรฉrencรฉ dans la configuration de notre site: 246 + 247 + ```yaml 248 + site_name: Galactic Empire project 249 + 250 + # configuration du thรจme 251 + theme: 252 + name: material 253 + logo: assets/death-star.png 254 + 255 + extra_css: 256 + - stylesheets/galactic-empire.css 257 + ``` 258 + 259 + Et voici notre site avec le thรจme et sa customisation. 260 + 261 + ![](create-docs-website-theme.png) 262 + 263 + # L'ajout de contenu 264 + L'ajout de contenu passe maintenant simplement par l'ajout de nouveaux fichiers _markdown_ dans le rรฉpertoire de documentation. 265 + 266 + Voici un exemple de page de contenu supplรฉmentaire: 267 + 268 + ```markdown 269 + --- 270 + title: Organisation 271 + author: Darth Vader 272 + --- 273 + 274 + # Organisation de l'Empire Galactique 275 + 276 + L'Empire Galactique est dirigรฉ par l'Empereur Palpatine. 277 + 278 + Son bras droit est le seigneur Vador. 279 + 280 + Le Grand Moff Tarkin est le gouverneur rรฉgional de la Bordure Extรฉrieur. 281 + Il est ร  la tรชte du projet "ร‰toile de la mort", et son commandant. 282 + ``` 283 + 284 + L'en-tรชte du fichier est au format _Front Matter_, qui a รฉtรฉ popularisรฉ par [_Jekyll_](https://jekyllrb.com/docs/front-matter/). 285 + 286 + Le rendu est le suivant: 287 + 288 + ![](create-docs-website-content-page.png) 289 + 290 + Notez que : 291 + 292 + * le titre de la page est celui du premier header Markdown `#` 293 + * dans la navigation de gauche, le titre utilisรฉ est celui du bloc de description de la page *Front Matter*. 294 + * le nom de l'auteur apparaรฎt dans les mรฉta-donnรฉes de la page gรฉnรฉrรฉe: 295 + 296 + ```html 297 + <head> 298 + ... 299 + <meta name="author" content="Darth Vader"> 300 + ... 301 + </head 302 + ``` 303 + 304 + # Publication avec _Github Actions_ & _Github Pages_ 305 + 306 + Maintenant que notre site web est fonctionnel, nous allons le mettre ร  disposition sur le web avec _Github Pages_. 307 + 308 + La crรฉation d'un repository _Github_ et les bases de _Github Actions_ sont en dehors du pรฉrimรจtre de cet article. 309 + 310 + La construction du site web se fait avec la commande `mkdocs build`. 311 + L'exรฉcution de cette commande produit un nouveau rรฉpertoire `site` qui contient le site web gรฉnรฉrรฉ: 312 + 313 + ```bash 314 + $ mkdocs build 315 + INFO - Cleaning site directory 316 + INFO - Building documentation to directory: ekit3/mkdocs-website-sample/site 317 + INFO - Documentation built in 0.16 seconds 318 + ``` 319 + Nous allons donc utiliser cette commmande pour gรฉnรฉrer notre site web ร  publier. 320 + 321 + Voici un workflow _Github Actions_, qui installe le langage _Python_, _MkDocs_ et _Material for MkDocs_, et construit notre site: 322 + 323 + ```yaml 324 + name: Build & Publish site 325 + 326 + on: 327 + push: 328 + branches: [ "main" ] 329 + pull_request: 330 + branches: [ "main" ] 331 + 332 + jobs: 333 + build: 334 + runs-on: ubuntu-latest 335 + steps: 336 + - uses: actions/checkout@v3 337 + - name: Set up Python ${{ matrix.python-version }} 338 + uses: actions/setup-python@v3 339 + - name: Install dependencies 340 + run: | 341 + python -m pip install mkdocs 342 + python -m pip install mkdocs-material 343 + - name: Build site 344 + run: | 345 + mkdocs build 346 + ``` 347 + 348 + L'รฉtape suivante consiste ร  publier le site construit sur _Github Pages_, ce qui se fait avec 2 actions dรฉdiรฉes. 349 + 350 + L'action `upload-pages-artifact` permet de sรฉlectionner un rรฉpertoire ร  envoyer ร  Github Pages, en l'occurence, notre rรฉpertoire `site`, qui contient notre site web. 351 + 352 + ```yaml 353 + - name: Upload Pages Artifact 354 + uses: actions/upload-pages-artifact@v1 355 + with: 356 + path: ./site 357 + ``` 358 + 359 + Cette action peut รชtre ajoutรฉe au job _build_ dรฉcrit plus haut. 360 + 361 + Enfin, l'action `deploy-pages` permet d'exรฉcuter le dรฉploiement, nous l'ajoutons dans un job sรฉparรฉ: 362 + 363 + ```yaml 364 + jobs: 365 + build: 366 + [...] 367 + deploy: 368 + needs: build 369 + runs-on: ubuntu-latest 370 + permissions: 371 + pages: write 372 + id-token: write 373 + environment: 374 + name: github-pages 375 + url: ${{ steps.deployment.outputs.page_url }} 376 + steps: 377 + - name: Deploy to GitHub Pages 378 + id: deployment 379 + uses: actions/deploy-pages@v1 380 + ``` 381 + 382 + Le fichier final complet est disponible sur [le repository _Github_](https://github.com/ekit3/mkdocs-website-sample/blob/main/.github/workflows/publish.yml) contenant le code source de cet article. 383 + 384 + ร€ noter que le dรฉploiement avec _Github Pages_ doit รชtre activรฉ dans le repository _Github_, et que le repository doit รชtre public : 385 + 386 + ![](create-docs-website-github-pages.png) 387 + 388 + Une fois le fichier Github Actions publiรฉ, le workflow pourra s'exรฉcuter, et publier le site web: 389 + 390 + ![](create-docs-website-workflow.png) 391 + 392 + Le rรฉsultat final est visible [via ce lien](https://ekit3.github.io/mkdocs-website-sample/). 393 + 394 + Le code source de cet article est disponible dans notre repository _Github_ [mkdocs-website-sample](https://github.com/ekit3/mkdocs-website-sample). 395 + 396 + # Conclusion 397 + 398 + En conclusion, nous avons vu les principes de documentation-as-code, et qu'il รฉtait trรจs simple de publier une documentation sous la forme d'un site web. 399 + Nous avons รฉgalement vu comment utiliser le format _markdown_, couplรฉ ร  l'outil _MkDocs_ et le thรจme _Material for MkDocs_ pour gรฉnรฉrer un site web et le personnaliser. 400 + Enfin, nous avons vu comment utiliser _Github Actions_ et _Github Pages_ pour publier notre site de documentation sur internet. 401 + 402 + _MkDocs_, couplรฉ ร  un hรฉbergement avec _Gitlab Pages_ ou _Github Pages_, permet de gรฉnรฉrer un site web en quelques รฉtapes rapides. 403 + Cela en fait l'outil idรฉal pour documenter un projet open-source ou interne. 404 + 405 + # Liens 406 + 407 + * [Documentation](https://www.mkdocs.org/) de _MkDocs_ 408 + * [Documentation](https://squidfunk.github.io/mkdocs-material/) de _Material for MkDocs_ 409 + * [La customisation](https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/) de _Material for MkDocs_ (couleurs, fonts, icรดnes) 410 + * L'icรดne _Death Star_ utilisรฉe pour le site gรฉnรฉrรฉ sur [pngrepo.com](https://www.pngrepo.com/svg/275952/death-star-star-wars) 411 + * Les actions Github utilisรฉes : 412 + * [upload-pages-artifact](https://github.com/actions/upload-pages-artifact) 413 + * [deploy-pages](https://github.com/actions/deploy-pages) 414 + * Le [code source](https://github.com/ekit3/mkdocs-website-sample) associรฉ ร  cet article
content/posts/2023-02-23-mkdocs-material/mkdocs-spring.png

This is a binary file and will not be displayed.

content/posts/2023-05-25-anatomie-requete-http/client-server.png

This is a binary file and will not be displayed.

content/posts/2023-05-25-anatomie-requete-http/http-anatomy.jpg

This is a binary file and will not be displayed.

+268
content/posts/2023-05-25-anatomie-requete-http/index.md
··· 1 + --- 2 + created: "2023-05-25" 3 + date: "2023-05-25T00:00:00Z" 4 + language: fr 5 + modified: "2023-07-01" 6 + tags: 7 + - Basics 8 + title: Anatomie d'une requรชte HTTP 9 + slug: anatomie-requete-http 10 + --- 11 + 12 + # Anatomie d'une requรชte HTTP 13 + 14 + ![](http-anatomy.jpg) 15 + 16 + HTTP, pour _Hypertext Transfer Protocol_, est le protocole principal pour les รฉchanges internet. Il est utilisรฉ aussi bien par le navigateur que vous utilisez pour lire cet article, que pour faire communiquer des applications. 17 + Il s'appuie sur un รฉhange de requรชte et rรฉponse, entre un client et un serveur, au format texte. L'avantage du format texte est qu'il est facile ร  implรฉmenter dans tous les langages de programmation. 18 + Le protocole HTTP est spรฉcifiรฉ par la [RFC 2616](https://www.rfc-editor.org/rfc/rfc2616), protocole dont la toute premiรจre version d'HTTP date de 1990. 19 + 20 + Cet article traite de la version 1.1 du protocole, qui a รฉtรฉ normalisรฉe en 1997. Une version 2.0 a รฉtรฉ normalisรฉe en 2015, et รฉtend la version 1.1 avec d'autres capacitรฉs. Les bases de la version 1.1 ne sont donc pas obsolรจtes&nbsp;! 21 + 22 + ![](client-server.png) 23 + 24 + Dans cet article, nous allons รฉtudier la structure d'une requรชte et d'une rรฉponse HTTP. 25 + 26 + ## La structure d'une requรชte 27 + 28 + Une requรชte est structurรฉe en 3 parties&nbsp;: 29 + 30 + * la ligne de requรชte, obligatoire, en premiรจre ligne 31 + * les entรชtes optionnels 32 + * le corps de requรชte, lui aussi optionnel 33 + 34 + ``` 35 + REQUEST-LINE 36 + [HEADERS] 37 + 38 + [BODY] 39 + ``` 40 + 41 + Exemple de requรชte HTTP _GET_ sans corps de requรชte&nbsp;: 42 + 43 + ``` 44 + GET /articles/http-anatomy?version=1#headers HTTP/1.1 45 + Host: ekite.tech 46 + Accept: text/plain 47 + Accept-Charset: utf-8 48 + Accept-Encoding: gzip 49 + Accept-Language: fr-fr 50 + ``` 51 + 52 + Exemple comportant un corps de requรชte&nbsp;: 53 + 54 + ``` 55 + POST /articles/ HTTP/1.1 56 + Host: ekite.tech 57 + Content-Type: application/json 58 + Content-Length: 31 59 + Authorization: Basic UmljayBBc3RsZXk6TmV2ZXIgR29ubmEgR2l2ZSBZb3UgVXAK 60 + 61 + {"title":"mon nouvel article"} 62 + ``` 63 + 64 + ### La _Request Line_ 65 + 66 + Les _HEADERS_ et _BODY_ sont facultatifs. 67 + 68 + La _REQUEST-LINE_ est dรฉfinie de cette maniรจre&nbsp;: 69 + 70 + ``` 71 + METHOD REQUEST-URI HTTP-VERSION 72 + ``` 73 + 74 + _METHOD_ est le verbe HTTP. Il peut รชtre `GET`, `POST`, `PUT`, `DELETE`, qui sont les verbes HTTP les plus courants. 75 + La RFC 2616 dรฉfinit aussi des mรฉthodes supplรฉmentaires, comme `HEAD`, `OPTIONS`, `TRACE`, `CONNECT`. 76 + 77 + _REQUEST-URI_ est la ressource ร  appeler. Elle peut รชtre une URI absolue, comme `https://ekite.tech/articles/http-anatomy`, ou une URI relative, comme `/articles/http-anatomy`. En pratique, ce sont plutรดt des URI relatives qui sont utilisรฉes, en combinaison avec un _Header_ `Host`. 78 + 79 + Le champ `HTTP-VERSION` vaudra `HTTP/1.1`. 80 + 81 + Une requรชte HTTP minimale est&nbsp;: 82 + 83 + ``` 84 + GET /articles/http-anatomy HTTP/1.1 85 + ``` 86 + 87 + ### _URL_ et _URI_ 88 + 89 + Une _URI_, pour _Uniform Resource Identifier_, dรฉfinit une ressource internet. Cette ressource peut รชtre une page Web, un document au format PDF, ou encore une vidรฉo. 90 + 91 + Une _URL_, pour _Uniform Resource Locator_, est une _URI_ particuliรจre, qui contient les informations rรฉseau pour accรฉder ร  une ressource. 92 + Les _URI_ sont dรฉfinies par un format texte composรฉ de caractรจres _ASCII_. 93 + 94 + La [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) spรฉcifie les formats des _URI_. 95 + 96 + La structure d'une _URI_ absolue est&nbsp;: 97 + 98 + ``` 99 + SCHEME://HOST/PATH[?QUERY][#FRAGMENT] 100 + ``` 101 + Le _SCHEME_ est souvent associรฉ au protocole, _http_, _https_, ou encore _file_ quand des fichiers locaux sont dรฉsignรฉs. 102 + Le _HOST_ est le nom du serveur hรฉbergeant la ressource. 103 + Le _PATH_ identifie le chemin vers la ressource. 104 + La _QUERY_, aussi souvent appelรฉ _Query Strings_, dรฉfinit des paramรจtres supplรฉmentaires que la ressource peut traiter, sous la forme `name=value`. 105 + Le _FRAGMENT_ dรฉfinit la partie de la ressource consultรฉe. 106 + _QUERY_ et _FRAGMENT_ sont optionnels. 107 + 108 + Une _URI_ simple pour notre article est&nbsp;: 109 + 110 + ``` 111 + https://ekite.tech/articles/http-anatomy 112 + \___/ \________/ \___________________/ 113 + | | | 114 + scheme host path 115 + ``` 116 + 117 + Une _URI_ comportant des รฉlรฉments supplรฉmentaires&nbsp;: 118 + 119 + ``` 120 + https://ekite.tech/articles/http-anatomy?version=1#headers 121 + \___/ \________/ \___________________/ \_______/ \_____/ 122 + | | | | | 123 + scheme host path query fragment 124 + ``` 125 + 126 + Une _URI_ peut รฉgalement รชtre relative, et ne comporter qu'une partie du _PATH_. 127 + Par exemple&nbsp;: 128 + 129 + ``` 130 + /http-anatomy?version=1#headers 131 + ``` 132 + 133 + ### Les _Headers_ de requรชte 134 + 135 + Les _Headers_ dรฉfinissent des informations supplรฉmentaires ร  propos de la requรชte, comme le format de donnรฉes attendu en rรฉponse, ou des informations concernant les donnรฉes actuellement en cache cรดtรฉ client. 136 + 137 + Cette structure dรฉfinit les _Headers_&nbsp;: 138 + 139 + ``` 140 + NAME: VALUE 141 + ``` 142 + 143 + La [RFC 2616](https://www.rfc-editor.org/rfc/rfc2616#page-38), dรฉfinit des _Headers_ standards, mais les applications peuvent รฉgalement dรฉfinir leurs propres _Headers_. 144 + Les principaux _Headers_ standards sont `Accept`, `Accept-Charset`, `Accept-Encoding` et `Accept-Language` pour la nรฉgociation de contenu. 145 + Cette RFC dรฉfinit aussi le _Header_ `Authorization` pour l'authentification des clients. Le _Header_ `Host` prรฉcise l'hรดte auquel la requรชte est envoyรฉe s'il n'est pas prรฉcisรฉ dans l'URI de la requรชte. 146 + 147 + Une requรชte HTTP comportant des _Headers_ est&nbsp;: 148 + 149 + ``` 150 + GET /articles/http-anatomy HTTP/1.1 151 + Host: ekite.tech 152 + Accept: text/plain 153 + Accept-Charset: utf-8 154 + Accept-Encoding: gzip 155 + Accept-Language: fr-fr 156 + ``` 157 + 158 + ### Le _Body_ 159 + 160 + Lorsqu'une requรชte comporte un corps, les _Headers_ `Content-Type` et `Content-Length` doivent รชtre prรฉcisรฉs et dรฉfinir son type et sa taille en octets. 161 + Un saut de ligne doit รฉgalement sรฉparer les _Headers_ du _Body_. 162 + 163 + Exemple de requรชte avec un _Body_ au format `JSON`&nbsp;: 164 + 165 + ``` 166 + POST /articles/ HTTP/1.1 167 + Host: ekite.tech 168 + Content-Type: application/json 169 + Content-Length: 31 170 + 171 + {"title":"mon nouvel article"} 172 + ``` 173 + ## La structure d'une rรฉponse 174 + 175 + Les rรฉponses HTTP ont un format assez similaire ร  celui des requรชtes. 176 + ``` 177 + STATUS-LINE 178 + [HEADERS] 179 + 180 + [BODY] 181 + ``` 182 + 183 + ### La _Status Line_ 184 + 185 + La _Status Line_ reprรฉsente la rรฉponse codifiรฉe du serveur ร  la requรชte. 186 + 187 + _STATUS-LINE_ est dรฉfinie de cette maniรจre&nbsp;: 188 + 189 + ``` 190 + HTTP-VERSION CODE PHRASE 191 + ``` 192 + 193 + Le premier รฉlรฉment de la rรฉponse est la version HTTP `HTTP/1.1` 194 + 195 + Les codes utilisรฉs sont reprรฉsentรฉs par 3 chiffres. 196 + 197 + * Les codes `1xx` sont informationnels et rarement utilisรฉs en pratique. 198 + * Les codes `2xx` reprรฉsentent une opรฉration en succรจs. 199 + * Les codes `3xx` indiquent une redirection. 200 + * Les codes `4xx` indiquent une erreur du client (requรชte mal formรฉe, ressource non existante). 201 + * Les codes `5xx` reprรฉsentent une erreur du serveur dans le traitement de la requรชte. 202 + 203 + Les codes sont suivis d'une _Phrase_ descriptive. 204 + 205 + Les codes les plus courants et des phrases associรฉes sont dรฉfinis dans la [RFC 2616](https://www.rfc-editor.org/rfc/rfc2616#section-6.1.1). 206 + 207 + Exemple de rรฉponse en erreur&nbsp;: 208 + 209 + ``` 210 + HTTP/1.1 404 Not Found 211 + ``` 212 + 213 + Exemple de rรฉponse en succรจs&nbsp;: 214 + 215 + ``` 216 + HTTP/1.1 200 OK 217 + ``` 218 + 219 + ### Les _Headers_ de rรฉponse 220 + 221 + Au mรชme titre qu'une requรชte, une rรฉponse peut contenir des _Headers_. Ils dรฉfinissent le type et la taille du _Body_ de rรฉponse, ou des paramรจtres pour indiquer au client que la rรฉponse peut รชtre stockรฉe en cache. D'autres _Headers_ dรฉfinissent la ressource ร  appeler en cas de redirection (code `3xx`). 222 + 223 + Les _Headers_ de rรฉponse sont dรฉfinis de la mรชme maniรจre que les requรชtes&nbsp;: 224 + 225 + ``` 226 + NAME: VALUE 227 + ``` 228 + 229 + Exemple de rรฉponse HTTP comportant un _Header_ `Location` pour une redirection vers une page `index.html`&nbsp;: 230 + 231 + ``` 232 + HTTP/1.1 301 Moved Permanently 233 + Location: index.html 234 + ``` 235 + 236 + ### Le _Body_ de rรฉponse 237 + 238 + Le _Body_ est dรฉfinit de la mรชme maniรจre que les requรชtes, et impose รฉgalement les mรชmes rรจgle de prรฉsence des _Headers_ `Content-Type` et `Content-Length`. 239 + 240 + Exemple de rรฉponse en succรจs comportant le contenu de notre article&nbsp;: 241 + 242 + ``` 243 + HTTP/1.1 200 OK 244 + Content-Type: application/json 245 + Content-Length: 31 246 + 247 + {"title":"mon nouvel article"} 248 + ``` 249 + 250 + Exemple d'une erreur serveur, avec une page HTML la reprรฉsentant&nbsp;: 251 + 252 + ``` 253 + HTTP/1.1 500 Internal Server Error 254 + Content-Type: text/html 255 + Content-Length: 56 256 + 257 + <html><body><h1>Erreur de traitement</h1></body></html> 258 + ``` 259 + ## Conclusion 260 + 261 + Le protocole HTTP dรฉcrit un format texte, sous la forme de requรชte et rรฉponse, facile ร  implรฉmenter dans tous les langages de programmation. 262 + Sa simplicitรฉ et son expressivitรฉ sont la clรฉ de son succรจs depuis les annรฉes 90, jusqu'aux nouvelles versions qui continuent de s'appuyer sur le mรชme format. 263 + 264 + ## Rรฉfรฉrences 265 + 266 + * [RFC 2616](https://www.rfc-editor.org/rfc/rfc2616)&nbsp;: Hypertext Transfer Protocol -- HTTP/1.1 267 + * [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986)&nbsp;: Uniform Resource Identifier (URI) : Generic Syntax 268 + * [RFC 7540](https://www.rfc-editor.org/rfc/rfc7540)&nbsp;: Hypertext Transfer Protocol Version 2 (HTTP/2)
content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-addon-create.png

This is a binary file and will not be displayed.

content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-env.png

This is a binary file and will not be displayed.

content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-open-starting.png

This is a binary file and will not be displayed.

content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-open.png

This is a binary file and will not be displayed.

content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-scale.png

This is a binary file and will not be displayed.

content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/create-sonarqube.png

This is a binary file and will not be displayed.

+10
content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/diagrams.drawio
··· 1 + <mxfile host="Electron" modified="2023-11-02T14:28:07.869Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.3.7 Chrome/112.0.5615.204 Electron/24.5.0 Safari/537.36" etag="qV1sjR1Wv6CTG9wR4SCB" version="21.3.7" type="device"> 2 + <diagram name="Page-1" id="ukJr07_c3Hn4pDndtCBV"> 3 + <mxGraphModel dx="144" dy="535" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0"> 4 + <root> 5 + <mxCell id="0" /> 6 + <mxCell id="1" parent="0" /> 7 + </root> 8 + </mxGraphModel> 9 + </diagram> 10 + </mxfile>
+421
content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/index.md
··· 1 + --- 2 + created: "2023-11-02" 3 + date: "2023-11-02T00:00:00Z" 4 + language: fr 5 + modified: "2023-11-09" 6 + slug: "deploy-sonarqube-on-clever-cloud" 7 + tags: 8 + - Clever Cloud 9 + - SonarQube 10 + - Tutorial 11 + title: Dรฉployer une instance de SonarQube sur Clever Cloud 12 + --- 13 + 14 + Dans cet article, nous allons voir comment dรฉployer _SonarQube_ sur _Clever Cloud_ en deux temps. Le premier consistera en un dรฉploiement trรจs simple, qui est รฉquivalent ร  une installation locale. Dans un second temps, nous utiliserons une base de donnรฉes _PostgreSQL_ externalisรฉe pour assurer la persistance des donnรฉes. 15 + 16 + Cet article suppose que vous avez dรฉjร  un compte actif sur _Clever Cloud_, et que votre CLI est installรฉ et configurรฉ. 17 + L'installation du CLI est dรฉcrite dans [la documentation de _Clever Cloud_](https://www.clever-cloud.com/doc/getting-started/cli/). 18 + 19 + # Le dรฉploiement simple 20 + 21 + La [documentation _SonarQube_](https://docs.sonarsource.com/sonarqube/latest/try-out-sonarqube/#installing-a-local-instance-of-sonarqube) propose de dรฉployer une instance locale en utilisant la commande suivante&nbsp;: 22 + 23 + ```bash 24 + $ docker container run -d \ 25 + --name sonarqube \ 26 + -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true \ 27 + -p 9000:9000 \ 28 + sonarqube:latest 29 + ``` 30 + 31 + _SonarQube_ fournit une [image _Docker_](https://hub.docker.com/_/sonarqube) prรชte ร  l'emploi que nous allons utiliser. Nous utiliserons le tag _Docker_ `10-community` pour nous assurer de rester sur la version majeure `10`. 32 + 33 + La variable d'environnement `SONAR_ES_BOOTSTRAP_CHECKS_DISABLE` permet ร  _SonarQube_ d'ignorer les contrรดles de dรฉmarrage du processus _Elasticsearch_ embarquรฉ dans son serveur. 34 + 35 + _SonarQube_ รฉcoute par dรฉfaut sur le port `9000`. 36 + 37 + Ces informations nous seront utiles par la suite&nbsp;! 38 + 39 + ## Crรฉation de l'application dans _Clever Cloud_ 40 + 41 + Nous allons tout d'abord crรฉer un _repository_ Git qui hรฉbergera notre code (et nos scripts si besoin), et qui sera utilisรฉ par le CLI `clever` pour nos dรฉploiements. 42 + 43 + ```bash 44 + $ git init 45 + ``` 46 + 47 + Crรฉer une application dans _Clever Cloud_ consiste en une ligne de commande&nbsp;: 48 + 49 + ```bash 50 + $ clever create \ 51 + --type docker \ 52 + sonarqube-app 53 + 54 + Your application has been successfully created! 55 + ``` 56 + 57 + Si vous dรฉployez votre code dans une organisation, ajoutez le paramรจtre `--org` ร  votre ligne de commande&nbsp;: 58 + 59 + ```bash 60 + $ clever create \ 61 + --type docker \ 62 + --org orga_a4fdf186-bcaa-4d9f-9249-b09d57bf4beb \ 63 + sonarqube-app 64 + 65 + Your application has been successfully created! 66 + ``` 67 + 68 + L'application ainsi crรฉรฉe apparaรฎt dans la console _Clever Cloud_&nbsp;: 69 + 70 + ![L'application crรฉรฉe dans _Clever Cloud_](create-sonarqube.png) 71 + 72 + La commande `clever create` gรฉnรจre un fichier `.clever.json` dans notre rรฉpertoire courant qui contient les informations de notre application, en particulier son identifiant. 73 + 74 + ```json 75 + { 76 + "apps": [ 77 + { 78 + "app_id": "app_765c79a9-e316-460b-a75a-054738784efd", 79 + "org_id": "orga_a4fdf186-bcaa-4d9f-9249-b09d57bf4beb", 80 + "deploy_url": "https://push-n3-par-clevercloud-customers.services.clever-cloud.com/app_765c79a9-e316-460b-a75a-054738784efd.git", 81 + "name": "sonarqube-app", 82 + "alias": "sonarqube-app" 83 + } 84 + ] 85 + } 86 + ``` 87 + 88 + Ce fichier peut รชtre archivรฉ dans _repository_ Git&nbsp;: 89 + 90 + ```bash 91 + $ git add .clever.json && git commit -m "๐Ÿ‘ท : add .clever.json" 92 + ``` 93 + 94 + ## Dimensionnement de l'instance 95 + 96 + _SonarQube_ a besoin d'au moins 2&nbsp;Go de RAM pour fonctionner ainsi que 1&nbsp;Go de RAM disponible sur l'OS, nous allons donc utiliser une instance `M` qui disposera de 4&nbsp;Go de RAM au total. 97 + 98 + La modification du type d'instance se fait รฉgalement en une ligne de commande&nbsp;: 99 + 100 + ```bash 101 + $ clever scale --flavor M 102 + 103 + App rescaled successfuly 104 + ``` 105 + 106 + Une fois la commande exรฉcutรฉe, la modification est visible dans l'onglet _Scalability_ de l'application&nbsp;: 107 + 108 + ![L'application avec la taille d'instance M](/assets/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-scale.png) 109 + 110 + ## Configuration des variables d'environnement 111 + 112 + _Clever Cloud_ requiert que les applications dรฉployรฉes รฉcoutent sur le port `8080`. 113 + 114 + Nous avons รฉgalement vu prรฉcรฉdemment que par dรฉfaut _SonarQube_ รฉcoute sur le port `9000`. 115 + 116 + La configuration de notre instance _SonarQube_ peut se faire avec des variables d'environnement ([doc](https://docs.sonarsource.com/sonarqube/latest/setup-and-upgrade/configure-and-operate-a-server/environment-variables/)). 117 + 118 + Nous allons donc configurer la variable d'environnement `SONAR_WEB_PORT` avec la valeur `8080`. 119 + Nous allons รฉgalement en profiter pour configurer la variable `SONAR_ES_BOOTSTRAP_CHECKS_DISABLE` qui รฉtait prรฉcisรฉe dans la ligne de lancement `docker` issue de la documentation _SonarQube_. 120 + Pour configurer ces variables, nous utilisons la commande `clever env set`&nbsp;: 121 + 122 + ```bash 123 + $ clever env set SONAR_WEB_PORT 8080 124 + 125 + Your environment variable has been successfully saved 126 + 127 + $ clever env set SONAR_ES_BOOTSTRAP_CHECKS_DISABLE true 128 + 129 + Your environment variable has been successfully saved 130 + ``` 131 + 132 + Les variables d'environnement configurรฉes sont visibles sur la console _Clever Cloud_, dans l'onglet _Environment Variables_&nbsp;: 133 + 134 + ![Les variables d'environnement configurรฉes sur la console _Clever Cloud_](/assets/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-env.png) 135 + 136 + ## Dรฉploiement de l'image _Docker_ 137 + 138 + Une fois notre application crรฉรฉe et configurรฉe, il nous faut la dรฉployer. 139 + 140 + Nous crรฉons un simple `Dockerfile` dans notre _repository_&nbsp;: 141 + 142 + ```docker 143 + FROM sonarqube:10-community 144 + ``` 145 + 146 + Puis nous dรฉployons l'application en crรฉant un _commit_, et en faisant un `clever deploy`&nbsp;: 147 + 148 + ```bash 149 + $ git add Dockerfile && git commit -m "๐Ÿ‹ : init Dockerfile" 150 + $ clever deploy 151 + 152 + App is brand new, no commits on remote yet 153 + New local commit to push is 371a4224151b9e9bb8888a403a9626c88a0b1312 (from refs/heads/main) 154 + Pushing source code to Clever Cloudโ€ฆ 155 + Your source code has been pushed to Clever Cloud. 156 + Waiting for deployment to startโ€ฆ 157 + Deployment started (deployment_a13a283f-5e63-45da-b675-666603212a18) 158 + Waiting for application logsโ€ฆ 159 + 160 + [...] 161 + 162 + 2023-10-31T09:16:39.007Z: 2023.10.31 09:16:37 INFO ce[][o.s.s.p.ServerFileSystemImpl] SonarQube home: /opt/sonarqube 163 + 2023-10-31T09:16:39.007Z: 2023.10.31 09:16:37 INFO ce[][o.s.c.c.CePluginRepository] Load plugins 164 + 2023-10-31T09:16:39.007Z: 2023.10.31 09:16:38 INFO ce[][o.s.c.c.ComputeEngineContainerImpl] Running Community edition 165 + 2023-10-31T09:16:39.007Z: 2023.10.31 09:16:38 INFO ce[][o.s.ce.app.CeServer] Compute Engine is started 166 + 2023-10-31T09:16:39.007Z: 2023.10.31 09:16:38 INFO app[][o.s.a.SchedulerImpl] Process[ce] is up 167 + 2023-10-31T09:16:39.007Z: 2023.10.31 09:16:38 INFO app[][o.s.a.SchedulerImpl] SonarQube is operational 168 + 169 + Deployment successful 170 + ``` 171 + 172 + Le message `Deployment successful` indique que notre instance est bien dรฉmarrรฉe&nbsp;! 173 + 174 + Nous pouvons maintenant ouvrir notre instance de _SonarQube_ avec la commande&nbsp;: 175 + 176 + ```bash 177 + $ clever open 178 + 179 + Opening the application in your browser 180 + ``` 181 + 182 + La page de dรฉmarrage de _SonarQube_ s'ouvre&nbsp;: 183 + 184 + ![La page de dรฉmarrage de _SonarQube_](/assets/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-open-starting.png) 185 + 186 + Quelques instants plus tard, une fois que l'instance _SonarQube_ est complรจtement dรฉmarrรฉe, la page de _login_ s'affiche&nbsp;: 187 + 188 + ![La page de login de _SonarQube_](/assets/2023-11-02-deploy-sonarqube-on-clever-cloud/sonarqube-login.png) 189 + 190 + Nous nous loguons avec les identifiants par dรฉfaut `admin` / `admin`, puis nous changeons le mot de passe du compte `admin`. 191 + Une fois ces รฉtapes effectuรฉes, la page d'accueil de notre instance _SonarQube_ s'affiche&nbsp;: 192 + 193 + ![Notre instance de _SonarQube_ fonctionnelle](/assets/2023-11-02-deploy-sonarqube-on-clever-cloud/sonarqube-empty.png) 194 + 195 + Le message affichรฉ en bas de page nous indique que notre dรฉploiement est, certes, fonctionnel, mais non adaptรฉ ร  un usage en production. Nous allons donc maintenant utiliser une base de donnรฉes externalisรฉe. 196 + 197 + # Externaliser la base de donnรฉes 198 + 199 + Une base de donnรฉes externalisรฉe va permettre de rendre nos donnรฉes persistantes. 200 + _SonarQube_ est compatible avec les bases de donnรฉes _PostgreSQL_, _SQL Server_ et _Oracle_. 201 + 202 + _Clever Cloud_ propose diverses bases de donnรฉes dans la section _Add-On_ de la console, ou _via_ les commandes CLI `clever addon`. _PostgreSQL_ fait partie des bases de donnรฉes supportรฉes, ce qui est parfait pour notre instance de _SonarQube_&nbsp;! 203 + 204 + ## Crรฉer l'_addon_ _PostgreSQL_ 205 + 206 + Pour lister les _addons_ disponibles, nous utilisons la commande `clever addon providers`, ce qui va nous permettre de rรฉcupรฉrer l'identifiant de l'_addon_ _PostgreSQL_&nbsp;: 207 + 208 + ```bash 209 + $ clever addon providers 210 + 211 + addon-matomo Matomo Analytics Matomo is a web analytics application as a service. 212 + addon-pulsar Pulsar Namespace with all Pulsar possibilities 213 + cellar-addon Cellar S3 storage S3-like online file storage web service 214 + config-provider Configuration provider Expose configuration to your applications (via environment variables) 215 + es-addon Elastic Stack Elasticsearch with Kibana and APM server as options 216 + fs-bucket FS Buckets Persistent file system for your application 217 + jenkins Jenkins Automation & CI with Clever Cloud runners 218 + mailpace MailPace - Transactional Email Fast & Reliable Transactional Email 219 + mongodb-addon MongoDB A noSQL document-oriented database 220 + mysql-addon MySQL An open source relational database management system 221 + postgresql-addon PostgreSQL A powerful, open source object-relational database system 222 + redis-addon Redis Redis by Clever Cloud is an in-memory key-value data store, powered by Clever Cloud 223 + ``` 224 + 225 + L'_addon_ que nous allons utiliser est donc nommรฉ `postgresql-addon`. 226 + 227 + Nous listons ensuite les diffรฉrentes versions de l'_addon_ _PostgreSQL_, et ses plans de facturation&nbsp;: 228 + 229 + ```bash 230 + $ clever addon providers show postgresql-addon 231 + 232 + PostgreSQL: A powerful, open source object-relational database system 233 + 234 + Available regions: jed, mtl, par, rbx, rbxhds, scw, sgp, syd, wsw 235 + 236 + Available plans 237 + Plan dev 238 + Backups: Daily - 7 Retained 239 + Logs: No 240 + Max DB size: 256 MB 241 + Max connection limit: 5 242 + Memory: Shared 243 + Metrics: No 244 + Migration Tool: Yes 245 + Type: Shared 246 + vCPUS: Shared 247 + Plan xxs_sml 248 + Backups: Daily - 7 Retained 249 + Logs: Yes 250 + Max DB size: 1 GB 251 + Max connection limit: 45 252 + Memory: 512 MB 253 + Metrics: Yes 254 + Migration Tool: Yes 255 + Type: Dedicated 256 + vCPUS: 1 257 + Available versions: 10, 11, 12, 13, 14 (default), 15 258 + Options for version 10: 259 + encryption: default=false 260 + Options for version 11: 261 + encryption: default=false 262 + Options for version 12: 263 + encryption: default=false 264 + Options for version 13: 265 + encryption: default=false 266 + Options for version 14: 267 + encryption: default=false 268 + Options for version 15: 269 + encryption: default=false 270 + [...] 271 + ``` 272 + 273 + Le plan _xxs_sml_ est le plus petit plan avec des ressources dรฉdiรฉes. 1&nbsp;CPU, 512&nbsp;Mo de RAM et 1&nbsp;Go de stockage sont suffisants pour dรฉmarrer, sachant que le plan pourra รชtre modifiรฉ ร  tout instant si besoin. 274 + 275 + Nous pouvons maintenant crรฉer notre _addon_ avec la commande `clever addon create`&nbsp;: 276 + 277 + ```bash 278 + $ clever addon create \ 279 + --plan xxs_sml \ 280 + --org orga_a4fdf186-bcaa-4d9f-9249-b09d57bf4beb \ 281 + postgresql-addon \ 282 + sonarqube-db 283 + 284 + Addon sonarqube-db (id: addon_2cc8bfaf-8800-43ef-87a0-4f162be73f2e) successfully created 285 + ``` 286 + 287 + Une fois la commande exรฉcutรฉe, notre base de donnรฉes apparaรฎt dans la console&nbsp;: 288 + 289 + ![La base de donnรฉes crรฉรฉe](/assets/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-addon-create.png) 290 + 291 + Nous pouvons ensuite lier notre base de donnรฉes avec notre application. Ce lien va permettre de partager des variables d'environnement entre la base de donnรฉes et notre application&nbsp;: 292 + 293 + ```bash 294 + $ clever service link-addon sonarqube-db 295 + 296 + Addon sonarqube-db successfully linked 297 + ``` 298 + 299 + Une fois l'application liรฉe ร  la base de donnรฉes, les variables d'environnement de la base de donnรฉes apparaissent dans l'onglet _Environment Variables_ de notre application&nbsp;: 300 + 301 + ![Les variables d'environnement de notre application](/assets/2023-11-02-deploy-sonarqube-on-clever-cloud/clever-service-link-addon.png) 302 + 303 + ## Reconfigurer notre instance _SonarQube_ 304 + 305 + Notre addon _Clever Cloud_ expose des variables d'environnement _POSTGRESQL_ADDON_ qui vont nous servir pour configurer notre instance de _SonarQube_. 306 + Cependant, _SonarQube_ se configure avec les variables d'environnement suivantes&nbsp;: 307 + 308 + ``` 309 + SONAR_JDBC_USERNAME 310 + SONAR_JDBC_PASSWORD 311 + SONAR_JDBC_URL 312 + ``` 313 + 314 + L'URL JDBC suit un schรฉma prรฉcis, qui est `jdbc:<driver>://<host>:<port>/<db>`. _Clever Cloud_ expose une variable d'environnement pour les `host`, `port` et `db`, donc nous pouvons calculer notre variable `SONAR_JDBC_URL` en utilisant ces variables. Voici donc la liste des variables fournies par l'_addon_ que nous allons utiliser&nbsp;: 315 + 316 + ```env 317 + # pour SONAR_JDBC_USERNAME 318 + POSTGRESQL_ADDON_USER 319 + # pour SONAR_JDBC_PASSWORD 320 + POSTGRESQL_ADDON_PASSWORD 321 + # pour SONAR_JDBC_URL 322 + POSTGRESQL_ADDON_HOST 323 + POSTGRESQL_ADDON_PORT 324 + POSTGRESQL_ADDON_DB 325 + ``` 326 + 327 + ### Copie des variables d'environnement 328 + 329 + {% include admonition.html type="note" title="Update 2023-11-09" body="Suite aux รฉchanges avec le support de _Clever Cloud_, ils m'ont proposรฉ un autre moyen de positionner les variables d'environnement. Cet autre moyen est dรฉcrit dans la section suivante. Cette section est donc obsolรจte. Le code source sur Github a รฉgalement รฉtรฉ mis ร  jour." %} 330 + 331 + Malheureusement, ni _SonarQube_ ni _Clever Cloud_ ne supporte de renommer ses variables d'environnement, ou de les interpoler. 332 + Nous devons donc crรฉer les variables d'environnement _SONAR_ avec des valeurs en dur, issues des variables d'environnement _POSTGRESQL_ADDON_. 333 + 334 + Notez que cette approche implique que notre application doit รชtre reconfigurรฉe en cas de changement de variables d'environnement, ce qui n'est pas idรฉal. 335 + 336 + Nous allons donc dans un premier temps rรฉcupรฉrer les variables d'environnement de notre application, et les stocker dans un fichier avec la commande `clever env`. Nous chargeons ensuite le fichier crรฉรฉ avec la commande `source` pour avoir les variables d'environnement disponibles dans notre _shell_&nbsp;: 337 + 338 + ```bash 339 + $ clever env --add-export > clever-env-vars.sh 340 + 341 + $ source clever-env-vars.sh 342 + 343 + $ echo $POSTGRESQL_ADDON_USER 344 + u6qkhfs3dduj1rrlra99 345 + ``` 346 + 347 + Les commandes suivantes permettent de configurer la connexion ร  notre base de donnรฉes avec les variables d'environnement _SONAR_&nbsp;: 348 + 349 + ```bash 350 + $ clever env set SONAR_JDBC_USERNAME $POSTGRESQL_ADDON_USER 351 + $ clever env set SONAR_JDBC_PASSWORD $POSTGRESQL_ADDON_PASSWORD 352 + $ clever env set SONAR_JDBC_URL "jdbc:postgresql://${POSTGRESQL_ADDON_HOST}:${POSTGRESQL_ADDON_PORT}/${POSTGRESQL_ADDON_DB}" 353 + ``` 354 + 355 + Pour dรฉployer notre instance avec sa nouvelle configuration, il faut simplement redรฉmarrer l'application avec la commande `clever restart`&nbsp;: 356 + 357 + ```bash 358 + $ clever restart 359 + ``` 360 + 361 + Une fois _SonarQube_ redรฉmarrรฉ, il nous demande ร  nouveau de changer le mot de passe de l'utilisateur `admin` puisque le prรฉcรฉdent mot de passe a รฉtรฉ stockรฉ dans la base de donnรฉes embarquรฉe, et donc perdu ร  la migration. 362 + 363 + ### Script de dรฉmarrage customisรฉ 364 + 365 + {% include admonition.html type="note" title="Update 2023-11-09" body="Cette section a รฉtรฉ ajoutรฉe suite aux รฉchanges avec le support de _Clever Cloud_" %} 366 + 367 + Malheureusement, ni _SonarQube_ ni _Clever Cloud_ ne supporte de renommer ses variables d'environnement, ou de les interpoler. 368 + Nous allons donc ajouter un script dans notre image _Docker_ pour retravailler nos variables d'enviroonement. 369 + 370 + L'image _Docker_ de _SonarQube_ utilise pour `ENTRYPOINT` un script nommรฉ `/opt/sonarqube/docker/entrypoint.sh`. 371 + 372 + Notre script que nous appelons `clever-entrypoint.sh` va donc positionner les variables d'environnement nรฉcessaires au dรฉmarrage de _SonarQube_ et rappeler le script de _SonarQube_ &nbsp;: 373 + 374 + ```bash 375 + #!/bin/sh 376 + 377 + export SONAR_JDBC_USERNAME=$POSTGRESQL_ADDON_USER 378 + export SONAR_JDBC_PASSWORD=$POSTGRESQL_ADDON_PASSWORD 379 + export SONAR_JDBC_URL="jdbc:postgresql://${POSTGRESQL_ADDON_HOST}:${POSTGRESQL_ADDON_PORT}/${POSTGRESQL_ADDON_DB}" 380 + 381 + exec /opt/sonarqube/docker/entrypoint.sh 382 + ``` 383 + 384 + Nous ajoutons ce script dans le rรฉpertoire `/opt/sonarqube/docker` au niveau de notre `Dockerfile`, nous modifions l'`ENTRYPOINT` de notre image pour pointer vers notre script&nbsp;: 385 + 386 + ```docker 387 + FROM sonarqube:10-community 388 + 389 + ADD clever-entrypoint.sh /opt/sonarqube/docker/ 390 + 391 + ENTRYPOINT ["/opt/sonarqube/docker/clever-entrypoint.sh"] 392 + ``` 393 + 394 + Un `git commit` suivi d'un `clever deploy` nous permettent de mettre ร  jour notre application avec le script embarquรฉ et de pointer vers notre base de donnรฉes. 395 + 396 + ```bash 397 + $ git add Dockerfile clever-entrypoint.sh 398 + 399 + $ git commit -m "๐Ÿ”ง : add custom entrypoint for Clever Cloud" 400 + 401 + $ clever deploy 402 + ``` 403 + 404 + Une fois _SonarQube_ redรฉmarrรฉ, il nous demande ร  nouveau de changer le mot de passe de l'utilisateur `admin` puisque le prรฉcรฉdent mot de passe a รฉtรฉ stockรฉ dans la base de donnรฉes embarquรฉe, et donc perdu ร  la migration. 405 + 406 + # Conclusion 407 + 408 + Il est relativement facile de dรฉployer _SonarQube_ sur _Clever Cloud_. L'image _Docker_ fournie par _SonarQube_ nous permet de dรฉmarrer rapidement une instance. 409 + 410 + Les bases de donnรฉes proposรฉes par _Clever Cloud_ sont รฉgalement pratiques pour dรฉmarrer rapidement. Cependant, le manque de souplesse de _SonarQube_ dans sa configuration et l'impossibilitรฉ de renommer des variables d'environnement sur _Clever Cloud_ rendent la derniรจre รฉtape de la configuration peu pratique et peu robuste. Un peu de scripting permet de rendre cette รฉtape plus propre. 411 + 412 + Pour exรฉcuter l'infrastructure proposรฉe dans cet article, il vous en coรปtera environ 81,25&nbsp;โ‚ฌ/mois&nbsp;: 413 + 414 + | article | prix/mois | 415 + | ---------------------------- | ----------- | 416 + | PostgreSQL - XXS Small Space | 5,25&nbsp;โ‚ฌ | 417 + | Node Docker - Plan M | 76&nbsp;โ‚ฌ | 418 + 419 + ร€ titre de comparaison, un container de 4&nbsp;CPU et 4&nbsp;Go de RAM sur GCP Cloud Run coรปte 174&nbsp;โ‚ฌ/mois, avec l'option _CPU always allocated_ requise par _SonarQube_ pour exรฉcuter ses traitements en arriรจre-plan. Cela fait de _Clever Cloud_ un excellent choix รฉconomique&nbsp;! 420 + 421 + Les scripts de cet article sont disponibles sur [Github](https://github.com/juwit/sonarqube-clever-cloud).
content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/sonarqube-admin-pass.png

This is a binary file and will not be displayed.

content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/sonarqube-empty.png

This is a binary file and will not be displayed.

content/posts/2023-11-02-deploy-sonarqube-on-clever-cloud/sonarqube-login.png

This is a binary file and will not be displayed.

+36
hugo.toml
··· 1 + baseURL = 'https://codeka.io/' 2 + languageCode = 'en-us' 3 + title = 'Julien Wittouck' 4 + theme = "poison" 5 + 6 + [permalinks] 7 + [permalinks.page] 8 + posts = '/:year/:month/:day/:slug' 9 + 10 + [params] 11 + brand = "Julien Wittouck" 12 + description = "freelance solution & software architect ๐Ÿ— - containers ๐Ÿ‹ & linux ๐Ÿง โค๏ธ - teacher & trainer ๐ŸŽ“ @ univ-lille.fr - speaker ๐ŸŽ™" 13 + front_page_content = ["posts", "projects"] 14 + 15 + 16 + menu = [ 17 + {Name = "Posts", URL = "/posts/", Pre = "Recent", HasChildren = true, Limit = 5}, 18 + {Name = "Talks", URL = "/talks/"}, 19 + {Name = "Projects", URL = "/projects/"} 20 + ] 21 + 22 + email_url = "mailto://julien.wittouck@gmail.com" 23 + github_url = "https://github.com/juwit" 24 + linkedin_url = "https://www.linkedin.com/in/julien-wittouck" 25 + twitter_url = "https://www.twitter.com/CodeKaio" 26 + 27 + 28 + # Hex colors for your sidebar. 29 + moon_sun_background_color = "#515151" # default is #515151 30 + moon_sun_color = "#FFF" # default is #FFF 31 + sidebar_a_color = "#FFF" # default is #FFF 32 + sidebar_bg_color = "#5ea4e2" # default is #202020 33 + sidebar_h1_color = "#FFF" # default is #FFF 34 + sidebar_img_border_color = "#515151" # default is #515151 35 + sidebar_p_color = "#111111" # default is #909090 36 + sidebar_socials_color = "#FFF" # default is #FFF