Skip to content

Commit aae819c

Browse files
authored
Merge pull request #14 from DoodleScheduling/DK-2230
Some performance improvements DK-2230
2 parents 72541ce + 679bbab commit aae819c

23 files changed

+501
-198
lines changed

api/v1beta1/database_types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ type DatabaseSpec struct {
3838
DatabaseName string `json:"databaseName"`
3939

4040
// The connect URI
41-
// +required
42-
Address string `json:"address"`
41+
// +optional
42+
Address string `json:"address,omitempty"`
4343

4444
// Contains a credentials set of a user with enough permission to manage databases and user accounts
4545
// +required
@@ -74,6 +74,9 @@ type SecretReference struct {
7474

7575
type Role struct {
7676
Name string `json:"name"`
77+
78+
// +optional
79+
DB string `json:"db,omitempty"`
7780
}
7881

7982
// Extension is a resource representing database extension

api/v1beta1/mongodbdatabase_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
// MongoDBDatabaseSpec defines the desired state of MongoDBDatabase
2525
type MongoDBDatabaseSpec struct {
2626
*DatabaseSpec `json:",inline"`
27+
AtlasGroupId string `json:"atlasGroupId,omitempty"`
2728
}
2829

2930
// GetStatusConditions returns a pointer to the Status.Conditions slice
@@ -57,6 +58,10 @@ type MongoDBDatabase struct {
5758
Status MongoDBDatabaseStatus `json:"status,omitempty"`
5859
}
5960

61+
func (in *MongoDBDatabase) GetAtlasGroupId() string {
62+
return in.Spec.AtlasGroupId
63+
}
64+
6065
func (in *MongoDBDatabase) GetAddress() string {
6166
return in.Spec.Address
6267
}

api/v1beta1/mongodbuser_type.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,12 @@ func (in *MongoDBUser) GetCredentials() *SecretReference {
7676
return in.Spec.Credentials
7777
}
7878

79-
func (in *MongoDBUser) GetRoles() *[]Role {
80-
return in.Spec.Roles
79+
func (in *MongoDBUser) GetRoles() []Role {
80+
if in.Spec.Roles == nil {
81+
return []Role{}
82+
}
83+
84+
return *in.Spec.Roles
8185
}
8286

8387
// +kubebuilder:object:root=true

api/v1beta1/postgresqldatabase_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ type PostgreSQLDatabase struct {
5757
Status PostgreSQLDatabaseStatus `json:"status,omitempty"`
5858
}
5959

60+
func (in *PostgreSQLDatabase) GetAtlasGroupId() string {
61+
return ""
62+
}
63+
6064
func (in *PostgreSQLDatabase) GetAddress() string {
6165
return in.Spec.Address
6266
}

api/v1beta1/postgresqluser_type.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ func (in *PostgreSQLUser) GetCredentials() *SecretReference {
6868
return in.Spec.Credentials
6969
}
7070

71-
func (in *PostgreSQLUser) GetRoles() *[]Role {
71+
func (in *PostgreSQLUser) GetRoles() []Role {
7272
// NOOP
73-
return nil
73+
return []Role{}
7474
}
7575

7676
// +kubebuilder:object:root=true

common/db/atlas.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package db
2+
3+
import (
4+
"context"
5+
"errors"
6+
7+
"github.com/mongodb-forks/digest"
8+
"go.mongodb.org/atlas/mongodbatlas"
9+
)
10+
11+
type AtlasRepository struct {
12+
atlas *mongodbatlas.Client
13+
groupId string
14+
}
15+
16+
func NewAtlasRepository(ctx context.Context, groupId, publicKey, privateKey string) (Handler, error) {
17+
t := digest.NewTransport(publicKey, privateKey)
18+
tc, err := t.Client()
19+
if err != nil {
20+
return nil, err
21+
}
22+
23+
return &AtlasRepository{
24+
groupId: groupId,
25+
atlas: mongodbatlas.NewClient(tc),
26+
}, nil
27+
}
28+
29+
func (m *AtlasRepository) Close(ctx context.Context) error {
30+
return nil
31+
}
32+
33+
// CreateDatabaseIfNotExists is a dummy to apply to fulfill the contract,
34+
// we don't need to create the database on Atlas
35+
func (m *AtlasRepository) CreateDatabaseIfNotExists(ctx context.Context, database string) error {
36+
return nil
37+
}
38+
39+
func (m *AtlasRepository) SetupUser(ctx context.Context, database string, username string, password string, roles Roles) error {
40+
doesUserExist, err := m.doesUserExist(ctx, database, username)
41+
if err != nil {
42+
return err
43+
}
44+
45+
if !doesUserExist {
46+
if err := m.createUser(context.Background(), database, username, password, roles); err != nil {
47+
return err
48+
}
49+
if doesUserExistNow, err := m.doesUserExist(ctx, database, username); err != nil {
50+
return err
51+
} else if !doesUserExistNow {
52+
return errors.New("user doesn't exist after create")
53+
}
54+
} else {
55+
if err := m.updateUserPasswordAndRoles(ctx, database, username, password, roles); err != nil {
56+
return err
57+
}
58+
}
59+
60+
return nil
61+
}
62+
63+
func (m *AtlasRepository) DropUser(ctx context.Context, database string, username string) error {
64+
//not implemented
65+
return errors.New("not yet supported")
66+
}
67+
68+
func (m *AtlasRepository) EnableExtension(ctx context.Context, name string) error {
69+
// NOOP
70+
return nil
71+
}
72+
73+
func (m *AtlasRepository) doesUserExist(ctx context.Context, database string, username string) (bool, error) {
74+
_, _, err := m.atlas.DatabaseUsers.Get(ctx, database, m.groupId, username)
75+
if err != nil {
76+
return false, nil
77+
}
78+
79+
return true, err
80+
}
81+
82+
func (m *AtlasRepository) getRoles(database string, roles Roles) []mongodbatlas.Role {
83+
// by default, assign readWrite role (backward compatibility)
84+
if len(roles) == 0 {
85+
return []mongodbatlas.Role{{
86+
RoleName: "readWrite",
87+
DatabaseName: database,
88+
}}
89+
}
90+
91+
rs := make([]mongodbatlas.Role, 0)
92+
for _, r := range roles {
93+
db := r.DB
94+
if db == "" {
95+
db = database
96+
}
97+
98+
rs = append(rs, mongodbatlas.Role{
99+
RoleName: r.Name,
100+
DatabaseName: db,
101+
})
102+
}
103+
104+
return rs
105+
}
106+
107+
func (m *AtlasRepository) createUser(ctx context.Context, database string, username string, password string, roles Roles) error {
108+
user := &mongodbatlas.DatabaseUser{
109+
Username: username,
110+
Password: password,
111+
DatabaseName: database,
112+
Roles: m.getRoles(database, roles),
113+
}
114+
115+
_, _, err := m.atlas.DatabaseUsers.Create(ctx, m.groupId, user)
116+
if err != nil {
117+
return err
118+
}
119+
120+
return nil
121+
}
122+
123+
func (m *AtlasRepository) updateUserPasswordAndRoles(ctx context.Context, database string, username string, password string, roles Roles) error {
124+
user := &mongodbatlas.DatabaseUser{
125+
Username: username,
126+
Password: password,
127+
Roles: m.getRoles(database, roles),
128+
}
129+
130+
_, _, err := m.atlas.DatabaseUsers.Update(ctx, m.groupId, username, user)
131+
if err != nil {
132+
return err
133+
}
134+
135+
return nil
136+
}

common/db/db.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package db
2+
3+
import (
4+
"context"
5+
)
6+
7+
type Roles []Role
8+
type Role struct {
9+
Name string `json:"role" bson:"role"`
10+
DB string `json:"db" bson:"db"`
11+
}
12+
13+
type Users []User
14+
type User struct {
15+
User string `json:"user" bson:"user"`
16+
DB string `json:"db" bson:"db"`
17+
Roles Roles `json:"roles" bson:"roles"`
18+
}
19+
20+
// Invoke a database handler
21+
type Invoke func(ctx context.Context, uri, database, username, password string) (Handler, error)
22+
23+
// Handler is a wrapper arround a certain database client
24+
type Handler interface {
25+
Close(ctx context.Context) error
26+
SetupUser(ctx context.Context, database string, username string, password string, roles Roles) error
27+
DropUser(ctx context.Context, database string, username string) error
28+
CreateDatabaseIfNotExists(ctx context.Context, database string) error
29+
EnableExtension(ctx context.Context, name string) error
30+
}

common/db/handler.go

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)