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
68 changes: 54 additions & 14 deletions .github/workflows/stack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,72 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Create stacks
id: create_stacks
run: |
set -euo pipefail
RELEASE=$(cat VERSION)

# oci-ods-aqua
STACKNAME=oci-ods-aqua
STACK_FILES="ai-quick-actions/policies/terraform/*"
RELEASE=$(cat VERSION)
ASSETS+="${STACKNAME}.zip"
echo "::group::Processing $STACKNAME"
zip -r ${STACKNAME}-stack.zip $STACK_FILES || { printf '\n⛔ Unable to create %s stack.\n'; exit 1; }
cp ${STACKNAME}-stack.zip ${STACKNAME}.zip || { printf '\n⛔ Unable to create %s stack.\n'; exit 1; }
zip -r ${STACKNAME}-stack.zip $STACK_FILES
cp ${STACKNAME}-stack.zip ${STACKNAME}.zip
echo "::endgroup::"

# ai-document-converter-app
DOC_CONVERTER_STACKNAME=ai-document-converter
DOC_CONVERTER_FILES="ai-hub/ai-document-converter/policies/terraform/*"
echo "::group::Packaging $DOC_CONVERTER_STACKNAME"
zip -r ${DOC_CONVERTER_STACKNAME}-stack.zip $DOC_CONVERTER_FILES
cp ${DOC_CONVERTER_STACKNAME}-stack.zip ${DOC_CONVERTER_STACKNAME}.zip
echo "::endgroup::"

# ai-translation-app
TRANSLATION_STACKNAME=ai-translation
TRANSLATION_FILES="ai-hub/ai-translation/policies/terraform/*"
echo "::group::Packaging $TRANSLATION_STACKNAME"
zip -r ${TRANSLATION_STACKNAME}-stack.zip $TRANSLATION_FILES
cp ${TRANSLATION_STACKNAME}-stack.zip ${TRANSLATION_STACKNAME}.zip
echo "::endgroup::"
echo "::set-output name=assets::$ASSETS"
echo "::set-output name=release::$RELEASE"
echo "::set-output name=prefix::$STACKNAME"

ASSETS="${STACKNAME}.zip ${DOC_CONVERTER_STACKNAME}.zip ${TRANSLATION_STACKNAME}.zip"

{
echo "assets=${ASSETS}"
echo "release=${RELEASE}"
echo "aqua=${STACKNAME}"
echo "ai_document_converter=${DOC_CONVERTER_STACKNAME}"
echo "ai_translation=${TRANSLATION_STACKNAME}"
} >> $GITHUB_OUTPUT

- name: Prepare Release Notes
shell: bash
run: |
#
printf '%s\n' '${{ steps.create_stacks.outputs.prefix }} Stack - v${{ steps.create_stacks.outputs.release }}' >release.md
printf '%s\n' '' '## [![Deploy to Oracle Cloud][magic_button]][magic_stack]' >>release.md
printf '%s\n' '' '' >>release.md
printf '%s\n' '' '[magic_button]: https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg' >>release.md
printf '%s\n' '' '[magic_stack]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/${{ github.repository }}/releases/download/${{ steps.create_stacks.outputs.release }}/${{ steps.create_stacks.outputs.prefix }}.zip' >>release.md
rel="${{ steps.create_stacks.outputs.release }}"
aqua="${{ steps.create_stacks.outputs.aqua }}"
ai_document_converter="${{ steps.create_stacks.outputs.ai_document_converter }}"
ai_translation="${{ steps.create_stacks.outputs.ai_translation }}"

{
printf '# Stacks - v%s\n\n' "$rel"
printf '### %s\n' "$aqua"
printf '## [![Deploy to Oracle Cloud][magic_button]][magic_stack_aqua]\n\n'

printf '### %s\n' "$ai_document_converter"
printf '## [![Deploy to Oracle Cloud][magic_button]][magic_stack_ai_document_converter]\n\n'

printf '### %s\n' "$ai_translation"
printf '## [![Deploy to Oracle Cloud][magic_button]][magic_stack_ai_translation]\n\n'

printf '[magic_button]: https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg\n'
printf '[magic_stack_aqua]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/${{ github.repository }}/releases/download/%s/%s.zip\n' "$rel" "$aqua"
printf '[magic_stack_ai_document_converter]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/${{ github.repository }}/releases/download/%s/%s.zip\n' "$rel" "$ai_document_converter"
printf '[magic_stack_ai_translation]: https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/${{ github.repository }}/releases/download/%s/%s.zip\n' "$rel" "$ai_translation"
} > release.md

