Skip to content

Commit

Permalink
Merge branch 'main' into feat/cognito-auth-service
Browse files Browse the repository at this point in the history
  • Loading branch information
bramelfrink committed Oct 9, 2024
2 parents b8d2432 + 8cac4b7 commit 8cef40e
Show file tree
Hide file tree
Showing 37 changed files with 691 additions and 66 deletions.
2 changes: 1 addition & 1 deletion .test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
set -euo pipefail

python -m mypy ./src
python -m pyright .
python -m mypy ./tests
python -m pytest -vv
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## v0.5.0 (2024-10-07)

### Feat

- **core**: add environment and execution mode property to base controller
- **llm**: add llm base controller and aws controller
- **vllm**: saving endpoint base url in parameter store

### Fix

- **llm**: move the cloud agnostic methods of the controller to the base
- **core**: broken import after clean up __init__ files
- **llm, example**: pulumi only works with `__main__.py` file name
- **core**: init all controllers when using `from damavand...controllers`
- **vllm**: make api route open ai compatible

## v0.4.1 (2024-10-03)

### Refactor
Expand Down
95 changes: 93 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,93 @@
# damavand
## Introduction
# Damavand

<p align="center">
<img src="docs/assets/damavand-logo-inverted.png" width="100" height="100""/>
</p>

## What is Damavand?
Damavand is a comprehensive cloud-native application development framework designed to go beyond traditional Infrastructure as Code (IaC). It simplifies both application logic and cloud infrastructure management, providing developers with a unified, Pythonic approach to building, deploying, and scaling cloud-native applications. Damavand implements the ARC (Application, Resource, Controller) design pattern, ensuring that your cloud resources and application logic work seamlessly together without the complexity of deeply understanding cloud provider-specific details.

With Damavand, your focus remains on writing business logic while the framework handles cloud architecture, leveraging Pulumi to generate cloud infrastructure code for multi-cloud environments.

## Why Damavand?
Damavand is built for developers who want to focus on writing applications, not spending countless hours configuring and managing infrastructure. Here’s why Damavand stands out:

- **Unified Application and Infrastructure:** Develop both cloud resources and business applications in a unified codebase with a clean, logical structure.
- **ARC Design Pattern:** Follow the proven Application, Resource, and Controller pattern to keep code organized, scalable, and maintainable.
- **Best Practices and Flexibility:** Offers optimized architecture designs while allowing developers to customize each part of the framework when needed.
- **Vendor Independence:** Support for multiple cloud providers, avoiding vendor lock-in and giving you the freedom to deploy anywhere.
- **Rapid Time-to-Market:** Dramatically shortens the time it takes to build and deploy cloud-native applications through pre-architected, cloud-agnostic templates and patterns.

## How Damavand Works

Damavand empowers developers to handle both the application layer and resource layer within one framework. By following the ARC design pattern, it decouples business logic from cloud complexities, enabling easy customization and scalability across different cloud providers.

### Example

> [!TIP]
> Checkout the [examples](examples) directory for more examples.
Here's an example using Damavand to create an Spark application on AWS (used AWS Glue for compute infrastructure):

```python
import os
from damavand.cloud.provider import AwsProvider
from damavand.factories import SparkControllerFactory

from applications.orders import CustomerOrders
from applications.products import Products


def main() -> None:
spark_factory = SparkControllerFactory(
provider=AwsProvider(
app_name="my-app",
region="us-west-2",
),
tags={"env": "dev"},
)

spark_controller = spark_factory.new(
name="my-spark",
applications=[
Products(),
CustomerOrders(),
],
)

app_name = os.getenv("APP_NAME", "default_app") # Get app name on runtime

spark_controller.provision()
spark_controller.run_application(app_name)


if __name__ == "__main__":
main()
```

## Key Features
- **ARC Design Pattern:** Implements the Application, Resource, and Controller layers to streamline the development process.
- **Pulumi-Powered IaC:** Uses Pulumi to manage cloud infrastructure resources in a cloud-agnostic way, reducing complexity.
- **Multi-Cloud Support:** Enables you to build applications that can run on AWS, Azure, and more, avoiding vendor lock-in.
- **Pythonic Flexibility:** Written natively in Python, Damavand allows you to easily modify and extend the framework to meet your application's needs.
- **No Extra Dependencies:** Requires only the Pulumi CLI for cloud infrastructure management—no unnecessary dependencies.

