diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cba348..51c403f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [v0.4.0] - 2024-01-21 + +### Added + +- Added the resource `neon_project_permission` to manage the project's permissions. + +### Changed + +- Updated dependencies: Neon Go SDK [v0.4.3](https://github.com/kislerdm/neon-sdk-go/releases/tag/v0.4.3) + ## [v0.3.2] - 2024-01-11 ### Fixed diff --git a/go.mod b/go.mod index cb7e873..22e7136 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/kislerdm/terraform-provider-neon go 1.21 require ( + github.com/google/uuid v1.3.1 github.com/hashicorp/terraform-plugin-docs v0.13.0 github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.31.0 @@ -22,7 +23,6 @@ require ( github.com/fatih/color v1.13.0 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/uuid v1.3.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/internal/provider/resource_project_permission_test.go b/internal/provider/resource_project_permission_test.go index 5836912..48d5b86 100644 --- a/internal/provider/resource_project_permission_test.go +++ b/internal/provider/resource_project_permission_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "testing" + "time" neon "github.com/kislerdm/neon-sdk-go" ) @@ -157,5 +158,187 @@ func Test_resourceProjectPermissionDelete(t *testing.T) { } func Test_resourceProjectPermissionRead(t *testing.T) { + t.Parallel() + const ( + projectID = "myproject" + permissionID = "mypermission" + id = projectID + "/" + permissionID + ) + + t.Run("shall find the permission given the resource id", func(t *testing.T) { + const email = "foo@bar.baz" + resource := resourceProjectPermission() + definition := resource.TestResourceData() + definition.SetId(id) + + meta := &sdkClientStub{ + stubProjectPermission: stubProjectPermission{ + ProjectPermissions: neon.ProjectPermissions{ + ProjectPermissions: []neon.ProjectPermission{ + { + GrantedAt: time.Now().UTC(), + GrantedToEmail: email, + ID: permissionID, + }, + }, + }, + }, + } + + d := resourceProjectPermissionRead(context.TODO(), definition, meta) + if d.HasError() { + t.Fatalf("unexpected errors: %v", d) + } + + gotEmail := definition.Get("grantee").(string) + if gotEmail != email { + t.Fatalf("unexpected grantee email found: want=%s, got=%s", email, gotEmail) + } + + gotProjectID := definition.Get("project_id").(string) + if gotProjectID != projectID { + t.Fatalf("unexpected projectID found: want=%s, got=%s", projectID, gotProjectID) + } + }) + t.Run("shall find no permission by its id", func(t *testing.T) { + resource := resourceProjectPermission() + definition := resource.TestResourceData() + definition.SetId(id) + + meta := &sdkClientStub{ + stubProjectPermission: stubProjectPermission{ + ProjectPermissions: neon.ProjectPermissions{}, + }, + } + + d := resourceProjectPermissionRead(context.TODO(), definition, meta) + if d.HasError() { + t.Fatalf("unexpected errors: %v", d) + } + + gotEmail := definition.Get("grantee").(string) + if gotEmail != "" { + t.Fatalf("unexpected grantee email found: want=%s, got=%s", "", gotEmail) + } + + gotProjectID := definition.Get("project_id").(string) + if gotProjectID != "" { + t.Fatalf("unexpected projectID found: want=%s, got=%s", "", gotProjectID) + } + }) + + t.Run("shall fail when listing project's permissions", func(t *testing.T) { + resource := resourceProjectPermission() + definition := resource.TestResourceData() + definition.SetId(id) + + meta := &sdkClientStub{ + stubProjectPermission: stubProjectPermission{ + err: errors.New("foobar"), + }, + } + + d := resourceProjectPermissionRead(context.TODO(), definition, meta) + if !d.HasError() { + t.Fatal("error expected") + } + }) +} + +func Test_resourceProjectPermissionImport(t *testing.T) { + t.Parallel() + + const ( + projectID = "foo" + permissionID = "bar" + id = projectID + "/" + permissionID + email = "foo@bar.baz" + ) + + t.Run("shall import the permission given its id", func(t *testing.T) { + resource := resourceProjectPermission() + definition := resource.TestResourceData() + definition.SetId(id) + + meta := &sdkClientStub{ + stubProjectPermission: stubProjectPermission{ + ProjectPermissions: neon.ProjectPermissions{ + ProjectPermissions: []neon.ProjectPermission{ + { + GrantedAt: time.Now().UTC(), + GrantedToEmail: email, + ID: permissionID, + }, + }, + }, + }, + } + + resources, err := resourceProjectPermissionImport(context.TODO(), definition, meta) + if err != nil { + t.Fatalf("unexpected errors: %v", err) + } + + d := resources[0] + + gotEmail := d.Get("grantee").(string) + if gotEmail != email { + t.Fatalf("unexpected grantee email found: want=%s, got=%s", email, gotEmail) + } + + gotProjectID := d.Get("project_id").(string) + if gotProjectID != projectID { + t.Fatalf("unexpected projectID found: want=%s, got=%s", projectID, gotProjectID) + } + }) + + t.Run("shall fail because no permission was found by its id", func(t *testing.T) { + resource := resourceProjectPermission() + definition := resource.TestResourceData() + definition.SetId(id) + + meta := &sdkClientStub{ + stubProjectPermission: stubProjectPermission{ + ProjectPermissions: neon.ProjectPermissions{}, + }, + } + + _, err := resourceProjectPermissionImport(context.TODO(), definition, meta) + const wantErrStr = "no permission found" + if err.Error() != wantErrStr { + t.Fatalf("'%s' error expected", wantErrStr) + } + }) + + t.Run("shall fail because provided id is not correct", func(t *testing.T) { + resource := resourceProjectPermission() + definition := resource.TestResourceData() + definition.SetId("qux") + + meta := &sdkClientStub{} + _, err := resourceProjectPermissionImport(context.TODO(), definition, meta) + + const wantErrStr = "not recognized format of the project permission resource's ID" + if err.Error() != wantErrStr { + t.Fatalf("'%s' error expected", wantErrStr) + } + }) + + t.Run("shall fail when listing project's permissions", func(t *testing.T) { + resource := resourceProjectPermission() + definition := resource.TestResourceData() + definition.SetId(id) + + meta := &sdkClientStub{ + stubProjectPermission: stubProjectPermission{ + err: errors.New("foobar"), + }, + } + + _, err := resourceProjectPermissionImport(context.TODO(), definition, meta) + if err == nil { + t.Fatal("error expected") + } + }) }