Skip to main content

Tutorial Using a Sample Online Boutique App

Overview

In this tutorial you'll experience the basic usage of Raftt operating in connect mode - adding development capabilities to an existing env deployed to a Kubernetes namespace.
If you wish to try Raftt operating in orchestration mode - the mode in which Raftt is also responsible for spawning and managing dev envs, see our orchestration mode tutorial.

This tutorial includes the following steps -

  1. Spawn the Online Boutique demo project - the project used for this tutorial
  2. Add Raftt to the env to enable an excellent developer experience (DevX)
  3. Experience the DevX first-hand by changing the project's code - fixing a backend bug and modifying the UX
  4. Interactively debug the project
  5. Onboard an additional workload to Raftt to allow developing it easily and efficiently

The Project

We forked Online Boutique, a sample microservices application (originally created by Google), as a sample project to help you onboard Raftt quickly, without using your code.

The project includes microservices written in a variety of languages, but familiarity with these languages isn't necessary to complete the tutorial.

Online Boutique

Prerequisites

This tutorial demonstrates Raftt's ability to enhance the development experience of existing K8s envs. It means that you need a K8s cluster (local or remote) on which you can deploy the demo environment using helm charts. You also need kubectl and helm installed locally (see here and here for installation guides).
If you don't have a cluster but want to try this tutorial, you can use tools like minikube to create a local Kubernetes cluster.

Install Raftt

Use Homebrew or cURL to install Raftt CLI on macOS.

brew install rafttio/tap/raftt  

Or

curl -fsSL get.raftt.io/install | bash
Validate

To verify the installation was successful, run raftt version in your shell.

Deploying the Project

In this section, we'll deploy the Online Boutique app to your cluster. Take the following steps -

  1. Make sure that your Kubernetes context is correct
kubectl config get-contexts
  1. Clone the Online Boutique repo
git clone https://github.com/rafttio/online-boutique
  1. cd into the repo's folder -
cd online-boutique
  1. Create a namespace called demo and deploy the app in it -
helm install -n demo --create-namespace demo ./helm-chart
  1. See all pods were started successfully -
kubectl get pods -n demo
  1. After connecting Raftt to the env in the next section, you'll be able to access the application from your browser.

Development Mode

Now we're getting to the interesting part - adding advanced dev capabilities to the existing env, using Raftt. To do it, perform the following actions -

  1. Add Raftt to the environment by running raftt connect demo
    1. You will be prompted to log in to Raftt using one of several third-party services (Google, GitHub, etc.).
    2. Once completed, you can see a list of all the namespace workloads.
raftt connect demo
  1. Convert some of the workloads into dev-mode - raftt dev frontend recommendations. It will allow you to experience the DevX provided by Raftt in the following tutorial sections.
raftt dev frontend recommendations
  1. Run raftt status to see they are marked as in "dev-mode" and the list of mapped ports.
raftt status

`raftt status` output

  1. As seen in the command output, the open port of the frontend container is mapped to the local port 8888. Let's see what happens when you browse it.

Under the Hood

If you're interested in the inner workings of Raftt, this section explains what happened internally when running the raftt connect and raftt dev commands. You can jump to the next section, if you just want to continue with the tutorial.

When you ran raftt connect, you started a sequence of events -

  1. Raftt's env controller is added to your namespace (a workload named sandcastle).
  2. Your repo is mirrored to the cluster and live syncing is started.
  3. You can start using raftt sh and raftt logs commands to inspect all your workloads.

After connecting to the env, you got the frontend and recommendations deployments into dev-mode, using raftt dev frontend recommendations. This triggered the following actions -

  1. The dev-mode definitions of the frontend and recommendations workloads are read from the .raftt file (found here).
  2. The existing frontend and recommendations deployments are taken down (scaled down to 0 replicas in case of deployments) and new deployments are spawned.
  3. The new deployments differ from the old ones in the following characteristics -
    1. Their name has the suffix -raftt. This is only true for deployments and replica sets. All other resource kinds are replaced if they enter dev-mode.
    2. The lifecycle of the container is split from the lifecycle of its main process. You can restart the process without respawning the container, and the main process crashing doesn't result in the termination of the container, allowing much better inspection. See here for more information.
    3. All changes defined in the .raftt file for the specified resources are applied. In this case, the changes are -
      1. Code is now continuously synced to the container, allowing you to write code in your favorite local IDE and see the changes affect the cluster (lines 8 and 13).
      2. A port is mapped locally from the frontend container (line 9).
    4. You can now run all raftt commands that are relevant to workloads, e.g., restart and rebuild.
  4. All the rest of the namespace resources (those not specified in the dev/rebuild command) remain unchanged.

Let's Develop!

Since your env is up and you got some workloads into dev-mode you can play around with the code and see how your changes affect the app!

Change the page title

We'll start with an easy to do and easy to see change - change the title.
Let's say you want to bring some honesty into your marketing, and admit that the products you present on the frontpage aren't actually hot, they are the entire catalog. To do that, you need to change the string inside the h3 tag in home.html line 36 to "All Products".

<h3>All Products</h3>

To see this change taking effect, run raftt restart frontend to restart the workload's main process.

raftt restart frontend

Fix the recommendations engine