## What is Damavand Useful For?

Damavand is perfect for:

- **Startups:** Accelerate the development and deployment of cloud-native applications.
- **Enterprises:** Ensure scalability, maintainability, and flexibility in cloud applications.
- **Developers:** Damavand allows you to focus on your expertise—whether it's backend development, data engineering, or another area—without worrying about the complexities of cloud architecture. For advanced users, it provides rich layers of customization to push the boundaries of optimizing solutions for specific cloud providers.

## What Damavand is Not

Damavand is not just an Infrastructure as Code (IaC) tool. It is not meant to be a full-fledged cloud platform, but rather a framework that integrates both application development and cloud infrastructure in a seamless, unified approach.

## Supported Languages

Damavand is developed in Python, with a focus on Python developers looking for a flexible, yet powerful framework for building cloud-native applications.

## Getting Help

For support, issues, or feature requests, please open an issue on the Damavand GitHub repository or contact us at [email protected]. We're here to help you build your next cloud-native application efficiently and effectively!
30 changes: 15 additions & 15 deletions devenv.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"devenv": {
"locked": {
"dir": "src/modules",
"lastModified": 1722262342,
"lastModified": 1727963652,
"owner": "cachix",
"repo": "devenv",
"rev": "11a1ca0ad80bc172d2efda34ae542494442dcf48",
"treeHash": "c1be883f8fad6adb0369cef0ac6e6c9bd7f3ec66",
"rev": "cb0052e25dbcc8267b3026160dc73cddaac7d5fd",
"treeHash": "4d81a7de8e23f71c47c22a2d33fe63787fc2d2e1",
"type": "github"
},
"original": {
Expand Down Expand Up @@ -38,11 +38,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1710146030,
"lastModified": 1726560853,
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"treeHash": "bd263f021e345cb4a39d80c126ab650bebc3c10c",
"rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"treeHash": "0cbff24102dddab81e4c2940d7b356205c955fc6",
"type": "github"
},
"original": {
Expand Down Expand Up @@ -95,11 +95,11 @@
]
},
"locked": {
"lastModified": 1720642556,
"lastModified": 1724996935,
"owner": "nlewo",
"repo": "nix2container",
"rev": "3853e5caf9ad24103b13aa6e0e8bcebb47649fe4",
"treeHash": "a9c2f1d3f52f288515ca0fb11f9aed970fd869b6",
"rev": "fa6bb0a1159f55d071ba99331355955ae30b3401",
"treeHash": "a934d246fadcf8b36d28f3577fad413f5ab3f7d3",
"type": "github"
},
"original": {
Expand All @@ -126,11 +126,11 @@
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1722221733,
"lastModified": 1727907660,
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "12bf09802d77264e441f48e25459c10c93eada2e",
"treeHash": "e959ebf2e25b21ec31266bef769b447e4b907916",
"rev": "5966581aa04be7eff830b9e1457d56dc70a0b798",
"treeHash": "55b5fb46cd5d19fe4690148056c5f013a899d746",
"type": "github"
},
"original": {
Expand All @@ -150,11 +150,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1721042469,
"lastModified": 1727854478,
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "f451c19376071a90d8c58ab1a953c6e9840527fd",
"treeHash": "91f40b7a3b9f6886bd77482cba5b5cd890415a2e",
"rev": "5f58871c9657b5fc0a7f65670fe2ba99c26c1d79",
"treeHash": "9bd8fa1bb0d757e1eb29a1eb0d8da485b57b1b31",
"type": "github"
},
"original": {
Expand Down
27 changes: 10 additions & 17 deletions devenv.nix
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
{
pkgs,
lib,
config,
inputs,
...
}:
{ pkgs, lib, config, inputs, ... }:

{
name = "dmv";
# https://devenv.sh/basics/
env = {
GREET = "🛠️ Let's hack ";
};
env = { GREET = "🛠️ Let's hack "; };

# https://devenv.sh/scripts/
scripts.hello.exec = "echo $GREET";
Expand All @@ -34,13 +26,7 @@
};

# https://devenv.sh/packages/
packages = with pkgs; [
nixfmt-rfc-style
bat
jq
tealdeer
git
];
packages = with pkgs; [ nixfmt-rfc-style bat jq tealdeer git ];

languages = {
# pyright requires npm
Expand Down Expand Up @@ -84,6 +70,13 @@
yamllint = {
enable = true;
settings.preset = "relaxed";
settings.configuration = ''
---
extends: relaxed
rules:
line-length: disable
'';
};

ruff.enable = true;
Expand Down
Binary file added docs/assets/damavand-logo-inverted.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/damavand-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/assets/damavand-logo.psd
Binary file not shown.
1 change: 1 addition & 0 deletions docs/assets/damavand-logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions examples/advance-aws-llm-with-dspy/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: dspy_application
runtime:
name: python
options:
toolchain: pip
virtualenv: venv
description: A minimal Dspy application
31 changes: 31 additions & 0 deletions examples/advance-aws-llm-with-dspy/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import os
from controller import AwsDspyController
from damavand.environment import Environment

controller = AwsDspyController(
name="my-dspy",
region="eu-west-1",
)


def lambda_handler(event, context):
return controller.build_or_run(
app_id=event.get("app_id", "default"),
question=event.get("question", "What llm are you?"),
)


if __name__ == "__main__":
if controller.environment == Environment.LOCAL:
# run the lambda handler locally
event = {
"app_id": os.environ.get("APP_ID", "default"),
"question": os.environ.get("QUESTION", "What llm are you?"),
}
context = {}

if response := lambda_handler(event, context):
print(response)
else:
# aws automatically calls lambda_handler
pass
14 changes: 14 additions & 0 deletions examples/advance-aws-llm-with-dspy/applications.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import json
import dspy


def default_question(connection: dspy.OpenAI, question: str) -> dict:
dspy.settings.configure(lm=connection)
predict = dspy.Predict("question -> answer")
answer = predict(question=question)

return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps({"response": answer}),
}
64 changes: 64 additions & 0 deletions examples/advance-aws-llm-with-dspy/controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import dspy
from typing import Callable, Optional

from damavand.base.controllers.base_controller import runtime
from damavand.cloud.aws.controllers.llm import AwsLlmController

import applications


API_KEY = "EMPTY"


class AwsDspyController(AwsLlmController):
def __init__(
self,
name,
region: str,
model: Optional[str] = None,
tags: dict[str, str] = {},
**kwargs,
) -> None:
super().__init__(name, region, model, tags, **kwargs)
self.applications: dict[str, Callable] = {
"default": applications.default_question,
}

@property
@runtime
def connection(self) -> dspy.OpenAI:
"""Return the dspy OpenAI model."""

return dspy.OpenAI(
model=self.model_id,
api_base=f"{self.base_url}/",
api_key=API_KEY,
model_type="chat",
)

@runtime
def run_application(self, app_id: str, question: str, **kwargs) -> dict:
"""Run the specified application."""

return self.applications[app_id](question, **kwargs)

@runtime
def build_or_run(self, **kwargs) -> None | dict:
"""
Build or run the application based on the execution mode.
Parameters
----------
kwargs
arguments to be passed to the application. Check the `run_application` method for more information.
Returns
-------
None | dict
If the execution mode is runtime, return the output of the application otherwise None.
"""

if self.is_runtime_execution:
self.run_application(**kwargs)
else:
self.provision()
5 changes: 5 additions & 0 deletions examples/advance-aws-llm-with-dspy/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-e ../../../damavand
pulumi
boto3
dspy-ai
sagemaker
7 changes: 7 additions & 0 deletions examples/aws-llm-with-openai-client/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: llm-openai-client
runtime:
name: python
options:
toolchain: pip
virtualenv: venv
description: A simple llm application that uses OpenAI's client.
Loading

0 comments on commit 8cef40e

Please sign in to comment.