diff --git a/.catalog-onboard-pipeline.yaml b/.catalog-onboard-pipeline.yaml index a57b29f9..b7ebd023 100644 --- a/.catalog-onboard-pipeline.yaml +++ b/.catalog-onboard-pipeline.yaml @@ -1,7 +1,7 @@ --- apiVersion: v1 offerings: - - name: Retrieval_Augmented_Generation_Pattern + - name: Landing_zone_for_cloud_native_AI_applications kind: solution catalog_id: 7df1e4ca-d54c-4fd0-82ce-3d13247308cd offering_id: 5fdd0045-30fc-4013-a8bc-6db9d5447a52 @@ -22,3 +22,6 @@ offerings: scc: instance_id: 1c7d5f78-9262-44c3-b779-b28fe4d88c37 region: us-south + - name: quickstart + mark_ready: true + install_type: fullstack diff --git a/.gitignore b/.gitignore index 97d93660..bec79e62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,15 @@ .def.json .terraform +**/.terraform/* + *.tfstate +*.tfstate.* + +*.terraform.lock.hcl *.lock.hcl + .DS_Store .idea +*.tfvars +*.tfvars.json +*.log diff --git a/ibm_catalog.json b/ibm_catalog.json index 324c46e1..a33eaaf2 100644 --- a/ibm_catalog.json +++ b/ibm_catalog.json @@ -60,7 +60,7 @@ "description": "Ensures trust by configuring the IBM Cloud account to align with compliance settings as defined in the Financial Services framework." } ], - "support_details": "This product is in the community registry, as such support is handled through the originated repo. If you experience issues please open an issue in that repository [https://github.com/terraform-ibm-modules/stack-retrieval-augmented-generation/issues](https://github.com/terraform-ibm-modules/stack-retrieval-augmented-generation/issues). Please note this product is not supported via the IBM Cloud Support Center.", + "support_details": "This product is in the community registry, support is handled through the [original repo](https://github.com/terraform-ibm-modules/stack-retrieval-augmented-generation). If you experience issues kindly open an issue [here](https://github.com/terraform-ibm-modules/stack-retrieval-augmented-generation/issues). Please note that this product is not currently supported through the IBM Cloud Support Center.", "flavors": [ { "label": "Basic with sample application (Deploy on Code Engine)", @@ -1342,6 +1342,225 @@ } ], "install_type": "fullstack" + }, + { + "label": "QuickStart", + "name": "quickstart", + "index": 5, + "short_description": "Ideal for users new to IBM Cloud or watsonx who want to get started without configuring underlying infrastructure.", + "install_type": "fullstack", + "ignore_readme": true, + "dependency_version_2": true, + "working_directory": "solutions/quickstart", + "iam_permissions": [ + { + "service_name": "Resource group only", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Viewer" + ], + "notes": "Viewer access is required in the resource group you want to provision in." + }, + { + "service_name": "cloud-object-storage", + "role_crns": [ + "crn:v1:bluemix:public:iam::::serviceRole:Manager", + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to manage Object Storage for the watsonx.ai." + }, + { + "service_name": "kms", + "role_crns": [ + "crn:v1:bluemix:public:iam::::serviceRole:Manager", + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required as Key Protect is used for encryption." + }, + { + "service_name": "data-science-experience", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create an instance of watsonx.ai Studio." + }, + { + "service_name": "pm-20", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create an instance of watsonx.ai Runtime." + }, + { + "service_name": "discovery", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create an instance of Watson Discovery." + }, + { + "service_name": "conversation", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create an instance of watsonx Assistant." + }, + { + "service_name": "aiopenscale", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create an instance of watsonx.governance." + }, + { + "service_name": "lakehouse", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create an instance of watsonx.data" + }, + { + "service_name": "watsonx-orchestrate", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create an instance of watsonx Orchestrate." + }, + { + "service_name": "databases-for-elasticsearch", + "role_crns": [ + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create the Databases for Elasticsearch instance." + }, + { + "service_name": "container-registry", + "role_crns": [ + "crn:v1:bluemix:public:iam::::serviceRole:Manager" + ], + "notes": "Required to manage namespaces, repositories, and access policies in Container Registry." + }, + { + "service_name": "codeengine", + "role_crns": [ + "crn:v1:bluemix:public:iam::::serviceRole:Writer", + "crn:v1:bluemix:public:iam::::role:Editor" + ], + "notes": "Required to create Code Engine instance." + } + ], + "architecture": { + "features": [ + { + "title": " ", + "description": "Ideal for users new to IBM Cloud or watsonx.ai who want to get started without configuring underlying infrastructure." + }, + { + "title": " ", + "description": "Quickly provisions watsonx.ai, watsonx Assistant, watsonx Orchestrate, watson Discovery, watsonx.data, watsonx.governance, Elasticsearch, Object Storage, Key Management Services and Code Engine. Includes all necessary services to deploy a sample Retrieval-Augmented Generation (RAG) application leveraging Code Engine." + } + ], + "diagrams": [ + { + "diagram": { + "caption": "Landing zone for cloud-native AI applications - QuickStart", + "url": "https://raw.githubusercontent.com/terraform-ibm-modules/terraform-ibm-cloud-native-ai/main/reference-architectures/deployable-architecture-cn-ai-qs.svg", + "type": "image/svg+xml" + }, + "description": "This deployable architecture provisions a suite of AI and data services on IBM Cloud to support rapid development and deployment of Landing zone for cloud-native AI applications. It includes watsonx.ai for foundation model training and inference, watsonx Assistant for conversational AI, watson Discovery for intelligent document understanding, watsonx.data to support enterprise-grade requirements by using additional services, watsonx.governance to analyze your AI with trust and transparency and IBM Cloud Databases for Elasticsearch. The solution also provisions IBM Cloud Object Storage (COS) for persistent storage of model artifacts, application data, and logs, and Key Management Services (KMS) to ensure secure handling of sensitive information and encryption keys across services. Once the foundational services are provisioned, a sample Retrieval-Augmented Generation (RAG) application can be deployed to demonstrate how enterprise-grade AI solutions can be built using IBM Cloud-native services. The application leverages `watsonx.ai` for generative responses, Elasticsearch for document retrieval, and Code Engine to orchestrate the runtime environment." + } + ] + }, + "configuration": [ + { + "key": "prefix", + "type": "string", + "required": true, + "default_value": "cnai", + "random_string": { + "length": 4 + }, + "value_constraints": [ + { + "type": "regex", + "description": "Prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It must not end with a hyphen('-'), and cannot contain consecutive hyphens ('--'). It should not exceed 16 characters.", + "value": "^$|^__NULL__$|^[a-z](?!.*--)(?:[a-z0-9-]{0,14}[a-z0-9])?$" + } + ] + }, + { + "key": "existing_resource_group_name", + "display_name": "resource_group", + "custom_config": { + "type": "resource_group", + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "identifier": "rg_name" + } + } + }, + { + "key": "ibmcloud_api_key", + "type": "password", + "required": true + }, + { + "key": "region", + "required": true, + "options": [ + { + "displayname": "Dallas (us-south)", + "value": "us-south" + }, + { + "displayname": "Sydney (au-syd)", + "value": "au-syd" + }, + { + "displayname": "Frankfurt (eu-de)", + "value": "eu-de" + }, + { + "displayname": "London (eu-gb)", + "value": "eu-gb" + }, + { + "displayname": "Tokyo (jp-tok)", + "value": "jp-tok" + } + ] + }, + { + "key": "provider_visibility", + "options": [ + { + "displayname": "private", + "value": "private" + }, + { + "displayname": "public", + "value": "public" + }, + { + "displayname": "public-and-private", + "value": "public-and-private" + } + ], + "hidden": true + }, + { + "key": "resource_tags", + "custom_config": { + "type": "array", + "grouping": "deployment", + "original_grouping": "deployment", + "config_constraints": { + "type": "string" + } + } + } + ], + "terraform_version": "1.12.2" } ] } diff --git a/reference-architectures/deployable-architecture-cn-ai-qs.svg b/reference-architectures/deployable-architecture-cn-ai-qs.svg new file mode 100644 index 00000000..b4f69377 --- /dev/null +++ b/reference-architectures/deployable-architecture-cn-ai-qs.svg @@ -0,0 +1,4 @@ + + + +IBM CloudRegionResource Groupwatsonx serviceswatsonx Assistantwatsonx.datawatsonx.governancewatsonx.ai Runtimewatsonx.ai Studiowatsonx.aiWatson DiscoveryObject StorageRead/Write projects dataKey ProtectKey RingKeys for watsonx.ai and watsonx.dataDatabase for ElasticsearchCode Engine ProjectImage BuildSecretsAppsDeploy the RAG ApplicationElasticsearch stores vector embeddings for fast, scalable semantic search across ML-generated content.watsonx OrchestrateContainer RegistryNamespaceContainer registry stores images built by IBM Code Engine. \ No newline at end of file diff --git a/solutions/quickstart/README.md b/solutions/quickstart/README.md new file mode 100644 index 00000000..a9c64e01 --- /dev/null +++ b/solutions/quickstart/README.md @@ -0,0 +1,3 @@ +# Landing zone for cloud-native AI applications (QuickStart) + +:exclamation: **Important:** This solution is not intended to be called by other modules because it contains a provider configuration and is not compatible with the `for_each`, `count`, and `depends_on` arguments. For more information, see [Providers Within Modules](https://developer.hashicorp.com/terraform/language/modules/develop/providers). diff --git a/solutions/quickstart/catalogValidationValues.json.template b/solutions/quickstart/catalogValidationValues.json.template new file mode 100644 index 00000000..2d3d4bf2 --- /dev/null +++ b/solutions/quickstart/catalogValidationValues.json.template @@ -0,0 +1,4 @@ +{ + "ibmcloud_api_key": $VALIDATION_APIKEY, + "prefix": $PREFIX +} diff --git a/solutions/quickstart/main.tf b/solutions/quickstart/main.tf new file mode 100644 index 00000000..490e80cd --- /dev/null +++ b/solutions/quickstart/main.tf @@ -0,0 +1,330 @@ +############################################################################################################## +# Locals Block +############################################################################################################## + +locals { + + prefix = var.prefix != null ? trimspace(var.prefix) != "" ? "${var.prefix}-" : "" : "" + service_endpoints = "public-and-private" + + # KMS + key_ring_name = "${local.prefix}keyring" + key_name = "${local.prefix}key" + wx_data_key_name = "${local.prefix}wxd-key" + + # ICD Elastic Search + es_credentials = { + "elasticsearch_admin" : "Administrator", + "elasticsearch_operator" : "Operator", + "elasticsearch_viewer" : "Viewer", + "elasticsearch_editor" : "Editor", + } + + # Watson + watson_plan = { + "studio" = "professional-v1", + "runtime" = "v2-professional", + "discovery" = "plus", + "assistant" = "enterprise", + "governance" = "essentials", + "data" = "lakehouse-enterprise", + "orchestrate" = "essentials-agentic-mau" + } + +} + +############################################################################################################## +# Resource Group +############################################################################################################## + +module "resource_group" { + source = "terraform-ibm-modules/resource-group/ibm" + version = "1.4.0" + existing_resource_group_name = var.existing_resource_group_name +} + +############################################################################## +# COS +############################################################################## + +module "cos" { + source = "terraform-ibm-modules/cos/ibm//modules/fscloud" + version = "10.5.2" + resource_group_id = module.resource_group.resource_group_id + cos_instance_name = "${local.prefix}cos" + cos_plan = "standard" + cos_tags = var.resource_tags +} + +############################################################################## +# Key Protect +############################################################################## + +module "key_protect_all_inclusive" { + source = "terraform-ibm-modules/kms-all-inclusive/ibm" + version = "5.5.0" + resource_group_id = module.resource_group.resource_group_id + region = var.region + key_protect_instance_name = "${local.prefix}kp" + resource_tags = var.resource_tags + keys = [ + { + key_ring_name = local.key_ring_name + keys = [ + { + key_name = local.key_name + force_delete = true + }, + { + key_name = local.wx_data_key_name + force_delete = true + } + ] + } + ] +} + +############################################################################################################## +# watsonx.ai +############################################################################################################## + +data "ibm_iam_auth_token" "restapi" {} + +module "watsonx_ai" { + source = "terraform-ibm-modules/watsonx-ai/ibm" + version = "2.10.1" + region = var.region + resource_group_id = module.resource_group.resource_group_id + resource_tags = var.resource_tags + project_name = "${local.prefix}project-cnai" + + watsonx_ai_studio_instance_name = "${local.prefix}wx-studio" + watsonx_ai_studio_plan = local.watson_plan["studio"] + + watsonx_ai_runtime_instance_name = "${local.prefix}wx-runtime" + watsonx_ai_runtime_plan = local.watson_plan["runtime"] + + enable_cos_kms_encryption = true + cos_instance_crn = module.cos.cos_instance_crn + cos_kms_key_crn = module.key_protect_all_inclusive.keys["${local.key_ring_name}.${local.key_name}"].crn +} + +############################################################################################################## +# Watson Discovery +############################################################################################################## + +module "watson_discovery" { + source = "terraform-ibm-modules/watsonx-discovery/ibm" + version = "1.11.2" + region = var.region + resource_group_id = module.resource_group.resource_group_id + resource_tags = var.resource_tags + plan = local.watson_plan["discovery"] + watson_discovery_name = "${local.prefix}discovery" + service_endpoints = local.service_endpoints +} + +############################################################################################################## +# watsonx Assistant +############################################################################################################## + +module "watsonx_assistant" { + source = "terraform-ibm-modules/watsonx-assistant/ibm" + version = "1.5.2" + region = var.region + resource_group_id = module.resource_group.resource_group_id + resource_tags = var.resource_tags + plan = local.watson_plan["assistant"] + watsonx_assistant_name = "${local.prefix}assistant" + service_endpoints = local.service_endpoints +} + +############################################################################################################## +# watsonx.governance +############################################################################################################## + +module "watsonx_governance" { + source = "terraform-ibm-modules/watsonx-governance/ibm" + version = "1.11.6" + region = var.region + resource_group_id = module.resource_group.resource_group_id + plan = local.watson_plan["governance"] + watsonx_governance_name = "${local.prefix}governance" + resource_tags = var.resource_tags +} + +############################################################################################################## +# watsonx.data +############################################################################################################## + +module "watsonx_data" { + source = "terraform-ibm-modules/watsonx-data/ibm" + version = "1.12.7" + region = var.region + resource_group_id = module.resource_group.resource_group_id + watsonx_data_name = "${local.prefix}data" + plan = local.watson_plan["data"] + use_case = "workloads" + resource_tags = var.resource_tags + enable_kms_encryption = true + skip_iam_authorization_policy = false + watsonx_data_kms_key_crn = module.key_protect_all_inclusive.keys["${local.key_ring_name}.${local.wx_data_key_name}"].crn +} + +############################################################################################################## +# watsonx Orchestrate +############################################################################################################## + +module "watsonx_orchestrate" { + source = "terraform-ibm-modules/watsonx-orchestrate/ibm" + version = "1.11.6" + region = var.region + resource_group_id = module.resource_group.resource_group_id + watsonx_orchestrate_name = "${local.prefix}orchestrate" + plan = local.watson_plan["orchestrate"] + resource_tags = var.resource_tags +} + +############################################################################################################## +# Elastic search +############################################################################################################## + +module "icd_elasticsearch" { + source = "terraform-ibm-modules/icd-elasticsearch/ibm" + version = "2.4.5" + resource_group_id = module.resource_group.resource_group_id + name = "${local.prefix}data-store" + region = var.region + plan = "enterprise" + elasticsearch_version = "8.15" + tags = var.resource_tags + service_endpoints = "private" + member_host_flavor = "multitenant" + deletion_protection = false + service_credential_names = local.es_credentials +} + +############################################################################################################## +# Container Registry +############################################################################################################## + +module "icr_namespace" { + source = "terraform-ibm-modules/container-registry/ibm" + version = "2.2.1" + resource_group_id = module.resource_group.resource_group_id + namespace_name = "${local.prefix}namespace" +} + +module "cr_endpoint" { + source = "terraform-ibm-modules/container-registry/ibm//modules/endpoint" + version = "2.3.5" + region = var.region +} + +############################################################################################################## +# Code Engine - Project, Secret, Build, Application +############################################################################################################## + +locals { + env_vars = [{ + type = "secret_key_reference" + name = "WATSONX_AI_APIKEY" + key = "WATSONX_AI_APIKEY" + reference = "wx-ai" + }, + { + type = "literal" + name = "WATSONX_SERVICE_URL" + value = "https://${var.region}.ml.cloud.ibm.com" + }, + { + type = "literal" + name = "WATSONX_PROJECT_ID" + value = module.watsonx_ai.watsonx_ai_project_id + }, + { + type = "literal" + name = "ENABLE_WXASST" + value = "true" + }, + { + type = "literal" + name = "WXASST_REGION" + value = var.region + }, + { + type = "literal" + name = "ENABLE_RAG_LLM" + value = "true" + } + ] + + ce_secrets = merge( + { + # Secret for Watsonx + "wx-ai" = { + format = "generic" + data = { + "WATSONX_AI_APIKEY" = var.ibmcloud_api_key + } + } + }, + # Secret for Container Registry + { + "${local.prefix}registry-secret" = { + format = "registry" + data = { + username = "iamapikey" + password = var.ibmcloud_api_key + server = module.cr_endpoint.container_registry_endpoint_private + } + } + } + ) + source_url = "https://github.com/IBM/ai-agent-for-loan-risk" + output_image = "${module.cr_endpoint.container_registry_endpoint_private}/${module.icr_namespace.namespace_name}/ai-agent-for-loan-risk" + strategy = "dockerfile" + ce_app_name = "ai-agent-for-loan-risk" +} + +module "code_engine" { + source = "terraform-ibm-modules/code-engine/ibm" + version = "4.6.12" + resource_group_id = module.resource_group.resource_group_id + project_name = "${local.prefix}project" + secrets = local.ce_secrets +} + +############################################################################## +# Code Engine Build +############################################################################## + +module "code_engine_build" { + source = "terraform-ibm-modules/code-engine/ibm//modules/build" + version = "4.6.12" + name = "${local.prefix}ce-build" + ibmcloud_api_key = var.ibmcloud_api_key + project_id = module.code_engine.project_id + existing_resource_group_id = module.resource_group.resource_group_id + source_type = "git" + output_image = local.output_image + output_secret = "${local.prefix}registry-secret" + source_url = local.source_url + region = var.region + strategy_type = local.strategy +} + +############################################################################## +# Code Engine Application +############################################################################## +module "code_engine_app" { + source = "terraform-ibm-modules/code-engine/ibm//modules/app" + version = "4.6.12" + project_id = module.code_engine.project_id + name = local.ce_app_name + image_reference = module.code_engine_build.output_image + image_secret = module.code_engine.secret["${local.prefix}registry-secret"].name + run_env_variables = local.env_vars +} + +# ############################################################################################################# diff --git a/solutions/quickstart/outputs.tf b/solutions/quickstart/outputs.tf new file mode 100644 index 00000000..5ed3fb46 --- /dev/null +++ b/solutions/quickstart/outputs.tf @@ -0,0 +1,175 @@ +######################################################################################################################## +# Resource Group +######################################################################################################################## + +output "resource_group_id" { + description = "The resource group ID to provision the Watson Discovery instance." + value = module.resource_group.resource_group_id +} + +output "resource_group_name" { + description = "The resource group name to provision the Watson Discovery instance." + value = module.resource_group.resource_group_name +} + +######################################################################################################################## +# KMS +######################################################################################################################## + +output "kms_key_crn" { + description = "CRN of the KMS Key." + value = module.key_protect_all_inclusive.keys["${local.key_ring_name}.${local.key_name}"].crn +} + +######################################################################################################################## +# watsonx.ai +######################################################################################################################## + +output "watsonx_ai" { + description = "Project configuration and instance details generate from the watsonx.ai module." + value = { + + # watsonx.ai Project + "watsonx_ai_project_id" = module.watsonx_ai.watsonx_ai_project_id + "watsonx_ai_project_url" = module.watsonx_ai.watsonx_ai_project_url + "watsonx_ai_project_bucket_name" = module.watsonx_ai.watsonx_ai_project_bucket_name + + # watsonx.ai Runtime + "watsonx_ai_runtime_crn" = module.watsonx_ai.watsonx_ai_runtime_crn + "watsonx_ai_runtime_guid" = module.watsonx_ai.watsonx_ai_runtime_guid + "watsonx_ai_runtime_name" = module.watsonx_ai.watsonx_ai_runtime_name + "watsonx_ai_runtime_plan_id" = module.watsonx_ai.watsonx_ai_runtime_plan_id + "watsonx_ai_runtime_dashboard_url" = module.watsonx_ai.watsonx_ai_runtime_dashboard_url + + # watsonx.ai Studio + "watsonx_ai_studio_crn" = module.watsonx_ai.watsonx_ai_studio_crn + "watsonx_ai_studio_guid" = module.watsonx_ai.watsonx_ai_studio_guid + "watsonx_ai_studio_name" = module.watsonx_ai.watsonx_ai_studio_name + "watsonx_ai_studio_plan_id" = module.watsonx_ai.watsonx_ai_studio_plan_id + "watsonx_ai_studio_dashboard_url" = module.watsonx_ai.watsonx_ai_studio_dashboard_url + } +} + +######################################################################################################################## +# watson Discovery +######################################################################################################################## + +output "watson_discovery" { + description = "Connection and configuration details for the Watson Discovery instance." + value = { + "crn" = module.watson_discovery.crn + "account_id" = module.watson_discovery.account_id + "guid" = module.watson_discovery.guid + "name" = module.watson_discovery.name + "plan_id" = module.watson_discovery.plan_id + "dashboard_url" = module.watson_discovery.dashboard_url + } +} + +######################################################################################################################## +# watsonx Assistant +######################################################################################################################## + +output "watsonx_assistant" { + description = "Connection and configuration details for the watsonx Assistant instance." + value = { + "crn" = module.watsonx_assistant.crn + "account_id" = module.watsonx_assistant.account_id + "guid" = module.watsonx_assistant.guid + "name" = module.watsonx_assistant.name + "plan_id" = module.watsonx_assistant.plan_id + "dashboard_url" = module.watsonx_assistant.dashboard_url + } +} + +######################################################################################################################## +# watsonx.governance +######################################################################################################################## + +output "watsonx_governance" { + description = "Connection and configuration details for the watsonx.governance instance." + value = { + "crn" = module.watsonx_governance.crn + "account_id" = module.watsonx_governance.account_id + "guid" = module.watsonx_governance.guid + "name" = module.watsonx_governance.name + "plan_id" = module.watsonx_governance.plan_id + "dashboard_url" = module.watsonx_governance.dashboard_url + } +} + +######################################################################################################################## +# watsonx.data +######################################################################################################################## + +output "watsonx_data" { + description = "Connection and configuration details for the watsonx.data instance." + value = { + "crn" = module.watsonx_data.crn + "account_id" = module.watsonx_data.account_id + "guid" = module.watsonx_data.guid + "name" = module.watsonx_data.name + "plan_id" = module.watsonx_data.plan_id + "dashboard_url" = module.watsonx_data.dashboard_url + } +} + +######################################################################################################################## +# watsonx.data +######################################################################################################################## + +output "watsonx_orchestrate" { + description = "Connection and configuration details for the watsonx Orchestrate instance." + value = { + "crn" = module.watsonx_orchestrate.crn + "account_id" = module.watsonx_orchestrate.account_id + "guid" = module.watsonx_orchestrate.guid + "name" = module.watsonx_orchestrate.name + "plan_id" = module.watsonx_orchestrate.plan_id + "dashboard_url" = module.watsonx_orchestrate.dashboard_url + } +} + +######################################################################################################################## +# ICD - ElasticSearch +######################################################################################################################## + +output "icd_elastic_search" { + description = "ICD Elastic search output." + value = { + "crn" = module.icd_elasticsearch.crn + "id" = module.icd_elasticsearch.id + "version" = module.icd_elasticsearch.version + "hostname" = module.icd_elasticsearch.hostname + "port" = module.icd_elasticsearch.port + } +} + +output "icd_es_service_credentials_json" { + description = "ICD Elastic search credentials json." + value = module.icd_elasticsearch.service_credentials_json + sensitive = true +} + +######################################################################################################################## +# Container Registry +######################################################################################################################## +output "icr_namespace_crn" { + description = "CRN representing the Container Registry namespace" + value = module.icr_namespace.namespace_crn +} + +######################################################################################################################## +# Code Engine +######################################################################################################################## + +output "code_engine" { + description = "Code Engine output." + value = { + "project_id" = module.code_engine.project_id + "app_url" = module.code_engine_app.endpoint + "output_image" = local.output_image + } +} + +######################################################################################################################## diff --git a/solutions/quickstart/provider.tf b/solutions/quickstart/provider.tf new file mode 100644 index 00000000..01b2fa6d --- /dev/null +++ b/solutions/quickstart/provider.tf @@ -0,0 +1,16 @@ +provider "ibm" { + ibmcloud_api_key = var.ibmcloud_api_key + region = var.region + visibility = var.provider_visibility + private_endpoint_type = (var.provider_visibility == "private" && var.region == "ca-mon") ? "vpe" : null +} + +provider "restapi" { + uri = "https:" + write_returns_object = true + debug = true + headers = { + Authorization = data.ibm_iam_auth_token.restapi.iam_access_token + Content-Type = "application/json" + } +} diff --git a/solutions/quickstart/variables.tf b/solutions/quickstart/variables.tf new file mode 100644 index 00000000..88f99fe6 --- /dev/null +++ b/solutions/quickstart/variables.tf @@ -0,0 +1,65 @@ +############################################################################################################## +# Input Variables +############################################################################################################## + +variable "ibmcloud_api_key" { + type = string + description = "The IBM Cloud API key." + sensitive = true +} + +variable "existing_resource_group_name" { + type = string + description = "The name of an existing resource group to provision the resources. [Learn more](https://cloud.ibm.com/docs/account?topic=account-rgs&interface=ui#create_rgs) about how to create a resource group." + default = "Default" +} + +variable "provider_visibility" { + description = "Set the visibility value for the IBM terraform provider. [Learn more](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/guides/custom-service-endpoints)." + type = string + default = "private" + + validation { + condition = contains(["public", "private", "public-and-private"], var.provider_visibility) + error_message = "Invalid visibility option. Allowed values are 'public', 'private', or 'public-and-private'." + } +} + +variable "prefix" { + type = string + nullable = true + description = "The prefix to add to all resources that this solution creates (e.g `prod`, `test`, `dev`). To skip using a prefix, set this value to `null` or an empty string. [Learn more](https://terraform-ibm-modules.github.io/documentation/#/prefix.md)." + + validation { + # - null and empty string is allowed + # - Must not contain consecutive hyphens (--): length(regexall("--", var.prefix)) == 0 + # - Starts with a lowercase letter: [a-z] + # - Contains only lowercase letters (a–z), digits (0–9), and hyphens (-) + # - Must not end with a hyphen (-): [a-z0-9] + condition = (var.prefix == null || var.prefix == "" ? true : + alltrue([ + can(regex("^[a-z][-a-z0-9]*[a-z0-9]$", var.prefix)), + length(regexall("--", var.prefix)) == 0 + ]) + ) + error_message = "Prefix must begin with a lowercase letter and may contain only lowercase letters, digits, and hyphens '-'. It must not end with a hyphen('-'), and cannot contain consecutive hyphens ('--')." + } + + validation { + # must not exceed 16 characters in length + condition = var.prefix == null || var.prefix == "" ? true : length(var.prefix) <= 16 + error_message = "Prefix must not exceed 16 characters." + } +} + +variable "region" { + type = string + description = "Region in which all the resources will be deployed. [Learn More](https://terraform-ibm-modules.github.io/documentation/#/region)." + default = "us-south" +} + +variable "resource_tags" { + type = list(string) + description = "Optional list of tags to be added to the resources created by this solution." + default = [] +} diff --git a/solutions/quickstart/version.tf b/solutions/quickstart/version.tf new file mode 100644 index 00000000..91330e55 --- /dev/null +++ b/solutions/quickstart/version.tf @@ -0,0 +1,16 @@ +terraform { + required_version = ">= 1.9.0" + + # Lock DA into an exact provider version - renovate automation will keep it updated + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + version = "1.84.3" + } + + restapi = { + source = "Mastercard/restapi" + version = "1.20.0" + } + } +} diff --git a/tests/pr_test.go b/tests/pr_test.go index 92a1e114..f02d9cec 100644 --- a/tests/pr_test.go +++ b/tests/pr_test.go @@ -15,7 +15,9 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/common" + "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testhelper" "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testprojects" + "github.com/terraform-ibm-modules/ibmcloud-terratest-wrapper/testschematic" ) // Define a struct with fields that match the structure of the YAML data @@ -29,6 +31,20 @@ var validRegions = []string{ "us-south", } +// Use existing resource group +const resourceGroup = "geretain-test-resources" +const terraformVersion = "terraform_v1.12.2" // This should match the version in the ibm_catalog.json +var validQsRegions = []string{ + "us-south", + "eu-de", + "eu-gb", + "jp-tok", + "au-syd", + // Ignoring below regions as not supported for watsonx Assistant and watson Discovery + // "ca-tor", + // "us-east" +} + func TestMain(m *testing.M) { // Read the YAML file contents var err error @@ -42,6 +58,7 @@ func TestMain(m *testing.M) { const basicDaStackDefPath = "solutions/basic/stack_definition.json" const standardDaStackDefPath = "solutions/standard/stack_definition.json" +const quickStartTerraformDir = "solutions/quickstart" func TestProjectsBasicFullTest(t *testing.T) { t.Parallel() @@ -191,3 +208,63 @@ func TestProjectsStandardFullTest(t *testing.T) { t.Error("TestProjectsFullTest Failed") } } + +func setupQuickstartOptions(t *testing.T, prefix string) *testschematic.TestSchematicOptions { + + var region = validQsRegions[rand.Intn(len(validQsRegions))] + options := testschematic.TestSchematicOptionsDefault(&testschematic.TestSchematicOptions{ + Testing: t, + TemplateFolder: quickStartTerraformDir, + Prefix: prefix, + Region: region, + ResourceGroup: resourceGroup, + TarIncludePatterns: []string{ + quickStartTerraformDir + "/*.tf", + }, + + IgnoreDestroys: testhelper.Exemptions{ // Ignore for consistency check + List: []string{ + "module.watsonx_ai.module.configure_user.null_resource.configure_user", + "module.watsonx_ai.module.configure_user.null_resource.restrict_access", + }, + }, + IgnoreUpdates: testhelper.Exemptions{ // Ignore for consistency check + List: []string{ + "module.watsonx_ai.module.configure_user.null_resource.configure_user", + "module.watsonx_ai.module.configure_user.null_resource.restrict_access", + }, + }, + TerraformVersion: terraformVersion, + }) + + options.TerraformVars = []testschematic.TestSchematicTerraformVar{ + {Name: "ibmcloud_api_key", Value: options.RequiredEnvironmentVars["TF_VAR_ibmcloud_api_key"], DataType: "string", Secure: true}, + {Name: "prefix", Value: options.Prefix, DataType: "string"}, + {Name: "region", Value: options.Region, DataType: "string"}, + {Name: "provider_visibility", Value: "private", DataType: "string"}, + {Name: "existing_resource_group_name", Value: resourceGroup, DataType: "string"}, + } + + return options +} + +func TestRunQuickstartSolutionSchematics(t *testing.T) { + t.Parallel() + + options := setupQuickstartOptions(t, "rag-qs") + err := options.RunSchematicTest() + assert.Nil(t, err, "This should not have errored") +} + +// Upgrade test for the Quickstart DA +func TestRunQuickstartUpgradeSolutionSchematics(t *testing.T) { + t.Parallel() + + options := setupQuickstartOptions(t, "rag-qs-upg") + options.CheckApplyResultForUpgrade = true + + err := options.RunSchematicUpgradeTest() + if !options.UpgradeTestSkipped { + assert.Nil(t, err, "This should not have errored") + } +}
Container registry stores images built by IBM Code Engine.