If you click any of the products, you'll see the recommendation engine is broken - it always shows the same product. This must be solved so you can push people to spend more in your boutique!
To solve this we need to modify the code of the recommendation engine workload. On line 78, you can see that it doesn't iterate properly over the filtered_products list - try replacing filtered_products[0] with filtered_products[i].

prod_list = [filtered_products[i] for i in indices]

After fixing the bug you need to run raftt restart recommendations to restart the workload's main process.

raftt restart recommendations

Note the fast cycle time - with Raftt it only takes seconds from code change to seeing it in the env - no need to rebuild and redeploy images, which takes from minutes to over an hour in some cases.

Debugging the Workloads

Once a workload is in dev-mode, you can debug it using Visual Studio Code or any JetBrains IDE. For details on how to configure debug configuration see the debugging docs section. For this tutorial we already have the debug configurations committed to the repo, so you don't need to configure anything.

To debug the application, follow these steps -

  1. Open the project in the IDE.
  2. Install Raftt's plugin from the marketplace (JetBrains, VS Code)
  3. Add a breakpoint inside the function ListRecommendations in the file recommendation_server.py.
  4. Start debugging using the debug configuration recommendations.
    1. JetBrains IDEs may ask you to configure a Python interpreter. You can ignore the request or choose any interpreter of your choice. It doesn't affect the remote environment that uses its own interpreter.
  5. Click one of the products to get to its page.
  6. Success! - it stopped where you added the breakpoint.
  7. Debug the remote service as if it were local.

Raftt currently supports interactively debugging Python, Go, Node.js and Java code using Visual Studio Code or any JetBrains IDE. Join our Slack community or contact us to let us know need support for other languages, adding such support is very fast.

Configure Additional Workloads

The Online Boutique repo comes pre-configured for developing the frontend and recommendations workloads using Raftt. Now let's add the configuration for the email service. To enjoy the dev capabilities provided by Raftt, you need to add a few definitions for the email service in the env definition file.

The .raftt File - the Env Configuration File

A .raftt file is a file in which your Raftt environment is defined. It is written in Starlark - a Python-like scripting language. It usually starts with importing the resources definitions. In connect mode the definitions are usually loaded using the namespace_resources function, but there are other ways to load them. Once imported (to a Resources object), the definitions can be modified and enhanced. For the modification to take effect you need to use the deploy() function with the relevant resource/s as an argument. In this tutorial's case, we already have the calls to namespace_resources and deploy() in place, so you just need to get the handle to the relevant resource, and call the relevant functions between these two calls.
On every call to raftt dev RESOURCE (and every following call to raftt rebuild RESOURCE) the .raftt file is interpreted and the currently running instance of RESOURCE is replaced by the one defined in the .raftt file. All other resources remain unchanged.

Mount the Source Code

Mounting your code to the container allows you to enjoy hot-reloading of files into the container which enables a much shorter dev cycle. Depending on the language and framework used, it will require something between refreshing a page to building and restarting the main process. In any case it's much faster than rebuilding the whole container, which is rarely required when using Raftt.

To sync a local folder to the container, you can use the repo_volume() and mount() functions (see here for more details).
To understand what is the exact folder that needs to be mounted, you can refer to the Dockerfile of the email service.
As you can see in lines 40 and 49, the entry point is email_server.py and it runs from the workdir which is /email-server. It is copied to the image from the context of the Dockerfile execution (line 46). It means that the context of the Dockerfile - src/emailservice needs to be mapped to the workload's workdir - /email_service. In the syntax of the .raftt file, it will look like this (using the repo_root variable that was already assigned in the first line of env.raftt) -

email = resources.deployments["email"]
email.mount(repo_root.subpath("src/emailservice"), "/email_server")

To get email into dev-mode and apply these changes, run

raftt dev email

Add an Annotation

You can change many of the workload attributes using the .raftt file. You can find a list of all modifiable attributes in our docs. In this example we'll add an annotation using the following line of code -

email.metadata.annotations["raftt"] = "In dev-mode!!!"

Apply this change using

raftt rebuild email

Or if it's not yet in dev-mode, use

raftt dev email

You can verify it worked by reading the deployment annotation by running

kubectl -n demo get deploy email-raftt -o jsonpath='{.metadata.annotations.raftt}'

The expected output is -

Verify annotation added

Monitor Dependency Changes

If you wish to add a new dependency to your Python code, you change the requirements.txt and then run pip install -r requirements.txt inside the workload. Raftt could monitor the file and run it automatically every time you change it, using Raftt's file watching mechanism. This can be done by adding the following snippet to env.raftt -

register_hook(
on=events.OnFileChanged(
workload=email,
patterns="/email_server/requirements.txt"
),
do=actions.CMD(
workload=email,
cmd=["pip", "install", "-r", "requirements.txt"]
)
)

Apply this change using

raftt rebuild email

After applying this change, modify the requirements.txt file of the email service and check out the hook logs using

raftt logs --hooks

Additional Capabilities

You can do many other things in your .raftt file that are beyond what we can demonstrate in a short tutorial. You can find the full documentation of the .raftt file in our docs, to which we already referred many times on this tutorial.

Try It With Your Project

After seeing how easy it is to work with Raftt, you're welcome to use raftt on any project of yours - open source or private.
We'd love to hear about your experience in our Slack community or by contacting us directly.