- name: Create Release
run: gh release create ${{ steps.create_stacks.outputs.release }} --generate-notes -F release.md ${{ steps.create_stacks.outputs.assets }}
Expand Down
134 changes: 134 additions & 0 deletions ai-hub/ai-document-converter/policies/terraform/api_gateway.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# API Gateway
resource "oci_apigateway_gateway" "ai_application_oci_apigateway_gateway" {
compartment_id = var.compartment_id
display_name = "ai_application_api_gw_${random_string.randomstring.result}"
endpoint_type = "PUBLIC"
response_cache_details {
type = "NONE"
}
subnet_id = local.api_gw_subnet_id
}

# API Gateway Deployments
resource "oci_apigateway_deployment" "ai_application_apigateway_deployment" {
compartment_id = var.compartment_id
display_name = "api-deployment${random_string.randomstring.result}"
gateway_id = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.id
path_prefix = "/"
specification {
logging_policies {
execution_log {
log_level = "INFO"
}
}
request_policies {
authentication {
is_anonymous_access_allowed = "true"
token_auth_scheme = "Bearer"
token_header = "token"
type = "TOKEN_AUTHENTICATION"
validation_failure_policy {
client_details {
type = "VALIDATION_BLOCK"
}
logout_path = "/logout"
response_type = "CODE"
scopes = ["openid"]
source_uri_details {
type = "VALIDATION_BLOCK"
}
type = "OAUTH2"
use_cookies_for_intermediate_steps = "true"
use_cookies_for_session = "true"
max_expiry_duration_in_hours = 1
}
validation_policy {
additional_validation_policy {
issuers = ["https://identity.oraclecloud.com/"]
}
client_details {
client_id = oci_identity_domains_app.ai_application_confidential_app.name
client_secret_id = oci_vault_secret.idcs_app_client_secret.id
client_secret_version_number = "1"
type = "CUSTOM"
}
max_cache_duration_in_hours = "1"
source_uri_details {
type = "DISCOVERY_URI"
uri = "${data.oci_identity_domain.application_identity_domain.url}/.well-known/openid-configuration"
}
type = "REMOTE_DISCOVERY"
}
}
mutual_tls {
is_verified_certificate_required = "false"
}
}
routes {
backend {
type = "OAUTH2_LOGOUT_BACKEND"
}
logging_policies {
}
methods = ["GET"]
path = "/logout"
}
routes {
backend {
status = "200"
type = "STOCK_RESPONSE_BACKEND"
}
logging_policies {
}
methods = ["ANY"]
path = "/token"
response_policies {
header_transformations {
set_headers {
items {
if_exists = "OVERWRITE"
name = "token"
values = ["$${request.auth[id_token]}"]
}
items {
if_exists = "OVERWRITE"
name = "x-csrf-token"
values = ["$${request.auth[apigw_csrf_token]}"]
}
}
}
}
}
routes {
backend {
connect_timeout_in_seconds = "60"
is_ssl_verify_disabled = "false"
read_timeout_in_seconds = "120"
send_timeout_in_seconds = "120"
type = "HTTP_BACKEND"
url = "http://${data.oci_core_vnic.ai_application_container_instance_vnic.private_ip_address}:8080/$${request.path[req]}"
}
logging_policies {
}
methods = ["ANY"]
path = "/{req*}"
request_policies {
header_transformations {
set_headers {
items {
if_exists = "OVERWRITE"
name = "id_token"
values = ["$${request.auth[id_token]}"]
}
items {
if_exists = "OVERWRITE"
name = "Host"
values = ["$${request.host}"]
}
}
}
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
resource "oci_container_instances_container_instance" "ai_container_instance" {
#Required
availability_domain = var.availability_domain
compartment_id = var.vcn_compartment_id
containers {
#Required
image_url = local.image

#Optional
environment_variables = {
MULTIMODAL_LLM_PROVIDER = var.multimodal_llm_provider
MULTIMODAL_MODEL_NAME = var.multimodal_model_name
MULTIMODAL_MODEL_ENDPOINT = var.multimodal_model_endpoint
MAX_OUTPUT_TOKEN = var.multimodal_max_output_token
GENAI_COMPARTMENT_OCID = var.genai_compartment_ocid
PROMPT_VERSION = var.prompt_version
BACKEND_MD_URL = oci_datascience_model_deployment.ai_deployment.model_deployment_url
}
}
shape = var.container_shape
shape_config {
#Required
ocpus = var.ocpus

#Optional
memory_in_gbs = var.memory_in_gbs
}
vnics {
#Required
subnet_id = local.app_subnet_id
# private_ip = var.container_instance_private_ip
}

#Optional
display_name = var.container_display_name
}
25 changes: 25 additions & 0 deletions ai-hub/ai-document-converter/policies/terraform/datasources.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
data "oci_core_services" "all_oci_services" {
filter {
name = "name"
values = ["All .* Services In Oracle Services Network"]
regex = true
}
}

data "oci_identity_availability_domains" "get_availability_domains" {
compartment_id = var.compartment_ocid
}

data "oci_identity_domain" "application_identity_domain" {
domain_id = trimspace(var.identity_domain_id)
lifecycle {
precondition {
condition = var.identity_domain_id != null
error_message = "Existing domain id must be provided when using an existing domain."
}
}
}

data "oci_core_vnic" "ai_application_container_instance_vnic" {
vnic_id = oci_container_instances_container_instance.ai_container_instance.vnics[0].vnic_id
}
20 changes: 20 additions & 0 deletions ai-hub/ai-document-converter/policies/terraform/identity_app.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
resource "oci_identity_domains_app" "ai_application_confidential_app" {
based_on_template {
value = "CustomWebAppTemplateId"
well_known_id = "CustomWebAppTemplateId"
}
client_type = "confidential"
description = "Confidential Application for AI Translation Application"
display_name = "ai__translation_application_confidential_app_${random_string.randomstring.result}"
schemas = ["urn:ietf:params:scim:schemas:oracle:idcs:App"]
allowed_operations = ["introspect"]
idcs_endpoint = data.oci_identity_domain.application_identity_domain.url
active = true
is_oauth_client = true
bypass_consent = true
allowed_grants = ["authorization_code", "client_credentials", "urn:ietf:params:oauth:grant-type:jwt-bearer", "implicit"]
all_url_schemes_allowed = true
redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui","https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/gradio", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/playground","https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/ui/docs", "https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/callback"]
post_logout_redirect_uris = ["https://${oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname}/"]
audience = oci_apigateway_gateway.ai_application_oci_apigateway_gateway.hostname
}
43 changes: 43 additions & 0 deletions ai-hub/ai-document-converter/policies/terraform/model.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# dummy model artifact (zip) built from inline files
data "archive_file" "model_zip" {
type = "zip"
output_path = "${path.module}/model-artifact.zip"

# minimal runtime.yaml expected by OCI model artifacts
source {
filename = "runtime.yaml"
content = <<-YAML
kind: generic
type: python
entryPoint: "score.py"
pythonVersion: "3.11"
YAML
}

# Trivial scorer stub
source {
filename = "score.py"
content = <<-PY
def predict(data):
# no-op dummy implementation
return {"ok": True, "echo": data}
PY
}
}

# dummy Model catalog entry with artifact
resource "oci_datascience_model" "ai_model" {
compartment_id = var.data_science_project_compartment_id
project_id = var.project_ocid
display_name = var.model_display_name
description = local.model_desc

# Upload artifact inline (ZIP created above)
model_artifact = data.archive_file.model_zip.output_path
artifact_content_length = data.archive_file.model_zip.output_size
artifact_content_disposition = "attachment; filename=model-artifact.zip"

retention_setting {
archive_after_days = 365
}
}
Loading