Skip to content

Commit

Permalink
Feat: add parent_project_id as filter for data project resource (#762)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomerHeber authored Dec 13, 2023
1 parent d489bd4 commit c8fb2b4
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 12 deletions.
43 changes: 32 additions & 11 deletions env0/data_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,15 @@ func dataProject() *schema.Resource {
},
"parent_project_name": {
Type: schema.TypeString,
Description: "the name of the parent project. Can be used when there are multiple subprojects with the same name under different parent projects",
Description: "the name of the parent project. Can be used as a filter when there are multiple subprojects with the same name under different parent projects",
Optional: true,
},
"parent_project_id": {
Type: schema.TypeString,
Description: "the id of the parent project. Can be used as a filter when there are multiple subprojects with the same name under different parent projects",
Optional: true,
Computed: true,
},
"created_by": {
Type: schema.TypeString,
Description: "textual description of the entity who created the project",
Expand All @@ -49,11 +55,6 @@ func dataProject() *schema.Resource {
Description: "textual description of the project",
Computed: true,
},
"parent_project_id": {
Type: schema.TypeString,
Description: "if the project is a sub-project, returns the parent of this sub-project",
Computed: true,
},
},
}
}
Expand All @@ -73,7 +74,7 @@ func dataProjectRead(ctx context.Context, d *schema.ResourceData, meta interface
if !ok {
return diag.Errorf("either 'name' or 'id' must be specified")
}
project, err = getProjectByName(name.(string), d.Get("parent_project_name").(string), meta)
project, err = getProjectByName(name.(string), d.Get("parent_project_id").(string), d.Get("parent_project_name").(string), meta)
if err != nil {
return diag.Errorf("%v", err)
}
Expand All @@ -86,6 +87,21 @@ func dataProjectRead(ctx context.Context, d *schema.ResourceData, meta interface
return nil
}

func filterByParentProjectId(name string, parentId string, projects []client.Project) ([]client.Project, error) {
filteredProjects := make([]client.Project, 0)
for _, project := range projects {
if len(project.ParentProjectId) == 0 {
continue
}

if project.ParentProjectId == parentId {
filteredProjects = append(filteredProjects, project)
}
}

return filteredProjects, nil
}

func filterByParentProjectName(name string, parentName string, projects []client.Project, meta interface{}) ([]client.Project, error) {
filteredProjects := make([]client.Project, 0)
for _, project := range projects {
Expand All @@ -106,7 +122,7 @@ func filterByParentProjectName(name string, parentName string, projects []client
return filteredProjects, nil
}

func getProjectByName(name string, parentName string, meta interface{}) (client.Project, error) {
func getProjectByName(name string, parentId string, parentName string, meta interface{}) (client.Project, error) {
apiClient := meta.(client.ApiClientInterface)
projects, err := apiClient.Projects()
if err != nil {
Expand All @@ -119,9 +135,14 @@ func getProjectByName(name string, parentName string, meta interface{}) (client.
projectsByName = append(projectsByName, candidate)
}
}

if len(parentName) > 0 {
// Too many results. Use parentName filter to reduce the results.
if len(parentId) > 0 {
// Use parentId filter to reduce the results.
projectsByName, err = filterByParentProjectId(name, parentId, projectsByName)
if err != nil {
return client.Project{}, err
}
} else if len(parentName) > 0 {
// Use parentName filter to reduce the results.
projectsByName, err = filterByParentProjectName(name, parentName, projectsByName, meta)
if err != nil {
return client.Project{}, err
Expand Down
25 changes: 25 additions & 0 deletions env0/data_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ func TestProjectDataSource(t *testing.T) {
resource.TestCheckResourceAttr(accessor, "role", projectWithParent.Role),
resource.TestCheckResourceAttr(accessor, "description", projectWithParent.Description),
resource.TestCheckResourceAttr(accessor, "parent_project_id", projectWithParent.ParentProjectId),
resource.TestCheckResourceAttr(accessor, "parent_project_name", parentProject.Name),
),
},
},
Expand All @@ -156,6 +157,30 @@ func TestProjectDataSource(t *testing.T) {
)
})

t.Run("By Name with Parent Id", func(t *testing.T) {
runUnitTest(t,
resource.TestCase{
Steps: []resource.TestStep{
{
Config: dataSourceConfigCreate(resourceType, resourceName, map[string]interface{}{"name": projectWithParent.Name, "parent_project_id": parentProject.Id}),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(accessor, "id", projectWithParent.Id),
resource.TestCheckResourceAttr(accessor, "name", projectWithParent.Name),
resource.TestCheckResourceAttr(accessor, "created_by", projectWithParent.CreatedBy),
resource.TestCheckResourceAttr(accessor, "role", projectWithParent.Role),
resource.TestCheckResourceAttr(accessor, "description", projectWithParent.Description),
resource.TestCheckResourceAttr(accessor, "parent_project_id", projectWithParent.ParentProjectId),
resource.TestCheckNoResourceAttr(accessor, "parent_project_name"),
),
},
},
},
func(mock *client.MockApiClientInterface) {
mock.EXPECT().Projects().AnyTimes().Return([]client.Project{projectWithParent, otherProjectWithParent}, nil)
},
)
})

t.Run("Throw error when no name or id is supplied", func(t *testing.T) {
runUnitTest(t,
getErrorTestCase(map[string]interface{}{}, "one of `id,name` must be specified"),
Expand Down
2 changes: 1 addition & 1 deletion env0/resource_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ func resourceProjectImport(ctx context.Context, d *schema.ResourceData, meta int
} else {
tflog.Info(ctx, "Resolving project by name", map[string]interface{}{"name": id})

if project, err = getProjectByName(id, "", meta); err != nil {
if project, err = getProjectByName(id, "", "", meta); err != nil {
return nil, err
}
}
Expand Down
10 changes: 10 additions & 0 deletions examples/data-sources/env0_project/data-source.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
data "env0_project" "default_project" {
name = "Default Organization Project"
}

data "env0_project" "with_parent_name_filter" {
name = "Default Organization Project"
parent_project_name = "parent projet name"
}

data "env0_project" "with_parent_id_filter" {
name = "Default Organization Project"
parent_project_id = "parent-projet-id"
}
5 changes: 5 additions & 0 deletions tests/integration/002_project/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ data "env0_project" "data_by_name_with_parent_name" {
parent_project_name = env0_project.test_project_other.name
}

data "env0_project" "data_by_name_with_parent_id" {
name = env0_project.test_sub_project_other.name
parent_project_id = env0_project.test_project_other.id
}

output "test_project_name" {
value = replace(env0_project.test_project.name, random_string.random.result, "")
}
Expand Down

0 comments on commit c8fb2b4

Please sign in to comment.