Skip to content

Commit

Permalink
[feat]: [CDS-54508]: add support for terraform cloud connector
Browse files Browse the repository at this point in the history
  • Loading branch information
tmacari-harness committed Apr 26, 2023
1 parent ec102bb commit b3c585f
Show file tree
Hide file tree
Showing 11 changed files with 559 additions and 1 deletion.
58 changes: 58 additions & 0 deletions docs/data-sources/platform_connector_terraform_cloud.md
Original file line number Diff line number Diff line change
@@ -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 generated by tfplugindocs -->
## 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.

<a id="nestedblock--credentials"></a>
### 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))

<a id="nestedblock--credentials--api_token"></a>
### 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}.


92 changes: 92 additions & 0 deletions docs/resources/platform_connector_terraform_cloud.md
Original file line number Diff line number Diff line change
@@ -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 generated by tfplugindocs -->
## 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.

<a id="nestedblock--credentials"></a>
### 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))

<a id="nestedblock--credentials--api_token"></a>
### 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 <connector_id>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
data "harness_platform_connector_terraform_cloud" "example" {
identifier = "identifier"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Import using terrafrm cloud provider connector id
terraform import harness_platform_connector_terraform_cloud.example <connector_id>
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
155 changes: 155 additions & 0 deletions internal/service/platform/connector/terraform_cloud.go
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit b3c585f

Please sign in to comment.