Skip to content

Commit

Permalink
resolves #51 and fixes role password management
Browse files Browse the repository at this point in the history
resolves #51 and fixes role password management
  • Loading branch information
kislerdm authored Oct 22, 2023
2 parents bff2adf + 60a9f54 commit 9333a95
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 64 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,7 @@ jobs:
uses: actions/setup-go@v4
with:
go-version-file: 'go.mod'
cache: true
id: go
- run: go mod download
- name: Run testsacc
run: make testacc
env:
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ 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.2.3] - 2023-10-22

### Fixed

- [[#51](https://github.com/kislerdm/terraform-provider-neon/issues/51)] Fixed credentials content.
- Fixed management of the `resource_role` state:
- Fixed password reading.
- Removed the side effect upon the resource import: the role's password won't be reset now.

### Changed

- Updated dependencies: Neon Go SDK [v0.2.5](https://github.com/kislerdm/neon-sdk-go/releases/tag/v0.2.5)

## [v0.2.2] - 2023-09-19

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
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.29.0
github.com/kislerdm/neon-sdk-go v0.2.2
github.com/kislerdm/neon-sdk-go v0.2.5
)

require (
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+h
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kislerdm/neon-sdk-go v0.2.2 h1:f21FFBnN28D+MfsZS+kwzKD2lDvOcK68Hw6bulQYawk=
github.com/kislerdm/neon-sdk-go v0.2.2/go.mod h1:WSwEZ7oeR5KfQoCuDh/04LZxnSKDcvfsZyfG/QicDb8=
github.com/kislerdm/neon-sdk-go v0.2.5 h1:RL0AZOPgel3Wkmyc99OTCPoQjfG/GKMWDVTQNVIIEUo=
github.com/kislerdm/neon-sdk-go v0.2.5/go.mod h1:WSwEZ7oeR5KfQoCuDh/04LZxnSKDcvfsZyfG/QicDb8=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
Expand Down
57 changes: 52 additions & 5 deletions internal/provider/acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ func TestAccEndToEnd(t *testing.T) {
branchName string = "br-foo"
branchRoleName string = "role-foo"
dbName string = "db-foo"
customRoleName string = "qux"
)

resourceDefinition := fmt.Sprintf(
Expand Down Expand Up @@ -94,7 +95,7 @@ resource "neon_endpoint" "this" {
resource "neon_role" "this" {
project_id = neon_project.this.id
branch_id = neon_project.this.default_branch_id
name = "qux"
name = "%s"
}
resource "neon_database" "this" {
Expand All @@ -117,6 +118,7 @@ resource "neon_database" "this" {
branchName,
branchRoleName,
dbName,
customRoleName,
)

const resourceNameProject = "neon_project.this"
Expand Down Expand Up @@ -379,18 +381,63 @@ resource "neon_database" "this" {
return err
}

return resource.TestCheckResourceAttr(
if err := resource.TestCheckResourceAttr(
resourceNameProject, "database_name", db.Name,
)(state)
)(state); err != nil {
return err
}

return resource.TestCheckResourceAttr(
if err := resource.TestCheckResourceAttr(
resourceNameProject, "branch.0.database_name", db.Name,
)(state)
)(state); err != nil {
return err
}
}
}

return nil
},

// check the roles
func(state *terraform.State) error {
// WHEN
// list projects
resp, err := client.ListProjectBranchRoles(projectID, defaultBranchID)
if err != nil {
return err
}

// THEN
roles := resp.Roles
if len(roles) != 2 {
return errors.New("two roles are expected for the branch " + defaultBranchID)
}

for _, role := range roles {
// validate password
resp, err := client.GetProjectBranchRolePassword(projectID,
defaultBranchID, role.Name)
if err != nil {
return err
}

switch role.Name {
case customRoleName:
if err := resource.TestCheckResourceAttr(
"neon_role.this", "password", resp.Password,
)(state); err != nil {
return err
}
default:
if err := resource.TestCheckResourceAttr(
resourceNameProject, "database_password", resp.Password,
)(state); err != nil {
return err
}
}
}
return nil
},
),
},
{
Expand Down
3 changes: 2 additions & 1 deletion internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ func init() {
// 0.2.0: 4
// 0.2.1: 5
// 0.2.2: 6
const versionSchema = 6
// 0.2.3: 7
const versionSchema = 7

func New(version string) *schema.Provider {
return &schema.Provider{
Expand Down
54 changes: 22 additions & 32 deletions internal/provider/resource_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ The maximum value is 604800 seconds (1 week)`,
},
}

func mapToDfaultEndpointsSettings(v map[string]interface{}) *neon.DefaultEndpointSettings {
func mapToDefaultEndpointsSettings(v map[string]interface{}) *neon.DefaultEndpointSettings {
o := neon.DefaultEndpointSettings{}
if v, ok := v["autoscaling_limit_min_cu"].(float64); ok && v > 0 {
o.AutoscalingLimitMinCu = neon.ComputeUnit(v)
Expand Down Expand Up @@ -325,17 +325,14 @@ func mapToBranchSettings(v map[string]interface{}) *neon.ProjectCreateRequestPro
}

func newDbConnectionInfo(
c neon.Client,
projectID string,
branchID string,
endpoints []neon.Endpoint,
databases []neon.Database,
roles []neon.Role,
) dbConnectionInfo {
) (dbConnectionInfo, error) {
o := dbConnectionInfo{}

if endpoints == nil || databases == nil || roles == nil {
return o
}

for _, el := range endpoints {
if !el.Disabled && el.BranchID == branchID {
o.host = el.Host
Expand All @@ -351,16 +348,14 @@ func newDbConnectionInfo(
}
}

for _, el := range roles {
if el.BranchID == branchID && el.Name == o.userName {
if el.Protected {
o.pass = el.Password
break
}
}
resp, err := c.GetProjectBranchRolePassword(projectID, branchID, o.userName)
if err != nil {
return dbConnectionInfo{}, err
}

return o
o.pass = resp.Password

return o, nil
}

type dbConnectionInfo struct {
Expand Down Expand Up @@ -495,7 +490,7 @@ func resourceProjectCreate(ctx context.Context, d *schema.ResourceData, meta int

if v, ok := d.GetOk("default_endpoint_settings"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
if v, ok := v.([]interface{})[0].(map[string]interface{}); ok && len(v) > 0 {
projectDef.DefaultEndpointSettings = mapToDfaultEndpointsSettings(v)
projectDef.DefaultEndpointSettings = mapToDefaultEndpointsSettings(v)
}
}

Expand Down Expand Up @@ -529,13 +524,13 @@ func resourceProjectCreate(ctx context.Context, d *schema.ResourceData, meta int
d.SetId(projectID)

branch := resp.BranchResponse.Branch
if err := updateStateProject(
d, resp.ProjectResponse.Project, branch.ID, branch.Name,
newDbConnectionInfo(
branch.ID, resp.EndpointsResponse.Endpoints, resp.DatabasesResponse.Databases,
resp.RolesResponse.Roles,
),
); err != nil {
info, err := newDbConnectionInfo(client, projectID, branch.ID, resp.EndpointsResponse.Endpoints,
resp.DatabasesResponse.Databases)
if err != nil {
return diag.FromErr(err)
}

if err := updateStateProject(d, resp.ProjectResponse.Project, branch.ID, branch.Name, info); err != nil {
return diag.FromErr(err)
}

Expand All @@ -556,7 +551,7 @@ func resourceProjectUpdate(ctx context.Context, d *schema.ResourceData, meta int

if v, ok := d.GetOk("default_endpoint_settings"); ok && len(v.([]interface{})) > 0 && v.([]interface{})[0] != nil {
if v, ok := v.([]interface{})[0].(map[string]interface{}); ok && len(v) > 0 {
req.DefaultEndpointSettings = mapToDfaultEndpointsSettings(v)
req.DefaultEndpointSettings = mapToDefaultEndpointsSettings(v)
}
}

Expand Down Expand Up @@ -607,22 +602,17 @@ func resourceProjectRead(ctx context.Context, d *schema.ResourceData, meta inter
return diag.FromErr(err)
}

roles, err := client.ListProjectBranchRoles(d.Id(), branchMain.ID)
dbs, err := client.ListProjectBranchDatabases(d.Id(), branchMain.ID)
if err != nil {
return diag.FromErr(err)
}

dbs, err := client.ListProjectBranchDatabases(d.Id(), branchMain.ID)
info, err := newDbConnectionInfo(client, project.ID, branchMain.ID, endpoints.Endpoints, dbs.Databases)
if err != nil {
return diag.FromErr(err)
}

return diag.FromErr(
updateStateProject(
d, project, branchMain.ID, branchMain.Name,
newDbConnectionInfo(branchMain.ID, endpoints.Endpoints, dbs.Databases, roles.Roles),
),
)
return diag.FromErr(updateStateProject(d, project, branchMain.ID, branchMain.Name, info))
}

func resourceProjectDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) error {
Expand Down
8 changes: 2 additions & 6 deletions internal/provider/resource_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ func Test_resourceProjectCreate(t *testing.T) {
t.Run(
"shall request project with custom settings", func(t *testing.T) {
// GIVEN
meta := &sdkClientStub{
resp: neon.CreatedProject{},
}
meta := &sdkClientStub{}

resource := resourceProject()

Expand Down Expand Up @@ -209,9 +207,7 @@ func Test_resourceProjectCreate(t *testing.T) {
t.Run(
"shall request project with no data retention", func(t *testing.T) {
// GIVEN
meta := &sdkClientStub{
resp: neon.CreatedProject{},
}
meta := &sdkClientStub{}

resource := resourceProject()

Expand Down
38 changes: 29 additions & 9 deletions internal/provider/resource_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,16 @@ func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, meta interf

d.SetId(r.toString())

return updateStateRole(d, resp.Role)
role := resp.Role
if role.Password == "" {
r, err := meta.(neon.Client).GetProjectBranchRolePassword(r.ProjectID, r.ProjectID, role.Name)
if err != nil {
return err
}
role.Password = r.Password
}

return updateStateRole(d, role)
}

func resourceRoleReadRetry(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
Expand All @@ -111,7 +120,17 @@ func resourceRoleRead(ctx context.Context, d *schema.ResourceData, meta interfac
return err
}

return updateStateRole(d, resp.Role)
role := resp.Role
if role.Password == "" {
r, err := meta.(neon.Client).GetProjectBranchRolePassword(d.Get("project_id").(string),
d.Get("branch_id").(string), d.Get("name").(string))
if err != nil {
return err
}
role.Password = r.Password
}

return updateStateRole(d, role)
}

func resourceRoleDeleteRetry(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
Expand Down Expand Up @@ -147,19 +166,20 @@ func resourceRoleImport(ctx context.Context, d *schema.ResourceData, meta interf
return nil, err
}

resp, err := meta.(neon.Client).ResetProjectBranchRolePassword(
r.ProjectID,
r.BranchID,
r.Name,
)
resp, err := meta.(neon.Client).GetProjectBranchRolePassword(r.ProjectID, r.BranchID, r.Name)
if err != nil {
return nil, err
}

if err := updateStateRole(d, resp.Role); err != nil {
role := neon.Role{
BranchID: r.BranchID,
Name: r.Name,
Password: resp.Password,
}

if err := updateStateRole(d, role); err != nil {
return nil, err
}
setResourceDataFromComplexID(d, r)

return []*schema.ResourceData{d}, nil
}
Loading

0 comments on commit 9333a95

Please sign in to comment.