Skip to content

Commit

Permalink
Merge pull request fermyon#1264 from tpmccallum/componentize-py-docs
Browse files Browse the repository at this point in the history
Signed-off-by: tpmccallum <[email protected]>
  • Loading branch information
Timothy McCallum authored Apr 30, 2024
2 parents bf154ce + ee3a839 commit 16f670e
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 93 deletions.
93 changes: 82 additions & 11 deletions content/cloud/develop.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,13 +205,83 @@ $ spin plugins install js2wasm --yes

{{ startTab "Python" }}

You'll need the Spin `py2wasm` plugin:
> Historic: You may have seen a `py2wasm` plugin in your travels. Please note, `py2wasm` has since been replaced by `componentize-py`.
The process of getting your system ready to write Wasm-powered Python applications, using `componentize-py` is as follows:

<!-- @selectiveCpy -->

```bash
$ spin plugins update
$ spin plugins install py2wasm --yes
# As shown above, we install the Python SDK (which provides us with Spin's http-py template)
$ spin templates install --git https://github.com/fermyon/spin-python-sdk --update
```

Once we have the Spin template(s) from the `spin-python-sdk` repository we can scaffold out a new app. For this example, we will be using the `http-py` template. The scaffolded app, that the `http-py` template creates, has a `requirements.txt` file that facilitates the installation of `spin-sdk` and `componentize-py`. While you could manually install these using Pip, the `requirements.txt` file has the appropriate version numbers set making the process quicker and also more robust. Let's create a new Spin app and install the contents of `requirements.txt`:

<!-- @selectiveCpy -->

```bash
# We then create our app using http-py
$ spin new -t http-py hello-python --accept-defaults
```

Once the component is created, we can change into the `hello-python` directory, create and activate a virtual environment and then install the component's requirements:

<!-- @selectiveCpy -->

```bash
# Change into the app directory
$ cd hello-python
```

Create a virtual environment directory (we are still inside the Spin app directory):

<!-- @selectiveCpy -->

```console
# python<version> -m venv <virtual-environment-name>
$ python3 -m venv venv-dir
```

Activate the virtual environment (this command depends on which operating system you are using):

<!-- @selectiveCpy -->

```console
# macOS & Linux command to activate
$ source venv-dir/bin/activate
```

If you are using Windows, use the following commands:

```bash
C:\Work> python3 -m venv venv
C:\Work> venv\Scripts\activate
```

The `(venv-dir)` will prefix your terminal prompt now:

<!-- @nocpy -->

```console
(venv-dir) user@123-456-7-8 hello-python %
```

The `requirements.txt`, by default, contains the references to the `spin-sdk` and `componentize-py` packages. These can be installed in your virtual environment using the following command:

<!-- @selectiveCpy -->

```bash
# Now we can install Componentize-Py and the Spin SDK via the requirements file
$ pip3 install -r requirements.txt
```

From here the app is ready to build and run:

<!-- @selectiveCpy -->

```bash
$ spin build --up
```

[Learn more in the language guide.](/spin/python-components)
Expand Down Expand Up @@ -337,7 +407,7 @@ Use the `spin new` command and the `http-py` template to scaffold a new Spin app
$ spin new
Pick a template to start your application with:
> http-py (HTTP request handler using Python)
Enter a name for your new application: hello_python
Enter a name for your new application: hello-python
Description: My first Python Spin application
HTTP path: /...
```
Expand All @@ -352,7 +422,7 @@ spin_manifest_version = 2
[application]
authors = ["Your Name <[email protected]>"]
description = "My first Python Spin application"
name = "hello_python"
name = "hello-python"
version = "0.1.0"

[[trigger.http]]
Expand All @@ -362,8 +432,8 @@ component = "hello-python"
[component.hello-python]
source = "app.wasm"
[component.hello-python.build]
command = "spin py2wasm app -o app.wasm"
watch = ["app.py", "Pipfile"]
command = "componentize-py -w spin-http componentize app -o app.wasm"
watch = ["*.py", "requirements.txt"]
```

{{ blockEnd }}
Expand Down Expand Up @@ -492,15 +562,16 @@ If the build fails, check:

```bash
$ spin build
Building component hello-python with `spin py2wasm app -o app.wasm`
Spin-compatible module built successfully
Building component hello-python with `componentize-py -w spin-http componentize app -o app.wasm`
Component built successfully
Finished building all Spin components
```

If the build fails, check:

* Are you in the `hello_python` directory?
* Did you install the `py2wasm` plugin?
* Are you in the `hello-python` directory?
* Did you install the requirements?
* Is your virtual environment still activated?

{{ blockEnd }}

Expand Down
122 changes: 78 additions & 44 deletions content/cloud/variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ url = "https://github.com/fermyon/developer/blob/main/content/cloud/variables.md
---

