Skip to content

Instantly share code, notes, and snippets.

@douglasstarnes
Last active March 21, 2023 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save douglasstarnes/2f66226d43603444ded17cf58bb4a8bc to your computer and use it in GitHub Desktop.
Save douglasstarnes/2f66226d43603444ded17cf58bb4a8bc to your computer and use it in GitHub Desktop.
March Mempy Notes

Create new virtual environment

python3.10 -m venv .venv

Associate venv in VS Code

Create requirements.txt

flask
mongita
requests

Install requirements

$ pip install -r requirements.txt

Add app.py

import datetime
import uuid

from flask import Flask, redirect, render_template, request, url_for
from mongita import MongitaClientDisk
import requests

app = Flask(__name__)

client = MongitaClientDisk()
portfolio = client.portfolio
investments = portfolio.investments

@app.route("/")
@app.route("/<coin_id>")
def home(coin_id=None):
    if coin_id is None:
        all_investments = investments.find({})
    else:
        all_investments = investments.find({"coin_id": coin_id})
    return render_template("index.html", all_investments=all_investments)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000) 

Create templates folder

$ mkdir templates

Create templates/index.html

<html>
    <body>
        <a href="/new">New</a>
        <a href="/">Show All Investments</a>
        <ul>
        {% for investment in all_investments %} 
            <li><a href="/{{investment.coin_id}}">{{ investment.coin_id }}</a> {{ investment.price }} {{ investment.currency}} {{ investment.timestamp }}</li>
        {% endfor %}
        </ul>
    </body>
</html>

In app.py

@app.route("/new", methods=["GET", "POST"])
def add():
    if request.method == "GET":
        return render_template("new.html")
    else:
        coin_id = request.form["coin_id"]
        currency = request.form["currency"]
        data = requests.get(f"https://api.coingecko.com/api/v3/simple/price?ids={coin_id}&vs_currencies={currency}").                                json()
        new_coin = {
            "id": str(uuid.uuid4()),
            "coin_id": coin_id,
            "currency": currency,
            "price": data[coin_id][currency],
            "timestamp": datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
        }
        investments.insert_one(new_coin) 
        return redirect(url_for("home"))

Create templates/new.html

<html>
    <body>
        <form method="post">
            <div>
                <label for="coin_id">Coin ID</label>
                <input type="text" name="coin_id" id="coin_id">
            </div>
            <div>
                <label for="currency">Currency</label>
                <input type="text" name="currency" id="currency">
            </div>
            <input type="submit" value="Go">
        </form>
    </body>
</html>

Run the application

$ python app.py

Create Dockerfile

FROM python:3.10-alpine

WORKDIR /app

COPY requirements.txt .

RUN pip install -r requirements.txt

COPY . /app/

ENTRYPOINT [ "python3" ]
CMD [ "app.py" ]

Build container image

$ docker build -t mempy-mar23:v1 .

Start new container

docker run -d -p 8000:8000 mempy-mar23:v1

Create a resource group named mempy-mar23-rg

Create an Azure Container Registry

  • Resource group: mempy-mar23-rg

  • Name: mempymar23registry

  • SKU: Basic

Login to the registry

az acr login --name mempymar23registry

Tag the image

docker tag mempy-mar23:v1 mempymar23registry.azurecr.io/mempy-mar23:v1

Push the image to ACR

docker push mempymar23registry.azurecr.io/mempy-mar23:v1

Go to ACR in portal

  • Repositories

    • Look for mempy-mar23:v1
  • Access Keys

    • Set Admin user to Enabled

Create new Azure Container App

  • Resource Group: mempy-mar23-rg

  • Container app name: mempy-mar23-container-app

  • Region: eastus

Create new Container Apps Environment

  • Name: mempy-mar23-container-env

App Settings tab

  • Uncheck Use quickstart image

  • Image source: Azure Container Registry

  • Registry: mempymar23registry.azurecr.io

  • Image: mempy-mar23

  • Image tag: v1

  • Ingress: Check Enabled

  • Ingress traffic: Accepting traffic from anywhere

  • Ingress type: HTTP

  • Target port: 8000

Review and create

Overview tab

Goto url

Add Cosmos DB

Create new Cosmos DB Account

Use NoSQL API

  • Resource group: mempy-mar23-rg

  • Account name: mempy-mar23-cdb

  • Location: eastus

  • Capcity mode: Serverless

Review and create

In requirements.txt

azure-cosmos

Install dependencies

$ pip install -r requirements.txt

In app.py

from azure.cosmos import CosmosClient

# ...

COSMOS_KEY=""
COSMOS_ENDPOINT=""

client = CosmosClient(url=COSMOS_ENDPOINT, credential=COSMOS_KEY)
database = client.get_database_client("mempy-mar23-portfolio")
container = database.get_container_client("investments")

# Remove mongita setup

if coin_id is None:
    all_investments = list(container.read_all_items())
else:
    query = "SELECT * FROM i WHERE i.coin_id=@coin_id"
    parameters = [
        {"name": "@coin_id", "value": coin_id}
    ]
    all_investments = list(container.query_items(query=query, parameters=parameters, enable_cross_partition_query=True))

container.create_item(new_coin)

Goto Cosmos DB account page

  • Data Explorer

  • New Container

    • Database id: mempy-mar23-portfolio

    • Container id: investments

    • Partition key: /id

  • Keys

    • Copy and past URI and Primary Key in app.py constants COSMOS_ENDPOINT and COSMOS_KEY

Run app

Goto Container App page

  • Identity

  • Set Status to On

Create Azure Key Vault

  • Resource group: mempy-mar23-rg

  • Key vault name: mempy-mar23-vault

  • Region: eastus

  • Pricing tier: Standard

  • Access Policy Tab:

    • Create

    • Select Secret Management template

    • Search for container app principal

    • Review and create

  • Review and create

Add secrets

Goto secrets tab

Generate/Import

Upload options: Manual

  1. mempy-cosmos-endpoint

  2. mempy-cosmos-key

Goto container app page

  • Containers

    • Edit and deploy

      • Select container

        • Add environment variables (Manual entry)

        • KEY_VAULT_NAME

          • mempy-mar23-vault
        • COSMOS_ENDPOINT_SECRET_NAME

          • mempy-cosmos-endpoint
        • COSMOS_KEY_SECRET_NAME

          • mempy-cosmos-key

In requirements.txt

azure-identity
azure-keyvault-secrets

Install dependencies

$ pip install -r requirements.txt

In app.py

import os

 ...

from azure.keyvault.secrets import SecretClient
from azure.identity import DefaultAzureCredential

key_vault_name = os.environ["KEY_VAULT_NAME"]
cosmos_key_secret_name = os.environ["COSMOS_KEY_SECRET_NAME"]
cosmos_key_endpoint_secret_name = os.environ["COSMOS_ENDPOINT_SECRET_NAME"]

key_vault_endpoint = f"https://{key_vault_name}.vault.azure.net"

credential = DefaultAzureCredential()
secret_client = SecretClient(vault_url=key_vault_endpoint, credential=credential)

cosmos_key_secret = secret_client.get_secret(cosmos_key_secret_name)
cosmos_endpoint_secret = secret_client.get_secret(cosmos_endpoint_secret_name)

COSMOS_KEY = cosmos_key_secret.value
COSMOS_ENDPOINT = cosmos_endpoint_secret.value

Rebuild image

Retag image as v2

Push image to ACR

Change container image version

Redeploy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment