Skip to content

Commit

Permalink
✨ Add support for our custom domains for the API, same domain as dash…
Browse files Browse the repository at this point in the history
…board (#508)
  • Loading branch information
tiangolo authored Nov 13, 2024
1 parent 4b9c5fd commit 5b7b4d6
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ FRONTEND_HOST=http://localhost:5173
# FRONTEND_HOST=https://dashboard.fastapicloud.com
API_HOST=http://localhost:8000
# In staging, this should be
# API_HOST=https://api.fastapicloud.dev
# API_HOST=https://api.fastapicloud.work
# In production, this should be
# API_HOST=https://api.fastapicloud.com
API_DOMAIN=api.fastapicloud.site

DEPLOYMENTS_DOMAIN=fastapicloud.club

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/deploy-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ jobs:
DOMAIN: "${{ vars.DOMAIN }}"
FRONTEND_HOST: "${{ vars.FRONTEND_HOST }}"
API_HOST: "${{ vars.API_HOST }}"
API_DOMAIN: "${{ vars.API_DOMAIN }}"
DEPLOYMENTS_DOMAIN: "${{ vars.DEPLOYMENTS_DOMAIN }}"
ENVIRONMENT: ${{ matrix.environment }}
PROJECT_NAME: "${{ vars.PROJECT_NAME }}"
Expand Down Expand Up @@ -139,6 +140,7 @@ jobs:
DOMAIN: "${{ vars.DOMAIN }}"
FRONTEND_HOST: "${{ vars.FRONTEND_HOST }}"
API_HOST: "${{ vars.API_HOST }}"
API_DOMAIN: "${{ vars.API_DOMAIN }}"
DEPLOYMENTS_DOMAIN: "${{ vars.DEPLOYMENTS_DOMAIN }}"
ENVIRONMENT: ${{ matrix.environment }}
PROJECT_NAME: "${{ vars.PROJECT_NAME }}"
Expand Down
1 change: 1 addition & 0 deletions backend/app/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class MainSettings(SettingsEnv):
DEVICE_AUTH_POLL_INTERVAL_SECONDS: int = 5

FRONTEND_HOST: str = "http://localhost:5173"
API_DOMAIN: str = "api.fastapicloud.site"

BACKEND_CORS_ORIGINS: Annotated[
list[AnyUrl] | str,
Expand Down
97 changes: 94 additions & 3 deletions backend/app/docker_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def create_namespace_by_team(namespace: str) -> None:
raise e


def create_or_patch_custom_object(
def create_or_patch_custom_namespaced_object(
group: str,
version: str,
namespace: str,
Expand Down Expand Up @@ -140,6 +140,90 @@ def create_or_patch_custom_object(
raise e


def create_or_patch_custom_cluster_object(
*,
group: str,
version: str,
plural: str,
name: str,
body: dict[str, Any],
) -> None:
api_instance = get_kubernetes_client_custom_objects()

try:
# Try to get the custom object
api_instance.get_cluster_custom_object( # type: ignore
group=group, version=version, plural=plural, name=name
)

# Object exists, so patch it
api_response = api_instance.patch_cluster_custom_object( # type: ignore
group=group,
version=version,
plural=plural,
name=name,
body=body,
)
print(f"Custom object patched. Status='{api_response}'")

except K8sApiException as e:
if e.status == 404: # Not Found
# Object doesn't exist, so create it
api_response = api_instance.create_cluster_custom_object( # type: ignore
group=group,
version=version,
plural=plural,
body=body,
)
print(f"Custom object created. Status='{api_response}'")
else:
raise e


def create_custom_domain(*, namespace: str, domain: str, service_name: str) -> None:
domain_claim = {
"apiVersion": "networking.internal.knative.dev/v1alpha1",
"kind": "ClusterDomainClaim",
"metadata": {
"name": domain,
},
"spec": {
"namespace": namespace,
},
}
create_or_patch_custom_cluster_object(
group="networking.internal.knative.dev",
version="v1alpha1",
plural="clusterdomainclaims",
name=domain,
body=domain_claim,
)

domain_mapping = {
"apiVersion": "serving.knative.dev/v1beta1",
"kind": "DomainMapping",
"metadata": {
"name": domain,
"namespace": namespace,
},
"spec": {
"ref": {
"name": service_name,
"kind": "Service",
"apiVersion": "serving.knative.dev/v1",
},
},
}
create_or_patch_custom_namespaced_object(
group="serving.knative.dev",
version="v1beta1",
namespace=namespace,
plural="domainmappings",
name=domain,
body=domain_mapping,
)


def deploy_cloud(service_name: str, image_url: str, min_scale: int = 0) -> None:
main_settings = MainSettings.get_settings().model_dump(
mode="json", exclude_unset=True, exclude={"all_cors_origins"}
Expand All @@ -161,13 +245,20 @@ def deploy_cloud(service_name: str, image_url: str, min_scale: int = 0) -> None:

env_strs = {k: str(v) for k, v in env_data.items()}

namespace = "default"

deploy_to_kubernetes(
service_name,
image_url,
namespace="default",
namespace=namespace,
min_scale=min_scale,
env=env_strs,
)
create_custom_domain(
namespace=namespace,
domain=MainSettings.get_settings().API_DOMAIN,
service_name=service_name,
)


def deploy_to_kubernetes(
Expand Down Expand Up @@ -210,7 +301,7 @@ def deploy_to_kubernetes(
## TODO: Add resource limits and quotas by namespace
create_namespace_by_team(namespace)

create_or_patch_custom_object(
create_or_patch_custom_namespaced_object(
group="serving.knative.dev",
version="v1",
namespace=namespace,
Expand Down

0 comments on commit 5b7b4d6

Please sign in to comment.