- [Prerequisites](#prerequisites)
- [Creating Our Spin Application](#creating-our-spin-application)
- [Adding Variables to an Application Component](#adding-variables-to-an-application-component)
- [Using Variables in a Spin Application](#using-variables-in-a-spin-application)
- [Deploying the Application to Fermyon Cloud](#deploying-the-application-to-fermyon-cloud)
Expand All @@ -25,51 +24,73 @@ This tutorial will guide you through the process of creating a simple applicatio

Before starting, ensure that you have Spin v1.3.0 or greater installed on your computer. You can follow the official Fermyon Cloud Quickstart guide to [install Spin](/cloud/quickstart#install-spin) and [log into Fermyon Cloud](/cloud/quickstart#log-in-to-the-fermyon-cloud).

Since this example is written in Python, make sure you have the required tools installed to write Spin applications in Python. The Spin CLI facilitates the creation of new Spin applications using application [templates](/cloud/cli-reference#templates). In this tutorial, we will use the `http-py` template. Install it along with the `py2wasm` Spin plugin, which enables compiling Python apps to Wasm, using the following commands:
Since this example is written in Python, make sure you have the required tools installed to write Spin applications in Python. The Spin CLI facilitates the creation of new Spin applications using application [templates](/cloud/cli-reference#templates). In this tutorial, we will use the `http-py` template that provides a `requirements.txt` file to handle dependencies:

<!-- @selectiveCpy -->

```bash
$ spin templates install --git https://github.com/fermyon/spin-python-sdk --upgrade
$ spin plugins update
$ spin plugins install py2wasm --yes
# As shown above, we install the Python SDK (which provides us with Spin's http-py template)
$ spin templates install --git https://github.com/fermyon/spin-python-sdk --update
```

The output from the above commands should be similar to the following:
Once we have the Spin template(s) from the `spin-python-sdk` repository we can scaffold out a new app. For this example, we will be using the `http-py` template. The scaffolded app, that the `http-py` template creates, has a `requirements.txt` file that facilitates the installation of `spin-sdk` and `componentize-py`. While you could manually install these using Pip, the `requirements.txt` file has the appropriate version numbers set making the process quicker and also more robust. Let's create a new Spin app and install the contents of `requirements.txt`:

<!-- @nocpy -->
<!-- @selectiveCpy -->

```bash
# We then create our app using http-py
$ spin new -t http-py pw_checker --accept-defaults
```

Once the component is created, we can change into the `pw_checker` directory, create and activate a virtual environment and then install the component's requirements:

```text
Copying remote template source
Installing template http-py...
Installed 1 template(s)
<!-- @selectiveCpy -->

+---------------------------------------------+
| Name Description |
+=============================================+
| http-py HTTP request handler using Python |
+---------------------------------------------+
```bash
# Change into the app directory
$ cd pw_checker
```

Plugin 'py2wasm' was installed successfully!
Create a virtual environment directory (we are still inside the Spin app directory):

Description:
A plugin to convert Python applications to Spin compatible modules
<!-- @selectiveCpy -->

Homepage:
https://github.com/fermyon/spin-python-sdk
```console
# python<version> -m venv <virtual-environment-name>
$ python3 -m venv venv-dir
```

## Creating Our Spin Application
Activate the virtual environment (this command depends on which operating system you are using):

<!-- @selectiveCpy -->

```console
# macOS & Linux command to activate
$ source venv-dir/bin/activate
```

Let's start by [creating a new Spin application](/cloud/cli-reference#new) using the Python template. Follow the steps below:
If you are using Windows, use the following commands:

```bash
C:\Work> python3 -m venv venv
C:\Work> venv\Scripts\activate
```

The `(venv-dir)` will prefix your terminal prompt now:

<!-- @nocpy -->

```console
(venv-dir) user@123-456-7-8 pw_checker %
```

The `requirements.txt`, by default, contains the references to the `spin-sdk` and `componentize-py` packages. These can be installed in your virtual environment using the following command:

<!-- @selectiveCpy -->

```bash
$ spin new -t http-py
Enter a name for your new application: pw_checker
Description: A Spin app that validates a password
HTTP path: /...
# Now we can install Componentize-Py and the Spin SDK via the requirements file
$ pip3 install -r requirements.txt
```

## Adding Variables to an Application Component
Expand All @@ -81,19 +102,28 @@ In reality, you'd have multiple usernames and password hashes in a database, but
<!-- @nocpy -->

```toml
# Add this above the [component.pw-checker] section
# Add the [variables] above the [component.pw-checker] section, as shown below

[variables]
secret = { required = true }

[component.pw-checker]
source = "app.wasm"
```

To surface the variable to the `pw-checker` component, add a `[component.pw-checker.variables]` section in the component and specify the variable within it. Instead of statically assigning the value of the config variable, we are referencing the dynamic variable with [mustache](https://mustache.github.io/)-inspired string templates. Only components that explicitly use the variables in their configuration section will get access to them. This enables only exposing variables and secrets to the desired components of an application:

<!-- @nocpy -->

```toml
# Add this below the [component.pw-checker.build] section
# Add the [component.pw-checker.variables] below the [component.pw-checker.build] section, as shown below

[component.pw-checker.build]
command = "componentize-py -w spin-http componentize app -o app.wasm"
watch = ["*.py", "requirements.txt"]

[component.pw-checker.variables]
password = "\{{ secret }}"
password = "{{ secret }}"
```

The resulting application manifest should look similar to the following:
Expand Down Expand Up @@ -125,27 +155,31 @@ command = "cargo build --target wasm32-wasi --release"
watch = ["src/**/*.rs", "Cargo.toml"]

[component.pw-checker.variables]
password = "\{{ secret }}"
password = "{{ secret }}"
```

## Using Variables in a Spin Application

Now that we have defined our variables and surfaced them to our component, we are ready to implement our Spin application. The application should get the user-provided password from the body of the HTTP request, compare it to the expected password set in our configuration variable, and authenticate accordingly. We will use the Spin `spin_config` module to retrieve the value of the `password` variable:

<!-- @selectiveCpy -->

```py
from spin_http import Response
from spin_config import config_get

def handle_request(request):
password = request.body.decode("utf-8")
expected = config_get("password")
access = "denied"
if expected == password:
access = "accepted"
response = f'\{{"authentication": "{access}"}}'
return Response(200,
{"content-type": "application/json"},
bytes(response, "utf-8"))
from spin_sdk.http import IncomingHandler, Request, Response
from spin_sdk.variables import get

class IncomingHandler(IncomingHandler):
def handle_request(self, request: Request) -> Response:
password = request.body.decode("utf-8")
expected = get("password")
access = "denied"
if expected == password:
access = "accepted"
response = f'\{{"authentication": "{access}"}}'
return Response(
200,
{"content-type": "application/json"},
bytes(response, "utf-8"))
```

Build and run the application locally to test it out. We will use the [environment variable provider](/spin/dynamic-configuration.md#environment-variable-provider) to set the variable values locally. The provider gets the variable values from the `spin` process's environment, searching for environment variables prefixed with `SPIN_VARIABLE_`:
Expand Down
6 changes: 1 addition & 5 deletions content/spin/v2/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,11 +286,7 @@ Then install plugins by name.

Python:

<!-- @selectiveCpy -->

```bash
$ spin plugins install py2wasm --yes
```
> Historic: You may have seen a `py2wasm` plugin in your travels. Please note, that `py2wasm` has since been replaced by `componentize-py`. You no longer need to install additional tools as part of Spin installation. (Refer to [Building Spin Components in Python](./python-components.md#componentize-py) for the new way of building Python applications.)
Javascript:

Expand Down
1 change: 0 additions & 1 deletion content/spin/v2/managing-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ $ spin plugins search
befunge2wasm 1.4.0 [incompatible]
js2wasm 0.3.0 [installed]
js2wasm 0.4.0
py2wasm 0.1.0 [installed]
trigger-sqs 0.1.0
```

Expand Down
12 changes: 9 additions & 3 deletions content/spin/v2/python-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ Activate the virtual environment (this command depends on which operating system
$ source venv-dir/bin/activate
```

If you are using Windows, use the following commands:

```bash
C:\Work> python3 -m venv venv
C:\Work> venv\Scripts\activate
```

The `(venv-dir)` will prefix your terminal prompt now:

<!-- @nocpy -->
Expand Down Expand Up @@ -198,8 +205,6 @@ The important things to note in the implementation above:
- the `handle_request` method is the entry point for the Spin component.
- the component returns a `spin_sdk.http.Response`.

The source code for this Python HTTP component example is in the `app.py` file. The `app.py` file is compiled into a `.wasm` module thanks to the `py2wasm` plugin. This all happens behind the scenes.

### Building and Running the Application

All you need to do is run the `spin build` command from within the project's directory; as shown below:
Expand Down Expand Up @@ -365,7 +370,8 @@ component = "hello-world"
source = "app.wasm"
allowed_outbound_hosts = ["https://random-data-api.fermyon.app"]
[component.hello-world.build]
command = "spin py2wasm app -o app.wasm"
command = "componentize-py -w spin-http componentize app -o app.wasm"
watch = ["*.py", "requirements.txt"]
```

### Building and Running the Application
Expand Down
Loading

0 comments on commit 16f670e

Please sign in to comment.