diff --git a/docs/data-sources/platform_connector_terraform_cloud.md b/docs/data-sources/platform_connector_terraform_cloud.md
new file mode 100644
index 000000000..ce996e110
--- /dev/null
+++ b/docs/data-sources/platform_connector_terraform_cloud.md
@@ -0,0 +1,58 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "harness_platform_connector_terraform_cloud Data Source - terraform-provider-harness"
+subcategory: ""
+description: |-
+ Resource for looking up a Terraform Cloud connector.
+---
+
+# harness_platform_connector_terraform_cloud (Data Source)
+
+Resource for looking up a Terraform Cloud connector.
+
+## Example Usage
+
+```terraform
+data "harness_platform_connector_terraform_cloud" "example" {
+ identifier = "identifier"
+}
+```
+
+
+## Schema
+
+### Required
+
+- `credentials` (Block List, Min: 1, Max: 1) Credentials to connect to Terraform Cloud platform. (see [below for nested schema](#nestedblock--credentials))
+
+### Optional
+
+- `identifier` (String) Unique identifier of the resource.
+- `name` (String) Name of the resource.
+- `org_id` (String) Unique identifier of the organization.
+- `project_id` (String) Unique identifier of the project.
+
+### Read-Only
+
+- `delegate_selectors` (Set of String) Connect only using delegates with these tags.
+- `description` (String) Description of the resource.
+- `execute_on_delegate` (Boolean) Execute validation on delegate or not.
+- `id` (String) The ID of this resource.
+- `tags` (Set of String) Tags to associate with the resource.
+- `url` (String) URL of the Terraform Cloud platform.
+
+
+### Nested Schema for `credentials`
+
+Required:
+
+- `api_token` (Block List, Min: 1, Max: 1) API token credentials to use for authentication. (see [below for nested schema](#nestedblock--credentials--api_token))
+
+
+### Nested Schema for `credentials.api_token`
+
+Required:
+
+- `api_token_ref` (String) Reference to a secret containing the api token to use for authentication. To reference a secret at the organization scope, prefix 'org' to the expression: org.{identifier}. To reference a secret at the account scope, prefix 'account` to the expression: account.{identifier}.
+
+
diff --git a/docs/resources/platform_connector_terraform_cloud.md b/docs/resources/platform_connector_terraform_cloud.md
new file mode 100644
index 000000000..01e74c0ac
--- /dev/null
+++ b/docs/resources/platform_connector_terraform_cloud.md
@@ -0,0 +1,92 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "harness_platform_connector_terraform_cloud Resource - terraform-provider-harness"
+subcategory: ""
+description: |-
+ Resource for creating a TerraformCloud connector.
+---
+
+# harness_platform_connector_terraform_cloud (Resource)
+
+Resource for creating a TerraformCloud connector.
+
+## Example Usage
+
+```terraform
+# Create Terraform Cloud connector using API token as secret
+
+resource "harness_platform_connector_terraform_cloud" "terraform_cloud" {
+ identifier = "example_terraform_cloud_connector"
+ name = "Example terraform cloud connector"
+ description = "description of terraform cloud connector"
+ tags = ["foo:bar"]
+ delegate_selectors = ["harness-delegate"]
+ credentials {
+ api_token {
+ api_token_ref = "account.TEST_terraform_cloud_api_token"
+ }
+ }
+}
+
+# Add connectivity mode by providing execute_on_delegate value. Default is to execute on Delegate
+
+resource "harness_platform_connector_terraform_cloud" "terraform_cloud" {
+ identifier = "example_terraform_cloud_connector"
+ name = "Example terraform cloud connector"
+ description = "description of terraform cloud connector"
+ delegate_selectors = ["harness-delegate"]
+ tags = ["foo:bar"]
+ execute_on_delegate = false
+ credentials {
+ api_token {
+ api_token_ref = "account.TEST_terraform_cloud_api_token"
+ }
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `credentials` (Block List, Min: 1, Max: 1) Credentials to connect to Terraform Cloud platform. (see [below for nested schema](#nestedblock--credentials))
+- `identifier` (String) Unique identifier of the resource.
+- `name` (String) Name of the resource.
+- `url` (String) URL of Terraform Cloud platform.
+
+### Optional
+
+- `delegate_selectors` (Set of String) Connect only using delegates with these tags.
+- `description` (String) Description of the resource.
+- `execute_on_delegate` (Boolean) Execute validation on delegate or not.
+- `org_id` (String) Unique identifier of the organization.
+- `project_id` (String) Unique identifier of the project.
+- `tags` (Set of String) Tags to associate with the resource.
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+
+
+### Nested Schema for `credentials`
+
+Required:
+
+- `api_token` (Block List, Min: 1, Max: 1) API token credentials to use for authentication. (see [below for nested schema](#nestedblock--credentials--api_token))
+
+
+### Nested Schema for `credentials.api_token`
+
+Required:
+
+- `api_token_ref` (String) Reference to a secret containing the api token to use for authentication. To reference a secret at the organization scope, prefix 'org' to the expression: org.{identifier}. To reference a secret at the account scope, prefix 'account` to the expression: account.{identifier}.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# Import using terrafrm cloud provider connector id
+terraform import harness_platform_connector_terraform_cloud.example
+```
diff --git a/examples/data-sources/harness_platform_connector_terraform_cloud/data-source.tf b/examples/data-sources/harness_platform_connector_terraform_cloud/data-source.tf
new file mode 100644
index 000000000..29ab6f2c9
--- /dev/null
+++ b/examples/data-sources/harness_platform_connector_terraform_cloud/data-source.tf
@@ -0,0 +1,3 @@
+data "harness_platform_connector_terraform_cloud" "example" {
+ identifier = "identifier"
+}
diff --git a/examples/resources/harness_platform_connector_terraform_cloud/import.sh b/examples/resources/harness_platform_connector_terraform_cloud/import.sh
new file mode 100644
index 000000000..6e2db44e2
--- /dev/null
+++ b/examples/resources/harness_platform_connector_terraform_cloud/import.sh
@@ -0,0 +1,2 @@
+# Import using terrafrm cloud provider connector id
+terraform import harness_platform_connector_terraform_cloud.example
diff --git a/examples/resources/harness_platform_connector_terraform_cloud/resource.tf b/examples/resources/harness_platform_connector_terraform_cloud/resource.tf
new file mode 100644
index 000000000..a47eb74dc
--- /dev/null
+++ b/examples/resources/harness_platform_connector_terraform_cloud/resource.tf
@@ -0,0 +1,30 @@
+# Create Terraform Cloud connector using API token as secret
+
+resource "harness_platform_connector_terraform_cloud" "terraform_cloud" {
+ identifier = "example_terraform_cloud_connector"
+ name = "Example terraform cloud connector"
+ description = "description of terraform cloud connector"
+ tags = ["foo:bar"]
+ delegate_selectors = ["harness-delegate"]
+ credentials {
+ api_token {
+ api_token_ref = "account.TEST_terraform_cloud_api_token"
+ }
+ }
+}
+
+# Add connectivity mode by providing execute_on_delegate value. Default is to execute on Delegate
+
+resource "harness_platform_connector_terraform_cloud" "terraform_cloud" {
+ identifier = "example_terraform_cloud_connector"
+ name = "Example terraform cloud connector"
+ description = "description of terraform cloud connector"
+ delegate_selectors = ["harness-delegate"]
+ tags = ["foo:bar"]
+ execute_on_delegate = false
+ credentials {
+ api_token {
+ api_token_ref = "account.TEST_terraform_cloud_api_token"
+ }
+ }
+}
diff --git a/go.mod b/go.mod
index 50bdf9b08..8dbf48f07 100644
--- a/go.mod
+++ b/go.mod
@@ -84,5 +84,5 @@ require (
gotest.tools/v3 v3.3.0 // indirect
)
-// replace github.com/harness/harness-go-sdk => ../harness-go-sdk
+replace github.com/harness/harness-go-sdk => ../harness-go-sdk
// replace github.com/harness/harness-openapi-go-client => ../harness-openapi-go-client
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 752c7e47e..b905aa251 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -153,6 +153,7 @@ func Provider(version string) func() *schema.Provider {
"harness_platform_connector_prometheus": connector.DatasourceConnectorPrometheus(),
"harness_platform_connector_splunk": connector.DatasourceConnectorSplunk(),
"harness_platform_connector_spot": connector.DatasourceConnectorSpot(),
+ "harness_platform_connector_terraform_cloud": connector.DatasourceConnectorTerraformCloud(),
"harness_platform_connector_sumologic": connector.DatasourceConnectorSumologic(),
"harness_platform_current_user": pl_current_user.DataSourceCurrentUser(),
"harness_platform_user": pl_user.DataSourceUser(),
@@ -245,6 +246,7 @@ func Provider(version string) func() *schema.Provider {
"harness_platform_connector_prometheus": connector.ResourceConnectorPrometheus(),
"harness_platform_connector_splunk": connector.ResourceConnectorSplunk(),
"harness_platform_connector_spot": connector.ResourceConnectorSpot(),
+ "harness_platform_connector_terraform_cloud": connector.ResourceConnectorTerraformCloud(),
"harness_platform_connector_sumologic": connector.ResourceConnectorSumologic(),
"harness_platform_environment": pl_environment.ResourceEnvironment(),
"harness_platform_environment_group": pl_environment_group.ResourceEnvironmentGroup(),
diff --git a/internal/service/platform/connector/terraform_cloud.go b/internal/service/platform/connector/terraform_cloud.go
new file mode 100644
index 000000000..614b09d5b
--- /dev/null
+++ b/internal/service/platform/connector/terraform_cloud.go
@@ -0,0 +1,155 @@
+package connector
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/harness/harness-go-sdk/harness/nextgen"
+ "github.com/harness/terraform-provider-harness/helpers"
+ "github.com/harness/terraform-provider-harness/internal/utils"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func ResourceConnectorTerraformCloud() *schema.Resource {
+ resource := &schema.Resource{
+ Description: "Resource for creating a TerraformCloud connector.",
+ ReadContext: resourceConnectorTerraformCloudRead,
+ CreateContext: resourceConnectorTerraformCloudCreateOrUpdate,
+ UpdateContext: resourceConnectorTerraformCloudCreateOrUpdate,
+ DeleteContext: resourceConnectorDelete,
+ Importer: helpers.MultiLevelResourceImporter,
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Description: "URL of Terraform Cloud platform.",
+ Type: schema.TypeString,
+ Required: true,
+ },
+ "credentials": {
+ Description: "Credentials to connect to Terraform Cloud platform.",
+ Type: schema.TypeList,
+ MaxItems: 1,
+ Required: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "api_token": {
+ Description: "API token credentials to use for authentication.",
+ Type: schema.TypeList,
+ MaxItems: 1,
+ Required: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "api_token_ref": {
+ Description: "Reference to a secret containing the api token to use for authentication." + secret_ref_text,
+ Type: schema.TypeString,
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ "delegate_selectors": {
+ Description: "Connect only using delegates with these tags.",
+ Type: schema.TypeSet,
+ Optional: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ },
+ }
+
+ helpers.SetMultiLevelResourceSchema(resource.Schema)
+
+ return resource
+}
+
+func resourceConnectorTerraformCloudRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ conn, err := resourceConnectorReadBase(ctx, d, meta, nextgen.ConnectorTypes.TerraformCloud)
+ if err != nil {
+ return err
+ }
+
+ if conn == nil {
+ return nil
+ }
+
+ if err := readConnectorTerraformCloud(d, conn); err != nil {
+ return diag.FromErr(err)
+ }
+
+ return nil
+}
+
+func resourceConnectorTerraformCloudCreateOrUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
+ conn := buildConnectorTerraformCloud(d)
+
+ newConn, err := resourceConnectorCreateOrUpdateBase(ctx, d, meta, conn)
+ if err != nil {
+ return err
+ }
+
+ if err := readConnectorTerraformCloud(d, newConn); err != nil {
+ return diag.FromErr(err)
+ }
+
+ return nil
+}
+
+func buildConnectorTerraformCloud(d *schema.ResourceData) *nextgen.ConnectorInfo {
+ connector := &nextgen.ConnectorInfo{
+ Type_: nextgen.ConnectorTypes.TerraformCloud,
+ TerraformCloud: &nextgen.TerraformCloudConnector{
+ Credential: &nextgen.TerraformCloudCredential{
+ Type_: nextgen.TerraformCloudAuthTypes.ApiToken,
+ },
+ },
+ }
+
+ if attr, ok := d.GetOk("url"); ok {
+ connector.TerraformCloud.TerraformCloudUrl = attr.(string)
+ }
+
+ if attr, ok := d.GetOk("delegate_selectors"); ok {
+ connector.TerraformCloud.DelegateSelectors = utils.InterfaceSliceToStringSlice(attr.(*schema.Set).List())
+ }
+
+ if attr, ok := d.GetOk("credentials"); ok {
+ config := attr.([]interface{})[0].(map[string]interface{})
+ connector.TerraformCloud.Credential = &nextgen.TerraformCloudCredential{}
+
+ if attr := config["api_token"].([]interface{}); len(attr) > 0 {
+ config := attr[0].(map[string]interface{})
+ connector.TerraformCloud.Credential.Type_ = nextgen.TerraformCloudAuthTypes.ApiToken
+ connector.TerraformCloud.Credential.ApiToken = &nextgen.TerraformCloudTokenCredentials{}
+
+ if attr, ok := config["api_token_ref"]; ok {
+ connector.TerraformCloud.Credential.ApiToken.ApiToken = attr.(string)
+ }
+ }
+ }
+
+ return connector
+}
+
+func readConnectorTerraformCloud(d *schema.ResourceData, connector *nextgen.ConnectorInfo) error {
+ d.Set("url", connector.TerraformCloud.TerraformCloudUrl)
+ d.Set("delegate_selectors", connector.TerraformCloud.DelegateSelectors)
+
+ switch connector.TerraformCloud.Credential.Type_ {
+ case nextgen.TerraformCloudAuthTypes.ApiToken:
+ d.Set("credentials", []interface{}{
+ map[string]interface{}{
+ "api_token": []interface{}{
+ map[string]interface{}{
+ "api_token_ref": connector.TerraformCloud.Credential.ApiToken.ApiToken,
+ },
+ },
+ },
+ })
+ default:
+ return fmt.Errorf("unsupported Terraform Cloud credentials type: %s", connector.TerraformCloud.Credential.Type_)
+ }
+
+ return nil
+}
diff --git a/internal/service/platform/connector/terraform_cloud_data_source.go b/internal/service/platform/connector/terraform_cloud_data_source.go
new file mode 100644
index 000000000..ab1965697
--- /dev/null
+++ b/internal/service/platform/connector/terraform_cloud_data_source.go
@@ -0,0 +1,54 @@
+package connector
+
+import (
+ "github.com/harness/terraform-provider-harness/helpers"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func DatasourceConnectorTerraformCloud() *schema.Resource {
+ resource := &schema.Resource{
+ Description: "Resource for looking up a Terraform Cloud connector.",
+ ReadContext: resourceConnectorTerraformCloudRead,
+
+ Schema: map[string]*schema.Schema{
+ "url": {
+ Description: "URL of the Terraform Cloud platform.",
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ "delegate_selectors": {
+ Description: "Tags to filter delegates for connection.",
+ Type: schema.TypeSet,
+ Computed: true,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "credentials": {
+ Description: "Credentials to connect to Terraform Cloud platform.",
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "api_token": {
+ Description: "API token credentials to use for authentication.",
+ Type: schema.TypeList,
+ Computed: true,
+ Elem: &schema.Resource{
+ Schema: map[string]*schema.Schema{
+ "api_token_ref": {
+ Description: "Reference to a secret containing the api token to use for authentication." + secret_ref_text,
+ Type: schema.TypeString,
+ Computed: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+
+ helpers.SetMultiLevelDatasourceSchema(resource.Schema)
+
+ return resource
+}
diff --git a/internal/service/platform/connector/terraform_cloud_data_source_test.go b/internal/service/platform/connector/terraform_cloud_data_source_test.go
new file mode 100644
index 000000000..e4c05fb23
--- /dev/null
+++ b/internal/service/platform/connector/terraform_cloud_data_source_test.go
@@ -0,0 +1,79 @@
+package connector_test
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/harness/harness-go-sdk/harness/utils"
+ "github.com/harness/terraform-provider-harness/internal/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccDataSourceConnectorTerraformCloud(t *testing.T) {
+
+ var (
+ name = fmt.Sprintf("%s_%s", t.Name(), utils.RandStringBytes(4))
+ resourceName = "data.harness_platform_connector_terraform_cloud.test"
+ )
+
+ resource.UnitTest(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProviderFactories: acctest.ProviderFactories,
+ ExternalProviders: map[string]resource.ExternalProvider{
+ "time": {},
+ },
+ Steps: []resource.TestStep{
+ {
+ Config: testAccDataSourceConnectorTerraformCloud(name),
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "id", name),
+ resource.TestCheckResourceAttr(resourceName, "identifier", name),
+ resource.TestCheckResourceAttr(resourceName, "name", name),
+ resource.TestCheckResourceAttr(resourceName, "url", "https://app.terraform.io/"),
+ resource.TestCheckResourceAttr(resourceName, "description", "test"),
+ resource.TestCheckResourceAttr(resourceName, "tags.#", "1"),
+ resource.TestCheckResourceAttr(resourceName, "delegate_selectors.#", "1"),
+ ),
+ },
+ },
+ })
+}
+
+func testAccDataSourceConnectorTerraformCloud(name string) string {
+ return fmt.Sprintf(`
+ resource "harness_platform_secret_text" "test" {
+ identifier = "%[1]s"
+ name = "%[1]s"
+ description = "test"
+ tags = ["foo:bar"]
+
+ secret_manager_identifier = "harnessSecretManager"
+ value_type = "Inline"
+ value = "secret"
+ }
+
+ resource "harness_platform_connector_terraform_cloud" "test" {
+ url = "https://app.terraform.io/"
+ identifier = "%[1]s"
+ name = "%[1]s"
+ description = "test"
+ tags = ["foo:bar"]
+ delegate_selectors = ["harness-delegate"]
+ credentials {
+ api_token {
+ api_token_ref = "account.${harness_platform_secret_text.test.id}"
+ }
+ }
+ depends_on = [time_sleep.wait_4_seconds]
+ }
+
+ resource "time_sleep" "wait_4_seconds" {
+ depends_on = [harness_platform_secret_text.test]
+ destroy_duration = "4s"
+ }
+
+ data "harness_platform_connector_terraform_cloud" "test" {
+ identifier = harness_platform_connector_terraform_cloud.test.identifier
+ }
+ `, name)
+}
diff --git a/internal/service/platform/connector/terraform_cloud_test.go b/internal/service/platform/connector/terraform_cloud_test.go
new file mode 100644
index 000000000..87e25dffe
--- /dev/null
+++ b/internal/service/platform/connector/terraform_cloud_test.go
@@ -0,0 +1,83 @@
+package connector_test
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/harness/harness-go-sdk/harness/utils"
+ "github.com/harness/terraform-provider-harness/internal/acctest"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+)
+
+func TestAccResourceConnectorTerraformCloud(t *testing.T) {
+ id := fmt.Sprintf("%s_%s", t.Name(), utils.RandStringBytes(5))
+ name := id
+ executeTfCloudTest(t, testAccResourceConnectorTerraformCloud(id, name), "true", id, name)
+}
+
+func executeTfCloudTest(t *testing.T, config string, executeOnDelegate string, id string, name string) {
+ resourceName := "harness_platform_connector_terraform_cloud.test"
+
+ resource.UnitTest(t, resource.TestCase{
+ PreCheck: func() { acctest.TestAccPreCheck(t) },
+ ProviderFactories: acctest.ProviderFactories,
+ ExternalProviders: map[string]resource.ExternalProvider{
+ "time": {},
+ },
+ CheckDestroy: testAccConnectorDestroy(resourceName),
+ Steps: []resource.TestStep{
+ {
+ Config: config,
+ Check: resource.ComposeTestCheckFunc(
+ resource.TestCheckResourceAttr(resourceName, "id", id),
+ resource.TestCheckResourceAttr(resourceName, "identifier", id),
+ resource.TestCheckResourceAttr(resourceName, "name", name),
+ resource.TestCheckResourceAttr(resourceName, "url", "https://app.terraform.io/"),
+ resource.TestCheckResourceAttr(resourceName, "description", "test"),
+ resource.TestCheckResourceAttr(resourceName, "tags.#", "1"),
+ resource.TestCheckResourceAttr(resourceName, "delegate_selectors.#", "1"),
+ ),
+ },
+ {
+ ResourceName: resourceName,
+ ImportState: true,
+ ImportStateVerify: true,
+ },
+ },
+ })
+}
+
+func testAccResourceConnectorTerraformCloud(id string, name string) string {
+ return fmt.Sprintf(`
+ resource "harness_platform_secret_text" "test" {
+ identifier = "%[1]s"
+ name = "%[2]s"
+ description = "test"
+ tags = ["foo:bar"]
+
+ secret_manager_identifier = "harnessSecretManager"
+ value_type = "Inline"
+ value = "secret"
+ }
+
+ resource "harness_platform_connector_terraform_cloud" "test" {
+ url = "https://app.terraform.io/"
+ identifier = "%[1]s"
+ name = "%[2]s"
+ description = "test"
+ tags = ["foo:bar"]
+ delegate_selectors = ["harness-delegate"]
+ credentials {
+ api_token {
+ api_token_ref = "account.${harness_platform_secret_text.test.id}"
+ }
+ }
+ depends_on = [time_sleep.wait_4_seconds]
+ }
+
+ resource "time_sleep" "wait_4_seconds" {
+ depends_on = [harness_platform_secret_text.test]
+ destroy_duration = "4s"
+ }
+`, id, name)
+}