diff --git a/.changelog/578.txt b/.changelog/578.txt new file mode 100644 index 000000000..a14f98151 --- /dev/null +++ b/.changelog/578.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/harness_platform_gitops_cluster: Added support for IAM role in GitOps +``` diff --git a/docs/data-sources/platform_gitops_cluster.md b/docs/data-sources/platform_gitops_cluster.md index d84d8486c..77549e3e0 100644 --- a/docs/data-sources/platform_gitops_cluster.md +++ b/docs/data-sources/platform_gitops_cluster.md @@ -100,6 +100,8 @@ Read-Only: - `cluster_connection_type` (String) - `exec_provider_config` (List of Object) (see [below for nested schema](#nestedobjatt--request--cluster--config--exec_provider_config)) - `password` (String) +- `role_a_r_n` (String) +- `aws_cluster_name` (String) - `tls_client_config` (List of Object) (see [below for nested schema](#nestedobjatt--request--cluster--config--tls_client_config)) - `username` (String) diff --git a/docs/resources/platform_gitops_cluster.md b/docs/resources/platform_gitops_cluster.md index 19eff4f54..ef5b566e6 100644 --- a/docs/resources/platform_gitops_cluster.md +++ b/docs/resources/platform_gitops_cluster.md @@ -154,11 +154,13 @@ Read-Only: Optional: -- `aws_auth_config` (Block List) IAM authentication configuration for AWS. (see [below for nested schema](#nestedblock--request--cluster--config--aws_auth_config)) +- `aws_auth_config` (Block List) IAM authentication configuration for AWS. (deprecated) (see [below for nested schema](#nestedblock--request--cluster--config--aws_auth_config)) - `bearer_token` (String) Bearer authentication token the cluster. - `cluster_connection_type` (String) Identifies the authentication method used to connect to the cluster. - `exec_provider_config` (Block List) Configuration for an exec provider. (see [below for nested schema](#nestedblock--request--cluster--config--exec_provider_config)) - `password` (String) Password of the server of the cluster. +- `role_a_r_n` (String) Optional role ARN. If set then used for AWS IAM Authenticator. +- `aws_cluster_name` (String) AWS Cluster name. If set then AWS CLI EKS token command will be used to access cluster. - `tls_client_config` (Block List) Settings to enable transport layer security. (see [below for nested schema](#nestedblock--request--cluster--config--tls_client_config)) - `username` (String) Username of the server of the cluster. diff --git a/go.mod b/go.mod index d9523595b..1f9c5b862 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/antihax/optional v1.0.0 github.com/docker/docker v20.10.22+incompatible - github.com/harness/harness-go-sdk v0.3.29 + github.com/harness/harness-go-sdk v0.3.30 github.com/harness/harness-openapi-go-client v0.0.17 github.com/hashicorp/terraform-plugin-sdk/v2 v2.26.1 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index ca0856024..cf9644864 100644 --- a/go.sum +++ b/go.sum @@ -47,8 +47,8 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/harness/harness-go-sdk v0.3.29 h1:CPvXSrlHkO33R0yNHvhcRVHkYPDZxc5NvQzsldW2edw= -github.com/harness/harness-go-sdk v0.3.29/go.mod h1:CPXydorp4zd5Dz2u2FXiHyWL4yd5PQafOMN69cgPSvk= +github.com/harness/harness-go-sdk v0.3.30 h1:hdAXNHiaV/8fI6eHdnqvQkzLH7DiVY8Iz52HxAqX75U= +github.com/harness/harness-go-sdk v0.3.30/go.mod h1:CPXydorp4zd5Dz2u2FXiHyWL4yd5PQafOMN69cgPSvk= github.com/harness/harness-openapi-go-client v0.0.17 h1:EZneIyi6sV+dlTgXbawxdVD0OoDmG3mnGHEJbwslRzc= github.com/harness/harness-openapi-go-client v0.0.17/go.mod h1:u0vqYb994BJGotmEwJevF4L3BNAdU9i8ui2d22gmLPA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/internal/service/platform/gitops/applications/datasource_gitops_applications_test.go b/internal/service/platform/gitops/applications/datasource_gitops_applications_test.go index 13b1d1c0a..89dc99412 100644 --- a/internal/service/platform/gitops/applications/datasource_gitops_applications_test.go +++ b/internal/service/platform/gitops/applications/datasource_gitops_applications_test.go @@ -108,6 +108,7 @@ func testAccDataSourceGitopsApplication(id string, accountId string, name string org_id = harness_platform_organization.test.id account_id = "%[2]s" identifier = "%[1]s" + name = "%[3]s" cluster_id = "%[8]s" repo_id = "%[10]s" agent_id = "%[4]s" @@ -120,6 +121,7 @@ func testAccDataSourceGitopsApplication(id string, accountId string, name string org_id = harness_platform_organization.test.id agent_id = "%[4]s" repo_id = "%[10]s" + name = "%[3]s" } `, id, accountId, name, agentId, clusterName, namespace, clusterServer, clusterId, repo, repoId) diff --git a/internal/service/platform/gitops/applications/resource_gitops_applications_test.go b/internal/service/platform/gitops/applications/resource_gitops_applications_test.go index ed47fc4c9..0ccd8718b 100644 --- a/internal/service/platform/gitops/applications/resource_gitops_applications_test.go +++ b/internal/service/platform/gitops/applications/resource_gitops_applications_test.go @@ -2,13 +2,14 @@ package applications_test import ( "fmt" - "github.com/antihax/optional" - "github.com/harness/harness-go-sdk/harness/nextgen" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" "os" "strings" "testing" + "github.com/antihax/optional" + "github.com/harness/harness-go-sdk/harness/nextgen" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "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" @@ -281,6 +282,7 @@ func testAccResourceGitopsApplicationKustomize(id string, accountId string, name cluster_id = "%[8]s" repo_id = "%[10]s" agent_id = "%[4]s" + name = "%[3]s" } `, id, accountId, name, agentId, clusterName, namespace, clusterServer, clusterId, repo, repoId) } diff --git a/internal/service/platform/gitops/cluster/data_source_gitops_cluster.go b/internal/service/platform/gitops/cluster/data_source_gitops_cluster.go index 1cec64596..7fe5dcec0 100644 --- a/internal/service/platform/gitops/cluster/data_source_gitops_cluster.go +++ b/internal/service/platform/gitops/cluster/data_source_gitops_cluster.go @@ -213,24 +213,15 @@ func DataSourceGitopsCluster() *schema.Resource { }, }, }, - "aws_auth_config": { - Description: "IAM authentication configuration for AWS.", - Type: schema.TypeList, + "role_a_r_n": { + Description: "Optional role ARN. If set then used for AWS IAM Authenticator.", + Type: schema.TypeString, + Optional: true, + }, + "aws_cluster_name": { + Description: "AWS Cluster name. If set then AWS CLI EKS token command will be used to access cluster.", + Type: schema.TypeString, Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "cluster_name": { - Description: "AWS cluster name.", - Type: schema.TypeString, - Optional: true, - }, - "role_a_r_n": { - Description: "Optional role ARN. If set then used for AWS IAM Authenticator.", - Type: schema.TypeString, - Optional: true, - }, - }, - }, }, "exec_provider_config": { Description: "Configuration for an exec provider.", diff --git a/internal/service/platform/gitops/cluster/data_source_gitops_cluster_test.go b/internal/service/platform/gitops/cluster/data_source_gitops_cluster_test.go index 877db4d02..3960f8a75 100644 --- a/internal/service/platform/gitops/cluster/data_source_gitops_cluster_test.go +++ b/internal/service/platform/gitops/cluster/data_source_gitops_cluster_test.go @@ -2,11 +2,12 @@ package cluster_test import ( "fmt" - "github.com/harness/harness-go-sdk/harness/utils" "os" "strings" "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" ) @@ -37,6 +38,36 @@ func TestAccDataSourceGitopsCluster(t *testing.T) { }) } +func TestAccDataSourceGitopsClusterIAM(t *testing.T) { + + id := strings.ToLower(fmt.Sprintf("%s%s", t.Name(), utils.RandStringBytes(5))) + id = strings.ReplaceAll(id, "_", "") + name := id + agentId := os.Getenv("HARNESS_TEST_AWS_GITOPS_AGENT") + accountId := os.Getenv("HARNESS_ACCOUNT_ID") + clusterName := id + clusterServer := os.Getenv("HARNESS_TEST_AWS_CLUSTER_SERVER") + roleARN := os.Getenv("HARNESS_TEST_AWS_CLUSTER_ROLE_ARN") + awsClusterName := os.Getenv("HARNESS_TEST_AWS_CLUSTER_NAME") + caData := os.Getenv("HARNESS_TEST_AWS_CLUSTER_CA_DATA") + resourceName := "data.harness_platform_gitops_cluster.test" + + resource.UnitTest(t, resource.TestCase{ + PreCheck: func() { acctest.TestAccPreCheck(t) }, + ProviderFactories: acctest.ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceGitopsClusterIAM(id, accountId, name, agentId, clusterName, clusterServer, roleARN, awsClusterName, caData), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "identifier", id), + resource.TestCheckResourceAttr(resourceName, "org_id", id), + resource.TestCheckResourceAttr(resourceName, "project_id", id), + ), + }, + }, + }) +} + func testAccDataSourceGitopsCluster(id string, accountId string, name string, agentId string, clusterName string) string { return fmt.Sprintf(` resource "harness_platform_organization" "test" { @@ -88,3 +119,58 @@ func testAccDataSourceGitopsCluster(id string, accountId string, name string, ag `, id, accountId, name, agentId, clusterName) } + +func testAccDataSourceGitopsClusterIAM(id string, accountId string, name string, agentId string, clusterName string, clusterServer string, roleARN string, awsClusterName string, caData string) string { + return fmt.Sprintf(` + resource "harness_platform_organization" "test" { + identifier = "%[1]s" + name = "%[3]s" + } + + resource "harness_platform_project" "test" { + identifier = "%[1]s" + name = "%[3]s" + org_id = harness_platform_organization.test.id + } + resource "harness_platform_gitops_cluster" "test" { + identifier = "%[1]s" + account_id = "%[2]s" + project_id = harness_platform_project.test.id + org_id = harness_platform_organization.test.id + agent_id = "%[4]s" + + request { + upsert = true + cluster { + name = "%[5]s" + server = "%[6]s" + config { + tls_client_config { + insecure = false + ca_data = "%[9]s" + } + cluster_connection_type = "IRSA" + role_a_r_n = "%[7]s" + aws_cluster_name = "%[8]s" + } + + } + } + lifecycle { + ignore_changes = [ + request.0.upsert, request.0.cluster.0.config.0.bearer_token, request.0.cluster.0.info, + ] + } + } + data "harness_platform_gitops_cluster" "test" { + depends_on = [harness_platform_gitops_cluster.test] + identifier = harness_platform_gitops_cluster.test.id + account_id = "%[2]s" + project_id = harness_platform_project.test.id + org_id = harness_platform_organization.test.id + agent_id = "%[4]s" + + } + `, id, accountId, name, agentId, clusterName, clusterServer, roleARN, awsClusterName, caData) + +} diff --git a/internal/service/platform/gitops/cluster/resource_gitops_cluster.go b/internal/service/platform/gitops/cluster/resource_gitops_cluster.go index d61f6d0e7..e31021aab 100644 --- a/internal/service/platform/gitops/cluster/resource_gitops_cluster.go +++ b/internal/service/platform/gitops/cluster/resource_gitops_cluster.go @@ -219,24 +219,15 @@ func ResourceGitopsCluster() *schema.Resource { }, }, }, - "aws_auth_config": { - Description: "IAM authentication configuration for AWS.", - Type: schema.TypeList, + "role_a_r_n": { + Description: "Optional role ARN. If set then used for AWS IAM Authenticator.", + Type: schema.TypeString, + Optional: true, + }, + "aws_cluster_name": { + Description: "AWS Cluster name. If set then AWS CLI EKS token command will be used to access cluster.", + Type: schema.TypeString, Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "cluster_name": { - Description: "AWS cluster name.", - Type: schema.TypeString, - Optional: true, - }, - "role_a_r_n": { - Description: "Optional role ARN. If set then used for AWS IAM Authenticator.", - Type: schema.TypeString, - Optional: true, - }, - }, - }, }, "exec_provider_config": { Description: "Configuration for an exec provider.", @@ -606,8 +597,9 @@ func setClusterDetails(d *schema.ResourceData, cl *nextgen.Servicev1Cluster) { awsAuthConfig["cluster_name"] = cl.Cluster.Config.AwsAuthConfig.ClusterName awsAuthConfig["role_a_r_n"] = cl.Cluster.Config.AwsAuthConfig.RoleARN awsAuthConfigList = append(awsAuthConfigList, awsAuthConfig) - config["aws_auth_config"] = awsAuthConfigList } + config["role_a_r_n"] = cl.Cluster.Config.RoleARN + config["aws_cluster_name"] = cl.Cluster.Config.AwsClusterName if cl.Cluster.Config.ExecProviderConfig != nil { execProviderConfigList := []interface{}{} execProviderConfig := map[string]interface{}{} @@ -772,15 +764,12 @@ func buildClusterDetails(d *schema.ResourceData) *nextgen.ClustersCluster { } } - if clusterConfig["aws_auth_config"] != nil && len(clusterConfig["aws_auth_config"].([]interface{})) > 0 { - clusterDetails.Config.AwsAuthConfig = &nextgen.ClustersAwsAuthConfig{} - configAwsAuthConfig := clusterConfig["aws_auth_config"].([]interface{})[0].(map[string]interface{}) - if configAwsAuthConfig["cluster_name"] != nil { - clusterDetails.Config.AwsAuthConfig.ClusterName = configAwsAuthConfig["cluster_name"].(string) - } - if configAwsAuthConfig["role_a_r_n"] != nil { - clusterDetails.Config.AwsAuthConfig.RoleARN = configAwsAuthConfig["role_a_r_n"].(string) - } + if clusterConfig["role_a_r_n"] != nil { + clusterDetails.Config.RoleARN = clusterConfig["role_a_r_n"].(string) + } + + if clusterConfig["aws_cluster_name"] != nil { + clusterDetails.Config.AwsClusterName = clusterConfig["aws_cluster_name"].(string) } if clusterConfig["exec_provider_config"] != nil && len(clusterConfig["exec_provider_config"].([]interface{})) > 0 { diff --git a/internal/service/platform/gitops/cluster/resource_gitops_cluster_test.go b/internal/service/platform/gitops/cluster/resource_gitops_cluster_test.go index 946fed6a6..441e11d49 100644 --- a/internal/service/platform/gitops/cluster/resource_gitops_cluster_test.go +++ b/internal/service/platform/gitops/cluster/resource_gitops_cluster_test.go @@ -126,6 +126,46 @@ func TestAccResourceGitopsCluster(t *testing.T) { }, }, }) + + // Project Level with IAM + id = strings.ToLower(fmt.Sprintf("%s%s", t.Name(), utils.RandStringBytes(5))) + id = strings.ReplaceAll(id, "_", "") + name = id + clusterName = id + resourceName = "harness_platform_gitops_cluster.test" + clusterServer = os.Getenv("HARNESS_TEST_AWS_CLUSTER_SERVER") + roleARN := os.Getenv("HARNESS_TEST_AWS_CLUSTER_ROLE_ARN") + awsClusterName := os.Getenv("HARNESS_TEST_AWS_CLUSTER_NAME") + caData := os.Getenv("HARNESS_TEST_AWS_CLUSTER_CA_DATA") + agentId = os.Getenv("HARNESS_TEST_AWS_GITOPS_AGENT") + resource.UnitTest(t, resource.TestCase{ + PreCheck: func() { acctest.TestAccPreCheck(t) }, + ProviderFactories: acctest.ProviderFactories, + CheckDestroy: testAccResourceGitopsClusterDestroy(resourceName), + Steps: []resource.TestStep{ + { + Config: testAccResourceGitopsClusterProjectLevelIAM(id, accountId, name, agentId, clusterName, clusterServer, roleARN, awsClusterName, caData), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "id", id), + resource.TestCheckResourceAttr(resourceName, "identifier", id), + ), + }, + { + Config: testAccResourceGitopsClusterProjectLevelIAM(id, accountId, name, agentId, clusterName, clusterServer, roleARN, awsClusterName, caData), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "id", id), + resource.TestCheckResourceAttr(resourceName, "identifier", id), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"request.0.cluster.0.info"}, + ImportStateIdFunc: acctest.GitopsAgentProjectLevelResourceImportStateIdFunc(resourceName), + }, + }, + }) } func testAccGetCluster(resourceName string, state *terraform.State) (*nextgen.Servicev1Cluster, error) { @@ -261,3 +301,45 @@ func testAccResourceGitopsClusterProjectLevel(id string, accountId string, name } `, id, accountId, name, agentId, clusterName, clusterServer, clusterToken) } + +func testAccResourceGitopsClusterProjectLevelIAM(id string, accountId string, name string, agentId string, clusterName string, clusterServer string, roleARN string, awsClusterName string, caData string) string { + return fmt.Sprintf(` + resource "harness_platform_organization" "test" { + identifier = "%[1]s" + name = "%[3]s" + } + resource "harness_platform_project" "test" { + identifier = "%[1]s" + name = "%[3]s" + org_id = harness_platform_organization.test.id + } + resource "harness_platform_gitops_cluster" "test" { + identifier = "%[1]s" + account_id = "%[2]s" + agent_id = "%[4]s" + project_id = harness_platform_project.test.id + org_id = harness_platform_organization.test.id + request { + upsert = true + cluster { + server = "%[6]s" + name = "%[5]s" + config { + role_a_r_n = "%[7]s" + aws_cluster_name = "%[8]s" + tls_client_config { + insecure = false + ca_data = "%[9]s" + } + cluster_connection_type = "IRSA" + } + } + } + lifecycle { + ignore_changes = [ + request.0.upsert, request.0.cluster.0.config.0.bearer_token, request.0.cluster.0.info, + ] + } + } + `, id, accountId, name, agentId, clusterName, clusterServer, roleARN, awsClusterName, caData) +}