From 2d2d5ba6f699bc0f01a501df449117d0bbb2918b Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Tue, 29 Oct 2024 16:01:14 +0100 Subject: [PATCH 001/100] Add Flask tutorial --- docs/flask.rst | 678 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 678 insertions(+) create mode 100644 docs/flask.rst diff --git a/docs/flask.rst b/docs/flask.rst new file mode 100644 index 000000000..21f0e9d19 --- /dev/null +++ b/docs/flask.rst @@ -0,0 +1,678 @@ +================================================= +Write your first Kubernetes charm for a Flask app +================================================= + +Imagine you have a Flask application backed up by a database +such as PostgreSQL and need to deploy it. In a traditional setup, +this can be quite a challenge, but with Juju you’ll find yourself +deploying, configuring, scaling, integrating, monitoring, etc., +your Flask application in no time. Let’s get started! + +In this tutorial we will build a rock and Kubernetes charm for a +Flask application using the charm SDK, so we can have a Flask +application up and running with Juju in about 90 minutes. + +.. note:: + + **rock**: An Ubuntu LTS-based OCI compatible + container image designed to meet security, stability, and + reliability requirements for cloud-native software. + + **charm**: A package consisting of YAML files + Python code that will + automate every aspect of an application's lifecycle so it can + be easily orchestrated with Juju. + + **Juju**: An orchestration engine for software + operators that enables the deployment, integration and lifecycle + management of applications using charms. + +**What you’ll need:** + +- A workstation, e.g., a laptop, with amd64 or arm64 architecture which + has sufficient resources to launch a virtual machine with 4 CPUs, + 4 GB RAM, and a 50 GB disk +- Familiarity with Linux + +**What you’ll do:** + +- Set things up +- Create the Flask application +- Run the Flask application locally +- Pack the Flask application into a rock +- Create the charm +- Deploy the Flask application and expose via ingress +- Enable ``juju config flask-hello-world greeting=`` +- Integrate with a database +- Clean up environment + +.. hint:: + + Don't hesitate to get in touch on + `Matrix `_ or + `Discourse `_ (or follow the + "Edit this page on GitHub" on the bottom of + this document to comment directly on the document). + + +Set things up +============= + +Install Multipass. + +.. seealso:: + + See more: `Multipass | How to install Multipass `_ + +Use Multipass to launch an Ubuntu VM with the name ``charm-dev`` from the 24.04 blueprint: + +.. code-block:: bash + + multipass launch --cpus 4 --disk 50G --memory 4G --name charm-dev 24.04 + +Once the VM is up, open a shell into it: + +.. code-block:: bash + + multipass shell charm-dev + +In order to create the rock, you'll need to install Rockcraft: + +.. code-block:: bash + + sudo snap install rockcraft --classic + +``LXD`` will be required for building the rock. Make sure it is installed and initialised: + +.. code-block:: bash + + sudo snap install lxd + lxd init --auto + +In order to create the charm, you'll need to install Charmcraft: + +.. code-block:: bash + + sudo snap install charmcraft --channel latest/edge --classic + +.. warning:: + + This tutorial requires version ``3.0.0`` or later of Charmcraft. Check the + version of Charmcraft using ``charmcraft --version`` If you have an older + version of Charmcraft installed, use + ``sudo snap refresh charmcraft --channel latest/edge`` to get the latest + edge version of Charmcraft. + +MicroK8s is required to deploy the Flask application on Kubernetes. Install MicroK8s: + +.. code-block:: bash + + sudo snap install microk8s --channel 1.31-strict/stable + sudo adduser $USER snap_microk8s + newgrp snap_microk8s + +Wait for MicroK8s to be ready using ``sudo microk8s status --wait-ready``. +Several MicroK8s add-ons are required for deployment: + +.. code-block:: bash + + sudo microk8s enable hostpath-storage + # Required to host the OCI image of the Flask application + sudo microk8s enable registry + # Required to expose the Flask application + sudo microk8s enable ingress + +Juju is required to deploy the Flask application. +Install Juju and bootstrap a development controller: + +.. code-block:: bash + + sudo snap install juju --channel 3.5/stable + mkdir -p ~/.local/share + juju bootstrap microk8s dev-controller + +Finally, create a new directory for this tutorial and go inside it: + +.. code-block:: bash + + mkdir flask-hello-world + cd flask-hello-world + +Create the Flask application +============================ + +Start by creating the "Hello, world" Flask application that will be +used for this tutorial. + +Create a ``requirements.txt`` file, copy the following text into it +and then save it: + +.. code-block:: + + Flask + +In the same directory, copy and save the following into a text file +called ``app.py``: + +.. code-block:: python + + import flask + + app = flask.Flask(__name__) + + @app.route("/") + def index(): + return "Hello, world!\n" + + if __name__ == "__main__": + app.run() + +Run the Flask application locally +================================= + +Install ``python3-venv`` and create a virtual environment: + +.. code-block:: bash + + sudo apt-get update && sudo apt-get install python3-venv -y + python3 -m venv .venv + source .venv/bin/activate + pip install -r requirements.txt + +Now that we have a virtual environment with all the dependencies, let's +run the Flask application to verify that it works: + +.. code-block:: bash + + flask run -p 8000 + +Test the Flask application by using ``curl`` to send a request to the root +endpoint. You may need a new terminal for this; if you are using Multipass +use ``multipass shell charm-dev`` to get another terminal: + +.. code-block:: bash + + curl localhost:8000 + +The Flask application should respond with ``Hello, world!``. The Flask +application looks good, so we can stop for now using +:kbd:`Ctrl` + :kbd:`C`. + +Pack the Flask application into a rock +====================================== + +First, we'll need a ``rockcraft.yaml`` file. Rockcraft will automate its +creation and tailoring for a Flask application by using the +``flask-framework`` profile: + +.. code-block:: bash + + rockcraft init --profile flask-framework + +The ``rockcraft.yaml`` file will automatically be created and set the name +based on your working directory. Open the file in a text editor and check +that the ``name`` is ``flask-hello-world``. Ensure that ``platforms`` +includes the architecture of your host. For example, if your host uses the +ARM architecture, include ``arm64`` in ``platforms``. + +.. note:: + + For this tutorial, we'll use the ``name`` "flask-hello-world" and assume + you are on the ``amd64`` platform. Check the architecture of your system + using ``dpkg --print-architecture``. Choosing a different name or + running on a different platform will influence the names of the files + generated by Rockcraft. + +Pack the rock: + +.. code-block:: bash + + rockcraft pack + +.. note:: + + Depending on your system and network, this step can take a couple of minutes to finish. + +Once Rockcraft has finished packing the Flask rock, you'll find a new file +in your working directory with the ``.rock`` extension: + +.. code-block:: bash + + ls *.rock -l + +.. note:: + + If you changed the ``name`` or ``version`` in ``rockcraft.yaml`` or are + not on an ``amd64`` platform, the name of the ``.rock`` file will be + different for you. + +The rock needs to be copied to the Microk8s registry so that it can be +deployed in the Kubernetes cluster: + +.. code-block:: bash + + rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ + oci-archive:flask-hello-world_0.1_amd64.rock \ + docker://localhost:32000/flask-hello-world:0.1 + +.. seealso:: + + See more: `skopeo `_ + +Create the charm +================ + +Create a new directory for the charm and go inside it: + +.. code-block:: bash + + mkdir charm + cd charm + +We'll need a ``charmcraft.yaml``, ``requirements.txt`` and source code for +the charm. The source code contains the logic required to operate the Flask +application. Charmcraft will automate the creation of these files by using +the ``flask-framework`` profile: + +.. code-block:: bash + + charmcraft init --profile flask-framework --name flask-hello-world + +The files will automatically be created in your working directory. +Pack the charm: + +.. code-block:: bash + + charmcraft pack + +.. note:: + + Depending on your system and network, this step can take a couple of minutes to finish. + +Once Charmcraft has finished packing the charm, you'll find a new file in your +working directory with the ``.charm`` extension: + +.. code-block:: bash + + ls *.charm -l + +.. note:: + + If you changed the name in charmcraft.yaml or are not on the amd64 platform, + the name of the ``.charm`` file will be different for you. + +Deploy the Flask application +============================ + +A Juju model is needed to deploy the application. Let's create a new model: + +.. code-block:: bash + + juju add-model flask-hello-world + +.. warning:: + + If you are not on a host with the amd64 architecture, you will need to include + a constraint to the Juju model to specify your architecture. For example, for + the arm64 architecture, use + ``juju set-model-constraints -m flask-hello-world arch=arm64``. + Check the architecture of your system using ``dpkg --print-architecture``. + +Now the Flask application can be deployed using `Juju `_: + +.. code-block:: bash + + juju deploy ./flask-hello-world_ubuntu-22.04-amd64.charm \ + flask-hello-world --resource \ + flask-app-image=localhost:32000/flask-hello-world:0.1 + +.. note:: + + It will take a few minutes to deploy the Flask application. You can monitor the + progress using ``juju status --watch 5s``. Once the status of the App has gone + to ``active``, you can stop watching using :kbd:`Ctrl` + :kbd:`C`. + + See more: `Command 'juju status' `_ + +The Flask application should now be running. We can monitor the status of the deployment +using ``juju status`` which should be similar to the following output: + +.. code-block:: + + Model Controller Cloud/Region Version SLA Timestamp + flask-hello-world dev-controller microk8s/localhost 3.1.8 unsupported 17:04:11+10:00 + + App Version Status Scale Charm Channel Rev Address Exposed Message + flask-hello-world active 1 flask-hello-world 0 10.152.183.166 no + + Unit Workload Agent Address Ports Message + flask-hello-world/0* active idle 10.1.87.213 + +The deployment is finished when the status shows ``active``. Let's expose the +application using ingress. Deploy the ``nginx-ingress-integrator`` charm and integrate +it with the Flask app: + +.. code-block:: bash + + juju deploy nginx-ingress-integrator --channel=latest/edge + juju integrate nginx-ingress-integrator flask-hello-world + + +The hostname of the app needs to be defined so that it is accessible via the ingress. +We will also set the default route to be the root endpoint: + +.. code-block:: bash + + juju config nginx-ingress-integrator \ + service-hostname=flask-hello-world path-routes=/ + +Monitor ``juju status`` until everything has a status of ``active``. Test the +deployment using +``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` to send +a request via the ingress to the root endpoint. It should still be returning +the ``Hello, world!`` greeting. + +.. note:: + + The ``--resolve flask-hello-world:80:127.0.0.1`` option to the ``curl`` + command is a way of resolving the hostname of the request without + setting a DNS record. + +Configure the Flask application +=============================== + +Now let's customise the greeting using a configuration option. We will expect this +configuration option to be available in the Flask app configuration under the +keyword ``GREETING``. Go back out to the root directory of the project using +``cd ..`` and copy the following code into ``app.py``: + +.. code-block:: python + + import flask + + app = flask.Flask(__name__) + app.config.from_prefixed_env() + + + @app.route("/") + def index(): + greeting = app.config.get("GREETING", "Hello, world!") + return f"{greeting}\n" + + + if __name__ == "__main__": + app.run() + +Open ``rockcraft.yaml`` and update the version to ``0.2``. Run ``rockcraft pack`` +again, then upload the new OCI image to the MicroK8s registry: + +.. code-block:: bash + + rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ + oci-archive:flask-hello-world_0.2_amd64.rock \ + docker://localhost:32000/flask-hello-world:0.2 + +Change back into the charm directory using ``cd charm``. The ``flask-framework`` +Charmcraft extension supports adding configurations to ``charmcraft.yaml`` which +will be passed as environment variables to the Flask application. Add the +following to the end of the ``charmcraft.yaml`` file: + +.. code-block:: yaml + + config: + options: + greeting: + description: | + The greeting to be returned by the Flask application. + default: "Hello, world!" + type: string + +.. note:: + + Configuration options are automatically capitalised and ``-`` are replaced + by ``_``. A ``FLASK_`` prefix will also be added which will let Flask + identify which environment variables to include when running + ``app.config.from_prefixed_env()`` in ``app.py``. + +Run ``charmcraft pack`` again. The deployment can now be refreshed to +make use of the new code: + +.. code-block:: bash + + juju refresh flask-hello-world \ + --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ + --resource flask-app-image=localhost:32000/flask-hello-world:0.2 + +.. note:: + + For the refresh command, the ``--constraints`` option is not required if + you are not running on an ``amd64`` host as Juju will remember the + constraint for the life of the application deployment. + +Wait for ``juju status`` to show that the App is ``active`` again. Verify that +the new configuration has been added using +``juju config flask-hello-world | grep -A 6 greeting:`` which should show +the configuration option. + +.. note:: + + The ``grep`` command extracts a portion of the configuration to make + it easier to check whether the configuration option has been added. + +Using ``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` +shows that the response is still ``Hello, world!`` as expected. +The greeting can be changed using Juju: + +.. code-block:: bash + + juju config flask-hello-world greeting='Hi!' + +``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` +now returns the updated ``Hi!`` greeting. + +.. note:: + + It might take a short time for the configuration to take effect. + +Integrate with a database +========================= + +Now let's keep track of how many visitors your application has received. +This will require integration with a database to keep the visitor count. +This will require a few changes: + +* We will need to create a database migration that creates the ``visitors`` table +* We will need to keep track how many times the root endpoint has been called in the database +* We will need to add a new endpoint to retrieve the number of visitors from the database + +The charm created by the ``flask-framework`` extension will execute the +``migrate.py`` script if it exists. This script should ensure that the +database is initialised and ready to be used by the application. We will +create a ``migrate.py`` file containing this logic. + +Go back out to the tutorial root directory using ``cd ..``. Open the ``migrate.py`` +file using a text editor and paste the following code into it: + +.. code-block:: python + + import os + + import psycopg2 + + + DATABASE_URI = os.environ["POSTGRESQL_DB_CONNECT_STRING"] + + + def migrate(): + with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: + cur.execute(""" + CREATE TABLE IF NOT EXISTS visitors ( + timestamp TIMESTAMP NOT NULL, + user_agent TEXT NOT NULL + ); + """) + conn.commit() + + + if __name__ == "__main__": + migrate() + +.. note:: + + The charm will pass the Database connection string in the + ``POSTGRESQL_DB_CONNECT_STRING`` environment variable once + postgres has been integrated with the charm. + +Open the ``rockcraft.yaml`` file in a text editor and update the version to ``0.3``. + +To be able to connect to postgresql from the Flask app the ``psycopg2-binary`` +dependency needs to be added in ``requirements.txt``. The app code also needs +to be updated to keep track of the number of visitors and to include a new +endpoint to retrieve the number of visitors to the app. Open ``app.py`` in +a text editor and replace its contents with the following code: + +.. code-block:: python + + import datetime + import os + + import flask + import psycopg2 + + app = flask.Flask(__name__) + app.config.from_prefixed_env() + + DATABASE_URI = os.environ["POSTGRESQL_DB_CONNECT_STRING"] + + + @app.route("/") + def index(): + with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: + user_agent = flask.request.headers.get('User-Agent') + timestamp = datetime.datetime.now() + + cur.execute( + "INSERT INTO visitors (timestamp, user_agent) VALUES (%s, %s)", + (timestamp, user_agent) + ) + conn.commit() + + + greeting = app.config.get("GREETING", "Hello, world!") + return f"{greeting}\n" + + + @app.route("/visitors") + def visitors(): + with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: + cur.execute("SELECT COUNT(*) FROM visitors") + total_visitors = cur.fetchone()[0] + + return f"{total_visitors}\n" + + + if __name__ == "__main__": + app.run() + +Run ``rockcraft pack`` and upload the newly created rock to the MicroK8s registry: + +.. code-block:: bash + + rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ + oci-archive:flask-hello-world_0.3_amd64.rock \ + docker://localhost:32000/flask-hello-world:0.3 + +Go back into the charm directory using ``cd charm``. The Flask app now requires +a database which needs to be declared in the ``charmcraft.yaml`` file. Open +``charmcraft.yaml`` in a text editor and add the following section to the end: + +.. code-block:: yaml + + requires: + postgresql: + interface: postgresql_client + optional: false + +Pack the charm using ``charmcraft pack`` and refresh the deployment using Juju: + +.. code-block:: bash + + juju refresh flask-hello-world \ + --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ + --resource flask-app-image=localhost:32000/flask-hello-world:0.3 + +Deploy ``postgresql-k8s`` using Juju and integrate it with ``flask-hello-world``: + +.. code-block:: bash + + juju deploy postgresql-k8s --trust + juju integrate flask-hello-world postgresql-k8s + +Wait for ``juju status`` to show that the App is ``active`` again. +Running ``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` +should still return the ``Hi!`` greeting. To check the total visitors, use +``curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1`` +which should return ``1`` after the previous request to the root endpoint and +should be incremented each time the root endpoint is requested. If we perform +another request to +``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1``, +``curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1`` +will return ``2``. + +Clean up environment +==================== + +We've reached the end of this tutorial. We have created a Flask application, +deployed it locally, exposed it via ingress and integrated it with a database! + +If you'd like to reset your working environment, you can run the following +in the root directory for the tutorial: + +.. code-block:: bash + + # exit and delete the virtual environment + deactivate + rm -rf charm .venv __pycache__ + # delete all the files created during the tutorial + rm flask-hello-world_0.1_amd64.rock flask-hello-world_0.2_amd64.rock \ + flask-hello-world_0.3_amd64.rock rockcraft.yaml app.py \ + requirements.txt migrate.py + # Remove the juju model + juju destroy-model flask-hello-world --destroy-storage + +If you created an instance using Multipass, you can also clean it up. +Start by exiting it: + +.. code-block:: bash + + exit + +And then you can proceed with its deletion: + +.. code-block:: bash + + multipass delete charm-dev + multipass purge + +Next steps +========== + +.. list-table:: + :widths: 30 30 + :header-rows: 1 + + * - If you are wondering... + - Visit... + * - "How do I...?" + - `SDK How-to docs `_ + * - "How do I debug?" + - `Charm debugging tools `_ + * - "What is...?" + - `SDK Reference docs `_ + * - "Why...?", "So what?" + - `SDK Explanation docs `_ + + +**Contributors:** @econley, @jdkandersson , @tmihoc, @weii-wang + +------------------------- + From 1d8c5cdc878f0035f3bfbf218b23c1730d084d10 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Tue, 29 Oct 2024 16:02:09 +0100 Subject: [PATCH 002/100] nest in tutorial directory --- docs/{ => tutorial}/flask.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{ => tutorial}/flask.rst (100%) diff --git a/docs/flask.rst b/docs/tutorial/flask.rst similarity index 100% rename from docs/flask.rst rename to docs/tutorial/flask.rst From ec84743c0c4408c39320c45de556767172e32adb Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Tue, 29 Oct 2024 16:02:57 +0100 Subject: [PATCH 003/100] Add Flask tutorial to main index.rst --- docs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.rst b/docs/index.rst index b0bd33862..fe2136ad7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,6 +12,7 @@ Most of Charmcraft's documentation is available there. reference/index explanation/index + tutorial/flask .. grid:: 1 1 2 2 :reverse: From 3917b92de5b7f8663836a5962b525f8d9b51cc9e Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Tue, 29 Oct 2024 17:20:16 +0100 Subject: [PATCH 004/100] Create task.yaml added a few commands taken from the rockcraft task.yaml --- docs/tutorial/code/flask/task.yaml | 46 ++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 docs/tutorial/code/flask/task.yaml diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml new file mode 100644 index 000000000..f75023254 --- /dev/null +++ b/docs/tutorial/code/flask/task.yaml @@ -0,0 +1,46 @@ +########################################### +# IMPORTANT +# Comments matter! +# The docs use the wrapping comments as +# markers for including said instructions +# as snippets in the docs. +########################################### +summary: Getting started with Flask tutorial + +environment: + +execute: | + # [docs:create-venv] + sudo apt-get update && sudo apt-get install python3-venv -y + python3 -m venv .venv + source .venv/bin/activate + pip install -r requirements.txt + # [docs:create-venv-end] + + flask run -p 8000 & + retry -n 5 --wait 2 curl --fail localhost:8000 + + # [docs:curl-flask] + curl localhost:8000 + # [docs:curl-flask-end] + + kill $! + + # [docs:create-rockcraft-yaml] + rockcraft init --profile flask-framework + # [docs:create-rockcraft-yaml-end] + sed -i "s/name: .*/name: flask-hello-world/g" rockcraft.yaml + + # [docs:pack] + rockcraft pack + # [docs:pack-end] + + # [docs:ls-rock] + ls *.rock -l + # [docs:ls-rock-end] + + # [docs:skopeo-copy] + sudo rockcraft.skopeo --insecure-policy \ + copy oci-archive:flask-hello-world_0.1_amd64.rock \ + docker-daemon:flask-hello-world:0.1 + # [docs:skopeo-copy-end] From 3e6d311d99f685ca47c6fd5b9db16ca64985ee1b Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 08:50:26 +0100 Subject: [PATCH 005/100] add more commands to task.yaml skipped over the parts where code files were changed (for now) --- docs/tutorial/code/flask/task.yaml | 107 +++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index f75023254..2f310e676 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -44,3 +44,110 @@ execute: | copy oci-archive:flask-hello-world_0.1_amd64.rock \ docker-daemon:flask-hello-world:0.1 # [docs:skopeo-copy-end] + + # [docs:create-charm-dir] + mkdir charm + cd charm + # [docs:create-charm-dir-end] + + # [docs:charm-init] + charmcraft init --profile flask-framework --name flask-hello-world + # [docs:charm-init-end] + + # [docs:charm-pack] + charmcraft pack + # [docs:charm-pack-end] + + # [docs:ls-charm] + ls *.charm -l + # [docs:ls-charm-end] + + # [docs:add-juju-model] + juju add-model flask-hello-world + # [docs:add-juju-model-end] + + # [docs:deploy-juju-model] + juju deploy ./flask-hello-world_ubuntu-22.04-amd64.charm \ + flask-hello-world --resource \ + flask-app-image=localhost:32000/flask-hello-world:0.1 + # [docs:deploy-juju-model-end] + + # [docs:deploy-nginx] + juju deploy nginx-ingress-integrator --channel=latest/edge + juju integrate nginx-ingress-integrator flask-hello-world + # [docs:deploy-nginx-end] + + # [docs:config-nginx] + juju config nginx-ingress-integrator \ + service-hostname=flask-hello-world path-routes=/ + # [docs:config-nginx-end] + + # [docs:curl-init-deployment] + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + # [docs:curl-init-deployment-end] + + cd .. + sed -i "s/version: .*/version: 0.2/g" rockcraft.yaml + + # [docs:docker-run-update] + rockcraft pack + rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ + oci-archive:flask-hello-world_0.2_amd64.rock \ + docker://localhost:32000/flask-hello-world:0.2 + # [docs:docker-run-update-end] + + cd charm + charmcraft pack + + # [docs:refresh-deployment] + juju refresh flask-hello-world \ + --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ + --resource flask-app-image=localhost:32000/flask-hello-world:0.2 + # [docs:refresh-deployment-end] + + # [docs:change-config] + juju config flask-hello-world greeting='Hi!' + # [docs:change-config-end] + + cd .. + sed -i "s/version: .*/version: 0.3/g" rockcraft.yaml + + # [docs:docker-run-2nd-update] + rockcraft pack + rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ + oci-archive:flask-hello-world_0.3_amd64.rock \ + docker://localhost:32000/flask-hello-world:0.3 + # [docs:docker-run-2nd-update-end] + + cd charm + + charmcraft pack + + # [docs:refresh-2nd-deployment] + juju refresh flask-hello-world \ + --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ + --resource flask-app-image=localhost:32000/flask-hello-world:0.3 + # [docs:refresh-2nd-deployment-end] + + # [docs:deploy-postgres] + juju deploy postgresql-k8s --trust + juju integrate flask-hello-world postgresql-k8s + # [docs:deploy-postgres-end] + + # [docs:clean-environment] + # exit and delete the virtual environment + deactivate + rm -rf charm .venv __pycache__ + # delete all the files created during the tutorial + rm flask-hello-world_0.1_amd64.rock flask-hello-world_0.2_amd64.rock \ + flask-hello-world_0.3_amd64.rock rockcraft.yaml app.py \ + requirements.txt migrate.py + # Remove the juju model + juju destroy-model flask-hello-world --destroy-storage + # [docs:clean-environment-end] + + # [docs:destroy-multipass] + exit + multipass delete charm-dev + multipass purge + # [docs:destroy-multipass-end] From b073e1fcc09d4c7de295cbdb28817b2c02a607d7 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 08:51:23 +0100 Subject: [PATCH 006/100] Add files via upload --- docs/tutorial/code/flask/app.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 docs/tutorial/code/flask/app.py diff --git a/docs/tutorial/code/flask/app.py b/docs/tutorial/code/flask/app.py new file mode 100644 index 000000000..2ef2f596e --- /dev/null +++ b/docs/tutorial/code/flask/app.py @@ -0,0 +1,12 @@ +import flask + +app = flask.Flask(__name__) + + +@app.route("/") +def index(): + return "Hello, world!\n" + + +if __name__ == "__main__": + app.run() From b70ee972e4856e9a66cfc5e83879fac509db3496 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 09:48:07 +0100 Subject: [PATCH 007/100] Create requirements.txt --- docs/tutorial/code/flask/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/tutorial/code/flask/requirements.txt diff --git a/docs/tutorial/code/flask/requirements.txt b/docs/tutorial/code/flask/requirements.txt new file mode 100644 index 000000000..e3e9a71d9 --- /dev/null +++ b/docs/tutorial/code/flask/requirements.txt @@ -0,0 +1 @@ +Flask From af2fc63545108ac49fbb6bc4a2110adbedc98a8c Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 09:53:53 +0100 Subject: [PATCH 008/100] Create greeting_app.py --- docs/tutorial/code/flask/greeting_app.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/tutorial/code/flask/greeting_app.py diff --git a/docs/tutorial/code/flask/greeting_app.py b/docs/tutorial/code/flask/greeting_app.py new file mode 100644 index 000000000..dfa0a115d --- /dev/null +++ b/docs/tutorial/code/flask/greeting_app.py @@ -0,0 +1,14 @@ +import flask + +app = flask.Flask(__name__) +app.config.from_prefixed_env() + + +@app.route("/") +def index(): + greeting = app.config.get("GREETING", "Hello, world!") + return f"{greeting}\n" + + +if __name__ == "__main__": + app.run() From 5e71d204b595d0cfcdef0b619ddc221ca53eccf8 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 09:59:40 +0100 Subject: [PATCH 009/100] Create setup.rst 24.04 blueprint --- docs/reuse/tutorial/setup.rst | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 docs/reuse/tutorial/setup.rst diff --git a/docs/reuse/tutorial/setup.rst b/docs/reuse/tutorial/setup.rst new file mode 100644 index 000000000..0c282d86a --- /dev/null +++ b/docs/reuse/tutorial/setup.rst @@ -0,0 +1,72 @@ +Install Multipass. + +.. seealso:: + + See more: `Multipass | How to install Multipass `_ + +Use Multipass to launch an Ubuntu VM with the name ``charm-dev`` from the 24.04 blueprint: + +.. code-block:: bash + + multipass launch --cpus 4 --disk 50G --memory 4G --name charm-dev 24.04 + +Once the VM is up, open a shell into it: + +.. code-block:: bash + + multipass shell charm-dev + +In order to create the rock, you'll need to install Rockcraft: + +.. code-block:: bash + + sudo snap install rockcraft --classic + +``LXD`` will be required for building the rock. Make sure it is installed and initialised: + +.. code-block:: bash + + sudo snap install lxd + lxd init --auto + +In order to create the charm, you'll need to install Charmcraft: + +.. code-block:: bash + + sudo snap install charmcraft --channel latest/edge --classic + +.. warning:: + + This tutorial requires version ``3.0.0`` or later of Charmcraft. Check the + version of Charmcraft using ``charmcraft --version`` If you have an older + version of Charmcraft installed, use + ``sudo snap refresh charmcraft --channel latest/edge`` to get the latest + edge version of Charmcraft. + +MicroK8s is required to deploy the Flask application on Kubernetes. Install MicroK8s: + +.. code-block:: bash + + sudo snap install microk8s --channel 1.31-strict/stable + sudo adduser $USER snap_microk8s + newgrp snap_microk8s + +Wait for MicroK8s to be ready using ``sudo microk8s status --wait-ready``. +Several MicroK8s add-ons are required for deployment: + +.. code-block:: bash + + sudo microk8s enable hostpath-storage + # Required to host the OCI image of the Flask application + sudo microk8s enable registry + # Required to expose the Flask application + sudo microk8s enable ingress + +Juju is required to deploy the Flask application. +Install Juju and bootstrap a development controller: + +.. code-block:: bash + + sudo snap install juju --channel 3.5/stable + mkdir -p ~/.local/share + juju bootstrap microk8s dev-controller From 371ad5e8d5f19803056dedd2b1166e88767fcfd6 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:06:21 +0100 Subject: [PATCH 010/100] Update flask.rst Move setup text to its own file Fix some linting issues --- docs/tutorial/flask.rst | 85 +++++------------------------------------ 1 file changed, 9 insertions(+), 76 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 21f0e9d19..c64a305c0 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -57,78 +57,7 @@ application up and running with Juju in about 90 minutes. Set things up ============= -Install Multipass. - -.. seealso:: - - See more: `Multipass | How to install Multipass `_ - -Use Multipass to launch an Ubuntu VM with the name ``charm-dev`` from the 24.04 blueprint: - -.. code-block:: bash - - multipass launch --cpus 4 --disk 50G --memory 4G --name charm-dev 24.04 - -Once the VM is up, open a shell into it: - -.. code-block:: bash - - multipass shell charm-dev - -In order to create the rock, you'll need to install Rockcraft: - -.. code-block:: bash - - sudo snap install rockcraft --classic - -``LXD`` will be required for building the rock. Make sure it is installed and initialised: - -.. code-block:: bash - - sudo snap install lxd - lxd init --auto - -In order to create the charm, you'll need to install Charmcraft: - -.. code-block:: bash - - sudo snap install charmcraft --channel latest/edge --classic - -.. warning:: - - This tutorial requires version ``3.0.0`` or later of Charmcraft. Check the - version of Charmcraft using ``charmcraft --version`` If you have an older - version of Charmcraft installed, use - ``sudo snap refresh charmcraft --channel latest/edge`` to get the latest - edge version of Charmcraft. - -MicroK8s is required to deploy the Flask application on Kubernetes. Install MicroK8s: - -.. code-block:: bash - - sudo snap install microk8s --channel 1.31-strict/stable - sudo adduser $USER snap_microk8s - newgrp snap_microk8s - -Wait for MicroK8s to be ready using ``sudo microk8s status --wait-ready``. -Several MicroK8s add-ons are required for deployment: - -.. code-block:: bash - - sudo microk8s enable hostpath-storage - # Required to host the OCI image of the Flask application - sudo microk8s enable registry - # Required to expose the Flask application - sudo microk8s enable ingress - -Juju is required to deploy the Flask application. -Install Juju and bootstrap a development controller: - -.. code-block:: bash - - sudo snap install juju --channel 3.5/stable - mkdir -p ~/.local/share - juju bootstrap microk8s dev-controller +.. include:: /reuse/tutorial/setup.rst Finally, create a new directory for this tutorial and go inside it: @@ -230,7 +159,8 @@ Pack the rock: .. note:: - Depending on your system and network, this step can take a couple of minutes to finish. + Depending on your system and network, this step can take a couple of + minutes to finish. Once Rockcraft has finished packing the Flask rock, you'll find a new file in your working directory with the ``.rock`` extension: @@ -286,7 +216,8 @@ Pack the charm: .. note:: - Depending on your system and network, this step can take a couple of minutes to finish. + Depending on your system and network, this step can take a couple + of minutes to finish. Once Charmcraft has finished packing the charm, you'll find a new file in your working directory with the ``.charm`` extension: @@ -481,8 +412,10 @@ This will require integration with a database to keep the visitor count. This will require a few changes: * We will need to create a database migration that creates the ``visitors`` table -* We will need to keep track how many times the root endpoint has been called in the database -* We will need to add a new endpoint to retrieve the number of visitors from the database +* We will need to keep track how many times the root endpoint has been called +in the database +* We will need to add a new endpoint to retrieve the number of visitors from the +database The charm created by the ``flask-framework`` extension will execute the ``migrate.py`` script if it exists. This script should ensure that the From 0ed76edede2799f017a1f8f5637333e648fe5aab Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:11:28 +0100 Subject: [PATCH 011/100] fix lint issues in task.yaml --- docs/tutorial/code/flask/task.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 2f310e676..3735968b6 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -1,8 +1,8 @@ ########################################### # IMPORTANT # Comments matter! -# The docs use the wrapping comments as -# markers for including said instructions +# The docs use the wrapping comments as +# markers for including said instructions # as snippets in the docs. ########################################### summary: Getting started with Flask tutorial @@ -36,14 +36,14 @@ execute: | # [docs:pack-end] # [docs:ls-rock] - ls *.rock -l + ls *.rock -l # [docs:ls-rock-end] # [docs:skopeo-copy] sudo rockcraft.skopeo --insecure-policy \ copy oci-archive:flask-hello-world_0.1_amd64.rock \ docker-daemon:flask-hello-world:0.1 - # [docs:skopeo-copy-end] + # [docs:skopeo-copy-end] # [docs:create-charm-dir] mkdir charm @@ -120,7 +120,6 @@ execute: | # [docs:docker-run-2nd-update-end] cd charm - charmcraft pack # [docs:refresh-2nd-deployment] From 416e28a26c06e4898dc4153e68612bc89c210a42 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:26:39 +0100 Subject: [PATCH 012/100] Update task.yaml --- docs/tutorial/code/flask/task.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 3735968b6..520381f91 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -88,13 +88,13 @@ execute: | cd .. sed -i "s/version: .*/version: 0.2/g" rockcraft.yaml - - # [docs:docker-run-update] rockcraft pack + + # [docs:docker-update] rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ oci-archive:flask-hello-world_0.2_amd64.rock \ docker://localhost:32000/flask-hello-world:0.2 - # [docs:docker-run-update-end] + # [docs:docker-update-end] cd charm charmcraft pack From 4491fb5a8ab301912dec73e1096553ede86fa64e Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:29:47 +0100 Subject: [PATCH 013/100] Update task.yaml --- docs/tutorial/code/flask/task.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 520381f91..8d071a45d 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -111,13 +111,13 @@ execute: | cd .. sed -i "s/version: .*/version: 0.3/g" rockcraft.yaml - - # [docs:docker-run-2nd-update] rockcraft pack + + # [docs:docker-2nd-update] rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ oci-archive:flask-hello-world_0.3_amd64.rock \ docker://localhost:32000/flask-hello-world:0.3 - # [docs:docker-run-2nd-update-end] + # [docs:docker-2nd-update-end] cd charm charmcraft pack From 5fdd47f8779e4538489d5fa3b54373d575b31ca8 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:33:24 +0100 Subject: [PATCH 014/100] Replace code blocks with task.yaml snippets --- docs/tutorial/flask.rst | 234 +++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 123 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index c64a305c0..aa030fd09 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -75,37 +75,24 @@ used for this tutorial. Create a ``requirements.txt`` file, copy the following text into it and then save it: -.. code-block:: - - Flask +.. literalinclude:: code/flask/requirements.txt In the same directory, copy and save the following into a text file called ``app.py``: -.. code-block:: python - - import flask - - app = flask.Flask(__name__) - - @app.route("/") - def index(): - return "Hello, world!\n" - - if __name__ == "__main__": - app.run() +.. literalinclude:: code/flask/app.py + :language: python Run the Flask application locally ================================= Install ``python3-venv`` and create a virtual environment: -.. code-block:: bash - - sudo apt-get update && sudo apt-get install python3-venv -y - python3 -m venv .venv - source .venv/bin/activate - pip install -r requirements.txt +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:create-venv] + :end-before: [docs:create-venv-end] + :dedent: 2 Now that we have a virtual environment with all the dependencies, let's run the Flask application to verify that it works: @@ -118,9 +105,11 @@ Test the Flask application by using ``curl`` to send a request to the root endpoint. You may need a new terminal for this; if you are using Multipass use ``multipass shell charm-dev`` to get another terminal: -.. code-block:: bash - - curl localhost:8000 +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:curl-flask] + :end-before: [docs:curl-flask-end] + :dedent: 2 The Flask application should respond with ``Hello, world!``. The Flask application looks good, so we can stop for now using @@ -133,9 +122,11 @@ First, we'll need a ``rockcraft.yaml`` file. Rockcraft will automate its creation and tailoring for a Flask application by using the ``flask-framework`` profile: -.. code-block:: bash - - rockcraft init --profile flask-framework +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:create-rockcraft-yaml] + :end-before: [docs:create-rockcraft-yaml-end] + :dedent: 2 The ``rockcraft.yaml`` file will automatically be created and set the name based on your working directory. Open the file in a text editor and check @@ -153,9 +144,11 @@ ARM architecture, include ``arm64`` in ``platforms``. Pack the rock: -.. code-block:: bash - - rockcraft pack +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:pack] + :end-before: [docs:pack-end] + :dedent: 2 .. note:: @@ -165,9 +158,11 @@ Pack the rock: Once Rockcraft has finished packing the Flask rock, you'll find a new file in your working directory with the ``.rock`` extension: -.. code-block:: bash - - ls *.rock -l +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:ls-rock] + :end-before: [docs:ls-rock-end] + :dedent: 2 .. note:: @@ -175,14 +170,14 @@ in your working directory with the ``.rock`` extension: not on an ``amd64`` platform, the name of the ``.rock`` file will be different for you. -The rock needs to be copied to the Microk8s registry so that it can be +The rock needs to be copied to the MicroK8s registry so that it can be deployed in the Kubernetes cluster: -.. code-block:: bash - - rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ - oci-archive:flask-hello-world_0.1_amd64.rock \ - docker://localhost:32000/flask-hello-world:0.1 +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:skopeo-copy] + :end-before: [docs:skopeo-copy-end] + :dedent: 2 .. seealso:: @@ -193,26 +188,31 @@ Create the charm Create a new directory for the charm and go inside it: -.. code-block:: bash - - mkdir charm - cd charm +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:create-charm-dir] + :end-before: [docs:create-charm-dir-end] + :dedent: 2 We'll need a ``charmcraft.yaml``, ``requirements.txt`` and source code for the charm. The source code contains the logic required to operate the Flask application. Charmcraft will automate the creation of these files by using the ``flask-framework`` profile: -.. code-block:: bash - - charmcraft init --profile flask-framework --name flask-hello-world +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:charm-init] + :end-before: [docs:charm-init-end] + :dedent: 2 The files will automatically be created in your working directory. Pack the charm: -.. code-block:: bash - - charmcraft pack +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:charm-pack] + :end-before: [docs:charm-pack-end] + :dedent: 2 .. note:: @@ -222,9 +222,11 @@ Pack the charm: Once Charmcraft has finished packing the charm, you'll find a new file in your working directory with the ``.charm`` extension: -.. code-block:: bash - - ls *.charm -l +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:ls-charm] + :end-before: [docs:ls-charm-end] + :dedent: 2 .. note:: @@ -236,9 +238,11 @@ Deploy the Flask application A Juju model is needed to deploy the application. Let's create a new model: -.. code-block:: bash - - juju add-model flask-hello-world +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:add-juju-model] + :end-before: [docs:add-juju-model-end] + :dedent: 2 .. warning:: @@ -250,11 +254,11 @@ A Juju model is needed to deploy the application. Let's create a new model: Now the Flask application can be deployed using `Juju `_: -.. code-block:: bash - - juju deploy ./flask-hello-world_ubuntu-22.04-amd64.charm \ - flask-hello-world --resource \ - flask-app-image=localhost:32000/flask-hello-world:0.1 +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:deploy-juju-model] + :end-before: [docs:deploy-juju-model-end] + :dedent: 2 .. note:: @@ -282,19 +286,20 @@ The deployment is finished when the status shows ``active``. Let's expose the application using ingress. Deploy the ``nginx-ingress-integrator`` charm and integrate it with the Flask app: -.. code-block:: bash - - juju deploy nginx-ingress-integrator --channel=latest/edge - juju integrate nginx-ingress-integrator flask-hello-world - +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:deploy-nginx] + :end-before: [docs:deploy-nginx-end] + :dedent: 2 The hostname of the app needs to be defined so that it is accessible via the ingress. We will also set the default route to be the root endpoint: -.. code-block:: bash - - juju config nginx-ingress-integrator \ - service-hostname=flask-hello-world path-routes=/ +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:config-nginx] + :end-before: [docs:config-nginx-end] + :dedent: 2 Monitor ``juju status`` until everything has a status of ``active``. Test the deployment using @@ -316,31 +321,17 @@ configuration option to be available in the Flask app configuration under the keyword ``GREETING``. Go back out to the root directory of the project using ``cd ..`` and copy the following code into ``app.py``: -.. code-block:: python - - import flask - - app = flask.Flask(__name__) - app.config.from_prefixed_env() - - - @app.route("/") - def index(): - greeting = app.config.get("GREETING", "Hello, world!") - return f"{greeting}\n" - - - if __name__ == "__main__": - app.run() +.. literalinclude:: code/flask/greeting_app.py + :language: python Open ``rockcraft.yaml`` and update the version to ``0.2``. Run ``rockcraft pack`` again, then upload the new OCI image to the MicroK8s registry: -.. code-block:: bash - - rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ - oci-archive:flask-hello-world_0.2_amd64.rock \ - docker://localhost:32000/flask-hello-world:0.2 +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:docker-update] + :end-before: [docs:docker-update-end] + :dedent: 2 Change back into the charm directory using ``cd charm``. The ``flask-framework`` Charmcraft extension supports adding configurations to ``charmcraft.yaml`` which @@ -367,11 +358,11 @@ following to the end of the ``charmcraft.yaml`` file: Run ``charmcraft pack`` again. The deployment can now be refreshed to make use of the new code: -.. code-block:: bash - - juju refresh flask-hello-world \ - --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ - --resource flask-app-image=localhost:32000/flask-hello-world:0.2 +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:refresh-deployment] + :end-before: [docs:refresh-deployment-end] + :dedent: 2 .. note:: @@ -393,9 +384,11 @@ Using ``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` shows that the response is still ``Hello, world!`` as expected. The greeting can be changed using Juju: -.. code-block:: bash - - juju config flask-hello-world greeting='Hi!' +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:change-config] + :end-before: [docs:change-config-end] + :dedent: 2 ``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` now returns the updated ``Hi!`` greeting. @@ -508,11 +501,11 @@ a text editor and replace its contents with the following code: Run ``rockcraft pack`` and upload the newly created rock to the MicroK8s registry: -.. code-block:: bash - - rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ - oci-archive:flask-hello-world_0.3_amd64.rock \ - docker://localhost:32000/flask-hello-world:0.3 +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:docker-2nd-update] + :end-before: [docs:docker-2nd-update-end] + :dedent: 2 Go back into the charm directory using ``cd charm``. The Flask app now requires a database which needs to be declared in the ``charmcraft.yaml`` file. Open @@ -527,18 +520,19 @@ a database which needs to be declared in the ``charmcraft.yaml`` file. Open Pack the charm using ``charmcraft pack`` and refresh the deployment using Juju: -.. code-block:: bash - - juju refresh flask-hello-world \ - --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ - --resource flask-app-image=localhost:32000/flask-hello-world:0.3 +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:refresh-2nd-deployment] + :end-before: [docs:refresh-2nd-deployment-end] + :dedent: 2 Deploy ``postgresql-k8s`` using Juju and integrate it with ``flask-hello-world``: -.. code-block:: bash - - juju deploy postgresql-k8s --trust - juju integrate flask-hello-world postgresql-k8s +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:deploy-postgres] + :end-before: [docs:deploy-postgres-end] + :dedent: 2 Wait for ``juju status`` to show that the App is ``active`` again. Running ``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` @@ -560,17 +554,11 @@ deployed it locally, exposed it via ingress and integrated it with a database! If you'd like to reset your working environment, you can run the following in the root directory for the tutorial: -.. code-block:: bash - - # exit and delete the virtual environment - deactivate - rm -rf charm .venv __pycache__ - # delete all the files created during the tutorial - rm flask-hello-world_0.1_amd64.rock flask-hello-world_0.2_amd64.rock \ - flask-hello-world_0.3_amd64.rock rockcraft.yaml app.py \ - requirements.txt migrate.py - # Remove the juju model - juju destroy-model flask-hello-world --destroy-storage +.. literalinclude:: code/flask/task.yaml + :language: bash + :start-after: [docs:clean-environment] + :end-before: [docs:clean-environment-end] + :dedent: 2 If you created an instance using Multipass, you can also clean it up. Start by exiting it: From dac9233dcb0649675bc43add5770dbe4bd8709fe Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:35:29 +0100 Subject: [PATCH 015/100] Update task.yaml --- docs/tutorial/code/flask/task.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 8d071a45d..c85929aeb 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -87,6 +87,7 @@ execute: | # [docs:curl-init-deployment-end] cd .. + cat greeting_app.py > app.py sed -i "s/version: .*/version: 0.2/g" rockcraft.yaml rockcraft pack @@ -144,9 +145,3 @@ execute: | # Remove the juju model juju destroy-model flask-hello-world --destroy-storage # [docs:clean-environment-end] - - # [docs:destroy-multipass] - exit - multipass delete charm-dev - multipass purge - # [docs:destroy-multipass-end] From ecbbb94250c0dec752e5603b69d212ff0bdff5ce Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:36:17 +0100 Subject: [PATCH 016/100] Create visitors_app.py --- docs/tutorial/code/flask/visitors_app.py | 40 ++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 docs/tutorial/code/flask/visitors_app.py diff --git a/docs/tutorial/code/flask/visitors_app.py b/docs/tutorial/code/flask/visitors_app.py new file mode 100644 index 000000000..2830d4a55 --- /dev/null +++ b/docs/tutorial/code/flask/visitors_app.py @@ -0,0 +1,40 @@ +import datetime +import os + +import flask +import psycopg2 + +app = flask.Flask(__name__) +app.config.from_prefixed_env() + +DATABASE_URI = os.environ["POSTGRESQL_DB_CONNECT_STRING"] + + +@app.route("/") +def index(): + with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: + user_agent = flask.request.headers.get('User-Agent') + timestamp = datetime.datetime.now() + + cur.execute( + "INSERT INTO visitors (timestamp, user_agent) VALUES (%s, %s)", + (timestamp, user_agent) + ) + conn.commit() + + + greeting = app.config.get("GREETING", "Hello, world!") + return f"{greeting}\n" + + +@app.route("/visitors") +def visitors(): + with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: + cur.execute("SELECT COUNT(*) FROM visitors") + total_visitors = cur.fetchone()[0] + + return f"{total_visitors}\n" + + +if __name__ == "__main__": + app.run() From 73cc0fe78216f9d36f0dd7b610f3694a870d6eaa Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:36:48 +0100 Subject: [PATCH 017/100] Update task.yaml --- docs/tutorial/code/flask/task.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index c85929aeb..85d832d74 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -111,6 +111,7 @@ execute: | # [docs:change-config-end] cd .. + cat visitors_app.py > app.py sed -i "s/version: .*/version: 0.3/g" rockcraft.yaml rockcraft pack From 90bdb74ba2621b345e109a55421131546c03aaa5 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:37:13 +0100 Subject: [PATCH 018/100] Create migrate.py --- docs/tutorial/code/flask/migrate.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/tutorial/code/flask/migrate.py diff --git a/docs/tutorial/code/flask/migrate.py b/docs/tutorial/code/flask/migrate.py new file mode 100644 index 000000000..2e303cea4 --- /dev/null +++ b/docs/tutorial/code/flask/migrate.py @@ -0,0 +1,21 @@ +import os + +import psycopg2 + + +DATABASE_URI = os.environ["POSTGRESQL_DB_CONNECT_STRING"] + + +def migrate(): + with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: + cur.execute(""" + CREATE TABLE IF NOT EXISTS visitors ( + timestamp TIMESTAMP NOT NULL, + user_agent TEXT NOT NULL + ); + """) + conn.commit() + + +if __name__ == "__main__": + migrate() From efc85d1c0aab2479ffe7ef84f43ccfd71f880ad6 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:46:01 +0100 Subject: [PATCH 019/100] Replace more code with corresponding files migrate.py visitors_app.py --- docs/tutorial/flask.rst | 69 +++-------------------------------------- 1 file changed, 4 insertions(+), 65 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index aa030fd09..9e65c4e25 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -418,29 +418,8 @@ create a ``migrate.py`` file containing this logic. Go back out to the tutorial root directory using ``cd ..``. Open the ``migrate.py`` file using a text editor and paste the following code into it: -.. code-block:: python - - import os - - import psycopg2 - - - DATABASE_URI = os.environ["POSTGRESQL_DB_CONNECT_STRING"] - - - def migrate(): - with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: - cur.execute(""" - CREATE TABLE IF NOT EXISTS visitors ( - timestamp TIMESTAMP NOT NULL, - user_agent TEXT NOT NULL - ); - """) - conn.commit() - - - if __name__ == "__main__": - migrate() +.. literalinclude:: code/flask/migrate.py + :language: python .. note:: @@ -456,48 +435,8 @@ to be updated to keep track of the number of visitors and to include a new endpoint to retrieve the number of visitors to the app. Open ``app.py`` in a text editor and replace its contents with the following code: -.. code-block:: python - - import datetime - import os - - import flask - import psycopg2 - - app = flask.Flask(__name__) - app.config.from_prefixed_env() - - DATABASE_URI = os.environ["POSTGRESQL_DB_CONNECT_STRING"] - - - @app.route("/") - def index(): - with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: - user_agent = flask.request.headers.get('User-Agent') - timestamp = datetime.datetime.now() - - cur.execute( - "INSERT INTO visitors (timestamp, user_agent) VALUES (%s, %s)", - (timestamp, user_agent) - ) - conn.commit() - - - greeting = app.config.get("GREETING", "Hello, world!") - return f"{greeting}\n" - - - @app.route("/visitors") - def visitors(): - with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: - cur.execute("SELECT COUNT(*) FROM visitors") - total_visitors = cur.fetchone()[0] - - return f"{total_visitors}\n" - - - if __name__ == "__main__": - app.run() +.. literalinclude:: code/flask/visitors_app.py + :language: python Run ``rockcraft pack`` and upload the newly created rock to the MicroK8s registry: From 31536bba20ee8b134858aa72d3cb7452c87ec1bb Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:57:34 +0100 Subject: [PATCH 020/100] Update setup.rst to fix linting issues --- docs/reuse/tutorial/setup.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/reuse/tutorial/setup.rst b/docs/reuse/tutorial/setup.rst index 0c282d86a..63386a4be 100644 --- a/docs/reuse/tutorial/setup.rst +++ b/docs/reuse/tutorial/setup.rst @@ -2,9 +2,11 @@ Install Multipass. .. seealso:: - See more: `Multipass | How to install Multipass `_ + See more: `Multipass | How to install Multipass + `_ -Use Multipass to launch an Ubuntu VM with the name ``charm-dev`` from the 24.04 blueprint: +Use Multipass to launch an Ubuntu VM with the name ``charm-dev`` +from the 24.04 blueprint: .. code-block:: bash @@ -22,7 +24,8 @@ In order to create the rock, you'll need to install Rockcraft: sudo snap install rockcraft --classic -``LXD`` will be required for building the rock. Make sure it is installed and initialised: +``LXD`` will be required for building the rock. +Make sure it is installed and initialised: .. code-block:: bash From 81377c0bcbb6a01c199d1ae10c2126b4556e8927 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 10:58:43 +0100 Subject: [PATCH 021/100] Update visitors_app.py to remove trailing whitespace --- docs/tutorial/code/flask/visitors_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/visitors_app.py b/docs/tutorial/code/flask/visitors_app.py index 2830d4a55..e4119c6b3 100644 --- a/docs/tutorial/code/flask/visitors_app.py +++ b/docs/tutorial/code/flask/visitors_app.py @@ -15,7 +15,7 @@ def index(): with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: user_agent = flask.request.headers.get('User-Agent') timestamp = datetime.datetime.now() - + cur.execute( "INSERT INTO visitors (timestamp, user_agent) VALUES (%s, %s)", (timestamp, user_agent) From b98a43aef00a558b1218bb38c4c35755ca4984f6 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 11:03:57 +0100 Subject: [PATCH 022/100] Fix trailing whitespaces --- docs/tutorial/code/flask/task.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 85d832d74..b84b5c8b8 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -90,7 +90,7 @@ execute: | cat greeting_app.py > app.py sed -i "s/version: .*/version: 0.2/g" rockcraft.yaml rockcraft pack - + # [docs:docker-update] rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ oci-archive:flask-hello-world_0.2_amd64.rock \ @@ -114,7 +114,7 @@ execute: | cat visitors_app.py > app.py sed -i "s/version: .*/version: 0.3/g" rockcraft.yaml rockcraft pack - + # [docs:docker-2nd-update] rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ oci-archive:flask-hello-world_0.3_amd64.rock \ From f1db5a61a0eb9ba4dd09f5c92ed6af9ca2ea740d Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 11:35:31 +0100 Subject: [PATCH 023/100] Fix indent issue in task.yaml --- docs/tutorial/code/flask/task.yaml | 112 ++++++++++++++--------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index b84b5c8b8..5698016f3 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -68,8 +68,8 @@ execute: | # [docs:deploy-juju-model] juju deploy ./flask-hello-world_ubuntu-22.04-amd64.charm \ - flask-hello-world --resource \ - flask-app-image=localhost:32000/flask-hello-world:0.1 + flask-hello-world --resource \ + flask-app-image=localhost:32000/flask-hello-world:0.1 # [docs:deploy-juju-model-end] # [docs:deploy-nginx] @@ -79,7 +79,7 @@ execute: | # [docs:config-nginx] juju config nginx-ingress-integrator \ - service-hostname=flask-hello-world path-routes=/ + service-hostname=flask-hello-world path-routes=/ # [docs:config-nginx-end] # [docs:curl-init-deployment] @@ -93,56 +93,56 @@ execute: | # [docs:docker-update] rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ - oci-archive:flask-hello-world_0.2_amd64.rock \ - docker://localhost:32000/flask-hello-world:0.2 - # [docs:docker-update-end] - - cd charm - charmcraft pack - - # [docs:refresh-deployment] - juju refresh flask-hello-world \ - --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ - --resource flask-app-image=localhost:32000/flask-hello-world:0.2 - # [docs:refresh-deployment-end] - - # [docs:change-config] - juju config flask-hello-world greeting='Hi!' - # [docs:change-config-end] - - cd .. - cat visitors_app.py > app.py - sed -i "s/version: .*/version: 0.3/g" rockcraft.yaml - rockcraft pack - - # [docs:docker-2nd-update] - rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ - oci-archive:flask-hello-world_0.3_amd64.rock \ - docker://localhost:32000/flask-hello-world:0.3 - # [docs:docker-2nd-update-end] - - cd charm - charmcraft pack - - # [docs:refresh-2nd-deployment] - juju refresh flask-hello-world \ - --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ - --resource flask-app-image=localhost:32000/flask-hello-world:0.3 - # [docs:refresh-2nd-deployment-end] - - # [docs:deploy-postgres] - juju deploy postgresql-k8s --trust - juju integrate flask-hello-world postgresql-k8s - # [docs:deploy-postgres-end] - - # [docs:clean-environment] - # exit and delete the virtual environment - deactivate - rm -rf charm .venv __pycache__ - # delete all the files created during the tutorial - rm flask-hello-world_0.1_amd64.rock flask-hello-world_0.2_amd64.rock \ - flask-hello-world_0.3_amd64.rock rockcraft.yaml app.py \ - requirements.txt migrate.py - # Remove the juju model - juju destroy-model flask-hello-world --destroy-storage - # [docs:clean-environment-end] + oci-archive:flask-hello-world_0.2_amd64.rock \ + docker://localhost:32000/flask-hello-world:0.2 + # [docs:docker-update-end] + + cd charm + charmcraft pack + + # [docs:refresh-deployment] + juju refresh flask-hello-world \ + --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ + --resource flask-app-image=localhost:32000/flask-hello-world:0.2 + # [docs:refresh-deployment-end] + + # [docs:change-config] + juju config flask-hello-world greeting='Hi!' + # [docs:change-config-end] + + cd .. + cat visitors_app.py > app.py + sed -i "s/version: .*/version: 0.3/g" rockcraft.yaml + rockcraft pack + + # [docs:docker-2nd-update] + rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ + oci-archive:flask-hello-world_0.3_amd64.rock \ + docker://localhost:32000/flask-hello-world:0.3 + # [docs:docker-2nd-update-end] + + cd charm + charmcraft pack + + # [docs:refresh-2nd-deployment] + juju refresh flask-hello-world \ + --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ + --resource flask-app-image=localhost:32000/flask-hello-world:0.3 + # [docs:refresh-2nd-deployment-end] + + # [docs:deploy-postgres] + juju deploy postgresql-k8s --trust + juju integrate flask-hello-world postgresql-k8s + # [docs:deploy-postgres-end] + + # [docs:clean-environment] + # exit and delete the virtual environment + deactivate + rm -rf charm .venv __pycache__ + # delete all the files created during the tutorial + rm flask-hello-world_0.1_amd64.rock flask-hello-world_0.2_amd64.rock \ + flask-hello-world_0.3_amd64.rock rockcraft.yaml app.py \ + requirements.txt migrate.py + # Remove the juju model + juju destroy-model flask-hello-world --destroy-storage + # [docs:clean-environment-end] From bb66b895e0202549e98c832f055d8c7575cc7992 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 30 Oct 2024 16:43:19 +0100 Subject: [PATCH 024/100] Add spread test for tutorial --- spread.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/spread.yaml b/spread.yaml index 4083ee765..88b09be45 100644 --- a/spread.yaml +++ b/spread.yaml @@ -129,6 +129,24 @@ prepare: | install_charmcraft suites: + docs/tutorial/code/: + summary: tests tutorial from the docs + systems: + - ubuntu-22.04-64 + prepare: | + sudo snap install rockcraft --classic + sudo snap install lxd + lxd init --auto + sudo snap install charmcraft --channel latest/edge --classic + sudo snap install microk8s --channel 1.31-strict/stable + sudo adduser $USER snap_microk8s + newgrp snap_microk8s + sudo microk8s enable hostpath-storage + sudo microk8s enable registry + sudo microk8s enable ingress + sudo snap install juju --channel 3.5/stable + mkdir -p ~/.local/share + juju bootstrap microk8s dev-controller tests/spread/commands/: summary: simple charmcraft commands tests/spread/charms/: From 9fba6d806f09ebd5197f7126804fa0a103cf9f7f Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Thu, 31 Oct 2024 15:39:54 +0100 Subject: [PATCH 025/100] Update task.yaml --- docs/tutorial/code/flask/task.yaml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 5698016f3..d9c235dbf 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -30,19 +30,21 @@ execute: | rockcraft init --profile flask-framework # [docs:create-rockcraft-yaml-end] sed -i "s/name: .*/name: flask-hello-world/g" rockcraft.yaml + sed -i "s/amd64/$(dpkg --print-architecture)/g" rockcraft.yaml # [docs:pack] rockcraft pack # [docs:pack-end] + ls -la # [docs:ls-rock] ls *.rock -l # [docs:ls-rock-end] # [docs:skopeo-copy] - sudo rockcraft.skopeo --insecure-policy \ - copy oci-archive:flask-hello-world_0.1_amd64.rock \ - docker-daemon:flask-hello-world:0.1 + rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ + oci-archive:flask-hello-world_0.1_$(dpkg --print-architecture).rock \ + docker://localhost:32000/flask-hello-world:0.1 # [docs:skopeo-copy-end] # [docs:create-charm-dir] @@ -66,8 +68,10 @@ execute: | juju add-model flask-hello-world # [docs:add-juju-model-end] + juju set-model-constraints -m flask-hello-world arch=$(dpkg --print-architecture) + # [docs:deploy-juju-model] - juju deploy ./flask-hello-world_ubuntu-22.04-amd64.charm \ + juju deploy ./flask-hello-world_ubuntu-22.04-$(dpkg --print-architecture).charm \ flask-hello-world --resource \ flask-app-image=localhost:32000/flask-hello-world:0.1 # [docs:deploy-juju-model-end] @@ -93,7 +97,7 @@ execute: | # [docs:docker-update] rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ - oci-archive:flask-hello-world_0.2_amd64.rock \ + oci-archive:flask-hello-world_0.2_$(dpkg --print-architecture).rock \ docker://localhost:32000/flask-hello-world:0.2 # [docs:docker-update-end] @@ -102,7 +106,7 @@ execute: | # [docs:refresh-deployment] juju refresh flask-hello-world \ - --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ + --path=./flask-hello-world_ubuntu-22.04-$(dpkg --print-architecture).charm \ --resource flask-app-image=localhost:32000/flask-hello-world:0.2 # [docs:refresh-deployment-end] @@ -117,7 +121,7 @@ execute: | # [docs:docker-2nd-update] rockcraft.skopeo --insecure-policy copy --dest-tls-verify=false \ - oci-archive:flask-hello-world_0.3_amd64.rock \ + oci-archive:flask-hello-world_0.3_$(dpkg --print-architecture).rock \ docker://localhost:32000/flask-hello-world:0.3 # [docs:docker-2nd-update-end] @@ -126,7 +130,7 @@ execute: | # [docs:refresh-2nd-deployment] juju refresh flask-hello-world \ - --path=./flask-hello-world_ubuntu-22.04-amd64.charm \ + --path=./flask-hello-world_ubuntu-22.04-$(dpkg --print-architecture).charm \ --resource flask-app-image=localhost:32000/flask-hello-world:0.3 # [docs:refresh-2nd-deployment-end] @@ -140,8 +144,8 @@ execute: | deactivate rm -rf charm .venv __pycache__ # delete all the files created during the tutorial - rm flask-hello-world_0.1_amd64.rock flask-hello-world_0.2_amd64.rock \ - flask-hello-world_0.3_amd64.rock rockcraft.yaml app.py \ + rm flask-hello-world_0.1_$(dpkg --print-architecture).rock flask-hello-world_0.2_$(dpkg --print-architecture).rock \ + flask-hello-world_0.3_$(dpkg --print-architecture).rock rockcraft.yaml app.py \ requirements.txt migrate.py # Remove the juju model juju destroy-model flask-hello-world --destroy-storage From d377244b4e1bc6d1df383c45fc85c0a7fc518ae4 Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 12 Nov 2024 15:02:30 -0500 Subject: [PATCH 026/100] update spread Multipass VM and prepare instructions --- spread.yaml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/spread.yaml b/spread.yaml index 88b09be45..ca3dc12b7 100644 --- a/spread.yaml +++ b/spread.yaml @@ -52,7 +52,7 @@ backends: system=$(echo "${SPREAD_SYSTEM}" | tr . -) instance_name="spread-${SPREAD_BACKEND}-${instance_num}-${system}" - multipass launch --cpus 2 --disk 20G --memory 2G --name "${instance_name}" "${multipass_image}" + multipass launch --cpus 4 --disk 50G --memory 4G --name "${instance_name}" "${multipass_image}" # Enable PasswordAuthentication for root over SSH. multipass exec "$instance_name" -- \ @@ -134,18 +134,19 @@ suites: systems: - ubuntu-22.04-64 prepare: | - sudo snap install rockcraft --classic - sudo snap install lxd + snap install rockcraft --classic + snap install lxd lxd init --auto - sudo snap install charmcraft --channel latest/edge --classic - sudo snap install microk8s --channel 1.31-strict/stable - sudo adduser $USER snap_microk8s - newgrp snap_microk8s - sudo microk8s enable hostpath-storage - sudo microk8s enable registry - sudo microk8s enable ingress - sudo snap install juju --channel 3.5/stable + snap refresh charmcraft --channel=latest/edge --amend + snap install microk8s --channel=1.31-strict/stable + #adduser $USER snap_microk8s + #newgrp snap_microk8s + snap install juju --channel=3.5/stable + lxc network set lxdbr0 ipv6.address none mkdir -p ~/.local/share + microk8s enable hostpath-storage + microk8s enable registry + microk8s enable ingress juju bootstrap microk8s dev-controller tests/spread/commands/: summary: simple charmcraft commands From 9cbdf8edf3d50327ba902d88338ac0210146b860 Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 12 Nov 2024 15:08:30 -0500 Subject: [PATCH 027/100] update files for Flask tutorial spread test --- .../code/flask/greeting_charmcraft.yaml | 7 ++++ docs/tutorial/code/flask/task.yaml | 38 ++++++++++++++++++- .../code/flask/visitors_charmcraft.yaml | 4 ++ docs/tutorial/code/flask/visitors_migrate.py | 21 ++++++++++ 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 docs/tutorial/code/flask/greeting_charmcraft.yaml create mode 100644 docs/tutorial/code/flask/visitors_charmcraft.yaml create mode 100644 docs/tutorial/code/flask/visitors_migrate.py diff --git a/docs/tutorial/code/flask/greeting_charmcraft.yaml b/docs/tutorial/code/flask/greeting_charmcraft.yaml new file mode 100644 index 000000000..005c8d5da --- /dev/null +++ b/docs/tutorial/code/flask/greeting_charmcraft.yaml @@ -0,0 +1,7 @@ +config: + options: + greeting: + description: | + The greeting to be returned by the Flask application. + default: "Hello, world!" + type: string diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index d9c235dbf..c13878b5e 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -10,6 +10,10 @@ summary: Getting started with Flask tutorial environment: execute: | + #move everything to $HOME so that Juju deployment works + mv *.yaml *.py *.txt $HOME + cd $HOME + # [docs:create-venv] sudo apt-get update && sudo apt-get install python3-venv -y python3 -m venv .venv @@ -35,7 +39,6 @@ execute: | # [docs:pack] rockcraft pack # [docs:pack-end] - ls -la # [docs:ls-rock] ls *.rock -l @@ -86,10 +89,16 @@ execute: | service-hostname=flask-hello-world path-routes=/ # [docs:config-nginx-end] + # give Juju some time to deploy the apps + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + juju wait-for application nginx-ingress-integrator --query='status=="active"' --timeout 10m + # [docs:curl-init-deployment] curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 # [docs:curl-init-deployment-end] + juju status + cd .. cat greeting_app.py > app.py sed -i "s/version: .*/version: 0.2/g" rockcraft.yaml @@ -101,6 +110,7 @@ execute: | docker://localhost:32000/flask-hello-world:0.2 # [docs:docker-update-end] + cat greeting_charmcraft.yaml >> ./charm/charmcraft.yaml cd charm charmcraft pack @@ -110,13 +120,23 @@ execute: | --resource flask-app-image=localhost:32000/flask-hello-world:0.2 # [docs:refresh-deployment-end] + # give Juju some time to refresh the app + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + # [docs:change-config] juju config flask-hello-world greeting='Hi!' # [docs:change-config-end] + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + cd .. + cat visitors_migrate.py >> migrate.py cat visitors_app.py > app.py sed -i "s/version: .*/version: 0.3/g" rockcraft.yaml + echo "psycopg2-binary" >> requirements.txt rockcraft pack # [docs:docker-2nd-update] @@ -125,6 +145,7 @@ execute: | docker://localhost:32000/flask-hello-world:0.3 # [docs:docker-2nd-update-end] + cat visitors_charmcraft.yaml >> ./charm/charmcraft.yaml cd charm charmcraft pack @@ -139,6 +160,19 @@ execute: | juju integrate flask-hello-world postgresql-k8s # [docs:deploy-postgres-end] + # give Juju some time to deploy and refresh the apps + juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + + juju status + + curl --fail http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + curl --fail http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 + curl --fail http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + curl --fail http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 + + cd .. + # [docs:clean-environment] # exit and delete the virtual environment deactivate @@ -148,5 +182,5 @@ execute: | flask-hello-world_0.3_$(dpkg --print-architecture).rock rockcraft.yaml app.py \ requirements.txt migrate.py # Remove the juju model - juju destroy-model flask-hello-world --destroy-storage + juju destroy-model flask-hello-world --destroy-storage --no-prompt # [docs:clean-environment-end] diff --git a/docs/tutorial/code/flask/visitors_charmcraft.yaml b/docs/tutorial/code/flask/visitors_charmcraft.yaml new file mode 100644 index 000000000..239f014d8 --- /dev/null +++ b/docs/tutorial/code/flask/visitors_charmcraft.yaml @@ -0,0 +1,4 @@ +requires: + postgresql: + interface: postgresql_client + optional: false diff --git a/docs/tutorial/code/flask/visitors_migrate.py b/docs/tutorial/code/flask/visitors_migrate.py new file mode 100644 index 000000000..2e303cea4 --- /dev/null +++ b/docs/tutorial/code/flask/visitors_migrate.py @@ -0,0 +1,21 @@ +import os + +import psycopg2 + + +DATABASE_URI = os.environ["POSTGRESQL_DB_CONNECT_STRING"] + + +def migrate(): + with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: + cur.execute(""" + CREATE TABLE IF NOT EXISTS visitors ( + timestamp TIMESTAMP NOT NULL, + user_agent TEXT NOT NULL + ); + """) + conn.commit() + + +if __name__ == "__main__": + migrate() From 60d8da811c807229653e05b16e7f1902342153a6 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 13 Nov 2024 15:04:07 -0500 Subject: [PATCH 028/100] unset staging store env vars for flask spread test --- spread.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spread.yaml b/spread.yaml index ca3dc12b7..a10bf1e65 100644 --- a/spread.yaml +++ b/spread.yaml @@ -148,6 +148,10 @@ suites: microk8s enable registry microk8s enable ingress juju bootstrap microk8s dev-controller + # Don't use the staging store for this spread test + unset CHARMCRAFT_STORE_API_URL + unset CHARMCRAFT_UPLOAD_URL + unset CHARMCRAFT_REGISTRY_URL tests/spread/commands/: summary: simple charmcraft commands tests/spread/charms/: From 314caaaeb6d7159d9005addb33ed9017684911f9 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 13 Nov 2024 16:10:06 -0500 Subject: [PATCH 029/100] update Flask spread test to not use staging store --- docs/tutorial/code/flask/task.yaml | 4 ++++ spread.yaml | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index c13878b5e..83e0dbf3c 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -13,6 +13,10 @@ execute: | #move everything to $HOME so that Juju deployment works mv *.yaml *.py *.txt $HOME cd $HOME + #don't use the staging store for this test + unset CHARMCRAFT_STORE_API_URL + unset CHARMCRAFT_UPLOAD_URL + unset CHARMCRAFT_REGISTRY_URL # [docs:create-venv] sudo apt-get update && sudo apt-get install python3-venv -y diff --git a/spread.yaml b/spread.yaml index a10bf1e65..ca3dc12b7 100644 --- a/spread.yaml +++ b/spread.yaml @@ -148,10 +148,6 @@ suites: microk8s enable registry microk8s enable ingress juju bootstrap microk8s dev-controller - # Don't use the staging store for this spread test - unset CHARMCRAFT_STORE_API_URL - unset CHARMCRAFT_UPLOAD_URL - unset CHARMCRAFT_REGISTRY_URL tests/spread/commands/: summary: simple charmcraft commands tests/spread/charms/: From 9f4dffa7517ba1c7d0d6377237475a2f073ce70e Mon Sep 17 00:00:00 2001 From: erinecon Date: Thu, 14 Nov 2024 09:16:17 -0500 Subject: [PATCH 030/100] update wait-for commands for debugging --- docs/tutorial/code/flask/task.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 83e0dbf3c..afadc14f6 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -94,8 +94,8 @@ execute: | # [docs:config-nginx-end] # give Juju some time to deploy the apps - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m - juju wait-for application nginx-ingress-integrator --query='status=="active"' --timeout 10m + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status + juju wait-for application nginx-ingress-integrator --query='status=="active"' --timeout 10m | juju status # [docs:curl-init-deployment] curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 From 187ac5f82e71fcf3b3f969b3987d9d9f2cb17ee4 Mon Sep 17 00:00:00 2001 From: erinecon Date: Thu, 14 Nov 2024 16:09:54 -0500 Subject: [PATCH 031/100] set kill-timeout for flask test --- docs/tutorial/code/flask/task.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index afadc14f6..18fd70053 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -7,6 +7,8 @@ ########################################### summary: Getting started with Flask tutorial +kill-timeout: 90m + environment: execute: | From 29e6b0b41803f8f61ce439d56832bf8f0b57b50c Mon Sep 17 00:00:00 2001 From: erinecon Date: Thu, 14 Nov 2024 16:11:53 -0500 Subject: [PATCH 032/100] add microk8s status command to flask spread test --- spread.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/spread.yaml b/spread.yaml index ca3dc12b7..ce1773997 100644 --- a/spread.yaml +++ b/spread.yaml @@ -144,6 +144,7 @@ suites: snap install juju --channel=3.5/stable lxc network set lxdbr0 ipv6.address none mkdir -p ~/.local/share + microk8s status --wait-ready microk8s enable hostpath-storage microk8s enable registry microk8s enable ingress From ecbf30bee73313ae10df3deaf270c6a9d468d917 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Fri, 15 Nov 2024 11:07:16 -0500 Subject: [PATCH 033/100] Delete docs/tutorial/code/flask/migrate.py So that the spread test won't pick it up too early in the test (causing a blocked status in the flask-hello-world app) --- docs/tutorial/code/flask/migrate.py | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 docs/tutorial/code/flask/migrate.py diff --git a/docs/tutorial/code/flask/migrate.py b/docs/tutorial/code/flask/migrate.py deleted file mode 100644 index 2e303cea4..000000000 --- a/docs/tutorial/code/flask/migrate.py +++ /dev/null @@ -1,21 +0,0 @@ -import os - -import psycopg2 - - -DATABASE_URI = os.environ["POSTGRESQL_DB_CONNECT_STRING"] - - -def migrate(): - with psycopg2.connect(DATABASE_URI) as conn, conn.cursor() as cur: - cur.execute(""" - CREATE TABLE IF NOT EXISTS visitors ( - timestamp TIMESTAMP NOT NULL, - user_agent TEXT NOT NULL - ); - """) - conn.commit() - - -if __name__ == "__main__": - migrate() From 5018e110f041305541714e06c1ee2c934d949817 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 15 Nov 2024 13:20:02 -0500 Subject: [PATCH 034/100] Run CI From c8bc3472f5d688c25ca2b8892651c520656d2f90 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 18 Nov 2024 07:38:28 -0500 Subject: [PATCH 035/100] update Juju version for Flask spread test --- spread.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spread.yaml b/spread.yaml index ce1773997..3af575717 100644 --- a/spread.yaml +++ b/spread.yaml @@ -141,7 +141,7 @@ suites: snap install microk8s --channel=1.31-strict/stable #adduser $USER snap_microk8s #newgrp snap_microk8s - snap install juju --channel=3.5/stable + snap install juju --channel=3.6/edge lxc network set lxdbr0 ipv6.address none mkdir -p ~/.local/share microk8s status --wait-ready From 17921d7acaa16d614f214ee005f540abc3d32987 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 18 Nov 2024 09:00:11 -0500 Subject: [PATCH 036/100] update Juju version for Flask spread test --- spread.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spread.yaml b/spread.yaml index 3af575717..111ba2aae 100644 --- a/spread.yaml +++ b/spread.yaml @@ -141,7 +141,7 @@ suites: snap install microk8s --channel=1.31-strict/stable #adduser $USER snap_microk8s #newgrp snap_microk8s - snap install juju --channel=3.6/edge + snap install juju --channel=3.6/beta lxc network set lxdbr0 ipv6.address none mkdir -p ~/.local/share microk8s status --wait-ready From 1e6291174cff0f9f469a5e122a9b49daf71d8faa Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 18 Nov 2024 12:01:23 -0500 Subject: [PATCH 037/100] update postgresql version for Flask spread test --- docs/tutorial/code/flask/task.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 18fd70053..9fe726055 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -127,7 +127,7 @@ execute: | # [docs:refresh-deployment-end] # give Juju some time to refresh the app - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 @@ -135,7 +135,7 @@ execute: | juju config flask-hello-world greeting='Hi!' # [docs:change-config-end] - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 cd .. @@ -162,13 +162,13 @@ execute: | # [docs:refresh-2nd-deployment-end] # [docs:deploy-postgres] - juju deploy postgresql-k8s --trust + juju deploy postgresql-k8s --trust --channel=14/beta juju integrate flask-hello-world postgresql-k8s # [docs:deploy-postgres-end] # give Juju some time to deploy and refresh the apps - juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m | juju status + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status juju status From 66a9c41cb47566d512e10278eab69d2196550c99 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 18 Nov 2024 13:17:46 -0500 Subject: [PATCH 038/100] Run CI From e3ab3ca6b5a71e31a2ab932afc7621ede86eab31 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 18 Nov 2024 16:13:42 -0500 Subject: [PATCH 039/100] force update Juju version in Flask spread test --- docs/tutorial/code/flask/task.yaml | 4 +++- spread.yaml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 9fe726055..800d28cdf 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -19,6 +19,8 @@ execute: | unset CHARMCRAFT_STORE_API_URL unset CHARMCRAFT_UPLOAD_URL unset CHARMCRAFT_REGISTRY_URL + #make sure that Juju version is correct + snap refresh juju --channel=3.5/stable --amend # [docs:create-venv] sudo apt-get update && sudo apt-get install python3-venv -y @@ -162,7 +164,7 @@ execute: | # [docs:refresh-2nd-deployment-end] # [docs:deploy-postgres] - juju deploy postgresql-k8s --trust --channel=14/beta + juju deploy postgresql-k8s --trust juju integrate flask-hello-world postgresql-k8s # [docs:deploy-postgres-end] diff --git a/spread.yaml b/spread.yaml index 111ba2aae..ce1773997 100644 --- a/spread.yaml +++ b/spread.yaml @@ -141,7 +141,7 @@ suites: snap install microk8s --channel=1.31-strict/stable #adduser $USER snap_microk8s #newgrp snap_microk8s - snap install juju --channel=3.6/beta + snap install juju --channel=3.5/stable lxc network set lxdbr0 ipv6.address none mkdir -p ~/.local/share microk8s status --wait-ready From 1a0df9b3bd79c69689176cf65bbd6cdb8a7ecf0e Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 19 Nov 2024 08:52:04 -0500 Subject: [PATCH 040/100] move prepare section to task.yaml file --- docs/tutorial/code/flask/task.yaml | 16 +++++++++++++++- spread.yaml | 16 ---------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 800d28cdf..881b4e1d9 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -20,7 +20,21 @@ execute: | unset CHARMCRAFT_UPLOAD_URL unset CHARMCRAFT_REGISTRY_URL #make sure that Juju version is correct - snap refresh juju --channel=3.5/stable --amend + snap install rockcraft --classic + snap install lxd + lxd init --auto + snap refresh charmcraft --channel=latest/edge --amend + snap install microk8s --channel=1.31-strict/stable + #adduser $USER snap_microk8s + #newgrp snap_microk8s + snap install juju --channel=3.5/stable + lxc network set lxdbr0 ipv6.address none + mkdir -p ~/.local/share + microk8s status --wait-ready + microk8s enable hostpath-storage + microk8s enable registry + microk8s enable ingress + juju bootstrap microk8s dev-controller # [docs:create-venv] sudo apt-get update && sudo apt-get install python3-venv -y diff --git a/spread.yaml b/spread.yaml index ce1773997..fb902101a 100644 --- a/spread.yaml +++ b/spread.yaml @@ -133,22 +133,6 @@ suites: summary: tests tutorial from the docs systems: - ubuntu-22.04-64 - prepare: | - snap install rockcraft --classic - snap install lxd - lxd init --auto - snap refresh charmcraft --channel=latest/edge --amend - snap install microk8s --channel=1.31-strict/stable - #adduser $USER snap_microk8s - #newgrp snap_microk8s - snap install juju --channel=3.5/stable - lxc network set lxdbr0 ipv6.address none - mkdir -p ~/.local/share - microk8s status --wait-ready - microk8s enable hostpath-storage - microk8s enable registry - microk8s enable ingress - juju bootstrap microk8s dev-controller tests/spread/commands/: summary: simple charmcraft commands tests/spread/charms/: From 7e5d4ca0391b5beb4c6a0f607973ed361a997f1d Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 19 Nov 2024 10:59:01 -0500 Subject: [PATCH 041/100] snap refresh juju --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 881b4e1d9..afba6d395 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -27,7 +27,7 @@ execute: | snap install microk8s --channel=1.31-strict/stable #adduser $USER snap_microk8s #newgrp snap_microk8s - snap install juju --channel=3.5/stable + snap refresh juju --channel=3.5/stable --amend lxc network set lxdbr0 ipv6.address none mkdir -p ~/.local/share microk8s status --wait-ready From 87cc035324c151a38131727fd7e93f4c555adc2e Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 19 Nov 2024 13:59:42 -0500 Subject: [PATCH 042/100] remove fail flag from curl commands --- docs/tutorial/code/flask/task.yaml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index afba6d395..9b4357f13 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -188,10 +188,14 @@ execute: | juju status - curl --fail http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 - curl --fail http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 - curl --fail http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 - curl --fail http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 + #curl --fail http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + #curl --fail http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 + #curl --fail http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + #curl --fail http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 cd .. From 0b3bdd68f3f74bee0772777ae1d0fec724b2dd00 Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 19 Nov 2024 16:26:15 -0500 Subject: [PATCH 043/100] add force and no-wait to destroy-model command --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 9b4357f13..d5427536a 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -208,5 +208,5 @@ execute: | flask-hello-world_0.3_$(dpkg --print-architecture).rock rockcraft.yaml app.py \ requirements.txt migrate.py # Remove the juju model - juju destroy-model flask-hello-world --destroy-storage --no-prompt + juju destroy-model flask-hello-world --destroy-storage --no-prompt --force --no-wait # [docs:clean-environment-end] From 07a3506a0e87c5a8cc3a99b1660ebe45c591e520 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 20 Nov 2024 06:43:43 -0500 Subject: [PATCH 044/100] remove force flag --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index d5427536a..cdb515fb5 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -208,5 +208,5 @@ execute: | flask-hello-world_0.3_$(dpkg --print-architecture).rock rockcraft.yaml app.py \ requirements.txt migrate.py # Remove the juju model - juju destroy-model flask-hello-world --destroy-storage --no-prompt --force --no-wait + juju destroy-model flask-hello-world --destroy-storage --no-prompt --force # [docs:clean-environment-end] From 2e2be0560e5fd810253b62e64515fde59833f381 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 20 Nov 2024 12:02:37 -0500 Subject: [PATCH 045/100] explicitly set charmcraft env vars in environment section --- docs/tutorial/code/flask/task.yaml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index cdb515fb5..c3c26e224 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -10,15 +10,19 @@ summary: Getting started with Flask tutorial kill-timeout: 90m environment: + CHARMCRAFT_STORE_API_URL: https://api.charmhub.io + CHARMCRAFT_UPLOAD_URL: https://storage.snapcraftcontent.com + CHARMCRAFT_REGISTRY_URL: https://registry.jujucharms.com + CHARMCRAFT_AUTH: null execute: | #move everything to $HOME so that Juju deployment works mv *.yaml *.py *.txt $HOME cd $HOME #don't use the staging store for this test - unset CHARMCRAFT_STORE_API_URL - unset CHARMCRAFT_UPLOAD_URL - unset CHARMCRAFT_REGISTRY_URL + #unset CHARMCRAFT_STORE_API_URL + #unset CHARMCRAFT_UPLOAD_URL + #unset CHARMCRAFT_REGISTRY_URL #make sure that Juju version is correct snap install rockcraft --classic snap install lxd From a3db0da19feb5c16afd0a4af5ee65c7f29b209de Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 20 Nov 2024 14:34:04 -0500 Subject: [PATCH 046/100] revert changes for charmcraft env vars, specify base of nginx --- docs/tutorial/code/flask/task.yaml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index c3c26e224..67cf17ff3 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -10,19 +10,15 @@ summary: Getting started with Flask tutorial kill-timeout: 90m environment: - CHARMCRAFT_STORE_API_URL: https://api.charmhub.io - CHARMCRAFT_UPLOAD_URL: https://storage.snapcraftcontent.com - CHARMCRAFT_REGISTRY_URL: https://registry.jujucharms.com - CHARMCRAFT_AUTH: null execute: | #move everything to $HOME so that Juju deployment works mv *.yaml *.py *.txt $HOME cd $HOME #don't use the staging store for this test - #unset CHARMCRAFT_STORE_API_URL - #unset CHARMCRAFT_UPLOAD_URL - #unset CHARMCRAFT_REGISTRY_URL + unset CHARMCRAFT_STORE_API_URL + unset CHARMCRAFT_UPLOAD_URL + unset CHARMCRAFT_REGISTRY_URL #make sure that Juju version is correct snap install rockcraft --classic snap install lxd @@ -106,7 +102,7 @@ execute: | # [docs:deploy-juju-model-end] # [docs:deploy-nginx] - juju deploy nginx-ingress-integrator --channel=latest/edge + juju deploy nginx-ingress-integrator --channel=latest/edge --base ubuntu@20.04 juju integrate nginx-ingress-integrator flask-hello-world # [docs:deploy-nginx-end] From dd2e254166297886228981a5100f4286cf7e8635 Mon Sep 17 00:00:00 2001 From: erinecon Date: Thu, 21 Nov 2024 08:53:19 -0500 Subject: [PATCH 047/100] specify revision of nginx --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 67cf17ff3..665bb80f7 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -102,7 +102,7 @@ execute: | # [docs:deploy-juju-model-end] # [docs:deploy-nginx] - juju deploy nginx-ingress-integrator --channel=latest/edge --base ubuntu@20.04 + juju deploy nginx-ingress-integrator --channel=latest/edge --revision 122 juju integrate nginx-ingress-integrator flask-hello-world # [docs:deploy-nginx-end] From f4fa1a71720714ca35fd38ec8f497e5c334978ba Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 11:38:32 -0500 Subject: [PATCH 048/100] remove contributors from tutorial --- docs/tutorial/flask.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 9e65c4e25..d951ad93d 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -531,8 +531,5 @@ Next steps * - "Why...?", "So what?" - `SDK Explanation docs `_ - -**Contributors:** @econley, @jdkandersson , @tmihoc, @weii-wang - ------------------------- From 9926ddcbd329c9dc7c8c9e3a4286c62d7adba630 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 11:53:07 -0500 Subject: [PATCH 049/100] changes from review --- docs/tutorial/code/flask/task.yaml | 50 ++++++++++++++++-------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 665bb80f7..c30b3996c 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -12,28 +12,35 @@ kill-timeout: 90m environment: execute: | - #move everything to $HOME so that Juju deployment works + # Move everything to $HOME so that Juju deployment works mv *.yaml *.py *.txt $HOME cd $HOME - #don't use the staging store for this test + + # Don't use the staging store for this test unset CHARMCRAFT_STORE_API_URL unset CHARMCRAFT_UPLOAD_URL unset CHARMCRAFT_REGISTRY_URL - #make sure that Juju version is correct + + # Add setup instructions here + # (Ran into issues in prepare section) snap install rockcraft --classic snap install lxd lxd init --auto snap refresh charmcraft --channel=latest/edge --amend snap install microk8s --channel=1.31-strict/stable - #adduser $USER snap_microk8s - #newgrp snap_microk8s snap refresh juju --channel=3.5/stable --amend + + # Juju config setup lxc network set lxdbr0 ipv6.address none mkdir -p ~/.local/share + + # MicroK8s config setup microk8s status --wait-ready microk8s enable hostpath-storage microk8s enable registry microk8s enable ingress + + # Bootstrap controller juju bootstrap microk8s dev-controller # [docs:create-venv] @@ -55,6 +62,7 @@ execute: | # [docs:create-rockcraft-yaml] rockcraft init --profile flask-framework # [docs:create-rockcraft-yaml-end] + sed -i "s/name: .*/name: flask-hello-world/g" rockcraft.yaml sed -i "s/amd64/$(dpkg --print-architecture)/g" rockcraft.yaml @@ -112,15 +120,13 @@ execute: | # [docs:config-nginx-end] # give Juju some time to deploy the apps - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status - juju wait-for application nginx-ingress-integrator --query='status=="active"' --timeout 10m | juju status + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + juju wait-for application nginx-ingress-integrator --query='status=="active"' --timeout 10m # [docs:curl-init-deployment] curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 # [docs:curl-init-deployment-end] - juju status - cd .. cat greeting_app.py > app.py sed -i "s/version: .*/version: 0.2/g" rockcraft.yaml @@ -143,15 +149,16 @@ execute: | # [docs:refresh-deployment-end] # give Juju some time to refresh the app - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m - curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + # curl and check that the response is Hi + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi # [docs:change-config] juju config flask-hello-world greeting='Hi!' # [docs:change-config-end] - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 cd .. @@ -183,20 +190,15 @@ execute: | # [docs:deploy-postgres-end] # give Juju some time to deploy and refresh the apps - juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m | juju status - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status - - juju status + juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m - #curl --fail http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 - #curl --fail http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 - #curl --fail http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 - #curl --fail http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 - curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 - curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 - curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 - curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi + curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 | grep 1 + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi + curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 | grep 2 + # Back out to main directory for clean-up cd .. # [docs:clean-environment] From a7815279a83f6c320a56d26c94b38c1e8d02a41c Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 13:04:01 -0500 Subject: [PATCH 050/100] remove trailing whitespace --- docs/tutorial/code/flask/task.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index c30b3996c..c68cc4f4c 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -20,8 +20,8 @@ execute: | unset CHARMCRAFT_STORE_API_URL unset CHARMCRAFT_UPLOAD_URL unset CHARMCRAFT_REGISTRY_URL - - # Add setup instructions here + + # Add setup instructions # (Ran into issues in prepare section) snap install rockcraft --classic snap install lxd From 0ae0120ecc6d7c2a1d88a5d149108eb19b8fc499 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 13:06:15 -0500 Subject: [PATCH 051/100] add tutorial index --- docs/tutorial/index.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 docs/tutorial/index.rst diff --git a/docs/tutorial/index.rst b/docs/tutorial/index.rst new file mode 100644 index 000000000..3965c1272 --- /dev/null +++ b/docs/tutorial/index.rst @@ -0,0 +1,10 @@ +.. _tutorial: + +Tutorial +******** + +.. toctree:: + :maxdepth: 2 + + flask + From 1a8e45ddf7618b8083681e6f1c399bcc9669c9d9 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 13:06:49 -0500 Subject: [PATCH 052/100] add tutorial/index to main index --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index d35ec6069..22f17da46 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,7 +13,7 @@ Most of Charmcraft's documentation is available there. howto/index reference/index explanation/index - tutorial/flask + tutorial/index .. grid:: 1 1 2 2 From f1e16abbc510100fcbe99c763339db607d9a924b Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 13:22:48 -0500 Subject: [PATCH 053/100] fix grep commands on curl requests --- docs/tutorial/code/flask/task.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index c68cc4f4c..899b1a7f6 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -152,14 +152,14 @@ execute: | juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m # curl and check that the response is Hi - curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | Hello # [docs:change-config] juju config flask-hello-world greeting='Hi!' # [docs:change-config-end] juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m - curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | Hi cd .. cat visitors_migrate.py >> migrate.py From 6e69855012674a9e2a6725484ae038b072fd7c93 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 14:58:58 -0500 Subject: [PATCH 054/100] add a wait-for for maintenance --- docs/tutorial/code/flask/task.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 899b1a7f6..95389ff0f 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -151,14 +151,18 @@ execute: | # give Juju some time to refresh the app juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m - # curl and check that the response is Hi + # curl and check that the response is Hello curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | Hello # [docs:change-config] juju config flask-hello-world greeting='Hi!' # [docs:change-config-end] + # make sure that the application updates + juju wait-for application flask-hello-world --query='status=="maintenance"' --timeout 10m juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + + # curl and check that the response is now Hi curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | Hi cd .. From 3005bf2a209958439296ff17f8439eba820d7040 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 15:06:18 -0500 Subject: [PATCH 055/100] reorder Diataxis sections --- docs/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.rst b/docs/index.rst index 22f17da46..46bf6025c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -10,10 +10,10 @@ Most of Charmcraft's documentation is available there. :maxdepth: 1 :hidden: + tutorial/index howto/index reference/index explanation/index - tutorial/index .. grid:: 1 1 2 2 From 127b3861f1e4cbaf82934a599751f73a938e9bc4 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 22 Nov 2024 15:12:12 -0500 Subject: [PATCH 056/100] remove whitespace --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 95389ff0f..a1ebf866b 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -20,7 +20,7 @@ execute: | unset CHARMCRAFT_STORE_API_URL unset CHARMCRAFT_UPLOAD_URL unset CHARMCRAFT_REGISTRY_URL - + # Add setup instructions # (Ran into issues in prepare section) snap install rockcraft --classic From 6cac8cb748d87c2d87219146f398c67016f9baeb Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 25 Nov 2024 07:54:31 -0500 Subject: [PATCH 057/100] add some forgotten greps --- docs/tutorial/code/flask/task.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index a1ebf866b..a6f718f77 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -152,7 +152,7 @@ execute: | juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m # curl and check that the response is Hello - curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | Hello + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hello # [docs:change-config] juju config flask-hello-world greeting='Hi!' @@ -163,7 +163,7 @@ execute: | juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m # curl and check that the response is now Hi - curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | Hi + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi cd .. cat visitors_migrate.py >> migrate.py From 8ddb84114511038129809c66a825bc122af09cff Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 25 Nov 2024 07:59:48 -0500 Subject: [PATCH 058/100] remove note about constraints --- docs/tutorial/flask.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index d951ad93d..833c8e018 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -364,12 +364,6 @@ make use of the new code: :end-before: [docs:refresh-deployment-end] :dedent: 2 -.. note:: - - For the refresh command, the ``--constraints`` option is not required if - you are not running on an ``amd64`` host as Juju will remember the - constraint for the life of the application deployment. - Wait for ``juju status`` to show that the App is ``active`` again. Verify that the new configuration has been added using ``juju config flask-hello-world | grep -A 6 greeting:`` which should show From 210dcaa898c6555a02b8396c0f24933b7d98f2ed Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 25 Nov 2024 08:07:33 -0500 Subject: [PATCH 059/100] formatting changes --- docs/tutorial/flask.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 833c8e018..fe128b08d 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -344,7 +344,7 @@ following to the end of the ``charmcraft.yaml`` file: options: greeting: description: | - The greeting to be returned by the Flask application. + The greeting to be returned by the Flask application. default: "Hello, world!" type: string @@ -400,9 +400,9 @@ This will require a few changes: * We will need to create a database migration that creates the ``visitors`` table * We will need to keep track how many times the root endpoint has been called -in the database + in the database * We will need to add a new endpoint to retrieve the number of visitors from the -database + database The charm created by the ``flask-framework`` extension will execute the ``migrate.py`` script if it exists. This script should ensure that the From 1e23891319d595033f3c4057ea9d1f45a64b5489 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 25 Nov 2024 08:08:30 -0500 Subject: [PATCH 060/100] add preamble sentence --- docs/tutorial/flask.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index fe128b08d..bc87f7483 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -404,6 +404,7 @@ This will require a few changes: * We will need to add a new endpoint to retrieve the number of visitors from the database +Let's start with the database migration to create the required tables. The charm created by the ``flask-framework`` extension will execute the ``migrate.py`` script if it exists. This script should ensure that the database is initialised and ready to be used by the application. We will From 409ae625ea1928de192146d8d8974630dcbdba9b Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 25 Nov 2024 08:11:21 -0500 Subject: [PATCH 061/100] update file name in tutorial --- docs/tutorial/flask.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index bc87f7483..6ffa8e9fb 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -413,7 +413,7 @@ create a ``migrate.py`` file containing this logic. Go back out to the tutorial root directory using ``cd ..``. Open the ``migrate.py`` file using a text editor and paste the following code into it: -.. literalinclude:: code/flask/migrate.py +.. literalinclude:: code/flask/visitors_migrate.py :language: python .. note:: From 393226b9739b8baa6ef7e1471707e1b4063e0c36 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 25 Nov 2024 08:12:57 -0500 Subject: [PATCH 062/100] change period to a comma --- docs/tutorial/flask.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 6ffa8e9fb..cfcda2b6d 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -410,7 +410,7 @@ The charm created by the ``flask-framework`` extension will execute the database is initialised and ready to be used by the application. We will create a ``migrate.py`` file containing this logic. -Go back out to the tutorial root directory using ``cd ..``. Open the ``migrate.py`` +Go back out to the tutorial root directory using ``cd ..``, open the ``migrate.py`` file using a text editor and paste the following code into it: .. literalinclude:: code/flask/visitors_migrate.py From 8c65a8971a0fb5c4206fc7a08c889f9c6d456235 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 25 Nov 2024 08:18:36 -0500 Subject: [PATCH 063/100] add more spaces to yaml snippet --- docs/tutorial/flask.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index cfcda2b6d..4491e2995 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -344,7 +344,7 @@ following to the end of the ``charmcraft.yaml`` file: options: greeting: description: | - The greeting to be returned by the Flask application. + The greeting to be returned by the Flask application. default: "Hello, world!" type: string From 3985020851d0da2f2d202a8a043c1c893b59abee Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 27 Nov 2024 15:26:12 -0500 Subject: [PATCH 064/100] change charmcraft version to latest/stable --- docs/reuse/tutorial/setup.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reuse/tutorial/setup.rst b/docs/reuse/tutorial/setup.rst index 63386a4be..53c340cdc 100644 --- a/docs/reuse/tutorial/setup.rst +++ b/docs/reuse/tutorial/setup.rst @@ -36,7 +36,7 @@ In order to create the charm, you'll need to install Charmcraft: .. code-block:: bash - sudo snap install charmcraft --channel latest/edge --classic + sudo snap install charmcraft --channel latest/stable --classic .. warning:: From 1a88669c84ddd1e6c02250a529c4d131193ad224 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 27 Nov 2024 15:27:04 -0500 Subject: [PATCH 065/100] replace setup.rst with setup_stable.rst --- docs/reuse/tutorial/{setup.rst => setup_stable.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/reuse/tutorial/{setup.rst => setup_stable.rst} (100%) diff --git a/docs/reuse/tutorial/setup.rst b/docs/reuse/tutorial/setup_stable.rst similarity index 100% rename from docs/reuse/tutorial/setup.rst rename to docs/reuse/tutorial/setup_stable.rst From ed25c8c46bade031e43b0cc8fffc1df842b50ff6 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 27 Nov 2024 15:27:44 -0500 Subject: [PATCH 066/100] update setup filename --- docs/tutorial/flask.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 4491e2995..423c3c3f2 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -57,7 +57,7 @@ application up and running with Juju in about 90 minutes. Set things up ============= -.. include:: /reuse/tutorial/setup.rst +.. include:: /reuse/tutorial/setup_stable.rst Finally, create a new directory for this tutorial and go inside it: From f920c2a75637e1d5545142928309df892a93f903 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 27 Nov 2024 15:37:26 -0500 Subject: [PATCH 067/100] change nginx deploy to specify base instead of revision --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index a6f718f77..cc173268c 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -110,7 +110,7 @@ execute: | # [docs:deploy-juju-model-end] # [docs:deploy-nginx] - juju deploy nginx-ingress-integrator --channel=latest/edge --revision 122 + juju deploy nginx-ingress-integrator --channel=latest/edge --base ubuntu@20.04 juju integrate nginx-ingress-integrator flask-hello-world # [docs:deploy-nginx-end] From 78743090590a99cafdd050c537d5a2504063719f Mon Sep 17 00:00:00 2001 From: erinecon Date: Thu, 28 Nov 2024 07:35:27 -0500 Subject: [PATCH 068/100] trigger CI From 66961857edf487531841a19de5c35a23fdd12e81 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 29 Nov 2024 13:20:35 -0500 Subject: [PATCH 069/100] trigger CI From 8da4ae155f3b022dc633d11888675f83e20d526b Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 29 Nov 2024 15:37:02 -0500 Subject: [PATCH 070/100] add more time to juju wait-for command --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index cc173268c..ac5719e7f 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -195,7 +195,7 @@ execute: | # give Juju some time to deploy and refresh the apps juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m + juju wait-for application flask-hello-world --query='status=="active"' --timeout 15m curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 | grep 1 From 54b29f4bd34ffdedadc8e8c0dcee22ee60b9b28d Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 2 Dec 2024 07:57:15 -0500 Subject: [PATCH 071/100] add juju status for debugging --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index ac5719e7f..5f4869aac 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -195,7 +195,7 @@ execute: | # give Juju some time to deploy and refresh the apps juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m - juju wait-for application flask-hello-world --query='status=="active"' --timeout 15m + juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status --relations curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 | grep 1 From a61dce8e32c41366ddeca14728eb81ead9496f88 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 2 Dec 2024 11:23:28 -0500 Subject: [PATCH 072/100] add juju status for debugging --- docs/tutorial/code/flask/task.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 5f4869aac..2d1a3786c 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -197,6 +197,8 @@ execute: | juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status --relations + juju status --relations + curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 | grep 1 curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi From 989f805dfb9727587b8a69ffb4eb1b54dc285c88 Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 3 Dec 2024 07:41:19 -0500 Subject: [PATCH 073/100] remove juju status, increase flask-hello-world timeout --- docs/tutorial/code/flask/task.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 2d1a3786c..70a5adbb6 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -195,9 +195,7 @@ execute: | # give Juju some time to deploy and refresh the apps juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m - juju wait-for application flask-hello-world --query='status=="active"' --timeout 10m | juju status --relations - - juju status --relations + juju wait-for application flask-hello-world --query='status=="active"' --timeout 30m curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 | grep 1 From 5dcc37df506f6a574d2c2f33a61b4912b25be3d8 Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 3 Dec 2024 10:42:25 -0500 Subject: [PATCH 074/100] increase kill timeout of spread test --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 70a5adbb6..9ae86f262 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -7,7 +7,7 @@ ########################################### summary: Getting started with Flask tutorial -kill-timeout: 90m +kill-timeout: 150m environment: From 967b73cac8b167b9577d86546f147b576397b54f Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 3 Dec 2024 10:44:02 -0500 Subject: [PATCH 075/100] remove snap refresh charmcraft --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 9ae86f262..6dc42667e 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -23,10 +23,10 @@ execute: | # Add setup instructions # (Ran into issues in prepare section) + # (don't install charmcraft) snap install rockcraft --classic snap install lxd lxd init --auto - snap refresh charmcraft --channel=latest/edge --amend snap install microk8s --channel=1.31-strict/stable snap refresh juju --channel=3.5/stable --amend From 5719dcbe6153f7217e73e0333ca3b2a42f93d2c6 Mon Sep 17 00:00:00 2001 From: erinecon Date: Tue, 3 Dec 2024 13:59:13 -0500 Subject: [PATCH 076/100] add juju statuses back in for debugging --- docs/tutorial/code/flask/task.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 6dc42667e..a9bf251f7 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -195,7 +195,9 @@ execute: | # give Juju some time to deploy and refresh the apps juju wait-for application postgresql-k8s --query='status=="active"' --timeout 10m - juju wait-for application flask-hello-world --query='status=="active"' --timeout 30m + juju wait-for application flask-hello-world --query='status=="active"' --timeout 30m | juju status --relations + + juju status --relations curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1 | grep Hi curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1 | grep 1 From 8310400481b6f9893af6fbe8a80e9f3aa1d25007 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 4 Dec 2024 15:17:01 -0500 Subject: [PATCH 077/100] Update docs/tutorial/flask.rst Co-authored-by: Michael DuBelko --- docs/tutorial/flask.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 423c3c3f2..b3525316d 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -479,8 +479,8 @@ another request to ``curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1`` will return ``2``. -Clean up environment -==================== +Clean up the environment +======================== We've reached the end of this tutorial. We have created a Flask application, deployed it locally, exposed it via ingress and integrated it with a database! From 8415d8d17dd7a2fc8acc24704cbb7c5b47095729 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 15:33:27 -0500 Subject: [PATCH 078/100] change language to soften the steps --- docs/tutorial/flask.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 423c3c3f2..afd491ec3 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -59,7 +59,8 @@ Set things up .. include:: /reuse/tutorial/setup_stable.rst -Finally, create a new directory for this tutorial and go inside it: +Finally, let's create a new directory for this tutorial and go +inside it: .. code-block:: bash @@ -69,8 +70,8 @@ Finally, create a new directory for this tutorial and go inside it: Create the Flask application ============================ -Start by creating the "Hello, world" Flask application that will be -used for this tutorial. +Let's start by creating the "Hello, world" Flask application that +will be used for this tutorial. Create a ``requirements.txt`` file, copy the following text into it and then save it: @@ -86,7 +87,7 @@ called ``app.py``: Run the Flask application locally ================================= -Install ``python3-venv`` and create a virtual environment: +Let's install ``python3-venv`` and create a virtual environment: .. literalinclude:: code/flask/task.yaml :language: bash @@ -102,8 +103,8 @@ run the Flask application to verify that it works: flask run -p 8000 Test the Flask application by using ``curl`` to send a request to the root -endpoint. You may need a new terminal for this; if you are using Multipass -use ``multipass shell charm-dev`` to get another terminal: +endpoint. You will need a new terminal for this; use +``multipass shell charm-dev`` to get another terminal: .. literalinclude:: code/flask/task.yaml :language: bash @@ -142,7 +143,7 @@ ARM architecture, include ``arm64`` in ``platforms``. running on a different platform will influence the names of the files generated by Rockcraft. -Pack the rock: +Now let's pack the rock: .. literalinclude:: code/flask/task.yaml :language: bash @@ -186,7 +187,7 @@ deployed in the Kubernetes cluster: Create the charm ================ -Create a new directory for the charm and go inside it: +Let's create a new directory for the charm and go inside it: .. literalinclude:: code/flask/task.yaml :language: bash @@ -206,7 +207,7 @@ the ``flask-framework`` profile: :dedent: 2 The files will automatically be created in your working directory. -Pack the charm: +Let's pack the charm: .. literalinclude:: code/flask/task.yaml :language: bash @@ -355,7 +356,7 @@ following to the end of the ``charmcraft.yaml`` file: identify which environment variables to include when running ``app.config.from_prefixed_env()`` in ``app.py``. -Run ``charmcraft pack`` again. The deployment can now be refreshed to +Run ``charmcraft pack`` again. We can now refresh the deployment to make use of the new code: .. literalinclude:: code/flask/task.yaml @@ -494,7 +495,7 @@ in the root directory for the tutorial: :end-before: [docs:clean-environment-end] :dedent: 2 -If you created an instance using Multipass, you can also clean it up. +You can also clean up the Multipass instance. Start by exiting it: .. code-block:: bash From c40f19488edd1bb09925a481be53d87712ff55f5 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 15:35:32 -0500 Subject: [PATCH 079/100] include the estimate on a separate line --- docs/tutorial/flask.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index afd491ec3..b746b3044 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -10,7 +10,9 @@ your Flask application in no time. Let’s get started! In this tutorial we will build a rock and Kubernetes charm for a Flask application using the charm SDK, so we can have a Flask -application up and running with Juju in about 90 minutes. +application up and running with Juju. + +This tutorial should take 90 minutes for you to complete. .. note:: From f9adad24e7b8a91e7afacb9819fd0e36a3b61456 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 15:40:21 -0500 Subject: [PATCH 080/100] undress the model constraints warning --- docs/tutorial/flask.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index b746b3044..59b7af952 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -247,13 +247,15 @@ A Juju model is needed to deploy the application. Let's create a new model: :end-before: [docs:add-juju-model-end] :dedent: 2 -.. warning:: +If you are not on a host with the ``amd64`` architecture, you will need to include +a constraint to the Juju model to specify your architecture. Check the +architecture of your system using ``dpkg --print-architecture``. - If you are not on a host with the amd64 architecture, you will need to include - a constraint to the Juju model to specify your architecture. For example, for - the arm64 architecture, use - ``juju set-model-constraints -m flask-hello-world arch=arm64``. - Check the architecture of your system using ``dpkg --print-architecture``. +For the ``arm64`` architecture, set the model constraints using + +.. code-block:: + + juju set-model-constraints -m flask-hello-world arch=arm64 Now the Flask application can be deployed using `Juju `_: From d99de9d5364b95f8b895d75b8ba3ab532ec8f2d3 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 15:42:38 -0500 Subject: [PATCH 081/100] move Juju link to first instance --- docs/tutorial/flask.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 59b7af952..0715a0ae7 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -4,7 +4,8 @@ Write your first Kubernetes charm for a Flask app Imagine you have a Flask application backed up by a database such as PostgreSQL and need to deploy it. In a traditional setup, -this can be quite a challenge, but with Juju you’ll find yourself +this can be quite a challenge, but with +`Juju `_ you’ll find yourself deploying, configuring, scaling, integrating, monitoring, etc., your Flask application in no time. Let’s get started! @@ -257,7 +258,7 @@ For the ``arm64`` architecture, set the model constraints using juju set-model-constraints -m flask-hello-world arch=arm64 -Now the Flask application can be deployed using `Juju `_: +Now the Flask application can be deployed using Juju: .. literalinclude:: code/flask/task.yaml :language: bash From 3c9e82781b3231895c4e8e634490f6cd8c1018b8 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 15:46:30 -0500 Subject: [PATCH 082/100] remove note dressing on juju status note --- docs/tutorial/flask.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 0715a0ae7..248a6f1cd 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -266,11 +266,11 @@ Now the Flask application can be deployed using Juju: :end-before: [docs:deploy-juju-model-end] :dedent: 2 -.. note:: +It will take a few minutes to deploy the Flask application. You can monitor the +progress using ``juju status --watch 5s``. Once the status of the App has gone +to ``active``, you can stop watching using :kbd:`Ctrl` + :kbd:`C`. - It will take a few minutes to deploy the Flask application. You can monitor the - progress using ``juju status --watch 5s``. Once the status of the App has gone - to ``active``, you can stop watching using :kbd:`Ctrl` + :kbd:`C`. +.. seealso:: See more: `Command 'juju status' `_ From 83360296ce9ed50102b8df9f4bfcd0cdc33c9788 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 15:48:40 -0500 Subject: [PATCH 083/100] use terminal role for juju status output --- docs/tutorial/flask.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 248a6f1cd..8871bc349 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -277,7 +277,7 @@ to ``active``, you can stop watching using :kbd:`Ctrl` + :kbd:`C`. The Flask application should now be running. We can monitor the status of the deployment using ``juju status`` which should be similar to the following output: -.. code-block:: +.. terminal:: Model Controller Cloud/Region Version SLA Timestamp flask-hello-world dev-controller microk8s/localhost 3.1.8 unsupported 17:04:11+10:00 From ea702aa6c04b51d8a684ba1d92379b0d1c1b688e Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 15:51:07 -0500 Subject: [PATCH 084/100] split up curl commands into multiple lines --- docs/tutorial/flask.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 8871bc349..2552c4f64 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -476,11 +476,14 @@ Deploy ``postgresql-k8s`` using Juju and integrate it with ``flask-hello-world`` Wait for ``juju status`` to show that the App is ``active`` again. Running ``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` -should still return the ``Hi!`` greeting. To check the total visitors, use +should still return the ``Hi!`` greeting. + +To check the total visitors, use ``curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1`` which should return ``1`` after the previous request to the root endpoint and -should be incremented each time the root endpoint is requested. If we perform -another request to +should be incremented each time the root endpoint is requested. + +If we perform another request to ``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1``, ``curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1`` will return ``2``. From e0dbb2a8edb5b2b6baa77b50e8b5991b0c562f6d Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 15:51:59 -0500 Subject: [PATCH 085/100] move accomplishments to end of the tutorial --- docs/tutorial/flask.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 2552c4f64..b8c5cfa2c 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -491,9 +491,6 @@ will return ``2``. Clean up environment ==================== -We've reached the end of this tutorial. We have created a Flask application, -deployed it locally, exposed it via ingress and integrated it with a database! - If you'd like to reset your working environment, you can run the following in the root directory for the tutorial: @@ -517,6 +514,9 @@ And then you can proceed with its deletion: multipass delete charm-dev multipass purge +We've reached the end of this tutorial. We have created a Flask application, +deployed it locally, exposed it via ingress and integrated it with a database! + Next steps ========== From 8ff027af776c2c5a5b8a238e562d2bf3dc8fd534 Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 16:03:39 -0500 Subject: [PATCH 086/100] one-line summary of tested code --- docs/tutorial/code/flask/app.py | 2 ++ docs/tutorial/code/flask/greeting_app.py | 2 ++ docs/tutorial/code/flask/greeting_charmcraft.yaml | 2 ++ docs/tutorial/code/flask/visitors_app.py | 2 ++ docs/tutorial/code/flask/visitors_charmcraft.yaml | 2 ++ docs/tutorial/code/flask/visitors_migrate.py | 2 ++ 6 files changed, 12 insertions(+) diff --git a/docs/tutorial/code/flask/app.py b/docs/tutorial/code/flask/app.py index 2ef2f596e..c2c4f114b 100644 --- a/docs/tutorial/code/flask/app.py +++ b/docs/tutorial/code/flask/app.py @@ -1,3 +1,5 @@ +# initial hello world Flask app + import flask app = flask.Flask(__name__) diff --git a/docs/tutorial/code/flask/greeting_app.py b/docs/tutorial/code/flask/greeting_app.py index dfa0a115d..9f659d835 100644 --- a/docs/tutorial/code/flask/greeting_app.py +++ b/docs/tutorial/code/flask/greeting_app.py @@ -1,3 +1,5 @@ +# Flask app with a greeting configuration + import flask app = flask.Flask(__name__) diff --git a/docs/tutorial/code/flask/greeting_charmcraft.yaml b/docs/tutorial/code/flask/greeting_charmcraft.yaml index 005c8d5da..bf837f42d 100644 --- a/docs/tutorial/code/flask/greeting_charmcraft.yaml +++ b/docs/tutorial/code/flask/greeting_charmcraft.yaml @@ -1,3 +1,5 @@ +# configuration snippet for Flask application with a configuration + config: options: greeting: diff --git a/docs/tutorial/code/flask/visitors_app.py b/docs/tutorial/code/flask/visitors_app.py index e4119c6b3..67e32ea8f 100644 --- a/docs/tutorial/code/flask/visitors_app.py +++ b/docs/tutorial/code/flask/visitors_app.py @@ -1,3 +1,5 @@ +# Flask application that keeps track of visitors using a database + import datetime import os diff --git a/docs/tutorial/code/flask/visitors_charmcraft.yaml b/docs/tutorial/code/flask/visitors_charmcraft.yaml index 239f014d8..757935d58 100644 --- a/docs/tutorial/code/flask/visitors_charmcraft.yaml +++ b/docs/tutorial/code/flask/visitors_charmcraft.yaml @@ -1,3 +1,5 @@ +# requires snippet for Flask application with a database + requires: postgresql: interface: postgresql_client diff --git a/docs/tutorial/code/flask/visitors_migrate.py b/docs/tutorial/code/flask/visitors_migrate.py index 2e303cea4..6ef58bece 100644 --- a/docs/tutorial/code/flask/visitors_migrate.py +++ b/docs/tutorial/code/flask/visitors_migrate.py @@ -1,3 +1,5 @@ +# Adds database to Flask application + import os import psycopg2 From 69887033a5019cda7145ecfdf3beba3a8daf58ac Mon Sep 17 00:00:00 2001 From: erinecon Date: Wed, 4 Dec 2024 16:09:56 -0500 Subject: [PATCH 087/100] remove trailing whitespace --- docs/tutorial/flask.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 5ebb62b60..861fcb74a 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -476,7 +476,7 @@ Deploy ``postgresql-k8s`` using Juju and integrate it with ``flask-hello-world`` Wait for ``juju status`` to show that the App is ``active`` again. Running ``curl http://flask-hello-world --resolve flask-hello-world:80:127.0.0.1`` -should still return the ``Hi!`` greeting. +should still return the ``Hi!`` greeting. To check the total visitors, use ``curl http://flask-hello-world/visitors --resolve flask-hello-world:80:127.0.0.1`` From 5a7e3730e381c561125a06e2be01f888a1221e47 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 6 Dec 2024 10:49:15 -0500 Subject: [PATCH 088/100] increase kill-timeout of Flask spread test --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index a9bf251f7..8b99f0d23 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -7,7 +7,7 @@ ########################################### summary: Getting started with Flask tutorial -kill-timeout: 150m +kill-timeout: 180m environment: From 5fced4465d1a1e6eb6b71d3e5308648e35836d59 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 6 Dec 2024 13:18:25 -0500 Subject: [PATCH 089/100] remove hint paragraph and move Matrix link to next steps --- docs/tutorial/flask.rst | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 861fcb74a..42c1d56cd 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -48,15 +48,6 @@ This tutorial should take 90 minutes for you to complete. - Integrate with a database - Clean up environment -.. hint:: - - Don't hesitate to get in touch on - `Matrix `_ or - `Discourse `_ (or follow the - "Edit this page on GitHub" on the bottom of - this document to comment directly on the document). - - Set things up ============= @@ -530,6 +521,8 @@ Next steps - `SDK How-to docs `_ * - "How do I debug?" - `Charm debugging tools `_ + * - "How do I get in touch?" + - `Matrix channel `_ * - "What is...?" - `SDK Reference docs `_ * - "Why...?", "So what?" From 2ac20397ae09f10fce1d6fdd04fbc9cfc3a1b2f8 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 6 Dec 2024 13:21:24 -0500 Subject: [PATCH 090/100] Add Multipass link to text and remove seealso box --- docs/reuse/tutorial/setup_stable.rst | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/reuse/tutorial/setup_stable.rst b/docs/reuse/tutorial/setup_stable.rst index 53c340cdc..7737854e9 100644 --- a/docs/reuse/tutorial/setup_stable.rst +++ b/docs/reuse/tutorial/setup_stable.rst @@ -1,9 +1,4 @@ -Install Multipass. - -.. seealso:: - - See more: `Multipass | How to install Multipass - `_ +First, `install Multipass `_. Use Multipass to launch an Ubuntu VM with the name ``charm-dev`` from the 24.04 blueprint: From eed3d4649e25331c5345fdee4ba464a7bd7d5494 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 6 Dec 2024 13:44:42 -0500 Subject: [PATCH 091/100] incorporate note about rock name/platform into text and intro --- docs/tutorial/flask.rst | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 42c1d56cd..61c64ce2c 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -41,8 +41,8 @@ This tutorial should take 90 minutes for you to complete. - Set things up - Create the Flask application - Run the Flask application locally -- Pack the Flask application into a rock -- Create the charm +- Pack the Flask application into a rock called ``flask-hello-world`` +- Create the charm called ``flask-hello-world`` - Deploy the Flask application and expose via ingress - Enable ``juju config flask-hello-world greeting=`` - Integrate with a database @@ -124,18 +124,22 @@ creation and tailoring for a Flask application by using the :dedent: 2 The ``rockcraft.yaml`` file will automatically be created and set the name -based on your working directory. Open the file in a text editor and check -that the ``name`` is ``flask-hello-world``. Ensure that ``platforms`` -includes the architecture of your host. For example, if your host uses the -ARM architecture, include ``arm64`` in ``platforms``. +based on your working directory. Choosing a different name or running on +a platform different from ``amd64`` will influence the names of the files +generated by Rockcraft. + +Open the file in a text editor and check that the ``name`` is +``flask-hello-world``. + +Ensure that ``platforms`` includes the architecture of your host. Check +the architecture of your system: + +.. code-block:: bash + + dpkg --print-architecture -.. note:: - For this tutorial, we'll use the ``name`` "flask-hello-world" and assume - you are on the ``amd64`` platform. Check the architecture of your system - using ``dpkg --print-architecture``. Choosing a different name or - running on a different platform will influence the names of the files - generated by Rockcraft. +If your host uses the ARM architecture, include ``arm64`` in ``platforms``. Now let's pack the rock: From cf7b85e552b118b10b4ac8d42d131b06ced51d9f Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 6 Dec 2024 13:50:54 -0500 Subject: [PATCH 092/100] remove note about rock name, version, arhictecture --- docs/tutorial/flask.rst | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 61c64ce2c..854eb37de 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -149,10 +149,8 @@ Now let's pack the rock: :end-before: [docs:pack-end] :dedent: 2 -.. note:: - - Depending on your system and network, this step can take a couple of - minutes to finish. +Depending on your system and network, this step can take a couple of +minutes to finish. Once Rockcraft has finished packing the Flask rock, you'll find a new file in your working directory with the ``.rock`` extension: @@ -163,12 +161,6 @@ in your working directory with the ``.rock`` extension: :end-before: [docs:ls-rock-end] :dedent: 2 -.. note:: - - If you changed the ``name`` or ``version`` in ``rockcraft.yaml`` or are - not on an ``amd64`` platform, the name of the ``.rock`` file will be - different for you. - The rock needs to be copied to the MicroK8s registry so that it can be deployed in the Kubernetes cluster: From a3b39a86074b26c57e6670516b8980da47262dc5 Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 6 Dec 2024 14:08:29 -0500 Subject: [PATCH 093/100] wrap visitors_app.py code in a collapse env --- docs/tutorial/flask.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 854eb37de..7723cdb99 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -423,8 +423,10 @@ to be updated to keep track of the number of visitors and to include a new endpoint to retrieve the number of visitors to the app. Open ``app.py`` in a text editor and replace its contents with the following code: -.. literalinclude:: code/flask/visitors_app.py - :language: python +.. collapse:: visitors_app.py + + .. literalinclude:: code/flask/visitors_app.py + :language: python Run ``rockcraft pack`` and upload the newly created rock to the MicroK8s registry: From 9b19465004159cf8facb70d55c544054a4c48fcd Mon Sep 17 00:00:00 2001 From: erinecon Date: Fri, 6 Dec 2024 14:23:37 -0500 Subject: [PATCH 094/100] remove note dressing for charm pack time warning --- docs/tutorial/flask.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 7723cdb99..13090feb0 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -205,10 +205,8 @@ Let's pack the charm: :end-before: [docs:charm-pack-end] :dedent: 2 -.. note:: - - Depending on your system and network, this step can take a couple - of minutes to finish. +Depending on your system and network, this step can take a couple +of minutes to finish. Once Charmcraft has finished packing the charm, you'll find a new file in your working directory with the ``.charm`` extension: From 2b7e3d6c35de1629bb5118e16ae368aac41c95c1 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 9 Dec 2024 14:45:17 -0500 Subject: [PATCH 095/100] change multipass VM to 40gb --- spread.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spread.yaml b/spread.yaml index fb902101a..400711b01 100644 --- a/spread.yaml +++ b/spread.yaml @@ -52,7 +52,7 @@ backends: system=$(echo "${SPREAD_SYSTEM}" | tr . -) instance_name="spread-${SPREAD_BACKEND}-${instance_num}-${system}" - multipass launch --cpus 4 --disk 50G --memory 4G --name "${instance_name}" "${multipass_image}" + multipass launch --cpus 4 --disk 40G --memory 4G --name "${instance_name}" "${multipass_image}" # Enable PasswordAuthentication for root over SSH. multipass exec "$instance_name" -- \ From 9ff279e3943fbdf50650fa2d951884f42e33749c Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 9 Dec 2024 14:48:15 -0500 Subject: [PATCH 096/100] update introduction section --- docs/tutorial/flask.rst | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 13090feb0..a1eccb232 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -4,30 +4,23 @@ Write your first Kubernetes charm for a Flask app Imagine you have a Flask application backed up by a database such as PostgreSQL and need to deploy it. In a traditional setup, -this can be quite a challenge, but with -`Juju `_ you’ll find yourself -deploying, configuring, scaling, integrating, monitoring, etc., -your Flask application in no time. Let’s get started! +this can be quite a challenge, but with Charmcraft you’ll find +yourself packaging and deploying your Flask application in no time. +Let’s get started! -In this tutorial we will build a rock and Kubernetes charm for a -Flask application using the charm SDK, so we can have a Flask -application up and running with Juju. +In this tutorial we will build a Kubernetes charm for a Flask +application using Charmcraft, so we can have a Flask application +up and running with Juju. -This tutorial should take 90 minutes for you to complete. +This tutorial should take 90 minutes for you to complete. .. note:: - - **rock**: An Ubuntu LTS-based OCI compatible - container image designed to meet security, stability, and - reliability requirements for cloud-native software. - - **charm**: A package consisting of YAML files + Python code that will - automate every aspect of an application's lifecycle so it can - be easily orchestrated with Juju. - - **Juju**: An orchestration engine for software - operators that enables the deployment, integration and lifecycle - management of applications using charms. + If you're new to the charming world: Flask applications are + specifically supported with a coordinated pair of profiles + for an OCI container image (**rock**) and corresponding + packaged software (**charm**) that allow for the application + to be deployed, integrated and operated on a Kubernetes + cluster with the Juju orchestration engine. **What you’ll need:** From 5c86b49c79f357e55446b401ca46a498fd1e2c1f Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 9 Dec 2024 14:52:05 -0500 Subject: [PATCH 097/100] specify channel of postgresql-k8s --- docs/tutorial/code/flask/task.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index 8b99f0d23..13c5504e1 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -189,7 +189,7 @@ execute: | # [docs:refresh-2nd-deployment-end] # [docs:deploy-postgres] - juju deploy postgresql-k8s --trust + juju deploy postgresql-k8s --channel=14/stable --trust juju integrate flask-hello-world postgresql-k8s # [docs:deploy-postgres-end] From 7f8cccc12fdc27974d8921bf09ce4a82474fce24 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 9 Dec 2024 14:55:34 -0500 Subject: [PATCH 098/100] remove trailing whitespace --- docs/tutorial/flask.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index a1eccb232..31f1b89c6 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -12,7 +12,7 @@ In this tutorial we will build a Kubernetes charm for a Flask application using Charmcraft, so we can have a Flask application up and running with Juju. -This tutorial should take 90 minutes for you to complete. +This tutorial should take 90 minutes for you to complete. .. note:: If you're new to the charming world: Flask applications are From 1bc48a297b0f910b19dbaa2b25de79daa3932250 Mon Sep 17 00:00:00 2001 From: erinecon Date: Mon, 9 Dec 2024 16:48:15 -0500 Subject: [PATCH 099/100] format intro section titles as headings --- docs/tutorial/flask.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 31f1b89c6..37bfcc6bc 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -22,14 +22,16 @@ This tutorial should take 90 minutes for you to complete. to be deployed, integrated and operated on a Kubernetes cluster with the Juju orchestration engine. -**What you’ll need:** +What you’ll need +================ - A workstation, e.g., a laptop, with amd64 or arm64 architecture which has sufficient resources to launch a virtual machine with 4 CPUs, 4 GB RAM, and a 50 GB disk - Familiarity with Linux -**What you’ll do:** +What you’ll do +============== - Set things up - Create the Flask application From 936fa63be9dc2f84547f61638bbb9ac5033c03b0 Mon Sep 17 00:00:00 2001 From: Erin Conley Date: Wed, 11 Dec 2024 13:45:57 -0500 Subject: [PATCH 100/100] Update spread.yaml Co-authored-by: Alex Lowe --- spread.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spread.yaml b/spread.yaml index 400711b01..2f53cace3 100644 --- a/spread.yaml +++ b/spread.yaml @@ -132,7 +132,8 @@ suites: docs/tutorial/code/: summary: tests tutorial from the docs systems: - - ubuntu-22.04-64 + - ubuntu-22.04-64 + manual: true tests/spread/commands/: summary: simple charmcraft commands tests/spread/charms/: