Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What this repository is

A curated collection of example Fission functions and applications, organized by language and use case.
This is **not** an application codebase with a build/test pipeline — it is a catalog of standalone samples meant to be deployed onto a Fission/Kubernetes cluster.
Each example is self-contained and demonstrates one concept (a language runtime, a trigger type, a deployment strategy, an integration, etc.).

Most "commands" in this repo are `fission` CLI invocations that target a live cluster, not local build/test commands.
You generally cannot run these examples without a Kubernetes cluster with Fission installed.

## Layout

Top-level directories are language buckets (`python/`, `python-fastapi/`, `go/`, `nodejs/`, `java/`, `dotnet/`, `dotnet8/`, `ruby/`, `perl/`, `php7/`, `rust/`) plus `miscellaneous/` for cross-cutting use cases (message-queue triggers, specs, containers, observability, websockets, long-running functions, etc.).

## The two ways a function gets deployed

Every example follows one of these patterns. Recognize which one before editing.

1. **Single-file / inline** — deploy the source directly with the CLI:
```
fission environment create --name python --image ghcr.io/fission/python-env
fission function create --name hello-py --env python --code hello.py
fission function test --name hello-py
```

2. **Spec-based** — a `specs/` directory deployed atomically with `fission spec apply --wait`.
Spec dirs always contain `fission-deployment-config.yaml` (holds a generated `uid` — **never edit the uid**, it breaks `spec apply`), an `env-*.yaml` (`kind: Environment`), and `function-*.yaml` (`kind: Function`).
Builder-based languages add a `package-*.yaml` (`kind: Package` + `ArchiveUploadSpec`).
These YAMLs are generated by `fission spec init` / `fission spec apply`; preserve their structure and `apiVersion: fission.io/v1`.

## Function entrypoint conventions (differ per language)

When adding or fixing a function, match the runtime's expected signature:

- **Python** — module-level `def main():` (Flask `request`/`current_app` available via import).
- **Node.js** — `module.exports = async function(context) { return { status, body } }`.
- **Go** — `func Handler(w http.ResponseWriter, r *http.Request)`, `package main`. Deployed with `--entrypoint Handler`.
- **Ruby** — top-level `def handler`.
- **Java** — class implementing the Fission `Function` interface (e.g. `io.fission.HelloWorld`); function name in the spec is the FQCN.
- **.NET (legacy `dotnet/`)** — single `.cs` file; the function body is the file.
- **.NET 8 (`dotnet8/`)** — class with `public object Execute(FissionContext context)`; entrypoint is the FQ `Namespace.Class` (built via `--buildcmd /usr/local/bin/build`).
- **PHP** — plain script; `$logger` is injected.
- **Rust** — single-file mode: `pub async fn handler` with any axum handler signature. Cargo-project mode: a binary crate that serves HTTP on `127.0.0.1:$FISSION_RUNTIME_PORT` (any framework works).

## Builder vs. runtime environments

Interpreted single-file examples use the runtime image only.
Examples with dependencies (Go modules, Java/Maven, Python `requirements.txt`) need a **builder** environment and a `build.sh`.
`build.sh` runs inside the builder container and uses `${SRC_PKG}` (input) and `${DEPLOY_PKG}` (output) env vars — e.g. install deps into `${SRC_PKG}`, then `cp -r ${SRC_PKG} ${DEPLOY_PKG}`.
Java's `build.sh` instead shells out to a Maven Docker image so no local JDK is needed.

## Catalog metadata

Each language dir has an `examples.json` (flat entries: `name`/`description`/`path`/`tag`/`language`); the ones under `miscellaneous/` (including `message-queue-trigger/` and `spec-example/`) feed the "Misc" group.
These files are the source of truth for the examples catalog rendered at `fission.io/examples`.
**When you add a new example, add a corresponding entry** so it shows up.

