diff --git a/docs/tutorial/quarkusgetstarted.adoc b/docs/tutorial/quarkusgetstarted.adoc index 020607d6..18d49b96 100644 --- a/docs/tutorial/quarkusgetstarted.adoc +++ b/docs/tutorial/quarkusgetstarted.adoc @@ -15,217 +15,148 @@ This tutorial will walk through downloading and building one of the quarkus gett qDup connects to computers through ssh. You need to have a computer that will accept ssh connections. You can setup ssh on your own computer by following the steps in the link:./prerequisites.adoc[prerequisites] -Remember the username and hostname for your setup and use them in the `hosts` section of the qDup yaml +== Getting started -== Getting started with Getting started +We are going to use the link:https://quarkus.io/guides/getting-started[Quarkus getting started] project. The best practice is to open a terminal and test each command to get familiar with the input and output. We normally run commands in terminal before adding them to a qDup script to see how the commands behave. -We are going to use the link:https://quarkus.io/guides/getting-started[Quarkus getting started] project to substitute for our application. We follow the steps in their guide the same way we would follow the README for other applications. The best practice is to open a terminal and test each command to get familiar with the output. Start with the first command in the README. - -``` -git clone https://github.com/quarkusio/quarkus-quickstarts.git ``` -The first README step clones the example repository. We create a qDup script with the same step, but our script will first cd to the `tmp` directory. -```yaml +#> cat < quarkus.yaml scripts: + test-endpoint: + - wait-for: ready + then: + - sh: curl localhost:8080/hello + - signal: done #tells qDup that the "testing" is done + ensure-quarkus-cli: + - sh: quarkus version #to see if the command exists + then: + - regex: "command not found" + then: #install quarkus by following: https://quarkus.io/get-started/ + - sh: "curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/" + - sh: "curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio" + - sh: "source ~/.bashrc" # jbang change your environment if you don't have jbang in the PATH getting-started: - sh: cd /tmp/ - - sh: git clone https://github.com/quarkusio/quarkus-quickstarts.git + - sh: "[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts.git" # prevent cloning again - sh: cd quarkus-quickstarts + - sh: cd getting-started + - script: ensure-quarkus-cli + - sh: + command: quarkus dev + prompt: + "Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>": "r" + timer: + 2m: #a short timeout + - abort: quarkus dev did not exit before the timer expired + watch: + - regex: "Tests completed" + then: + - signal: ready + on-signal: + done: + - ctrlC #exits the process hosts: - test: me@localhost #replace this with your ssh username@hostname + test: $USER@localhost roles: - example: + setup-env: hosts: - test run-scripts: - getting-started + - test-endpoint +EOF ``` -Create a `qdup.yaml` script file with the above yaml and run it using qDup +Run with `java -jar qDup-0.8.5-uber.jar -i ~/.ssh/qdup quarkus.yaml -ix`. It will take some time and in the end you will see: ``` -java -jar qdup-uber.jar qdup.yaml +All 2 tests are passing (0 skipped), 2 tests were run in 4289ms. Tests completed at 13:34:11. +Press [e] to edit command line args (currently ''), [r] to re-run, [o] Toggle test output, [:] for the terminal, [h] for more options> +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 17.915 s +[INFO] Finished at: 2025-01-09T13:34:12-03:00 +[INFO] ------------------------------------------------------------------------ +Finished in 31.238 at /tmp/20250109_133335 ``` +It means that the qDup script worked fine and finished in 31 seconds. -The quarkus guide next talks about creating our own project using the `quarkus` cli. We are going to skip ahead and use the `getting-started` project. Remember to run the `cd getting-started` in the terminal too. Walking through each step in a terminal while writing the script prevents most errors related to unexpected output. +=== Checkout project -```yaml -scripts: - getting-started: - - sh: cd /tmp/ - - sh: git clone https://github.com/quarkusio/quarkus-quickstarts.git - - sh: cd quarkus-quickstarts - - sh: cd getting-started -``` +Change directory to `/tmp` and clone the repository if `quarkus-quickstarts` doesn't exist. Change directory to `quarkus-quickstarts` and then to `getting-started` -If you add the `sh: cd getting-started` to `qdup.yaml` and run it again you will likely see an error message from `git clone` complaining that the directory already exists. We normally remove the existing folder, if it exists, with some bash conditionals -```yaml: -- sh: "[[-d quarkus-quickstarts ]] && rm -rf quarkus-quickstarts" -``` -We do not want to download the full git repo after each change to our script. We will instead only run git clone if the directory does not exist ```yaml -scripts: - getting-started: - sh: cd /tmp/ - sh: "[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts.git" - sh: cd quarkus-quickstarts - sh: cd getting-started ``` -The next command in the getting started guide is to run `quarkus dev`. Try running it in a terminal; it will likely result in `command not found`. We need to ensure we have the quarkus cli installed. It is good practice to split this into a separate script (e.g. `ensure-quarkus-cli`) and follow the steps for installing the cli. Run each step in a terminal then add them to the script after you have an expectation for the output. +=== Install `quarkus` if needed -Once `quarkus dev` runs you will have a script that looks like the yaml below but if you run it the script will hang. +Call the `qDup` `ensure-quarkus-cli` script. ```yaml -scripts: - ensure-quarkus-cli: - - sh: quarkus version #to see if the command exists - then: - - regex: command not found - then: #https://quarkus.io/get-started/ - - sh: "curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/" - - sh: "curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio" - getting-started: - - sh: cd /tmp/ - - sh: "[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts.git" - - sh: cd quarkus-quickstarts - - sh: cd getting-started - - script: ensure-quarkus-cli - - sh: quarkus dev +- script: ensure-quarkus-cli ``` -Run `quarkus dev` in a terminal from the `/tmp/quarkus-quickstarts/getting-started` folder. We normally run commands in terminal before adding them to a qDup script to see how the commands behave. In this case, `quarkus dev` is interactive and expects user input. +Call `quarkus version` command and if the command has an output that matches `command not found`, then install `quarkus` using `jbang` -``` -Tests paused -Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options> -``` -The execution pauses waiting for an `r` to run the unit tests. It also does not wait for input on a new line. This means we should use `sh` with `prompt` to respond to the message. The `prompt` looks for a set of characters from the ssh connection and sends the associated response if it finds those characters. Using `prompt` means we have to use the yaml mapping syntax for `sh`. Most qdup commands support a simplified string format (e.g. `sh: "./runScript.sh"`) but also a more complex mapping that includes options that are not always needed: ```yaml -- sh: - command: quarkus dev - prompt: - "Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>": "r" + ensure-quarkus-cli: + - sh: quarkus version + then: + - regex: "command not found" + then: + - sh: "curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/" + - sh: "curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio" + - sh: "source ~/.bashrc" ``` -The above `sh` command responds to the quarkus prompt and runs the test but `quarkus dev` does not exit, and we want to test the endpoints while the process is running. We can start another script in `run-scripts` that will test an endpoint with a `curl` but we have to add coordination to ensure the script does not start testing before the process is ready. +=== prompt -Let's call our new script `test-endpoint` and use a signal named `ready` to coordinate the two scripts. First, we create our `test-endpoint` script that will `curl` the endpoint after quarkus is ready. +`quarkus dev` is interactive and expects user input. When the output matches `Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>` we simulate pressing the letter `r`. This will run the test but `quarkus dev` does not exit, and we want to test the endpoints while the process is running. When the output has `Tests completed`, send the link:./../reference/command/signal.adoc[signal] `ready`. ```yaml -sripts: - test-endpoint: - - wait-for: ready - then: - - sh: curl localhost:8080/hello #replace localhost if you used a different ssh computer name -``` -The `test-endpoint` script is ready; now we need to `signal` when `quarkus dev` is ready to receive requests. The `Tests paused` message from before the prompt occurs is an excellent option. We can `watch` the output and `regex: Test paused` to `signal` when quarkus is ready. The new `getting-started` scripts will now look like the following: -```yaml -scripts: - getting-started: - - sh: cd /tmp/ - - sh: "[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts.git" - - sh: cd quarkus-quickstarts - - sh: cd getting-started - - script: ensure-quarkus-cli - sh: command: quarkus dev prompt: - "Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>": "r" + "Press [e] to edit command line args (currently ''), [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>": "r" watch: - - regex: "Test paused" + - regex: "Tests completed" then: - signal: ready ``` -Our full qDup script now looks like the following: -```yaml -scripts: - test-endpoint: - - wait-for: ready - then: - - sh: curl localhost:8080/hello #replace localhost if you used a differnet ssh computer name - - ensure-quarkus-cli: - - sh: which quarkus - then: - - regex: no quarkus - then: #https://quarkus.io/get-started/ - - sh: "curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/" - - sh: "curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio" - - getting-started: - - sh: cd /tmp/ - - sh: "[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts.git" - - sh: cd quarkus-quickstarts - - sh: cd getting-started - - script: ensure-quarkus-cli - - sh: - command: quarkus dev - prompt: - "Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>": "r" - watch: - - regex: "Tests paused" - then: - - signal: ready +=== Wait for `ready` -hosts: - test: me@localhost #replace this with your ssh username@hostname -roles: - example: - hosts: - - test - run-scripts: - - test-endpoint - - getting-started -``` +When the `qDup` script `test-endpoint` receives the `ready` signal, call the endpoint and send the link:./../reference/command/signal.adoc[signal] `done` -If you run this you will see the curl output in the qDup console but qDup will not exit because the `quarkus dev` is still running. We need the `test-endoint` script to tell the `getting-started` script when it finished "testing" ( running `curl`) so that the script can end the `quarkus dev` command. We accomplish this with a signal from `test-endoint` that indicates the testing is `done` and we add an `on-signal` to the `sh: quarkus dev`. The new complete script should look like the following: +The curl output will show the output in the qDup console but qDup will not exit because the `quarkus dev` is still running. ```yaml -scripts: test-endpoint: - wait-for: ready then: - - sh: curl localhost:8080/hello #replace localhost if you used a different ssh computer name - - signal: done #tells qDup that the "testing" is done + - sh: curl localhost:8080/hello + - signal: done +``` - ensure-quarkus-cli: - - sh: which quarkus - then: - - regex: no quarkus - then: #https://quarkus.io/get-started/ - - sh: "curl -Ls https://sh.jbang.dev | bash -s - trust add https://repo1.maven.org/maven2/io/quarkus/quarkus-cli/" - - sh: "curl -Ls https://sh.jbang.dev | bash -s - app install --fresh --force quarkus@quarkusio" +=== Wait for `done` - getting-started: - - sh: cd /tmp/ - - sh: "[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts.git" - - sh: cd quarkus-quickstarts - - sh: cd getting-started - - script: ensure-quarkus-cli - - sh: - command: quarkus dev - prompt: - "Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>": "r" - watch: - - regex: "Tests paused" - then: - - signal: ready +When the `qDup` script receives the `done` signal, send the `SIGINT` link:https://man7.org/linux/man-pages/man7/signal.7.html[POSIX] signal. This will stop the `quarkus dev` command and exit the `qDup` script. + +```yaml on-signal: done: - - ctrlC #exits the process - -hosts: - test: me@localhost #replace this with your ssh username@hostname -roles: - example: - hosts: - - test - run-scripts: - - test-endpoint - - getting-started + - ctrlC ``` +=== Ignoring exit codes +If you rerun the script, it will fail because you have `quarkus-quickstarts` folder. In order to workaround that, we add the command `[[ ! -d quarkus-quickstarts ]] && git clone https://github.com/quarkusio/quarkus-quickstarts`. The command will have the exit code `0` if the folder doesn't exist. If the folder exists, the command will exit with code `1`. The `-ix` flag is added to the command line above to ignore individual status code checks for simplicity. However, in a production environment, your bash scripts should be designed to return an exit code of `0`. + +== Troubleshooting + Some of you may find the qDup process is still stuck and you are not seeing `curl` in the logs. This usually happens when `quarkus dev` does not log `Tests paused` because it had an issue starting. qDup has an internal web server that exposes diagnostics data. We can get the active commands with: ``` curl localhost:31337/active @@ -234,16 +165,14 @@ If you see `quarkus dev` as an active command then check the `output` for an err We don't want our qDup scripts getting stuck in our automated environment. We add a `timer` to any `sh` commands that do not automatically exit. This forces a limit on execution time and alerts us to errors. ```yaml -- sh: - command: "quarkus dev" timer: - 2m: #a short timeout + 2m: - abort: quarkus dev did not exit before the timer expired ``` == Next -At this point you know how to write a script and how to work with `sh` commands that prompt and do not automatically exit. Next we will explore using `setup-scripts` and `cleaup-scripts` and how to work with commands that package their own cli by using hyperfoil to load test the getting-started application +At this point you know how to write a script and how to work with `sh` commands that prompt and do not automatically exit. Next we will explore using `setup-scripts` and `cleaup-scripts` and how to work with commands that package their own cli by using link:./hyperfoil.adoc[hyperfoil] to load test the getting-started application