@@ -2,11 +2,6 @@ package migrate
2
2
3
3
import (
4
4
"database/sql"
5
- "fmt"
6
- "log"
7
- "net/url"
8
- "path/filepath"
9
- "strings"
10
5
11
6
"github.com/octavore/naga/service"
12
7
"github.com/rubenv/sql-migrate"
@@ -28,6 +23,7 @@ type Module struct {
28
23
migrationSource migrate.MigrationSource
29
24
30
25
suffixForTest string
26
+ env service.Environment
31
27
}
32
28
33
29
// Config for migrate module
@@ -43,203 +39,41 @@ type Datasource struct {
43
39
DSN string `json:"dsn"`
44
40
}
45
41
46
- func (m * Module ) printHelp (ctx * service.CommandContext ) {
47
- if len (ctx .Args ) != 1 {
48
- fmt .Println ("Please specify a db:" )
49
- if len (m .config .Datasources ) == 0 {
50
- fmt .Println (" no databases found!" )
51
- } else {
52
- for ds := range m .config .Datasources {
53
- fmt .Println (" " + ds )
54
- }
55
- }
56
- ctx .UsageExit ()
57
- }
58
- }
59
-
42
+ // Init the migrate module
60
43
func (m * Module ) Init (c * service.Config ) {
61
- c .AddCommand (& service.Command {
62
- Keyword : "db:migrate <db>" ,
63
- ShortUsage : "run db migrations" ,
64
- Run : func (ctx * service.CommandContext ) {
65
- if len (ctx .Args ) != 1 {
66
- m .printHelp (ctx )
67
- }
68
- err := m .Migrate (ctx .Args [0 ])
69
- if err != nil {
70
- log .Println ("migrate:" , err )
71
- }
72
- },
73
- })
74
-
75
- c .AddCommand (& service.Command {
76
- Keyword : "db:reset <db>" ,
77
- ShortUsage : "reset database" ,
78
- Run : func (ctx * service.CommandContext ) {
79
- if len (ctx .Args ) != 1 {
80
- m .printHelp (ctx )
81
- }
82
- dbname := ctx .Args [0 ]
83
- err := m .Reset (dbname )
84
- if err != nil {
85
- log .Println ("migrate:" , err )
86
- }
87
- err = m .Migrate (dbname )
88
- if err != nil {
89
- log .Println ("migrate:" , err )
90
- }
91
- },
92
- })
44
+ m .registerCommands (c )
93
45
94
46
c .Setup = func () error {
47
+ m .env = c .Env ()
95
48
err := m .Config .ReadConfig (& m .config )
96
49
if m .config .MigrationsTable != "" {
97
50
migrate .SetTable (m .config .MigrationsTable )
98
51
}
99
52
return err
100
53
}
101
-
102
- c .SetupTest = func () {
103
- }
104
- }
105
-
106
- func (m * Module ) getConfig (dbname string ) (* Datasource , error ) {
107
- ds , ok := m .config .Datasources [dbname ]
108
- if ! ok {
109
- return nil , fmt .Errorf ("migrate: %q not configured" , dbname )
110
- }
111
-
112
- // special case for parallelizing tests: add a suffix to the dbname
113
- if dbname == "test" {
114
- u , err := url .Parse (ds .DSN )
115
- if err != nil {
116
- return nil , err
117
- }
118
- database := strings .Trim (u .Path , "/" )
119
- if m .suffixForTest == "" {
120
- m .suffixForTest = randomToken ()
121
- }
122
- u .Path = database + "_" + m .suffixForTest
123
- ds .DSN = u .String ()
124
- }
125
- return & ds , nil
126
54
}
127
55
128
- // Connect to the given DB
129
- func (m * Module ) Connect ( dbname string ) (* sql.DB , error ) {
130
- ds , err := m .getConfig ( dbname )
56
+ // ConnectDefault to the DB with name specified by env
57
+ func (m * Module ) ConnectDefault ( ) (* sql.DB , error ) {
58
+ ds , err := m .GetBackend ( string ( m . env ) )
131
59
if err != nil {
132
60
return nil , err
133
61
}
134
- return sql .Open (ds .Driver , ds .DSN )
135
- }
136
-
137
- func (m * Module ) AddMigrations (migrationsDir string ) {
138
- panic ("todo" )
139
- }
140
-
141
- type (
142
- assetFunc func (path string ) ([]byte , error )
143
- assetDirFunc func (path string ) ([]string , error )
144
- )
145
-
146
- // SetMigrationSource sets the migration source, for compatibility with
147
- // embedded file assets.
148
- func (m * Module ) SetMigrationSource (asset assetFunc , assetDir assetDirFunc , dir string ) {
149
- m .migrationSource = & migrate.AssetMigrationSource {
150
- Asset : asset ,
151
- AssetDir : assetDir ,
152
- Dir : dir ,
153
- }
62
+ return ds .Connect ()
154
63
}
155
64
156
- // safeConnect connects to template1 so we can create/drop the desired database.
157
- func (m * Module ) safeConnect (dbname string ) (string , * sql.DB , error ) {
158
- ds , err := m .getConfig (dbname )
159
- if err != nil {
160
- return "" , nil , err
161
- }
162
-
163
- u , err := url .Parse (ds .DSN )
164
- if err != nil {
165
- return "" , nil , err
166
- }
167
-
168
- database := strings .Trim (u .Path , "/" )
169
- u .Path = "template1"
170
- u .RawPath = "template1"
171
-
172
- db , err := sql .Open (ds .Driver , u .String ())
173
- if err != nil {
174
- return "" , nil , err
175
- }
176
- return database , db , nil
65
+ // Connect is a helper function to connect to this datasource
66
+ func (d * Datasource ) Connect () (* sql.DB , error ) {
67
+ return sql .Open (d .Driver , d .DSN )
177
68
}
178
69
179
- // Reset drops and recreates the database
180
- func (m * Module ) Reset (dbname string ) error {
181
- err := m .Drop (dbname )
182
- if err != nil {
183
- return err
184
- }
185
-
186
- databaseName , db , err := m .safeConnect (dbname )
187
- if err != nil {
188
- return err
189
- }
190
- defer db .Close ()
191
-
192
- // using template0 in order to support test parallelism
193
- // cf http://stackoverflow.com/questions/4977171/pgerror-error-source-database-template1-is-being-accessed-by-other-users
194
- // you may be able to hack around by creating some kind of global lock to protect
195
- // connections to the template1 database?
196
- // or maybe drop the connection as soon as possible?
197
- _ , err = db .Exec (`CREATE DATABASE ` + databaseName + ` TEMPLATE template0` )
198
- return err
199
- }
200
-
201
- // Drop the database `dbname`
202
- func (m * Module ) Drop (dbname string ) error {
203
- databaseName , db , err := m .safeConnect (dbname )
70
+ // Migrate runs migrations in m
71
+ func (d * Datasource ) migrate (m migrate.MigrationSource ) error {
72
+ db , err := d .Connect ()
204
73
if err != nil {
205
74
return err
206
75
}
207
76
defer db .Close ()
208
- _ , err = db .Exec (`DROP DATABASE IF EXISTS ` + databaseName )
209
- return err
210
- }
211
-
212
- // getMigrationSource returns the m.migrationSource if set, otherwise
213
- // it defaults by reading from the MigrationsDir specified in
214
- func (m * Module ) getMigrationSource () (migrate.MigrationSource , error ) {
215
- if m .migrationSource != nil {
216
- return m .migrationSource , nil
217
- }
218
- configPath , err := filepath .Abs (m .Config .ConfigPath )
219
- if err != nil {
220
- return nil , err
221
- }
222
- migrationPath := filepath .Join (filepath .Dir (configPath ), m .config .MigrationsDir )
223
- return migrate.FileMigrationSource {Dir : migrationPath }, nil
224
- }
225
-
226
- // Migrate the given db
227
- func (m * Module ) Migrate (dbname string ) error {
228
- ds , err := m .getConfig (dbname )
229
- if err != nil {
230
- return err
231
- }
232
-
233
- db , err := sql .Open (ds .Driver , ds .DSN )
234
- if err != nil {
235
- return err
236
- }
237
- defer db .Close ()
238
- migrations , err := m .getMigrationSource ()
239
- if err != nil {
240
- return err
241
- }
242
-
243
- _ , err = migrate .Exec (db , ds .Driver , migrations , migrate .Up )
77
+ _ , err = migrate .Exec (db , d .Driver , m , migrate .Up )
244
78
return err
245
79
}
0 commit comments