Skip to content

Commit 7a21036

Browse files
authored
Feat/crud (#2)
* Upgrade go, map workflow to sqlserver primitives * implement crud handler
1 parent d541948 commit 7a21036

36 files changed

Lines changed: 927 additions & 1053 deletions

.github/workflows/publish.yml

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ jobs:
1818

1919
steps:
2020
- name: Checkout
21-
uses: actions/checkout@v3
22-
23-
- name: Set up Nullstone
24-
uses: nullstone-io/setup-nullstone-action@v0
21+
uses: actions/checkout@v5
2522

2623
- name: Setup Go
2724
uses: actions/setup-go@v4
@@ -32,14 +29,15 @@ jobs:
3229
make build
3330
make package
3431
32+
- name: Set up Nullstone
33+
uses: nullstone-io/setup-nullstone-action@v0
34+
3535
- name: Find version
3636
id: version
37-
run: echo "MODULE_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
37+
run: echo ::set-output name=tag::${GITHUB_REF#refs/tags/v}
3838

3939
- id: publish-aws
4040
name: Publish AWS
4141
working-directory: aws/tf
4242
run: |
43-
nullstone modules publish \
44-
--include=files/mss-db-admin.zip \
45-
--version=${{ env.MODULE_VERSION }}
43+
nullstone modules publish --version=${{ steps.version.outputs.tag }}

Makefile

Lines changed: 29 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,29 @@
1-
NAME := mss-db-admin
2-
3-
.PHONY: tools build
4-
5-
tools:
6-
go install github.com/aws/aws-lambda-go/cmd/build-lambda-zip@latest
7-
8-
build:
9-
mkdir -p ./aws/tf/files
10-
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o ./aws/tf/files/bootstrap ./aws/
11-
12-
package: tools
13-
# Package aws module using build-lambda-zip which produces a viable package from any OS
14-
cd ./aws/tf && build-lambda-zip --output files/mss-db-admin.zip files/bootstrap
15-
16-
acc: acc-up acc-run acc-down
17-
18-
acc-up:
19-
cd acc && docker-compose -p mss-db-admin-acc up -d db
20-
21-
acc-run:
22-
ACC=1 gotestsum ./acc/...
23-
24-
acc-down:
25-
cd acc && docker-compose -p mss-db-admin-acc down
1+
NAME := mss-db-admin
2+
3+
.PHONY: tools build
4+
5+
tools:
6+
go install github.com/aws/aws-lambda-go/cmd/build-lambda-zip@latest
7+
8+
build:
9+
mkdir -p ./aws/tf/files
10+
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o ./aws/tf/files/bootstrap ./aws/
11+
12+
package: tools
13+
# Package aws module using build-lambda-zip which produces a viable package from any OS
14+
cd ./aws/tf && build-lambda-zip --output files/mss-db-admin.zip files/bootstrap
15+
16+
acc: acc-up acc-wait acc-run acc-down
17+
18+
acc-up:
19+
cd acc && docker-compose -p mss-db-admin-acc up -d db
20+
21+
acc-wait:
22+
@echo "Waiting for SQL Server to start..."
23+
@sleep 15
24+
25+
acc-run:
26+
ACC=1 gotestsum ./acc/...
27+
28+
acc-down:
29+
cd acc && docker-compose -p mss-db-admin-acc down

acc/compose.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
services:
2+
db:
3+
image: mcr.microsoft.com/mssql/server:2022-latest
4+
ports:
5+
- "1433:1433"
6+
environment:
7+
- ACCEPT_EULA=Y
8+
- MSSQL_SA_PASSWORD=YourStr0ng!Pass

acc/database_access_test.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package acc
2+
3+
import (
4+
"github.com/nullstone-modules/mss-db-admin/sqlserver"
5+
"github.com/stretchr/testify/assert"
6+
"github.com/stretchr/testify/require"
7+
"os"
8+
"testing"
9+
)
10+
11+
func TestDatabaseAccess(t *testing.T) {
12+
if os.Getenv("ACC") != "1" {
13+
t.Skip("Set ACC=1 to run e2e tests")
14+
}
15+
16+
store := createStore(t)
17+
18+
// Create database
19+
_, err := store.Databases.Create(sqlserver.Database{Name: "access-test-db"})
20+
require.NoError(t, err, "create database")
21+
22+
// Create login
23+
_, err = store.Logins.Create(sqlserver.Login{
24+
Name: "access-test-user",
25+
Password: "Acc3ss!TestPass",
26+
})
27+
require.NoError(t, err, "create login")
28+
29+
// Grant access
30+
access := sqlserver.DatabaseAccess{
31+
Database: "access-test-db",
32+
Login: "access-test-user",
33+
}
34+
result, err := store.DatabaseAccess.Create(access)
35+
require.NoError(t, err, "grant database access")
36+
require.NotNil(t, result)
37+
assert.Equal(t, "access-test-db", result.Database)
38+
assert.Equal(t, "access-test-user", result.Login)
39+
40+
// Read access
41+
found, err := store.DatabaseAccess.Read(sqlserver.DatabaseAccessKey{
42+
Database: "access-test-db",
43+
Login: "access-test-user",
44+
})
45+
require.NoError(t, err, "read database access")
46+
require.NotNil(t, found)
47+
48+
// Revoke access
49+
ok, err := store.DatabaseAccess.Drop(sqlserver.DatabaseAccessKey{
50+
Database: "access-test-db",
51+
Login: "access-test-user",
52+
})
53+
require.NoError(t, err, "revoke database access")
54+
assert.True(t, ok)
55+
}

acc/database_test.go

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,29 @@
11
package acc
22

33
import (
4-
_ "github.com/lib/pq"
4+
"os"
5+
"testing"
6+
57
"github.com/nullstone-modules/mss-db-admin/sqlserver"
68
"github.com/stretchr/testify/assert"
79
"github.com/stretchr/testify/require"
8-
"os"
9-
"testing"
1010
)
1111

1212
func TestDatabase(t *testing.T) {
1313
if os.Getenv("ACC") != "1" {
1414
t.Skip("Set ACC=1 to run e2e tests")
1515
}
1616

17-
db := createDb(t)
18-
defer db.Close()
19-
20-
database := sqlserver.Database{Name: "database-test-database"}
21-
22-
ownerRole := sqlserver.Role{Name: database.Name}
23-
require.NoError(t, ownerRole.Ensure(db), "error creating owner role")
24-
database.Owner = ownerRole.Name
25-
26-
dbInfo, err := sqlserver.CalcDbConnectionInfo(db)
27-
require.NoError(t, err, "calc db info")
17+
store := createStore(t)
2818

29-
require.NoError(t, database.Create(db, *dbInfo), "unexpected error")
19+
database := sqlserver.Database{Name: "database-test-db"}
20+
result, err := store.Databases.Create(database)
21+
require.NoError(t, err, "create database")
22+
require.NotNil(t, result)
23+
assert.Equal(t, "database-test-db", result.Name)
3024

31-
find := &sqlserver.Database{Name: "database-test-database"}
32-
require.NoError(t, find.Read(db), "read database")
33-
assert.Equal(t, ownerRole.Name, find.Owner, "mismatched owner")
25+
found, err := store.Databases.Read("database-test-db")
26+
require.NoError(t, err, "read database")
27+
require.NotNil(t, found)
28+
assert.Equal(t, "database-test-db", found.Name)
3429
}

acc/db.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package acc
22

33
import (
4-
"database/sql"
4+
"github.com/nullstone-modules/mss-db-admin/sqlserver"
55
"testing"
6+
7+
_ "github.com/microsoft/go-mssqldb"
68
)
79

8-
func createDb(t *testing.T) *sql.DB {
9-
connUrl := "postgres://pda:pda@localhost:8432/postgres?sslmode=disable"
10-
db, err := sql.Open("postgres", connUrl)
11-
if err != nil {
12-
t.Fatalf("error connecting to postgres: %s", err)
13-
}
14-
return db
10+
const connUrl = "sqlserver://sa:YourStr0ng!Pass@localhost:1433?database=master"
11+
12+
func createStore(t *testing.T) *sqlserver.Store {
13+
store := sqlserver.NewStore(connUrl)
14+
t.Cleanup(func() { store.Close() })
15+
return store
1516
}

acc/docker-compose.yml

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

acc/full_test.go

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,68 @@
11
package acc
22

33
import (
4-
"database/sql"
54
"fmt"
6-
_ "github.com/lib/pq"
5+
_ "github.com/microsoft/go-mssqldb"
76
"github.com/nullstone-modules/mss-db-admin/sqlserver"
8-
"github.com/nullstone-modules/mss-db-admin/workflows"
97
"github.com/stretchr/testify/assert"
108
"github.com/stretchr/testify/require"
119
"net/url"
1210
"os"
1311
"strings"
1412
"testing"
15-
"time"
1613
)
1714

18-
// TestFull tests the entire workflow of create-database, create-user, create-db-access
15+
// TestFull tests the entire CRUD workflow:
16+
// create database -> create login -> grant access -> connect as user -> create table -> insert -> query
1917
func TestFull(t *testing.T) {
2018
if os.Getenv("ACC") != "1" {
2119
t.Skip("Set ACC=1 to run e2e tests")
2220
}
2321

24-
connUrl := "postgres://pda:pda@localhost:8432/postgres?sslmode=disable"
25-
db, err := sql.Open("postgres", connUrl)
26-
require.NoError(t, err, "connecting to postgres")
27-
defer db.Close()
28-
appConnUrl := "postgres://test-user:test-password@localhost:8432/test-database?sslmode=disable"
29-
appDb, err := sql.Open("postgres", appConnUrl)
30-
defer appDb.Close()
31-
fmt.Println(appDb.Ping())
22+
store := createStore(t)
3223

33-
newDatabase := sqlserver.Database{
34-
Name: "test-database",
35-
Owner: "test-database",
36-
}
37-
newUser := sqlserver.Role{
38-
Name: "test-user",
39-
Password: "test-password",
40-
}
24+
dbName := "full-test-db"
25+
loginName := "full-test-user"
26+
loginPass := "Full!Test0Pass"
27+
28+
// Create the database
29+
_, err := store.Databases.Create(sqlserver.Database{Name: dbName})
30+
require.NoError(t, err, "create database")
4131

42-
require.NoError(t, workflows.EnsureDatabase(db, newDatabase), "ensure database")
43-
require.NoError(t, workflows.EnsureUser(db, newUser), "ensure user")
44-
require.NoError(t, workflows.GrantDbAccess(db, appDb, newUser, newDatabase), "grant db access")
32+
// Create the login
33+
_, err = store.Logins.Create(sqlserver.Login{Name: loginName, Password: loginPass})
34+
require.NoError(t, err, "create login")
4535

46-
time.Sleep(500 * time.Millisecond)
36+
// Grant access
37+
_, err = store.DatabaseAccess.Create(sqlserver.DatabaseAccess{Database: dbName, Login: loginName})
38+
require.NoError(t, err, "grant database access")
4739

48-
// Attempt connection to newly-created app db
49-
u, _ := url.Parse(connUrl)
50-
u.Path = "/test-database"
51-
u.User = url.UserPassword(newUser.Name, newUser.Password)
40+
// Connect as the new user to the app database
41+
userConnUrl := fmt.Sprintf("sqlserver://%s:%s@localhost:1433?database=%s",
42+
url.PathEscape(loginName),
43+
url.PathEscape(loginPass),
44+
url.PathEscape(dbName),
45+
)
46+
userDb, err := sqlserver.OpenDatabase(userConnUrl, "")
47+
require.NoError(t, err, "connecting as app user")
48+
defer userDb.Close()
5249

53-
// Attempt to create schema objects
54-
_, err = appDb.Exec("CREATE TABLE todos ( id SERIAL NOT NULL, name varchar(255) );")
50+
// Create a table
51+
_, err = userDb.Exec("CREATE TABLE todos ( id INT IDENTITY(1,1) NOT NULL, name varchar(255) );")
5552
require.NoError(t, err, "create table")
5653

57-
// Attempt to insert records
54+
// Insert records
5855
sq := strings.Join([]string{
5956
`INSERT INTO todos (name) VALUES ('item1');`,
6057
`INSERT INTO todos (name) VALUES ('item2');`,
6158
`INSERT INTO todos (name) VALUES ('item3');`,
62-
}, "")
63-
_, err = appDb.Exec(sq)
59+
}, " ")
60+
_, err = userDb.Exec(sq)
6461
require.NoError(t, err, "insert todos")
6562

66-
// Attempt to retrieve them
63+
// Query records
6764
results := make([]string, 0)
68-
rows, err := appDb.Query(`SELECT * FROM todos`)
65+
rows, err := userDb.Query(`SELECT id, name FROM todos ORDER BY id`)
6966
require.NoError(t, err, "query todos")
7067
defer rows.Close()
7168
for rows.Next() {

acc/login_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package acc
2+
3+
import (
4+
"github.com/nullstone-modules/mss-db-admin/sqlserver"
5+
"github.com/stretchr/testify/assert"
6+
"github.com/stretchr/testify/require"
7+
"os"
8+
"testing"
9+
)
10+
11+
func TestLogin(t *testing.T) {
12+
if os.Getenv("ACC") != "1" {
13+
t.Skip("Set ACC=1 to run e2e tests")
14+
}
15+
16+
store := createStore(t)
17+
18+
login := sqlserver.Login{
19+
Name: "login-test-user",
20+
Password: "L0gin!TestPass",
21+
}
22+
result, err := store.Logins.Create(login)
23+
require.NoError(t, err, "create login")
24+
require.NotNil(t, result)
25+
assert.Equal(t, "login-test-user", result.Name)
26+
27+
found, err := store.Logins.Read("login-test-user")
28+
require.NoError(t, err, "read login")
29+
require.NotNil(t, found)
30+
assert.Equal(t, "login-test-user", found.Name)
31+
32+
updated, err := store.Logins.Update("login-test-user", sqlserver.Login{
33+
Name: "login-test-user",
34+
Password: "NewL0gin!Pass",
35+
})
36+
require.NoError(t, err, "update login password")
37+
require.NotNil(t, updated)
38+
}

0 commit comments

Comments
 (0)