schema-evolution-manager 0.9.24 → 0.9.25

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f558b6d464ff5f0df460c0a6cfdc2a9b3eadc062
4
- data.tar.gz: 59038ba0b4234da0ea505718d1846414fea3bb40
3
+ metadata.gz: bb6f13a7ee9457b87783a853e81388457ae38297
4
+ data.tar.gz: 6450ab24e9348ee9e21881256ba26081e97ddd8b
5
5
  SHA512:
6
- metadata.gz: 0d52b58665bbb777cee7eff41648fcbd0b11d1b69528c47f1175a039bb516ffb0854c1ff1b027729661edbbc87402b7514f72fc984ca58f581a9af17a9acb2a0
7
- data.tar.gz: 972a3132a497d487919031ec4acee6d25be979c73a5ac9727a92cb75ef821d947dacaec835675710909fe3c56929cae357b57d9b227da4a36f8d1cf15b003938
6
+ metadata.gz: 41f4a519bcb140564587b6f2faa2749be390523f86cac6520bb0b0f0af08ef213ec8b58ed58fbd74f607e92e4323f5ecb7ba44a1fd1f04e4602d834e5a6ffcb7
7
+ data.tar.gz: 9945e8b898c84a54ea1db077d862142cfa957b062d5d03f4268fb020f65b2b0f4cef1144cc123adc99a022ae8ed05c19f8ec7bc0b910202e7deb522074719840
data/README.md CHANGED
@@ -103,8 +103,7 @@ manage and release schema changes independent of application changes:
103
103
 
104
104
  ## Talks
105
105
 
