diff --git a/aws/internal/service/sagemaker/finder/finder.go b/aws/internal/service/sagemaker/finder/finder.go new file mode 100644 index 00000000000..025fd543c0c --- /dev/null +++ b/aws/internal/service/sagemaker/finder/finder.go @@ -0,0 +1,25 @@ +package finder + +import ( + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/sagemaker" +) + +// CodeRepositoryByName returns the code repository corresponding to the specified name. +// Returns nil if no code repository is found. +func CodeRepositoryByName(conn *sagemaker.SageMaker, name string) (*sagemaker.DescribeCodeRepositoryOutput, error) { + input := &sagemaker.DescribeCodeRepositoryInput{ + CodeRepositoryName: aws.String(name), + } + + output, err := conn.DescribeCodeRepository(input) + if err != nil { + return nil, err + } + + if output == nil { + return nil, nil + } + + return output, nil +} diff --git a/aws/provider.go b/aws/provider.go index c22517dd2b3..bf3d1c94755 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -829,6 +829,7 @@ func Provider() *schema.Provider { "aws_route_table": resourceAwsRouteTable(), "aws_default_route_table": resourceAwsDefaultRouteTable(), "aws_route_table_association": resourceAwsRouteTableAssociation(), + "aws_sagemaker_code_repository": resourceAwsSagemakerCodeRepository(), "aws_sagemaker_model": resourceAwsSagemakerModel(), "aws_sagemaker_endpoint_configuration": resourceAwsSagemakerEndpointConfiguration(), "aws_sagemaker_endpoint": resourceAwsSagemakerEndpoint(), diff --git a/aws/resource_aws_sagemaker_code_repository.go b/aws/resource_aws_sagemaker_code_repository.go new file mode 100644 index 00000000000..b85f11cf905 --- /dev/null +++ b/aws/resource_aws_sagemaker_code_repository.go @@ -0,0 +1,202 @@ +package aws + +import ( + "fmt" + "log" + "regexp" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/sagemaker" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/sagemaker/finder" +) + +func resourceAwsSagemakerCodeRepository() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsSagemakerCodeRepositoryCreate, + Read: resourceAwsSagemakerCodeRepositoryRead, + Update: resourceAwsSagemakerCodeRepositoryUpdate, + Delete: resourceAwsSagemakerCodeRepositoryDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + + "code_repository_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 63), + validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9](-*[a-zA-Z0-9])*$`), "Valid characters are a-z, A-Z, 0-9, and - (hyphen)."), + ), + }, + "git_config": { + Type: schema.TypeList, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "repository_url": { + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + "branch": { + Type: schema.TypeString, + ForceNew: true, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 1024), + }, + "secret_arn": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateArn, + }, + }, + }, + }, + }, + } +} + +func resourceAwsSagemakerCodeRepositoryCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).sagemakerconn + + name := d.Get("code_repository_name").(string) + + input := &sagemaker.CreateCodeRepositoryInput{ + CodeRepositoryName: aws.String(name), + GitConfig: expandSagemakerCodeRepositoryGitConfig(d.Get("git_config").([]interface{})), + } + + log.Printf("[DEBUG] sagemaker code repository create config: %#v", *input) + _, err := conn.CreateCodeRepository(input) + if err != nil { + return fmt.Errorf("error creating SageMaker code repository: %w", err) + } + + d.SetId(name) + + return resourceAwsSagemakerCodeRepositoryRead(d, meta) +} + +func resourceAwsSagemakerCodeRepositoryRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).sagemakerconn + + codeRepository, err := finder.CodeRepositoryByName(conn, d.Id()) + if err != nil { + if isAWSErr(err, "ValidationException", "Cannot find CodeRepository") { + d.SetId("") + log.Printf("[WARN] Unable to find SageMaker code repository (%s); removing from state", d.Id()) + return nil + } + return fmt.Errorf("error reading SageMaker code repository (%s): %w", d.Id(), err) + + } + + d.Set("code_repository_name", codeRepository.CodeRepositoryName) + d.Set("arn", codeRepository.CodeRepositoryArn) + + if err := d.Set("git_config", flattenSagemakerCodeRepositoryGitConfig(codeRepository.GitConfig)); err != nil { + return fmt.Errorf("error setting git_config for sagemaker code repository (%s): %w", d.Id(), err) + } + + return nil +} + +func resourceAwsSagemakerCodeRepositoryUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).sagemakerconn + + input := &sagemaker.UpdateCodeRepositoryInput{ + CodeRepositoryName: aws.String(d.Id()), + GitConfig: expandSagemakerCodeRepositoryUpdateGitConfig(d.Get("git_config").([]interface{})), + } + + log.Printf("[DEBUG] sagemaker code repository update config: %#v", *input) + _, err := conn.UpdateCodeRepository(input) + if err != nil { + return fmt.Errorf("error updating SageMaker code repository: %w", err) + } + + return resourceAwsSagemakerCodeRepositoryRead(d, meta) +} + +func resourceAwsSagemakerCodeRepositoryDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).sagemakerconn + + input := &sagemaker.DeleteCodeRepositoryInput{ + CodeRepositoryName: aws.String(d.Id()), + } + + if _, err := conn.DeleteCodeRepository(input); err != nil { + if isAWSErr(err, "ValidationException", "Cannot find CodeRepository") { + return nil + } + return fmt.Errorf("error deleting SageMaker code repository (%s): %w", d.Id(), err) + } + + return nil +} + +func expandSagemakerCodeRepositoryGitConfig(l []interface{}) *sagemaker.GitConfig { + if len(l) == 0 || l[0] == nil { + return nil + } + + m := l[0].(map[string]interface{}) + + config := &sagemaker.GitConfig{ + RepositoryUrl: aws.String(m["repository_url"].(string)), + } + + if v, ok := m["branch"].(string); ok && v != "" { + config.Branch = aws.String(v) + } + + if v, ok := m["secret_arn"].(string); ok && v != "" { + config.SecretArn = aws.String(v) + } + + return config +} + +func flattenSagemakerCodeRepositoryGitConfig(config *sagemaker.GitConfig) []map[string]interface{} { + if config == nil { + return []map[string]interface{}{} + } + + m := map[string]interface{}{ + "repository_url": aws.StringValue(config.RepositoryUrl), + } + + if config.Branch != nil { + m["branch"] = aws.StringValue(config.Branch) + } + + if config.SecretArn != nil { + m["secret_arn"] = aws.StringValue(config.SecretArn) + } + + return []map[string]interface{}{m} +} + +func expandSagemakerCodeRepositoryUpdateGitConfig(l []interface{}) *sagemaker.GitConfigForUpdate { + if len(l) == 0 || l[0] == nil { + return nil + } + + m := l[0].(map[string]interface{}) + + config := &sagemaker.GitConfigForUpdate{ + SecretArn: aws.String(m["secret_arn"].(string)), + } + + return config +} diff --git a/aws/resource_aws_sagemaker_code_repository_test.go b/aws/resource_aws_sagemaker_code_repository_test.go new file mode 100644 index 00000000000..4018a985c55 --- /dev/null +++ b/aws/resource_aws_sagemaker_code_repository_test.go @@ -0,0 +1,297 @@ +package aws + +import ( + "fmt" + "log" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/sagemaker" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/sagemaker/finder" +) + +func init() { + resource.AddTestSweepers("aws_sagemaker_code_repository", &resource.Sweeper{ + Name: "aws_sagemaker_code_repository", + F: testSweepSagemakerCodeRepositories, + }) +} + +func testSweepSagemakerCodeRepositories(region string) error { + client, err := sharedClientForRegion(region) + if err != nil { + return fmt.Errorf("error getting client: %s", err) + } + conn := client.(*AWSClient).sagemakerconn + + err = conn.ListCodeRepositoriesPages(&sagemaker.ListCodeRepositoriesInput{}, func(page *sagemaker.ListCodeRepositoriesOutput, lastPage bool) bool { + for _, instance := range page.CodeRepositorySummaryList { + name := aws.StringValue(instance.CodeRepositoryName) + + input := &sagemaker.DeleteCodeRepositoryInput{ + CodeRepositoryName: instance.CodeRepositoryName, + } + + log.Printf("[INFO] Deleting SageMaker Code Repository: %s", name) + if _, err := conn.DeleteCodeRepository(input); err != nil { + log.Printf("[ERROR] Error deleting SageMaker Code Repository (%s): %s", name, err) + continue + } + } + + return !lastPage + }) + + if testSweepSkipSweepError(err) { + log.Printf("[WARN] Skipping SageMaker Code Repository sweep for %s: %s", region, err) + return nil + } + + if err != nil { + return fmt.Errorf("Error retrieving SageMaker Code Repositorys: %w", err) + } + + return nil +} + +func TestAccAWSSagemakerCodeRepository_basic(t *testing.T) { + var notebook sagemaker.DescribeCodeRepositoryOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_sagemaker_code_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSagemakerCodeRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSagemakerCodeRepositoryBasicConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSagemakerCodeRepositoryExists(resourceName, ¬ebook), + resource.TestCheckResourceAttr(resourceName, "code_repository_name", rName), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "sagemaker", fmt.Sprintf("code-repository/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "git_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "git_config.0.repository_url", "https://github.com/terraform-providers/terraform-provider-aws.git"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSSagemakerCodeRepository_gitConfig_branch(t *testing.T) { + var notebook sagemaker.DescribeCodeRepositoryOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_sagemaker_code_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSagemakerCodeRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSagemakerCodeRepositoryGitConfigBranchConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSagemakerCodeRepositoryExists(resourceName, ¬ebook), + resource.TestCheckResourceAttr(resourceName, "code_repository_name", rName), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "sagemaker", fmt.Sprintf("code-repository/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "git_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "git_config.0.repository_url", "https://github.com/terraform-providers/terraform-provider-aws.git"), + resource.TestCheckResourceAttr(resourceName, "git_config.0.branch", "master"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSSagemakerCodeRepository_gitConfig_secret(t *testing.T) { + var notebook sagemaker.DescribeCodeRepositoryOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_sagemaker_code_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSagemakerCodeRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSagemakerCodeRepositoryGitConfigSecretConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSagemakerCodeRepositoryExists(resourceName, ¬ebook), + resource.TestCheckResourceAttr(resourceName, "code_repository_name", rName), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "sagemaker", fmt.Sprintf("code-repository/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "git_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "git_config.0.repository_url", "https://github.com/terraform-providers/terraform-provider-aws.git"), + resource.TestCheckResourceAttrPair(resourceName, "git_config.0.secret_arn", "aws_secretsmanager_secret.test", "arn"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSSagemakerCodeRepositoryGitConfigSecretUpdatedConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSagemakerCodeRepositoryExists(resourceName, ¬ebook), + resource.TestCheckResourceAttr(resourceName, "code_repository_name", rName), + testAccCheckResourceAttrRegionalARN(resourceName, "arn", "sagemaker", fmt.Sprintf("code-repository/%s", rName)), + resource.TestCheckResourceAttr(resourceName, "git_config.#", "1"), + resource.TestCheckResourceAttr(resourceName, "git_config.0.repository_url", "https://github.com/terraform-providers/terraform-provider-aws.git"), + resource.TestCheckResourceAttrPair(resourceName, "git_config.0.secret_arn", "aws_secretsmanager_secret.test2", "arn"), + ), + }, + }, + }) +} + +func TestAccAWSSagemakerCodeRepository_disappears(t *testing.T) { + var notebook sagemaker.DescribeCodeRepositoryOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_sagemaker_code_repository.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSagemakerCodeRepositoryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSagemakerCodeRepositoryBasicConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSagemakerCodeRepositoryExists(resourceName, ¬ebook), + testAccCheckResourceDisappears(testAccProvider, resourceAwsSagemakerCodeRepository(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccCheckAWSSagemakerCodeRepositoryDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).sagemakerconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_sagemaker_code_repository" { + continue + } + + codeRepository, err := finder.CodeRepositoryByName(conn, rs.Primary.ID) + if err != nil { + return nil + } + + if aws.StringValue(codeRepository.CodeRepositoryName) == rs.Primary.ID { + return fmt.Errorf("sagemaker Code Repository %q still exists", rs.Primary.ID) + } + } + + return nil +} + +func testAccCheckAWSSagemakerCodeRepositoryExists(n string, codeRepo *sagemaker.DescribeCodeRepositoryOutput) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No sagmaker Code Repository ID is set") + } + + conn := testAccProvider.Meta().(*AWSClient).sagemakerconn + resp, err := finder.CodeRepositoryByName(conn, rs.Primary.ID) + if err != nil { + return err + } + + *codeRepo = *resp + + return nil + } +} + +func testAccAWSSagemakerCodeRepositoryBasicConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_sagemaker_code_repository" "test" { + code_repository_name = %[1]q + + git_config { + repository_url = "https://github.com/terraform-providers/terraform-provider-aws.git" + } +} +`, rName) +} + +func testAccAWSSagemakerCodeRepositoryGitConfigBranchConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_sagemaker_code_repository" "test" { + code_repository_name = %[1]q + + git_config { + repository_url = "https://github.com/terraform-providers/terraform-provider-aws.git" + branch = "master" + } +} +`, rName) +} + +func testAccAWSSagemakerCodeRepositoryGitConfigSecretConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_secretsmanager_secret" "test" { + name = %[1]q +} + +resource "aws_secretsmanager_secret_version" "test" { + secret_id = aws_secretsmanager_secret.test.id + secret_string = jsonencode({ username = "example", passowrd = "example" }) +} + +resource "aws_sagemaker_code_repository" "test" { + code_repository_name = %[1]q + + git_config { + repository_url = "https://github.com/terraform-providers/terraform-provider-aws.git" + secret_arn = aws_secretsmanager_secret.test.arn + } + + depends_on = [aws_secretsmanager_secret_version.test] +} +`, rName) +} + +func testAccAWSSagemakerCodeRepositoryGitConfigSecretUpdatedConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_secretsmanager_secret" "test2" { + name = "%[1]s-2" +} + +resource "aws_secretsmanager_secret_version" "test2" { + secret_id = aws_secretsmanager_secret.test2.id + secret_string = jsonencode({ username = "example", passowrd = "example" }) +} + +resource "aws_sagemaker_code_repository" "test" { + code_repository_name = %[1]q + + git_config { + repository_url = "https://github.com/terraform-providers/terraform-provider-aws.git" + secret_arn = aws_secretsmanager_secret.test2.arn + } + + depends_on = [aws_secretsmanager_secret_version.test2] +} +`, rName) +} diff --git a/aws/resource_aws_sagemaker_notebook_instance_test.go b/aws/resource_aws_sagemaker_notebook_instance_test.go index a7bf3fd9ca8..506f9085560 100644 --- a/aws/resource_aws_sagemaker_notebook_instance_test.go +++ b/aws/resource_aws_sagemaker_notebook_instance_test.go @@ -549,6 +549,44 @@ func TestAccAWSSagemakerNotebookInstance_additional_code_repositories(t *testing }) } +func TestAccAWSSagemakerNotebookInstance_default_code_repository_sagemakerRepo(t *testing.T) { + var notebook sagemaker.DescribeNotebookInstanceOutput + rName := acctest.RandomWithPrefix("tf-acc-test") + var resourceName = "aws_sagemaker_notebook_instance.test" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSagemakerNotebookInstanceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSagemakerNotebookInstanceConfigDefaultCodeRepositorySageMakerRepo(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, ¬ebook), + resource.TestCheckResourceAttrPair(resourceName, "default_code_repository", "aws_sagemaker_code_repository.test", "code_repository_name"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSSagemakerNotebookInstanceBasicConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, ¬ebook), + resource.TestCheckResourceAttr(resourceName, "default_code_repository", ""), + ), + }, + { + Config: testAccAWSSagemakerNotebookInstanceConfigDefaultCodeRepositorySageMakerRepo(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSagemakerNotebookInstanceExists(resourceName, ¬ebook), + resource.TestCheckResourceAttrPair(resourceName, "default_code_repository", "aws_sagemaker_code_repository.test", "code_repository_name")), + }, + }, + }) +} + func testAccAWSSagemakerNotebookInstanceBaseConfig(rName string) string { return fmt.Sprintf(` resource "aws_iam_role" "test" { @@ -728,6 +766,25 @@ resource "aws_sagemaker_notebook_instance" "test" { `, rName, repo1, repo2) } +func testAccAWSSagemakerNotebookInstanceConfigDefaultCodeRepositorySageMakerRepo(rName string) string { + return testAccAWSSagemakerNotebookInstanceBaseConfig(rName) + fmt.Sprintf(` +resource "aws_sagemaker_code_repository" "test" { + code_repository_name = %[1]q + + git_config { + repository_url = "https://github.com/terraform-providers/terraform-provider-aws.git" + } +} + +resource "aws_sagemaker_notebook_instance" "test" { + name = %[1]q + role_arn = aws_iam_role.test.arn + instance_type = "ml.t2.medium" + default_code_repository = aws_sagemaker_code_repository.test.code_repository_name +} +`, rName) +} + func testAccAWSSagemakerNotebookInstanceKMSConfig(rName string) string { return testAccAWSSagemakerNotebookInstanceBaseConfig(rName) + fmt.Sprintf(` resource "aws_kms_key" "test" { diff --git a/website/docs/r/sagemaker_code_repository.htm.markdown b/website/docs/r/sagemaker_code_repository.htm.markdown new file mode 100644 index 00000000000..d5b8c5e6b5a --- /dev/null +++ b/website/docs/r/sagemaker_code_repository.htm.markdown @@ -0,0 +1,77 @@ +--- +subcategory: "Sagemaker" +layout: "aws" +page_title: "AWS: aws_sagemaker_code_repository" +description: |- + Provides a Sagemaker Code Repository resource. +--- + +# Resource: aws_sagemaker_code_repository + +Provides a Sagemaker Code Repository resource. + +## Example Usage + +### Basic usage + +```hcl +resource "aws_sagemaker_code_repository" "example" { + code_repository_name = "example" + + git_config { + repository_url = "https://github.com/terraform-providers/terraform-provider-aws.git" + } +} +``` + +### Example with Secret + +```hcl +resource "aws_secretsmanager_secret" "example" { + name = "example" +} + +resource "aws_secretsmanager_secret_version" "example" { + secret_id = aws_secretsmanager_secret.example.id + secret_string = jsonencode({ username = "example", passowrd = "example" }) +} + +resource "aws_sagemaker_code_repository" "example" { + code_repository_name = "example" + + git_config { + repository_url = "https://github.com/terraform-providers/terraform-provider-aws.git" + secret_arn = aws_secretsmanager_secret.example.arn + } + + depends_on = [aws_secretsmanager_secret_version.example] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `code_repository_name` - (Required) The name of the Code Repository (must be unique). +* `git_config` - (Required) Specifies details about the repository. see [Git Config](#git-config) details below. + +### Git Config + +* `repository_url` - (Required) The URL where the Git repository is located. +* `branch` - (Optional) The default branch for the Git repository. +* `secret_arn` - (Optional) The Amazon Resource Name (ARN) of the AWS Secrets Manager secret that contains the credentials used to access the git repository. The secret must have a staging label of AWSCURRENT and must be in the following format: `{"username": UserName, "password": Password}` + +## Attributes Reference + +The following attributes are exported: + +* `id` - The name of the Code Repository. +* `arn` - The Amazon Resource Name (ARN) assigned by AWS to this Code Repository. + +## Import + +Sagemaker Code Repositories can be imported using the `name`, e.g. + +``` +$ terraform import aws_sagemaker_code_repository.test_code_repository my-code-repo +``` diff --git a/website/docs/r/sagemaker_notebook_instance.html.markdown b/website/docs/r/sagemaker_notebook_instance.html.markdown index e89d4c35938..67adc650baa 100644 --- a/website/docs/r/sagemaker_notebook_instance.html.markdown +++ b/website/docs/r/sagemaker_notebook_instance.html.markdown @@ -12,7 +12,7 @@ Provides a Sagemaker Notebook Instance resource. ## Example Usage -Basic usage: +### Basic usage ```hcl resource "aws_sagemaker_notebook_instance" "ni" { @@ -26,6 +26,29 @@ resource "aws_sagemaker_notebook_instance" "ni" { } ``` +### Code repository usage + +```hcl +resource "aws_sagemaker_code_repository" "example" { + code_repository_name = "my-notebook-instance-code-repo" + + git_config { + repository_url = "https://github.com/terraform-providers/terraform-provider-aws.git" + } +} + +resource "aws_sagemaker_notebook_instance" "ni" { + name = "my-notebook-instance" + role_arn = aws_iam_role.role.arn + instance_type = "ml.t2.medium" + default_code_repository = aws_sagemaker_code_repository.example.code_repository_name + + tags = { + Name = "foo" + } +} +``` + ## Argument Reference The following arguments are supported: @@ -40,9 +63,9 @@ The following arguments are supported: * `lifecycle_config_name` - (Optional) The name of a lifecycle configuration to associate with the notebook instance. * `root_access` - (Optional) Whether root access is `Enabled` or `Disabled` for users of the notebook instance. The default value is `Enabled`. * `direct_internet_access` - (Optional) Set to `Disabled` to disable internet access to notebook. Requires `security_groups` and `subnet_id` to be set. Supported values: `Enabled` (Default) or `Disabled`. If set to `Disabled`, the notebook instance will be able to access resources only in your VPC, and will not be able to connect to Amazon SageMaker training and endpoint services unless your configure a NAT Gateway in your VPC. -* `default_code_repository` - (Optional) The Git repository associated with the notebook instance as its default code repository * `additional_code_repositories` - (Optional) An array of up to three Git repositories to associate with the notebook instance. These can be either the names of Git repositories stored as resources in your account, or the URL of Git repositories in [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) or in any other Git repository. These repositories are cloned at the same level as the default repository of your notebook instance. +* `default_code_repository` - (Optional) The Git repository associated with the notebook instance as its default code repository. This can be either the name of a Git repository stored as a resource in your account, or the URL of a Git repository in [AWS CodeCommit](https://docs.aws.amazon.com/codecommit/latest/userguide/welcome.html) or in any other Git repository. * `tags` - (Optional) A map of tags to assign to the resource. ## Attributes Reference