An open API service indexing awesome lists of open source software.

https://github.com/sourcefuse/terraform-aws-arc-sagemaker


https://github.com/sourcefuse/terraform-aws-arc-sagemaker

Last synced: 3 months ago
JSON representation

Awesome Lists containing this project

README

          

![Module Structure](./static/sagemaker-banner.png)
# AWS SageMaker Terraform Module
# [terraform-aws-arc-sagemaker](https://github.com/sourcefuse/terraform-aws-arc-sagemaker)

Latest Release Last Updated ![Terraform](https://img.shields.io/badge/terraform-%235835CC.svg?style=for-the-badge&logo=terraform&logoColor=white) ![GitHub Actions](https://img.shields.io/badge/github%20actions-%232671E5.svg?style=for-the-badge&logo=githubactions&logoColor=white)

[![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=sourcefuse_terraform-aws-arc-sagemaker&token=593eae6b5a514b62b2c08871c2f608e4ce172ec5)](https://sonarcloud.io/summary/new_code?id=sourcefuse_terraform-aws-arc-sagemaker)

## Overview

The ARC Terraform module provides a robust and fully extensible solution for managing SageMaker Studio domains, user profiles, models, endpoint, endpoint configurations, and pipelines. It supports custom app settings, and VPC integration to meet enterprise-grade machine learning needs. With dynamic configurations and secure defaults, the module enables rapid, consistent, and scalable SageMaker infrastructure provisioning using best practices.

### Prerequisites
Before using this module, ensure you have the following:

- AWS credentials configured.
- Terraform installed.
- A working knowledge of Terraform.

## Getting Started

1. **Define the Module**

Initially, it's essential to define a Terraform module, which is organized as a distinct directory encompassing Terraform configuration files. Within this module directory, input variables and output values must be defined in the variables.tf and outputs.tf files, respectively. The following illustrates an example directory structure:

```plaintext
sagemaker/
|-- main.tf
|-- variables.tf
|-- outputs.tf
```

2. **Define Input Variables**

Inside the `variables.tf` or in `*.tfvars` file, you should define values for the variables that the module requires.

3. **Use the Module in Your Main Configuration**
In your main Terraform configuration file (e.g., main.tf), you can use the module. Specify the source of the module, and version, For Example

```hcl
module "sagemaker_model" {
source = "sourcefuse/arc-sagemaker/aws"
version = "0.0.1"

name = "terraform-arc"
create_endpoint_config = true
create_model = true

primary_container = {
image = "683313688378.dkr.ecr.us-east-1.amazonaws.com/sagemaker-scikit-learn:1.0-1-cpu-py3"
model_data_url = "s3://your-sagemaker-model-bucket-21-05-25/model/model.tar.gz"
environment = {}
}

production_variants = [
{
variant_name = "AllTraffic"
initial_instance_count = 1
instance_type = "ml.m5.large"
initial_variant_weight = 1.0
}
]
tags = module.tags.tags
}
```

4. **Output Values**

Inside the `outputs.tf` file of the module, you can define output values that can be referenced in the main configuration. For example:

```hcl
output "model_name" {
description = "Name of the SageMaker model"
value = module.sagemaker_model.model_name
}

output "model_arn" {
description = "ARN of the SageMaker model"
value = module.sagemaker_model.model_arn
}

output "endpoint_config_arn" {
description = "ARN of the SageMaker endpoint configuration"
value = module.sagemaker_model.endpoint_config_arn
}

```

5. **.tfvars**

Inside the `.tfvars` file of the module, you can provide desired values that can be referenced in the main configuration.

## First Time Usage
***uncomment the backend block in [main.tf](./examples/endpoint//main.tf)***
```shell
terraform init -backend-config=config.dev.hcl
```
***If testing locally, `terraform init` should be fine***

Create a `dev` workspace
```shell
terraform workspace new dev
```

Plan Terraform
```shell
terraform plan -var-file dev.tfvars
```

Apply Terraform
```shell
terraform apply -var-file dev.tfvars
```

## Production Setup
```shell
terraform init -backend-config=config.prod.hcl
```

Create a `prod` workspace
```shell
terraform workspace new prod
```

Plan Terraform
```shell
terraform plan -var-file prod.tfvars
```

Apply Terraform
```shell
terraform apply -var-file prod.tfvars
```

## Cleanup
Destroy Terraform
```shell
terraform destroy -var-file dev.tfvars
```

## Requirements

| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.0 |
| [aws](#requirement\_aws) | ~> 5.0 |

## Providers

| Name | Version |
|------|---------|
| [aws](#provider\_aws) | 5.100.0 |

## Modules

| Name | Source | Version |
|------|--------|---------|
| [arc\_security\_group](#module\_arc\_security\_group) | sourcefuse/arc-security-group/aws | 0.0.1 |

## Resources

| Name | Type |
|------|------|
| [aws_iam_role.execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.pipeline_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role.sagemaker_execution_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy.execution_role_custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy.pipeline_role_custom](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource |
| [aws_iam_role_policy_attachment.attach_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.execution_role_all_policies](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_iam_role_policy_attachment.pipeline_role_sagemaker_full_access](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_sagemaker_domain.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sagemaker_domain) | resource |
| [aws_sagemaker_endpoint.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sagemaker_endpoint) | resource |
| [aws_sagemaker_endpoint_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sagemaker_endpoint_configuration) | resource |
| [aws_sagemaker_model.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sagemaker_model) | resource |
| [aws_sagemaker_pipeline.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sagemaker_pipeline) | resource |
| [aws_sagemaker_user_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sagemaker_user_profile) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| [additional\_iam\_policies](#input\_additional\_iam\_policies) | List of additional IAM policy ARNs to attach to the execution role | `list(string)` | `[]` | no |
| [additional\_security\_group\_ids](#input\_additional\_security\_group\_ids) | List of additional security group IDs to attach to the domain | `list(string)` | `[]` | no |
| [app\_network\_access\_type](#input\_app\_network\_access\_type) | Specifies the VPC used for non-EFS traffic. Valid values are PublicInternetOnly and VpcOnly | `string` | `"PublicInternetOnly"` | no |
| [app\_security\_group\_management](#input\_app\_security\_group\_management) | The entity that creates and manages the required security groups for inter-app communication in VPCOnly mode. Valid values are Service and Customer | `string` | `"Service"` | no |
| [async\_inference\_config](#input\_async\_inference\_config) | (Optional) Configuration for asynchronous inference. |

object({
output_config = object({
s3_output_path = string
s3_failure_path = optional(string)
kms_key_id = optional(string)
notification_config = optional(object({
include_inference_response_in = optional(string)
error_topic = optional(string)
success_topic = optional(string)
}))
})
client_config = optional(object({
max_concurrent_invocations_per_instance = optional(number)
}))
})
| `null` | no |
| [auth\_mode](#input\_auth\_mode) | The mode of authentication that members use to access the domain. Valid values are IAM and SSO | `string` | `"IAM"` | no |
| [container](#input\_container) | List of containers for inference pipeline (alternative to primary\_container) | `list(any)` | `null` | no |
| [create\_domain](#input\_create\_domain) | Whether to create the SageMaker domain | `bool` | `false` | no |
| [create\_endpoint](#input\_create\_endpoint) | Whether to create the SageMaker endpoint | `bool` | `false` | no |
| [create\_endpoint\_config](#input\_create\_endpoint\_config) | Whether to create the SageMaker endpoint configuration | `bool` | `false` | no |
| [create\_execution\_role](#input\_create\_execution\_role) | Whether to create an execution role for SageMaker | `bool` | `false` | no |
| [create\_model](#input\_create\_model) | Whether to create the SageMaker model | `bool` | `false` | no |
| [create\_pipeline](#input\_create\_pipeline) | Whether to create the SageMaker pipeline | `bool` | `false` | no |
| [create\_pipeline\_role](#input\_create\_pipeline\_role) | Whether to create a separate role for pipelines | `bool` | `false` | no |
| [create\_sagemaker\_execution\_role](#input\_create\_sagemaker\_execution\_role) | Whether to create an SageMaker execution role | `bool` | `false` | no |
| [create\_security\_groups](#input\_create\_security\_groups) | Whether to create security groups for SageMaker Studio | `bool` | `false` | no |
| [create\_user\_profile](#input\_create\_user\_profile) | Whether to create the SageMaker user profile | `bool` | `false` | no |
| [data\_capture\_config](#input\_data\_capture\_config) | (Optional) Configuration for capturing input/output data. |
object({
initial_sampling_percentage = number
destination_s3_uri = string
kms_key_id = optional(string)
enable_capture = optional(bool)
capture_options = list(object({
capture_mode = string
}))
capture_content_type_header = optional(object({
csv_content_types = optional(list(string))
json_content_types = optional(list(string))
}))
})
| `null` | no |
| [default\_space\_settings](#input\_default\_space\_settings) | The default space settings for the domain |
object({
execution_role_arn = string
security_groups = optional(list(string))

jupyter_server_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

kernel_gateway_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

jupyter_lab_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

space_storage_settings = optional(object({
default_ebs_storage_settings = optional(object({
default_ebs_volume_size_in_gb = number
maximum_ebs_volume_size_in_gb = number
}))
}))

custom_file_system_config = optional(object({
efs_file_system_config = optional(object({
file_system_id = string
file_system_path = string
}))
}))

custom_posix_user_config = optional(object({
gid = optional(number)
uid = optional(number)
}))
})
| `null` | no |
| [default\_user\_settings](#input\_default\_user\_settings) | The default user settings for the domain |
object({
execution_role_arn = string
auto_mount_home_efs = optional(string, "Disabled")
default_landing_uri = optional(string)
studio_web_portal = optional(string, "ENABLED")

jupyter_lab_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

app_lifecycle_management = optional(object({
idle_settings = optional(object({
lifecycle_management = optional(string, "ENABLED")
idle_timeout_in_minutes = optional(number, 60)
max_idle_timeout_in_minutes = optional(number, 480)
min_idle_timeout_in_minutes = optional(number, 60)
}))
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

code_repositories = optional(list(object({
repository_url = string
})))

lifecycle_config_arns = optional(list(string))
built_in_lifecycle_config_arn = optional(string)

emr_settings = optional(object({
assumable_role_arns = optional(list(string))
execution_role_arns = optional(list(string))
}))
}))

code_editor_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

app_lifecycle_management = optional(object({
idle_settings = optional(object({
lifecycle_management = optional(string, "ENABLED")
idle_timeout_in_minutes = optional(number, 60)
max_idle_timeout_in_minutes = optional(number, 480)
min_idle_timeout_in_minutes = optional(number, 60)
}))
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

lifecycle_config_arns = optional(list(string))
built_in_lifecycle_config_arn = optional(string)
}))

jupyter_server_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

code_repositories = optional(list(object({
repository_url = string
})))

lifecycle_config_arns = optional(list(string))
}))

kernel_gateway_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

lifecycle_config_arns = optional(list(string))
}))

canvas_app_settings = optional(object({
time_series_forecasting_settings = optional(object({
status = optional(string, "DISABLED")
amazon_forecast_role_arn = optional(string)
}))

model_register_settings = optional(object({
status = optional(string, "DISABLED")
cross_account_model_register_role_arn = optional(string)
}))

workspace_settings = optional(object({
s3_artifact_path = optional(string)
s3_kms_key_id = optional(string)
}))

direct_deploy_settings = optional(object({
status = optional(string, "DISABLED")
}))

kendra_settings = optional(object({
status = optional(string, "DISABLED")
}))

identity_provider_oauth_settings = optional(list(object({
data_source_name = optional(string)
secret_arn = optional(string)
status = optional(string, "DISABLED")
})))

emr_serverless_settings = optional(object({
execution_role_arn = optional(string)
status = optional(string, "DISABLED")
}))
}))

tensor_board_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

r_session_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))
}))

r_studio_server_pro_app_settings = optional(object({
access_status = optional(string, "DISABLED")
user_group = optional(string, "R_STUDIO_USER")
}))

sharing_settings = optional(object({
notebook_output_option = optional(string, "Disabled")
s3_kms_key_id = optional(string)
s3_output_path = optional(string)
}))

space_storage_settings = optional(object({
default_ebs_storage_settings = optional(object({
default_ebs_volume_size_in_gb = number
maximum_ebs_volume_size_in_gb = number
}))
}))

custom_file_system_config = optional(object({
efs_file_system_config = optional(object({
file_system_id = string
file_system_path = string
}))
}))

custom_posix_user_config = optional(object({
gid = optional(number)
uid = optional(number)
}))

studio_web_portal_settings = optional(object({
hidden_app_types = optional(list(string))
hidden_instance_types = optional(list(string))
hidden_ml_tools = optional(list(string))
}))
})
| `null` | no |
| [deployment\_config](#input\_deployment\_config) | Deployment configuration block |
object({
blue_green_update_policy = optional(object({
traffic_routing_configuration = object({
type = string
wait_interval_in_seconds = number
canary_size = optional(object({
type = string
value = number
}))
linear_step_size = optional(object({
type = string
value = number
}))
})
maximum_execution_timeout_in_seconds = optional(number)
termination_wait_in_seconds = optional(number)
}))
auto_rollback_configuration = optional(object({
alarms = list(object({
alarm_name = string
}))
}))
rolling_update_policy = optional(object({
wait_interval_in_seconds = number
maximum_execution_timeout_in_seconds = optional(number)
maximum_batch_size = object({
type = string
value = number
})
rollback_maximum_batch_size = optional(object({
type = string
value = number
}))
}))
})
| `null` | no |
| [domain\_name](#input\_domain\_name) | The name of the SageMaker domain | `string` | `"arc-sagemaker-domain"` | no |
| [domain\_settings](#input\_domain\_settings) | The domain settings |
object({
execution_role_identity_config = optional(string, "USER_PROFILE_NAME")
security_group_ids = optional(list(string))

docker_settings = optional(object({
enable_docker_access = optional(string, "ENABLED")
vpc_only_trusted_accounts = optional(list(string))
}))

r_studio_server_pro_domain_settings = optional(object({
domain_execution_role_arn = string
r_studio_connect_url = optional(string)
r_studio_package_manager_url = optional(string)

default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))
})
| `null` | no |
| [enable\_network\_isolation](#input\_enable\_network\_isolation) | Isolate the model container from external network | `bool` | `null` | no |
| [execution\_role\_name](#input\_execution\_role\_name) | Name of the execution role to create | `string` | `"SageMakerStudioExecutionRole"` | no |
| [execution\_role\_path](#input\_execution\_role\_path) | Path for the execution role | `string` | `"/"` | no |
| [inference\_execution\_config](#input\_inference\_execution\_config) | Multi-container execution configuration |
object({
mode = string
})
| `null` | no |
| [kms\_key\_arn](#input\_kms\_key\_arn) | (Optional) ARN of the KMS key to encrypt storage volume data. | `string` | `null` | no |
| [kms\_key\_id](#input\_kms\_key\_id) | The AWS KMS customer managed CMK used to encrypt the EFS volume attached to the domain | `string` | `null` | no |
| [name](#input\_name) | The name of the SageMaker model. | `string` | `"terraform-sg"` | no |
| [name\_prefix](#input\_name\_prefix) | (Optional) Prefix for the endpoint configuration name. Conflicts with name. | `string` | `null` | no |
| [pipeline\_role\_name](#input\_pipeline\_role\_name) | Name of the pipeline role to create | `string` | `"SageMakerPipelineExecutionRole"` | no |
| [pipeline\_role\_path](#input\_pipeline\_role\_path) | Path for the pipeline role | `string` | `"/"` | no |
| [pipelines](#input\_pipelines) | List of SageMaker pipelines to create |
list(object({
name = string
display_name = string
description = optional(string)
definition = optional(string)
role_arn = optional(string)
tags = optional(map(string))

pipeline_definition_s3_location = optional(object({
bucket = string
object_key = string
version_id = optional(string)
}))

parallelism_configuration = optional(object({
max_parallel_execution_steps = number
}))
}))
| `[]` | no |
| [primary\_container](#input\_primary\_container) | Primary container block |
object({
image = string
mode = optional(string)
model_data_url = optional(string)
model_package_name = optional(string)
container_hostname = optional(string)
environment = optional(map(string))
image_config = optional(object({
repository_access_mode = string
repository_auth_config = optional(object({
repository_credentials_provider_arn = string
}))
}))
inference_specification_name = optional(string)
multi_model_config = optional(object({
model_cache_setting = string
}))
model_data_source = optional(object({
s3_data_source = object({
compression_type = string
s3_data_type = string
s3_uri = string
model_access_config = optional(object({
accept_eula = bool
}))
})
}))
})
|
{
"environment": {},
"image": "683313688378.dkr.ecr.us-east-1.amazonaws.com/sagemaker-scikit-learn:1.0-1-cpu-py3",
"model_data_url": "s3://your-sagemaker-model-bucket-21-05-25/model/model.tar.gz"
}
| no |
| [production\_variants](#input\_production\_variants) | (Required) List of production variant configurations. |
list(object({
variant_name = optional(string)
model_name = optional(string)
initial_instance_count = optional(number)
instance_type = optional(string)
accelerator_type = optional(string)
container_startup_health_check_timeout_in_seconds = optional(number)
core_dump_config = optional(object({
destination_s3_uri = string
kms_key_id = string
}))
enable_ssm_access = optional(bool)
inference_ami_version = optional(string)
initial_variant_weight = optional(number)
model_data_download_timeout_in_seconds = optional(number)
routing_config = optional(object({
routing_strategy = string
}))
serverless_config = optional(object({
max_concurrency = number
memory_size_in_mb = number
provisioned_concurrency = optional(number)
}))
managed_instance_scaling = optional(object({
status = optional(string)
min_instance_count = optional(number)
max_instance_count = optional(number)
}))
volume_size_in_gb = optional(number)
}))
|
[
{
"initial_instance_count": 1,
"initial_variant_weight": 1,
"instance_type": "ml.m5.large",
"variant_name": "AllTraffic"
}
]
| no |
| [retention\_policy](#input\_retention\_policy) | The retention policy for the domain |
object({
home_efs_file_system = optional(string, "Retain")
})
| `null` | no |
| [security\_group\_data](#input\_security\_group\_data) | (optional) Security Group data |
object({
security_group_ids_to_attach = optional(list(string), [])
create = optional(bool, true)
description = optional(string, null)
ingress_rules = optional(list(object({
description = optional(string, null)
cidr_block = optional(string, null)
source_security_group_id = optional(string, null)
from_port = number
ip_protocol = string
to_port = string
self = optional(bool, false)
})), [])
egress_rules = optional(list(object({
description = optional(string, null)
cidr_block = optional(string, null)
destination_security_group_id = optional(string, null)
from_port = number
ip_protocol = string
to_port = string
prefix_list_id = optional(string, null)
})), [])
})
|
{
"create": false
}
| no |
| [security\_group\_name](#input\_security\_group\_name) | sagemaker security group name | `string` | `"sagemaker-sg"` | no |
| [shadow\_production\_variants](#input\_shadow\_production\_variants) | (Optional) List of shadow production variant configurations. |
list(object({
variant_name = optional(string)
model_name = string
initial_instance_count = optional(number)
instance_type = optional(string)
initial_variant_weight = optional(number)
}))
| `[]` | no |
| [subnet\_ids](#input\_subnet\_ids) | The VPC subnets that Studio uses for communication | `list(string)` | `[]` | no |
| [tag\_propagation](#input\_tag\_propagation) | Indicates whether custom tag propagation is supported for the domain. Valid values are ENABLED and DISABLED | `string` | `"DISABLED"` | no |
| [tags](#input\_tags) | Tags to assign to the SageMaker model | `map(string)` | `{}` | no |
| [user\_profiles](#input\_user\_profiles) | List of user profiles to create |
list(object({
name = string
single_sign_on_user_identifier = optional(string)
single_sign_on_user_value = optional(string)
tags = optional(map(string))

user_settings = optional(object({
execution_role_arn = optional(string)
auto_mount_home_efs = optional(string)
default_landing_uri = optional(string)
studio_web_portal = optional(string)
security_groups = optional(list(string))

jupyter_lab_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

app_lifecycle_management = optional(object({
idle_settings = optional(object({
lifecycle_management = optional(string)
idle_timeout_in_minutes = optional(number)
max_idle_timeout_in_minutes = optional(number)
min_idle_timeout_in_minutes = optional(number)
}))
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

code_repositories = optional(list(object({
repository_url = string
})))

lifecycle_config_arns = optional(list(string))
built_in_lifecycle_config_arn = optional(string)

emr_settings = optional(object({
assumable_role_arns = optional(list(string))
execution_role_arns = optional(list(string))
}))
}))

code_editor_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

app_lifecycle_management = optional(object({
idle_settings = optional(object({
lifecycle_management = optional(string)
idle_timeout_in_minutes = optional(number)
max_idle_timeout_in_minutes = optional(number)
min_idle_timeout_in_minutes = optional(number)
}))
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

lifecycle_config_arns = optional(list(string))
built_in_lifecycle_config_arn = optional(string)
}))

jupyter_server_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

code_repositories = optional(list(object({
repository_url = string
})))

lifecycle_config_arns = optional(list(string))
}))

kernel_gateway_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

lifecycle_config_arns = optional(list(string))
}))

canvas_app_settings = optional(object({
time_series_forecasting_settings = optional(object({
status = optional(string)
amazon_forecast_role_arn = optional(string)
}))

model_register_settings = optional(object({
status = optional(string)
cross_account_model_register_role_arn = optional(string)
}))

workspace_settings = optional(object({
s3_artifact_path = optional(string)
s3_kms_key_id = optional(string)
}))

direct_deploy_settings = optional(object({
status = optional(string)
}))

kendra_settings = optional(object({
status = optional(string)
}))

identity_provider_oauth_settings = optional(list(object({
data_source_name = optional(string)
secret_arn = optional(string)
status = optional(string)
})))

emr_serverless_settings = optional(object({
execution_role_arn = optional(string)
status = optional(string)
}))
}))

tensor_board_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

r_session_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))
}))

r_studio_server_pro_app_settings = optional(object({
access_status = optional(string)
user_group = optional(string)
}))

sharing_settings = optional(object({
notebook_output_option = optional(string)
s3_kms_key_id = optional(string)
s3_output_path = optional(string)
}))

space_storage_settings = optional(object({
default_ebs_storage_settings = optional(object({
default_ebs_volume_size_in_gb = number
maximum_ebs_volume_size_in_gb = number
}))
}))

custom_file_system_config = optional(object({
efs_file_system_config = optional(object({
file_system_id = string
file_system_path = string
}))
}))

custom_posix_user_config = optional(object({
gid = optional(number)
uid = optional(number)
}))

studio_web_portal_settings = optional(object({
hidden_app_types = optional(list(string))
hidden_instance_types = optional(list(string))
hidden_ml_tools = optional(list(string))
}))
}))
}))
| `[]` | no |
| [vpc\_config](#input\_vpc\_config) | VPC configuration for the model |
object({
security_group_ids = list(string)
subnets = list(string)
})
| `null` | no |
| [vpc\_id](#input\_vpc\_id) | The ID of the VPC that Studio uses for communication | `string` | `null` | no |

## Outputs

| Name | Description |
|------|-------------|
| [domain\_arn](#output\_domain\_arn) | ARN of the SageMaker domain |
| [domain\_id](#output\_domain\_id) | ID of the SageMaker domain |
| [domain\_url](#output\_domain\_url) | URL to access the SageMaker Studio |
| [endpoint\_arn](#output\_endpoint\_arn) | ARN of the SageMaker endpoint |
| [endpoint\_config\_arn](#output\_endpoint\_config\_arn) | ARN of the SageMaker endpoint configuration |
| [endpoint\_config\_name](#output\_endpoint\_config\_name) | Name of the SageMaker endpoint configuration |
| [endpoint\_name](#output\_endpoint\_name) | Name of the SageMaker endpoint |
| [model\_arn](#output\_model\_arn) | ARN of the SageMaker model |
| [model\_name](#output\_model\_name) | Name of the SageMaker model |
| [pipeline\_arns](#output\_pipeline\_arns) | List of SageMaker pipeline ARNs |
| [pipeline\_names](#output\_pipeline\_names) | List of SageMaker pipeline names |
| [user\_profile\_names](#output\_user\_profile\_names) | List of SageMaker user profile names |
| [user\_profiles](#output\_user\_profiles) | Map of SageMaker user profiles with their ARNs |

## Versioning
This project uses a `.version` file at the root of the repo which the pipeline reads from and does a git tag.

When you intend to commit to `main`, you will need to increment this version. Once the project is merged,
the pipeline will kick off and tag the latest git commit.

## Development

### Prerequisites

- [terraform](https://learn.hashicorp.com/terraform/getting-started/install#installing-terraform)
- [terraform-docs](https://github.com/segmentio/terraform-docs)
- [pre-commit](https://pre-commit.com/#install)
- [golang](https://golang.org/doc/install#install)
- [golint](https://github.com/golang/lint#installation)

### Configurations

- Configure pre-commit hooks
```sh
pre-commit install
```

### Versioning

while Contributing or doing git commit please specify the breaking change in your commit message whether its major,minor or patch

For Example

```sh
git commit -m "your commit message #major"
```
By specifying this , it will bump the version and if you don't specify this in your commit message then by default it will consider patch and will bump that accordingly

### Tests
- Tests are available in `test` directory
- Configure the dependencies
```sh
cd test/
go mod init github.com/sourcefuse/terraform-aws-refarch-
go get github.com/gruntwork-io/terratest/modules/terraform
```
- Now execute the test
```sh
go test -timeout 30m
```

## Authors

This project is authored by:
- SourceFuse ARC Team