Skip to content

Commit

Permalink
Feat: allow editing sub project parentId so it uses our new move proj… (
Browse files Browse the repository at this point in the history
#652)

* Feat: allow editing sub project parentId so it uses our new move project api

* fixed error

* added to option to make a subproject a project

* remove if
  • Loading branch information
TomerHeber committed May 22, 2023
1 parent d8bba92 commit 61abddd
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 9 deletions.
3 changes: 2 additions & 1 deletion client/api_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ type ApiClientInterface interface {
Projects() ([]Project, error)
Project(id string) (Project, error)
ProjectCreate(payload ProjectCreatePayload) (Project, error)
ProjectUpdate(id string, payload ProjectCreatePayload) (Project, error)
ProjectUpdate(id string, payload ProjectUpdatePayload) (Project, error)
ProjectDelete(id string) error
ProjectMove(id string, targetProjectId string) error
Template(id string) (Template, error)
Templates() ([]Template, error)
TemplateCreate(payload TemplateCreatePayload) (Template, error)
Expand Down
16 changes: 15 additions & 1 deletion client/api_client_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 22 additions & 1 deletion client/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ type ProjectCreatePayload struct {
ParentProjectId string `json:"parentProjectId,omitempty"`
}

type ProjectUpdatePayload struct {
Name string `json:"name"`
Description string `json:"description"`
}

func (client *ApiClient) Projects() ([]Project, error) {
organizationId, err := client.OrganizationId()
if err != nil {
Expand Down Expand Up @@ -68,7 +73,7 @@ func (client *ApiClient) ProjectDelete(id string) error {
return client.http.Delete("/projects/" + id)
}

func (client *ApiClient) ProjectUpdate(id string, payload ProjectCreatePayload) (Project, error) {
func (client *ApiClient) ProjectUpdate(id string, payload ProjectUpdatePayload) (Project, error) {
var result Project
err := client.http.Put("/projects/"+id, payload, &result)

Expand All @@ -77,3 +82,19 @@ func (client *ApiClient) ProjectUpdate(id string, payload ProjectCreatePayload)
}
return result, nil
}

func (client *ApiClient) ProjectMove(id string, targetProjectId string) error {
// Pass nil if a subproject becomes a project.
var targetProjectIdPtr *string
if targetProjectId != "" {
targetProjectIdPtr = &targetProjectId
}

payload := struct {
TargetProjectId *string `json:"targetProjectId"`
}{
targetProjectIdPtr,
}

return client.http.Post("/projects/"+id+"/move", payload, nil)
}
34 changes: 33 additions & 1 deletion client/project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ var _ = Describe("Project", func() {
Describe("ProjectUpdate", func() {
var mockedResponse Project
BeforeEach(func() {
payload := ProjectCreatePayload{
payload := ProjectUpdatePayload{
Name: "newName",
Description: "newDesc",
}
Expand Down Expand Up @@ -148,4 +148,36 @@ var _ = Describe("Project", func() {
Expect(projects).To(Equal(mockProjects))
})
})

Describe("ProjectMove", func() {
targetProjectId := "targetid"

payload := struct {
TargetProjectId *string `json:"targetProjectId"`
}{
&targetProjectId,
}

BeforeEach(func() {
httpCall = mockHttpClient.EXPECT().Post("/projects/"+mockProject.Id+"/move", payload, nil).Times(1)
apiClient.ProjectMove(mockProject.Id, targetProjectId)
})

It("Should send POST request with project id and target project id", func() {})
})

Describe("ProjectMove with no target project id", func() {
payload := struct {
TargetProjectId *string `json:"targetProjectId"`
}{
nil,
}

BeforeEach(func() {
httpCall = mockHttpClient.EXPECT().Post("/projects/"+mockProject.Id+"/move", payload, nil).Times(1)
apiClient.ProjectMove(mockProject.Id, "")
})

It("Should send POST request with project id and nil target project id", func() {})
})
})
11 changes: 9 additions & 2 deletions env0/resource_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ func resourceProject() *schema.Resource {
Type: schema.TypeString,
Description: "If set, the project becomes a 'sub-project' of the parent project. See https://docs.env0.com/docs/sub-projects",
Optional: true,
ForceNew: true,
},
},
}
Expand Down Expand Up @@ -110,7 +109,15 @@ func resourceProjectUpdate(ctx context.Context, d *schema.ResourceData, meta int
apiClient := meta.(client.ApiClientInterface)

id := d.Id()
var payload client.ProjectCreatePayload
var payload client.ProjectUpdatePayload

if d.HasChange("parent_project_id") {
parentProjectId := d.Get("parent_project_id").(string)

if err := apiClient.ProjectMove(id, parentProjectId); err != nil {
return diag.Errorf("could not move project: %v", err)
}
}

if err := readResourceData(&payload, d); err != nil {
return diag.Errorf("schema resource data deserialization failed: %v", err)
Expand Down
30 changes: 28 additions & 2 deletions env0/resource_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ func TestUnitProjectResource(t *testing.T) {
ParentProjectId: project.Id,
}

updatedSubproject := client.Project{
Id: "subProjectId",
Description: "sub project des2",
Name: "sub project nam2",
ParentProjectId: "other_parent_id",
}

t.Run("Test project", func(t *testing.T) {
testCase := resource.TestCase{
Steps: []resource.TestStep{
Expand Down Expand Up @@ -67,7 +74,7 @@ func TestUnitProjectResource(t *testing.T) {
Name: project.Name,
Description: project.Description,
}).Times(1).Return(project, nil)
mock.EXPECT().ProjectUpdate(updatedProject.Id, client.ProjectCreatePayload{
mock.EXPECT().ProjectUpdate(updatedProject.Id, client.ProjectUpdatePayload{
Name: updatedProject.Name,
Description: updatedProject.Description,
}).Times(1).Return(updatedProject, nil)
Expand Down Expand Up @@ -98,6 +105,19 @@ func TestUnitProjectResource(t *testing.T) {
resource.TestCheckResourceAttr(accessor, "parent_project_id", project.Id),
),
},
{
Config: resourceConfigCreate(resourceType, resourceName, map[string]interface{}{
"name": updatedSubproject.Name,
"description": updatedSubproject.Description,
"parent_project_id": updatedSubproject.ParentProjectId,
}),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(accessor, "id", subProject.Id),
resource.TestCheckResourceAttr(accessor, "name", updatedSubproject.Name),
resource.TestCheckResourceAttr(accessor, "description", updatedSubproject.Description),
resource.TestCheckResourceAttr(accessor, "parent_project_id", updatedSubproject.ParentProjectId),
),
},
},
}

Expand All @@ -108,7 +128,13 @@ func TestUnitProjectResource(t *testing.T) {
Description: subProject.Description,
ParentProjectId: project.Id,
}).Times(1).Return(subProject, nil),
mock.EXPECT().Project(subProject.Id).Times(1).Return(subProject, nil),
mock.EXPECT().Project(subProject.Id).Times(2).Return(subProject, nil),
mock.EXPECT().ProjectMove(subProject.Id, updatedSubproject.ParentProjectId).Times(1).Return(nil),
mock.EXPECT().ProjectUpdate(subProject.Id, client.ProjectUpdatePayload{
Name: updatedSubproject.Name,
Description: updatedSubproject.Description,
}).Times(1).Return(updatedSubproject, nil),
mock.EXPECT().Project(subProject.Id).Times(1).Return(updatedSubproject, nil),
mock.EXPECT().ProjectEnvironments(subProject.Id).Times(1).Return([]client.Environment{}, nil),
mock.EXPECT().ProjectDelete(subProject.Id).Times(1),
)
Expand Down
14 changes: 13 additions & 1 deletion tests/integration/002_project/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,24 @@ resource "env0_project" "test_project" {
description = "Test Description ${var.second_run ? "after update" : ""}"
}

resource "env0_project" "test_project2" {
name = "Test-Project-${random_string.random.result}2"
description = "Test Description2 ${var.second_run ? "after update" : ""}"
}

resource "env0_project" "test_sub_project" {
name = "Test-Sub-Project-${random_string.random.result}"
description = "Test Description ${var.second_run ? "after update" : ""}"
parent_project_id = env0_project.test_project.id
parent_project_id = var.second_run ? env0_project.test_project2.id : env0_project.test_project.id
}

resource "env0_project" "test_sub_project_to_project" {
name = "Test-Sub-Project-To-Project-${random_string.random.result}"
description = "Test Description ${var.second_run ? "after update" : ""}"
parent_project_id = var.second_run ? "" : env0_project.test_project.id
}


data "env0_project" "data_by_name" {
name = env0_project.test_project.name
}
Expand Down

0 comments on commit 61abddd

Please sign in to comment.