106
- First presented at PGDay NYC 2013:
107
- https://speakerdeck.com/mbryzek/schema-evolutions-at-gilt-groupe
106
+ First presented at [PGDay NYC 2013](https://speakerdeck.com/mbryzek/schema-evolutions-at-gilt-groupe)
108
107
 
109
108
  ## Dependencies
110
109
 
@@ -116,19 +115,25 @@ https://speakerdeck.com/mbryzek/schema-evolutions-at-gilt-groupe
116
115
 
117
116
  - plpgsql must be available in the database. If needed you can:
118
117
 
119
- createlang plpgsql template1
120
- [http://www.postgresql.org/docs/8.4/static/app-createlang.html]
118
+ [createlang plpgsql template1](http://www.postgresql.org/docs/8.4/static/app-createlang.html)
121
119
 
122
120
  - Git: Designed to use git for history (all versions since 1.7).
123
121
 
124
122
  ## Installation
125
123
 
126
- git clone git://github.com/mbryzek/schema-evolution-manager.git
127
- cd schema-evolution-manager
128
- git checkout 0.9.24
129
- ruby ./configure.rb
130
- sudo ./install.rb
124
+ There are two ways to install schema evolution manager:
131
125
 
126
+ 1. Direct install using ruby (no dependency on ruby gems)
127
+
128
+ git clone git://github.com/mbryzek/schema-evolution-manager.git
129
+ cd schema-evolution-manager
130
+ git checkout 0.9.25
131
+ ruby ./configure.rb
132
+ sudo ./install.rb
133
+
134
+ 2. If you have ruby gems:
135
+
136
+ gem install schema-evolution-manager
132
137
 
133
138
  ## Upgrading
134
139
 
@@ -207,6 +212,24 @@ You will likely see a number of create table statements (see data model section
207
212
  which tells you that if you apply these changes, that sql script will be applied to the sample db
208
213
 
209
214
 
215
+ ### Specifying database password
216
+
217
+ There are two recommended ways in which to pass user passwords to psql:
218
+
219
+ 1. Create a [~/.pgpass
220
+ file](http://www.postgresql.org/docs/9.4/static/libpq-pgpass.html)
221
+ with the appropriate credentials</li>
222
+
223
+ 2. Specify a [--password] flag when running sem-apply. You will
224
+ then be prompted to enter your password once. sem will create a
225
+ temporary file to store your password, using that file during the
226
+ duration of the command and ensuring the file is deleted after sem
227
+ completed.
228
+
229
+ Example:
230
+
231
+ sem-apply --url postgresql://postgres@localhost/sample --password
232
+
210
233
  ### Apply the changes
211
234
 
212
235
  sem-apply --url postgresql://postgres@localhost/sample
@@ -262,7 +285,7 @@ For details on these tables, see scripts/*sql where the tables themselves are de
262
285
  ## PLPGSQL Utilities
263
286
 
264
287
  We've included a copy of the schema conventions we practice at
265
- (Gilt Groupe)[CONVENTIONS.md]. There are also a number of utility plpgsql
288
+ [Gilt Groupe](CONVENTIONS.md). There are also a number of utility plpgsql
266
289
  functions to help developers apply these conventions in a systematic way.
267
290
 
268
291
  The helpers are defined in
@@ -283,6 +306,7 @@ and utilities in practice.
283
306
  - sem-add: Adds a database upgrade script
284
307
  - sem-dist: Create a distribution tar.gz file containing schema upgrade scripts
285
308
  - sem-apply: Apply any deltas from a distribution tarball to a particular database
309
+ - sem-baseline: Add any migration scripts to the schema tables without actually applying them. See [Migrating](#migrating)
286
310
 
287
311
 
288
312
  ## Attributes supported in sql migration scripts
@@ -311,15 +335,22 @@ Currently supported attributes:
311
335
  - -- sem.attribute.transaction = none
312
336
  - -- sem.attribute.transaction = single
313
337
 
338
+ ## Migrating
339
+
340
+ In some cases you may be migrating from no schema evolutions, or another schema evolution model.
314
341
 
315
- ## TODO
342
+ For these cases, sem provides a 'baseline' command.
316
343
 
317
- - Consider offering an option to install via ruby gems
344
+ Current workflow:
318
345
 
346
+ 1. sem-add your current schema
347
+ 1. Either via a database dump
348
+ 1. Or by sem-adding existing DB scripts
349
+ 1. Use sem-baseline to bootstrap the sem tables and add existing schema files to sem's migration table without actually applying them
319
350
 
320
351
  ## License
321
352
 
322
- Copyright 2013-2015 Gilt Groupe, Inc.
353
+ Copyright 2013-2016 Gilt Groupe, Inc.
323
354
 
324
355
  Licensed under the Apache License, Version 2.0 (the "License");
325
356
  you may not use this file except in compliance with the License.
data/bin/sem-apply CHANGED
@@ -8,24 +8,28 @@
8
8
  # sem-apply --host <database host> --user <db user> --name <db name>
9
9
  #
10
10
  # == Examples
11
- # sem-apply --url postgresql://postgres@localhost/sample
11
+ # sem-apply --url postgresql://postgres@localhost:port/sample
12
12
  # sem-apply --host localhost --user web --name test
13
13
  #
14
+ require 'tempfile'
14
15
 
15
16
  load File.join(File.dirname(__FILE__), 'sem-config')
16
17
 
17
- args = SchemaEvolutionManager::Args.from_stdin(:optional => %w(url host port name user dry_run))
18
+ args = SchemaEvolutionManager::Args.from_stdin(:optional => %w(url host port name user dry_run password))
18
19
 
19
- db = SchemaEvolutionManager::Db.from_args(args)
20
- db.bootstrap!
20
+ password = if args.password
21
+ SchemaEvolutionManager::Ask.for_password("Please enter the database user password")
22
+ else
23
+ nil
24
+ end
21
25
 
22
- dry_run = args.dry_run.nil? ? false : args.dry_run
23
-
24
- util = SchemaEvolutionManager::ApplyUtil.new(db, :dry_run => dry_run)
25
-
26
- puts "Upgrading schema for #{db.url}"
26
+ db = SchemaEvolutionManager::Db.from_args(args, :password => password)
27
+ util = SchemaEvolutionManager::ApplyUtil.new(db, :dry_run => args.dry_run || false)
27
28
 
28
29
  begin
30
+ db.bootstrap!
31
+
32
+ puts "Upgrading schema for #{db.url}"
29
33
  count = util.apply!("./scripts")
30
34
  if count == 0
31
35
  puts " All scripts have been previously applied"
@@ -1,5 +1,6 @@
1
1
  require 'fileutils'
2
2
  require 'pathname'
3
+ require 'io/console'
3
4
 
4
5
  dir = File.dirname(__FILE__)
5
6
  lib_dir = File.join(dir, "schema-evolution-manager")
@@ -16,6 +17,7 @@ load File.join(lib_dir, 'ask.rb')
16
17
  load File.join(lib_dir, 'version.rb')
17
18
  load File.join(lib_dir, 'args.rb')
18
19
  load File.join(lib_dir, 'scripts.rb')
20
+ load File.join(lib_dir, 'connection_data.rb')
19
21
  load File.join(lib_dir, 'db.rb')
20
22
  load File.join(lib_dir, 'apply_util.rb')
21
23
  load File.join(lib_dir, 'baseline_util.rb')
@@ -19,13 +19,14 @@ module SchemaEvolutionManager
19
19
  }
20
20
 
21
21
  FLAGS_NO_ARGUMENTS = {
22
+ :password => "Prompt user to enter password for the database user. Password is stored for the duration of the process",
22
23
  :dry_run => "Include flag to echo commands that will run without actually executing them",
23
24
  :help => "Display help",
24
25
  :verbose => "Enable verbose logging of all system calls",
25
26
  }
26
27
  end
27
28
 
28
- attr_reader :artifact_name, :host, :port, :name, :prefix, :url, :user, :dir, :dry_run, :tag
29
+ attr_reader :artifact_name, :host, :port, :name, :prefix, :url, :user, :dir, :dry_run, :tag, :password
29
30
 
30
31
  # args: Actual string arguments
31
32
  # :required => list of parameters that are required
@@ -52,7 +53,7 @@ module SchemaEvolutionManager
52
53
 
53
54
  @artifact_name = found_arguments.delete(:artifact_name)
54
55
  @host = found_arguments.delete(:host)
55
- @port = found_arguments.delete(:port)
56
+ @port = found_arguments.delete(:port)
56
57
  @name = found_arguments.delete(:name)
57
58
  @prefix = found_arguments.delete(:prefix)
58
59
  @url = found_arguments.delete(:url)
@@ -61,6 +62,7 @@ module SchemaEvolutionManager
61
62
  @tag = found_arguments.delete(:tag)
62
63
 
63
64
  @dry_run = found_arguments.delete(:dry_run)
65
+ @password = found_arguments.delete(:password)
64
66
  @help = found_arguments.delete(:help)
65
67
  @verbose = found_arguments.delete(:verbose)
66
68
 
@@ -7,8 +7,13 @@ module SchemaEvolutionManager
7
7
  TRUE_STRINGS = ['y', 'yes'] unless defined?(TRUE_STRINGS)
8
8
 
9
9
  # Asks the user a question. Expects a string back.
10
+ #
11
+ # @param default: A default value
12
+ # @param echo: If true (the default), we echo what the user types
13
+ # to the screen. If false, we do NOT echo.
10
14
  def Ask.for_string(message, opts={})
11
15
  default = opts.delete(:default)
16
+ echo = opts[:echo].nil? ? true : opts.delete(:echo)
12
17
  Preconditions.assert_empty_opts(opts)
13
18
 
14
19
  final_message = message.dup
@@ -19,7 +24,7 @@ module SchemaEvolutionManager
19
24
  value = nil
20
25
  while value.to_s == ""
21
26
  print final_message
22
- value = get_input.strip
27
+ value = get_input(echo).strip
23
28
  if value.to_s == "" && default
24
29
  value = default.to_s.strip
25
30
  end
@@ -34,9 +39,17 @@ module SchemaEvolutionManager
34
39
  TRUE_STRINGS.include?(value.downcase)
35
40
  end
36
41
 
42
+ def Ask.for_password(message)
43
+ Ask.for_string(message, :echo => false)
44
+ end
45
+
37
46
  # here to help with tests
38
- def Ask.get_input
39
- STDIN.gets
47
+ def Ask.get_input(echo)
48
+ if echo
49
+ STDIN.gets
50
+ else
51
+ STDIN.noecho(&:gets)
52
+ end
40
53
  end
41
54
 
42
55
  end
@@ -0,0 +1,68 @@
1
+ module SchemaEvolutionManager
2
+
3
+ class ConnectionData
4
+
5
+ DEFAULT_PORT = 5432 unless defined?(DEFAULT_PORT)
6
+
7
+ attr_reader :host, :name, :port, :user
8
+
9
+ def initialize(host, name, opts={})
10
+ @host = host
11
+ @name = name
12
+
13
+ port = opts.delete(:port).to_s
14
+ if port.to_s.empty?
15
+ @port = DEFAULT_PORT
16
+ else
17
+ @port = port.to_i
18
+ end
19
+ Preconditions.check_argument(@port > 0, "Port must be > 0")
20
+
21
+ @user = opts.delete(:user)
22
+ Preconditions.assert_empty_opts(opts)
23
+ end
24
+
25
+ # Returns a valid pgpass line entry representing this connection.
26
+ #
27
+ # @param password: Optional password to include in the connection string
28
+ def pgpass(password=nil)
29
+ [@host, @port, @name, @user, password.to_s].join(":")
30
+ end
31
+
32
+ # Parses a connection string into a ConnectionData instance. You
33
+ # will get an error if the URL could not be parsed.
34
+ #
35
+ # @param url e.g. postgres://user1@db.com:5553/test_db
36
+ def ConnectionData.parse_url(url)
37
+ protocol, rest = url.split("//", 2)
38
+ if rest.nil?
39
+ raise "Invalid url[%s]. Expected to start with postgres://" % url
40
+ end
41
+
42
+ lead, name = rest.split("/", 2)
43
+ if name.nil?
44
+ raise "Invalid url[%s]. Missing database name" % url
45
+ end
46
+
47
+ parts = lead.split("@", 2)
48
+ if parts.size == 2
49
+ user = parts[0]
50
+ db_host = parts[1]
51
+ else
52
+ user = nil
53
+ db_host = lead
54
+ end
55
+
56
+ host, port = db_host.split(":", 2)
57
+ if port
58
+ if port.to_i.to_s != port
59
+ raise "Invalid url[%s]. Expected database port[%s] to be an integer" % [url, port]
60
+ end
61
+ end
62
+
63
+ ConnectionData.new(host, name, :user => user, :port => port)
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -4,8 +4,16 @@ module SchemaEvolutionManager
4
4
 
5
5
  attr_reader :url
6
6
 
7
- def initialize(url)
7
+ def initialize(url, opts={})
8
8
  @url = Preconditions.check_not_blank(url, "url cannot be blank")
9
+ password = opts.delete(:password)
10
+ Preconditions.assert_empty_opts(opts)
11
+ connection_data = ConnectionData.parse_url(@url)
12
+
13
+ if password
14
+ ENV['PGPASSFILE'] = Library.write_to_temp_file(connection_data.pgpass(password))
15
+ puts "Created PGPASSFILE=%s" % ENV['PGPASSFILE']
16
+ end
9
17
  end
10
18
 
11
19
  # Installs schema_evolution_manager. Automatically upgrades schema_evolution_manager.
@@ -83,14 +91,18 @@ module SchemaEvolutionManager
83
91
  Db.from_args(args)
84
92
  end
85
93
 
86
- def Db.from_args(args)
94
+ # @param password: Optional password to use when connecting to the database.
95
+ def Db.from_args(args, opts={})
87
96
  Preconditions.assert_class(args, Args)
97
+ password = opts.delete(:password)
98
+ Preconditions.assert_empty_opts(opts)
99
+
88
100
  if args.url
89
- Db.new(args.url)
101
+ Db.new(args.url, :password => password)
90
102
  else
91
- base = "%s:%s/%s" % [args.host || "localhost", args.port || 5432, args.name]
103
+ base = "%s:%s/%s" % [args.host || "localhost", args.port || ConnectionData::DEFAULT_PORT, args.name]
92
104
  url = args.user ? "%s@%s" % [args.user, base] : base
93
- Db.new("postgres://" + url)
105
+ Db.new("postgres://" + url, :password => password)
94
106
  end
95
107
  end
96
108
 
@@ -2,7 +2,7 @@ module SchemaEvolutionManager
2
2
 
3
3
  module SemVersion
4
4
 
5
- VERSION = '0.9.24' # Automatically updated by util/create-release.rb
5
+ VERSION = '0.9.25' # Automatically updated by util/create-release.rb
6
6
 
7
7
  end
8
8
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schema-evolution-manager
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.24
4
+ version: 0.9.25
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bryzek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-28 00:00:00.000000000 Z
11
+ date: 2016-03-28 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: '["Michael Bryzek"]'
14
14
  email: mbryzek@alum.mit.edu
@@ -35,6 +35,7 @@ files:
35
35
  - lib/schema-evolution-manager/args.rb
36
36
  - lib/schema-evolution-manager/ask.rb
37
37
  - lib/schema-evolution-manager/baseline_util.rb
38
+ - lib/schema-evolution-manager/connection_data.rb
38
39
  - lib/schema-evolution-manager/db.rb
39
40
  - lib/schema-evolution-manager/install_template.rb
40
41
  - lib/schema-evolution-manager/library.rb