The catalog UI lives in the [fission/fission.io](https://github.com/fission/fission.io) repo, not here.
Its `tools/examples.py` reads these per-language files, groups them by language, adds logos/group tags, and regenerates `static/data/examples.json` (a different, grouped schema using `link`/`tags`).
After editing an `examples.json` here, that script must be re-run in the fission.io repo to refresh the site.

## Conventions

- Each example directory should have its own `README.md` showing the exact `fission ...` deploy/test commands for that sample — keep this when editing.
- Markdown: one sentence per line within paragraphs.
- `target/` (Java build output) and `node_modules/` are committed in some examples but are generally build artifacts; do not regenerate or hand-edit them.
36 changes: 27 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,65 @@
# Fission Examples & Samples

A place for examples of Fission functions from community and Fission team. These are sample codes and application that will help you understand Fission better. You can use these as stepping stone to build your real world use cases on Fission.
A place for examples of Fission functions from the community and the Fission team.
These are sample codes and applications that will help you understand Fission better.
Use them as a stepping stone to build your real-world use cases on Fission.

Currently, the examples in this repo are categorised based on the languages as mentioned below:
You can also browse these examples in the searchable catalog at [fission.io/examples](https://fission.io/examples).

The examples in this repo are categorised by language as listed below.
Each directory has its own `README.md` with the exact `fission` commands to deploy and test that example.

- [.NET](https://github.com/fission/examples/tree/main/dotnet)
- [.NET 8](https://github.com/fission/examples/tree/main/dotnet8)
- [Go](https://github.com/fission/examples/tree/main/go)
- [Java](https://github.com/fission/examples/tree/main/java)
- [NodeJS](https://github.com/fission/examples/tree/main/nodejs)
- [Perl](https://github.com/fission/examples/tree/main/perl)
- [Python](https://github.com/fission/examples/tree/main/python)
- [Python (FastAPI)](https://github.com/fission/examples/tree/main/python-fastapi)
- [PHP](https://github.com/fission/examples/tree/main/php7)
- [Ruby](https://github.com/fission/examples/tree/main/ruby)
- [Rust](https://github.com/fission/examples/tree/main/rust)
- [Miscellaneous](https://github.com/fission/examples/tree/main/miscellaneous)

There are other examples with respect to different use cases that are present under the `Miscellaneous` folder. You can find examples related to message triggers, specifications, using Fission for testing and much more.
The `Miscellaneous` folder holds examples for different use cases such as message-queue triggers, specs, container functions, observability, websockets, long-running functions, and more.

## Getting Started

The easiest way to getting started with Fission is shown below. This one is using Python, however, you can refer to the examples present for other langugages as well.
The easiest way to get started with Fission is shown below.
This uses Python; you can refer to the examples for other languages as well.

Create a Fission Python environment with the default Python runtime image (this does not include the build environment):

```
fission environment create --name python --image fission/python-env
fission environment create --name python --image ghcr.io/fission/python-env
```

Use the `hello.py` to create a Fission Python function:
Use `python/hello.py` to create a Fission Python function:

```
fission function create --name hello-py --env python --code hello.py
fission function create --name hello-py --env python --code python/hello.py
```

Test the function:

```
fission function test --name hello-py
```

For a full guide see the official documentation on [Python with Fission](https://fission.io/docs/usage/languages/python/).

## Contributing an example

Add your function under the relevant language directory with a short `README.md` showing how to deploy and test it.
To make it appear in the [catalog](https://fission.io/examples), add an entry to that directory's `examples.json` (fields: `name`, `description`, `path`, `tag`, `language`).
The catalog page is generated from these files in the [fission.io](https://github.com/fission/fission.io) repo, so no UI changes are needed here.

## Documentation

If you are new to Fission and want to know how it works, features and everything else, refer to the [Fission Documents](https://fission.io/docs/)
If you are new to Fission and want to know how it works, its features, and everything else, refer to the [Fission documentation](https://fission.io/docs/).

## Fission Blog

We are always working on getting new examples and use cases using Fission for you. For the latest updates on what's goind on with Fission, check out our [Fission Blog](https://fission.io/blog/).
We are always working on new examples and use cases for Fission.
For the latest updates on what's going on with Fission, check out the [Fission Blog](https://fission.io/blog/).
2 changes: 1 addition & 1 deletion dotnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This is the repository for all .NET sample codes for Fission.
Create a Fission .NET environment with the default .NET runtime image (this does not include the build environment):

```
fission env create --name dotnet --image fission/dotnet-env
fission env create --name dotnet --image ghcr.io/fission/dotnet-env
```

Use the `hello.cs` to create a Fission C# function:
Expand Down
14 changes: 14 additions & 0 deletions dotnet8/AsyncFunctionExample/AsyncFunctionExample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<Reference Include="Fission.DotNet.Common">
<HintPath>./Fission.DotNet.Common.dll</HintPath>
</Reference>
</ItemGroup>

</Project>
17 changes: 17 additions & 0 deletions dotnet8/AsyncFunctionExample/MyFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Fission.DotNet.Common;
using System.Threading.Tasks;

public class MyFunction
{
public object Execute(FissionContext context)
{
// Call the async method and wait for it to complete
return ExecuteAsync(context).GetAwaiter().GetResult();
}

public async Task<object> ExecuteAsync(FissionContext context)
{
await Task.Delay(1000); // Simulate an asynchronous operation
return "Hello from async function!";
}
}
11 changes: 11 additions & 0 deletions dotnet8/HelloWorld/HelloWorld.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="Fission.DotNet.Common">
<HintPath>./Fission.DotNet.Common.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
9 changes: 9 additions & 0 deletions dotnet8/HelloWorld/MyFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Fission.DotNet.Common;

public class MyFunction
{
public object Execute(FissionContext context)
{
return "Hello World!x";
}
}
11 changes: 11 additions & 0 deletions dotnet8/HttpTriggerExample/HttpTriggerExample.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net8.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Reference Include="Fission.DotNet.Common">
<HintPath>./Fission.DotNet.Common.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
14 changes: 14 additions & 0 deletions dotnet8/HttpTriggerExample/MyFunction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using Fission.DotNet.Common;

public class MyFunction
{
public object Execute(FissionContext context)
{
var httpContext = context as FissionHttpContext;
if (httpContext != null)
{
return $"Hello from HTTP trigger! Method: {httpContext.Method}, URL: {httpContext.Url}";
}
return "Hello from non-HTTP trigger!";
}
}
129 changes: 129 additions & 0 deletions dotnet8/MultiFileExample/Controllers/ApiController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using System;
using System.Threading.Tasks;
using MultiFileExample.Services;
using MultiFileExample.Models;
using Fission.DotNet.Common;

namespace MultiFileExample.Controllers
{
public class ApiController
{
private readonly WeatherService _weatherService;
private readonly UserService _userService;
private readonly DataProcessor _dataProcessor;

public ApiController()
{
// In production, use dependency injection
_weatherService = new WeatherService();
_userService = new UserService();
_dataProcessor = new DataProcessor();
}

public async Task<object> RouteRequest(FissionContext context)
{
var path = ExtractPath(context);
var method = ExtractMethod(context);

// Route to appropriate handler based on path
return path.ToLower() switch
{
"" or "multifile" => GetApiInfo(),
"weather" => await _weatherService.GetWeatherAsync(),
"weather/forecast" => await _weatherService.GetForecastAsync(),
"users" => _userService.GetAllUsers(),
"users/active" => _userService.GetActiveUsers(),
"process" => _dataProcessor.ProcessData(new DataRequest { Input = "test-data" }),
"health" => GetHealthStatus(),
_ => GetNotFoundResponse(path)
};
}

private string ExtractPath(FissionContext context)
{
// Try to get path from HTTP context
if (context is FissionHttpContext httpContext)
{
return httpContext.Url?.TrimStart('/') ?? "";
}

// Fallback to subpath argument for testing
if (context?.Arguments?.ContainsKey("subpath") == true)
{
return context.Arguments["subpath"]?.ToString() ?? "";
}

return "";
}

private string ExtractMethod(FissionContext context)
{
if (context is FissionHttpContext httpContext)
{
return httpContext.Method?.ToUpper() ?? "GET";
}
return "GET";
}

private object GetApiInfo()
{
return new
{
name = "Multi-File Example API",
description = "MVC-pattern Fission function with controller-based routing",
version = "2.0.0",
architecture = new
{
pattern = "MVC",
entryPoint = "MyFunction.cs",
controller = "ApiController.cs",
services = new[] { "WeatherService.cs", "UserService.cs", "DataProcessor.cs" },
models = new[] { "User.cs", "Weather.cs", "DataModels.cs" }
},
endpoints = GetAvailableEndpoints()
};
}

private object GetHealthStatus()
{
return new
{
status = "healthy",
service = "MultiFileExample",
version = "2.0.0",
timestamp = DateTime.UtcNow,
components = new
{
weatherService = "operational",
userService = "operational",
dataProcessor = "operational"
}
};
}

private object GetNotFoundResponse(string path)
{
return new
{
error = "Endpoint not found",
path = path,
statusCode = 404,
availableEndpoints = GetAvailableEndpoints()
};
}

private string[] GetAvailableEndpoints()
{
return new[]
{
"/ - API information",
"/weather - Current weather",
"/weather/forecast - 5-day forecast",
"/users - List all users",
"/users/active - List active users",
"/process - Data processing demo",
"/health - Health check"
};
}
}
}
Loading