-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: initial app controller code (#2)
Co-authored-by: Vladislav Yatsun <[email protected]>
- Loading branch information
1 parent
fe994e2
commit 8891a35
Showing
67 changed files
with
2,895 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
name: Dependency Review | ||
|
||
on: | ||
pull_request_target: | ||
types: | ||
- opened | ||
- synchronize | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
dependency-review: | ||
uses: epam/ai-dial-ci/.github/workflows/[email protected] | ||
secrets: | ||
ACTIONS_BOT_TOKEN: ${{ secrets.ACTIONS_BOT_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,5 @@ jobs: | |
run_tests: | ||
uses: epam/ai-dial-ci/.github/workflows/[email protected] | ||
secrets: inherit | ||
with: | ||
java_version: 21 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,7 +4,13 @@ on: | |
push: | ||
branches: [development, release-*] | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
jobs: | ||
release: | ||
uses: epam/ai-dial-ci/.github/workflows/[email protected] | ||
secrets: inherit | ||
with: | ||
java_version: 21 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Dockerfile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
FROM python:3.11-alpine | ||
|
||
ENV DIAL_BASE_URL='' | ||
ENV SOURCES='' | ||
ENV TARGET_DIR=/sources | ||
ENV TEMPLATES_DIR=/templates | ||
ENV API_KEY='' | ||
ENV JWT='' | ||
|
||
RUN pip install --no-cache-dir requests==2.32.3 packaging==24.1 | ||
|
||
WORKDIR /builder | ||
|
||
RUN adduser -u 1001 --disabled-password --gecos "" appuser | ||
|
||
# Prepare "output" directories for code sources and docker image templates | ||
RUN mkdir ${TARGET_DIR} ${TEMPLATES_DIR} && \ | ||
chown -R appuser:appuser ${TARGET_DIR} ${TEMPLATES_DIR} | ||
|
||
COPY . . | ||
|
||
RUN chmod +x entrypoint.sh | ||
|
||
USER appuser | ||
|
||
ENTRYPOINT ["/builder/entrypoint.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import os | ||
from pathlib import Path | ||
from typing import Mapping | ||
from urllib.parse import urljoin, unquote | ||
|
||
import requests | ||
from packaging.requirements import Requirement | ||
|
||
|
||
class AppValidationException(Exception): | ||
pass | ||
|
||
|
||
def download_files( | ||
dial_base_url: str, | ||
headers: Mapping, | ||
source_base: str | None, | ||
target: Path, | ||
files_metadata: list[dict[str, any]], | ||
): | ||
for file_metadata in files_metadata: | ||
if file_metadata["resourceType"] == "FILE": | ||
url = file_metadata["url"] | ||
file_path = target / unquote(url).removeprefix(source_base) | ||
download_file(dial_base_url, headers, url, file_path) | ||
|
||
|
||
def download_file(dial_base_url: str, headers: Mapping, file_url: str, target: Path): | ||
file_url = urljoin(dial_base_url, "v1/" + file_url) | ||
with requests.get(file_url, headers=headers, stream=True) as response: | ||
response.raise_for_status() | ||
|
||
print(f"{file_url} => {target}") | ||
target.parent.mkdir(parents=True, exist_ok=True) | ||
|
||
with target.open('wb') as file: | ||
for chunk in response.iter_content(chunk_size=8192): | ||
file.write(chunk) | ||
|
||
|
||
def validate_entrypoint(target: Path): | ||
entrypoint = target / "app.py" | ||
if not entrypoint.exists(): | ||
raise AppValidationException("Missing entrypoint file: app.py") | ||
|
||
|
||
def validate_packages(target: Path, allowed_packages: set[str]): | ||
requirements = target / "requirements.txt" | ||
requirements.touch(exist_ok=True) | ||
|
||
with open(target / "requirements.txt") as lines: | ||
for line in lines: | ||
line = line.strip() | ||
if not line or line.startswith('#'): | ||
continue | ||
|
||
requirement = parse_requirement(line) | ||
package_name = requirement.name | ||
if requirement.url: | ||
raise AppValidationException(f"URLs are not allowed in requirements.txt: {requirement.url}") | ||
|
||
if package_name not in allowed_packages: | ||
raise AppValidationException(f"Package '{package_name}' is forbidden.") | ||
|
||
|
||
def parse_requirement(line): | ||
if line.startswith("-"): | ||
raise AppValidationException(f"Pip options aren't allowed in requirements.txt: {line}") | ||
|
||
try: | ||
return Requirement(line) | ||
except Exception as e: | ||
raise AppValidationException(f"Unsupported requirement: {line}") from e | ||
|
||
|
||
def main(): | ||
dial_base_url = os.environ["DIAL_BASE_URL"] | ||
sources = os.environ["SOURCES"] | ||
target = Path(os.environ["TARGET_DIR"]) | ||
api_key = os.getenv("API_KEY") | ||
jwt = os.getenv("JWT") | ||
allowed_packages = os.getenv("ALLOWED_PACKAGES") | ||
|
||
print(f"Dial base url: {dial_base_url}") | ||
print(f"Sources: {sources}") | ||
print(f"Target folder: {target}") | ||
|
||
headers: dict[str, str] = {} | ||
if api_key: | ||
headers["api-key"] = api_key | ||
if jwt: | ||
headers["Authorization"] = f"Bearer {jwt}" | ||
|
||
metadata_url = urljoin(dial_base_url, f"v1/metadata/{sources}") | ||
params: dict[str, str] = {"recursive": "true"} | ||
while True: | ||
with requests.get(metadata_url, params, headers=headers) as response: | ||
response.raise_for_status() | ||
|
||
result: dict[str, any] = response.json() | ||
|
||
if not result["nodeType"] == "FOLDER": | ||
raise AppValidationException("Sources path must be a folder") | ||
|
||
download_files(dial_base_url, headers, unquote(sources), target, result.get("items", [])) | ||
|
||
token = result.get("nextToken") | ||
if not token: | ||
break | ||
|
||
params["token"] = token | ||
|
||
validate_entrypoint(target) | ||
validate_packages(target, set(allowed_packages.split())) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/bin/sh | ||
|
||
set -e | ||
|
||
cp -r templates/* "$TEMPLATES_DIR" | ||
|
||
exec python download_files.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Dockerfile |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
ARG PYTHON_IMAGE | ||
FROM $PYTHON_IMAGE | ||
|
||
# Allow statements and log messages to immediately appear in the logs | ||
ENV PYTHONUNBUFFERED=True | ||
|
||
# Create a non-root user | ||
RUN adduser -u 1001 --disabled-password --gecos "" appuser | ||
|
||
WORKDIR /app | ||
|
||
COPY requirements.txt . | ||
|
||
RUN pip install --no-cache-dir uvicorn==0.31.0 \ | ||
&& pip install --no-cache-dir --requirement requirements.txt | ||
|
||
COPY --chown=appuser . . | ||
|
||
EXPOSE 8080 | ||
|
||
USER appuser | ||
|
||
ENTRYPOINT ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<?xml version="1.0"?> | ||
|
||
<!DOCTYPE suppressions PUBLIC | ||
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN" | ||
"https://checkstyle.org/dtds/suppressions_1_2.dtd"> | ||
|
||
<suppressions> | ||
<!-- Suppress all checks for 3rd party knative classes --> | ||
<suppress checks=".*" files="com[\\/]epam[\\/]aidial[\\/]kubernetes[\\/]knative[\\/]" /> | ||
</suppressions> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
rootProject.name = '__RENAMEMEPLEASE__' | ||
rootProject.name = 'ai-dial-app-controller' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.epam.aidial; | ||
|
||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|
||
@SpringBootApplication | ||
public class Application { | ||
public static void main(String[] args) { | ||
SpringApplication.run(Application.class, args); | ||
} | ||
} |
Oops, something went wrong.