deploy_couch 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +14 -0
- data/README +0 -0
- data/Rakefile +1 -0
- data/bin/deploy_couch +16 -0
- data/deploy_couch.gemspec +20 -0
- data/deploy_couch.rake +0 -0
- data/lib/deploy_couch/config.rb +44 -0
- data/lib/deploy_couch/couch_db_schema.rb +58 -0
- data/lib/deploy_couch/delta.rb +36 -0
- data/lib/deploy_couch/delta_loader.rb +37 -0
- data/lib/deploy_couch/delta_processor.rb +60 -0
- data/lib/deploy_couch/deploy.rb +70 -0
- data/lib/deploy_couch/http_client.rb +48 -0
- data/lib/deploy_couch/repository.rb +71 -0
- data/lib/deploy_couch/version.rb +3 -0
- data/lib/deploy_couch.rb +13 -0
- data/spec/couchdb.yml +6 -0
- data/spec/integration/config_spec.rb +41 -0
- data/spec/integration/database_populator.rb +37 -0
- data/spec/integration/delta_loader_spec.rb +54 -0
- data/spec/integration/delta_processor_spec.rb +52 -0
- data/spec/integration/deltas/11_update_phone_with_std_codes.yml +13 -0
- data/spec/integration/deltas/12_delete_customer_name_1.yml +19 -0
- data/spec/integration/deltas/13_copy_and_create_new_customer.yml +20 -0
- data/spec/integration/deltas/1_add_address_to_customer.yml +14 -0
- data/spec/integration/deltas/2_add_phone_to_customer.yml +13 -0
- data/spec/integration/deltas/5_not_a_yaml_file.rb +0 -0
- data/spec/integration/deploy_spec.rb +56 -0
- data/spec/integration/repository_spec.rb +40 -0
- data/spec/spec_helper.rb +17 -0
- data/spec/unit/db_schema_spec.rb +66 -0
- data/spec/unit/delta_processor_spec.rb +61 -0
- data/spec/unit/deploy_spec.rb +94 -0
- data/spec/unit/repository_spec.rb +128 -0
- metadata +102 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/deploy_couch
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
if (ARGV.length != 1)
|
4
|
+
puts "usage: deploy_couch 'path/to/couchdb.yml' "
|
5
|
+
exit(-1)
|
6
|
+
end
|
7
|
+
if (!File.exists?(ARGV[0]))
|
8
|
+
puts "file '#{ARGV[0]}' does not exist "
|
9
|
+
exit(-1)
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'deploy_couch'
|
13
|
+
|
14
|
+
config = DeployCouch::Config.create_from_file(ARGV[0])
|
15
|
+
deploy = DeployCouch::Deploy.new(config)
|
16
|
+
deploy.run
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "deploy_couch/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "deploy_couch"
|
7
|
+
s.version = DeployCouch::VERSION
|
8
|
+
s.authors = ["venky/mln"]
|
9
|
+
s.email = ["venkatesh.swdev@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/venkateshcm/deploy_couch"
|
11
|
+
s.summary = "dbDeploy for couchdb"
|
12
|
+
s.description = "dbDeploy for couchdb"
|
13
|
+
|
14
|
+
s.rubyforge_project = "deploy_couch"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
end
|
data/deploy_couch.rake
ADDED
File without changes
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
|
3
|
+
class Config
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.create_from_file(config_file)
|
10
|
+
config = YAML.load_file(config_file)
|
11
|
+
config = config.merge("config_folder_path" => File.dirname(config_file))
|
12
|
+
Config.new(config)
|
13
|
+
end
|
14
|
+
|
15
|
+
def hostname
|
16
|
+
@config["hostname"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def port
|
20
|
+
@config["port"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def delta_path
|
24
|
+
@config["config_folder_path"] + "/" + @config["delta_path"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def database
|
28
|
+
@config["database"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def doc_type_field
|
32
|
+
@config["doc_type_field"]
|
33
|
+
end
|
34
|
+
|
35
|
+
def type_version_field
|
36
|
+
@config["type_version_field"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def merge_config(config)
|
40
|
+
@config = @config.merge(config)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
|
3
|
+
class DbSchema
|
4
|
+
|
5
|
+
def initialize(schema,repository)
|
6
|
+
@schema = schema
|
7
|
+
@repository = repository
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.load_or_create(config,repository)
|
11
|
+
default_schema = {"_id"=>"schema__schema_document_key__",config.doc_type_field=>"__schema__", 'applied_deltas'=>[], "type_versions"=>{}}
|
12
|
+
schema = repository.get_schema
|
13
|
+
if (schema.nil?)
|
14
|
+
repository.create_schema(default_schema)
|
15
|
+
schema = repository.get_schema
|
16
|
+
end
|
17
|
+
DbSchema.new(schema,repository)
|
18
|
+
end
|
19
|
+
|
20
|
+
def applied_deltas
|
21
|
+
@schema["applied_deltas"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def type_versions
|
25
|
+
@schema["type_versions"]
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_next_type_version_for(type)
|
29
|
+
current_version = type_versions[type]
|
30
|
+
current_version = 0 if current_version.nil?
|
31
|
+
current_version += 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def type_version_field
|
35
|
+
@schema["type_version_field"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def completed(delta)
|
39
|
+
@schema['applied_deltas'].push(delta.id)
|
40
|
+
current_type_version = @schema['type_versions'].has_key?(delta.type) ? @schema['type_versions'][delta.type] : 0
|
41
|
+
@schema['type_versions'][delta.type] = current_type_version + 1
|
42
|
+
|
43
|
+
@repository.put_document(@schema)
|
44
|
+
@schema = @repository.get_schema
|
45
|
+
end
|
46
|
+
|
47
|
+
def rollback(delta)
|
48
|
+
@schema['applied_deltas'].delete(delta.id)
|
49
|
+
current_type_version = @schema['type_versions'].has_key?(delta.type) ? @schema['type_versions'][delta.type] : 0
|
50
|
+
@schema['type_versions'][delta.type] = current_type_version - 1
|
51
|
+
|
52
|
+
@repository.put_document(@schema)
|
53
|
+
@schema = @repository.get_schema
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
|
3
|
+
class Delta
|
4
|
+
def initialize(id,file_name,type,map_function,rollback_function)
|
5
|
+
@id=id
|
6
|
+
@file_name = file_name
|
7
|
+
@type = type
|
8
|
+
@map_function = map_function
|
9
|
+
@rollback_function = rollback_function
|
10
|
+
end
|
11
|
+
|
12
|
+
def id
|
13
|
+
@id
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def file_name
|
18
|
+
@file_name
|
19
|
+
end
|
20
|
+
|
21
|
+
def type
|
22
|
+
@type
|
23
|
+
end
|
24
|
+
|
25
|
+
def map_function
|
26
|
+
@map_function
|
27
|
+
end
|
28
|
+
|
29
|
+
def rollback_function
|
30
|
+
@rollback_function
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
|
3
|
+
class DeltaLoader
|
4
|
+
def initialize(deltas_folder)
|
5
|
+
@deltas_folder = deltas_folder
|
6
|
+
end
|
7
|
+
|
8
|
+
def get_deltas
|
9
|
+
hash = {}
|
10
|
+
files = Dir["#{@deltas_folder}/*.yml"].select {|f| File.file?(f)}
|
11
|
+
files.each do |file|
|
12
|
+
file_name = File.basename(file)
|
13
|
+
key = file_name.split('_')[0].to_i
|
14
|
+
if (key == 0)
|
15
|
+
e = RuntimeError.new("invalid file name #{file_name}")
|
16
|
+
raise e
|
17
|
+
end
|
18
|
+
if (hash.has_key?(key))
|
19
|
+
e = RuntimeError.new("duplicate key found in file #{file_name}")
|
20
|
+
raise e
|
21
|
+
end
|
22
|
+
|
23
|
+
hash[key] = convert_to_delta(key,file)
|
24
|
+
end
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
|
28
|
+
def convert_to_delta(id, file)
|
29
|
+
delta_config = YAML.load_file(file)
|
30
|
+
file_name = File.basename(file)
|
31
|
+
raise "#{file_name} content is not valid " if delta_config['type'].nil? or delta_config['map_function'].nil?
|
32
|
+
Delta.new(id,file_name,delta_config['type'],delta_config['map_function'],delta_config['rollback_function'])
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
|
3
|
+
class DeltaProcessor
|
4
|
+
def initialize(next_type_version,config,delta,repository)
|
5
|
+
@repository = repository
|
6
|
+
@delta = delta
|
7
|
+
@config = config
|
8
|
+
@next_type_version = next_type_version
|
9
|
+
end
|
10
|
+
|
11
|
+
def apply
|
12
|
+
user_map_function = @delta.map_function.gsub("\"","\\\"")
|
13
|
+
map_function = <<-JSON
|
14
|
+
{
|
15
|
+
"map":"function(doc){if(doc.#{@config.doc_type_field}=='#{@delta.type}' && (!doc.#{@config.type_version_field} || doc.#{@config.type_version_field} < #{@next_type_version})){new_doc = eval(uneval(doc)); var method = map(new_doc); if(method) emit(method,new_doc);}}
|
16
|
+
#{user_map_function}"
|
17
|
+
}
|
18
|
+
JSON
|
19
|
+
modify_document(map_function,@next_type_version)
|
20
|
+
end
|
21
|
+
|
22
|
+
def rollback
|
23
|
+
user_rollback_function = @delta.rollback_function.gsub("\"","\\\"")
|
24
|
+
current_type_version = @next_type_version - 1
|
25
|
+
rollback_function = <<-JSON
|
26
|
+
{
|
27
|
+
"map":"function(doc){if(doc.#{@config.doc_type_field}=='#{@delta.type}' && (doc.#{@config.type_version_field} >= #{current_type_version})){new_doc = eval(uneval(doc)); var method = map(new_doc); if(method) emit(method,new_doc);}}
|
28
|
+
#{user_rollback_function}"
|
29
|
+
}
|
30
|
+
JSON
|
31
|
+
modify_document(rollback_function,current_type_version-1)
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
private
|
36
|
+
def modify_document(function,type_version)
|
37
|
+
@repository.get_documents_to_modify(function) do |x|
|
38
|
+
update_document(x['value'],type_version) if x['key'] == 'update'
|
39
|
+
create_document(x['value'],type_version) if x['key'] == 'create'
|
40
|
+
delete_document(x['value'],type_version) if x['key'] == 'delete'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def update_document(json_doc,type_version)
|
45
|
+
json_doc[@config.type_version_field] = type_version
|
46
|
+
@repository.put_document(json_doc)
|
47
|
+
end
|
48
|
+
|
49
|
+
def delete_document(json_doc,type_version)
|
50
|
+
@repository.delete_document(json_doc)
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_document(json_doc,type_version)
|
54
|
+
json_doc[@config.type_version_field] = type_version
|
55
|
+
@repository.post_document(json_doc)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
|
3
|
+
class Deploy
|
4
|
+
def initialize(config)
|
5
|
+
@config = config
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
repository = Repository.new(@config)
|
10
|
+
delta_loader = DeltaLoader.new(@config.delta_path)
|
11
|
+
deltas_map = delta_loader.get_deltas
|
12
|
+
couch_schema = DbSchema.load_or_create(@config,repository)
|
13
|
+
all_delta_keys = deltas_map.keys.sort
|
14
|
+
applied_deltas = couch_schema.applied_deltas.sort
|
15
|
+
last_applied_delta_id = 0
|
16
|
+
last_applied_delta_id = applied_deltas[-1] if applied_deltas.count > 0
|
17
|
+
delta_keys_to_apply = all_delta_keys.select {|key| key > last_applied_delta_id }
|
18
|
+
|
19
|
+
deltas = []
|
20
|
+
puts "Deltas #{all_delta_keys} found"
|
21
|
+
puts "Already applied deltas #{applied_deltas}"
|
22
|
+
puts "Applying deltas #{delta_keys_to_apply}"
|
23
|
+
puts ""
|
24
|
+
puts "Start applying deltas"
|
25
|
+
|
26
|
+
delta_keys_to_apply.each do |key|
|
27
|
+
delta = deltas_map[key]
|
28
|
+
type = couch_schema.get_next_type_version_for(delta.type)
|
29
|
+
DeltaProcessor.new(type,@config,delta,repository).apply
|
30
|
+
couch_schema.completed(delta)
|
31
|
+
deltas.push(delta)
|
32
|
+
puts "applied delta #{delta.file_name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
puts "Finished applying deltas"
|
36
|
+
puts ""
|
37
|
+
puts "Deltas #{all_delta_keys - applied_deltas - delta_keys_to_apply} where skiped"
|
38
|
+
|
39
|
+
deltas
|
40
|
+
end
|
41
|
+
|
42
|
+
def rollback
|
43
|
+
repository = Repository.new(@config)
|
44
|
+
delta_loader = DeltaLoader.new(@config.delta_path)
|
45
|
+
deltas_map = delta_loader.get_deltas
|
46
|
+
couch_schema = DbSchema.load_or_create(@config,repository)
|
47
|
+
applied_deltas = couch_schema.applied_deltas.sort.reverse
|
48
|
+
|
49
|
+
deltas = []
|
50
|
+
puts "Already applied deltas #{applied_deltas}"
|
51
|
+
puts "Rolling back deltas #{applied_deltas}"
|
52
|
+
puts ""
|
53
|
+
puts "Start rolling back deltas"
|
54
|
+
|
55
|
+
applied_deltas.each do |key|
|
56
|
+
delta = deltas_map[key]
|
57
|
+
type = couch_schema.get_next_type_version_for(delta.type)
|
58
|
+
DeltaProcessor.new(type,@config,delta,repository).rollback
|
59
|
+
couch_schema.rollback(delta)
|
60
|
+
deltas.push(delta)
|
61
|
+
puts "rollback delta #{delta.file_name}"
|
62
|
+
end
|
63
|
+
|
64
|
+
puts "Finished rolling back deltas"
|
65
|
+
deltas
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
|
3
|
+
class Server
|
4
|
+
def initialize(host, port)
|
5
|
+
@host = host
|
6
|
+
@port = port
|
7
|
+
end
|
8
|
+
|
9
|
+
def delete(uri, options = {:suppress_exceptions=>false})
|
10
|
+
request(Net::HTTP::Delete.new(uri),options)
|
11
|
+
end
|
12
|
+
|
13
|
+
def get(uri, options = {:suppress_exceptions=>false})
|
14
|
+
request(Net::HTTP::Get.new(uri),options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def put(uri, json, options = {:suppress_exceptions=>false})
|
18
|
+
req = Net::HTTP::Put.new(uri)
|
19
|
+
req["content-type"] = "application/json"
|
20
|
+
req.body = json
|
21
|
+
request(req,options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def post(uri, json, options = {:suppress_exceptions=>false})
|
25
|
+
req = Net::HTTP::Post.new(uri)
|
26
|
+
req["content-type"] = "application/json"
|
27
|
+
req.body = json
|
28
|
+
request(req,options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def request(req, options)
|
32
|
+
res = Net::HTTP.start(@host, @port) { |http|http.request(req) }
|
33
|
+
isError = !res.kind_of?(Net::HTTPSuccess)
|
34
|
+
shouldSupress = options[:suppress_exceptions]
|
35
|
+
if isError and !shouldSupress
|
36
|
+
handle_error(req, res)
|
37
|
+
end
|
38
|
+
res
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def handle_error(req, res)
|
44
|
+
e = RuntimeError.new("#{res.code}:#{res.message}\nMETHOD:#{req.method}\nURI:#{req.path}\n#{res.body}")
|
45
|
+
raise e
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
|
3
|
+
class Repository
|
4
|
+
PAGE_SIZE = 10
|
5
|
+
|
6
|
+
def initialize(couch_config)
|
7
|
+
@config = couch_config
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_documents(map_function)
|
11
|
+
server = Server.new(@config.hostname,@config.port)
|
12
|
+
no_of_records = 0
|
13
|
+
page_no = 0
|
14
|
+
finish_loading_all = false
|
15
|
+
|
16
|
+
while(!finish_loading_all)
|
17
|
+
response = server.post("/#{@config.database}/_temp_view?limit=#{PAGE_SIZE}&skip=#{PAGE_SIZE*page_no}",map_function)
|
18
|
+
json = JSON.parse(response.body)
|
19
|
+
json["rows"].each do |row|
|
20
|
+
yield row
|
21
|
+
end
|
22
|
+
page_no += 1
|
23
|
+
no_of_records += json["rows"].count
|
24
|
+
finish_loading_all = true if no_of_records >= json["total_rows"]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_documents_to_modify(map_function)
|
29
|
+
server = Server.new(@config.hostname,@config.port)
|
30
|
+
finish_loading_all = false
|
31
|
+
|
32
|
+
while(!finish_loading_all)
|
33
|
+
response = server.post("/#{@config.database}/_temp_view?limit=#{PAGE_SIZE}",map_function)
|
34
|
+
json = JSON.parse(response.body)
|
35
|
+
json["rows"].each do |row|
|
36
|
+
yield row
|
37
|
+
end
|
38
|
+
finish_loading_all = json["total_rows"] <= 10
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def put_document(json)
|
44
|
+
server = Server.new(@config.hostname,@config.port)
|
45
|
+
server.put("/#{@config.database}/#{json['_id']}",json.to_json)
|
46
|
+
end
|
47
|
+
|
48
|
+
def post_document(json)
|
49
|
+
server = Server.new(@config.hostname,@config.port)
|
50
|
+
server.post("/#{@config.database}",json.to_json)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def delete_document(json)
|
55
|
+
server = Server.new(@config.hostname,@config.port)
|
56
|
+
server.delete("/#{@config.database}/#{json['_id']}?rev=#{json['_rev']}")
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_schema
|
60
|
+
server = Server.new(@config.hostname,@config.port)
|
61
|
+
res = server.get("/#{@config.database}/schema__schema_document_key__",{:suppress_exceptions=>true})
|
62
|
+
json = JSON.parse(res.body) if res.kind_of?(Net::HTTPSuccess)
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_schema(json)
|
66
|
+
server = Server.new(@config.hostname,@config.port)
|
67
|
+
res = server.post("/#{@config.database}/",json.to_json)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
data/lib/deploy_couch.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'yaml'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
require 'deploy_couch/version'
|
6
|
+
require 'deploy_couch/config'
|
7
|
+
require 'deploy_couch/repository'
|
8
|
+
require 'deploy_couch/delta_processor'
|
9
|
+
require 'deploy_couch/delta_loader'
|
10
|
+
require 'deploy_couch/delta'
|
11
|
+
require 'deploy_couch/deploy'
|
12
|
+
require 'deploy_couch/couch_db_schema'
|
13
|
+
require 'deploy_couch/http_client'
|
data/spec/couchdb.yml
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
module DeployCouch
|
4
|
+
describe Config, "read couch db config" do
|
5
|
+
it "should load hostname from couchdb.yml" do
|
6
|
+
Config.create_from_file(File.dirname(__FILE__) + '/../couchdb.yml').hostname.should == "localhost"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should load portnumber from couchdb.yml" do
|
10
|
+
Config.create_from_file(File.dirname(__FILE__) + '/../couchdb.yml').port.should == 5984
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should load delta path" do
|
14
|
+
Config.create_from_file(File.dirname(__FILE__) + '/../couchdb.yml').delta_path.should == File.dirname(__FILE__) + "/../integration/deltas"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should load database name" do
|
18
|
+
Config.create_from_file(File.dirname(__FILE__) + '/../couchdb.yml').database.should == "test"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should load document type field" do
|
22
|
+
Config.create_from_file(File.dirname(__FILE__) + '/../couchdb.yml').doc_type_field.should == "type"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should load type version field" do
|
26
|
+
Config.create_from_file(File.dirname(__FILE__) + '/../couchdb.yml').type_version_field.should == "type_version"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
it "should merge config with passed in values" do
|
31
|
+
config = Config.create_from_file(File.dirname(__FILE__) + '/../couchdb.yml')
|
32
|
+
config.merge_config("database"=>"db")
|
33
|
+
config.database.should == "db"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should fail with an exception when config file is not found" do
|
37
|
+
lambda { Config.create_from_file(File.dirname(__FILE__) + '/../couchdb1.yml') }.should raise_error()
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module DeployCouch
|
2
|
+
class DatabasePopulator
|
3
|
+
def initialize(database)
|
4
|
+
@database = database
|
5
|
+
end
|
6
|
+
|
7
|
+
def with_type(doc_type)
|
8
|
+
@doc_type = doc_type
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_records(no_of_records)
|
13
|
+
@no_of_records = no_of_records
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def with_schema(schema_json)
|
18
|
+
@schema = schema_json
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def build
|
23
|
+
server = Server.new("localhost",5984)
|
24
|
+
res = server.get("/#{@database}/",{:suppress_exceptions=>true})
|
25
|
+
server.delete("/#{@database}/") if res.kind_of?(Net::HTTPSuccess)
|
26
|
+
server.put("/#{@database}/","")
|
27
|
+
(1..@no_of_records).each do |i|
|
28
|
+
h = {"name"=> "name_#{i}","type"=>@doc_type}
|
29
|
+
server.post("/#{@database}/",JSON.generate(h))
|
30
|
+
end
|
31
|
+
|
32
|
+
server.post("/#{@database}/",@schema.to_json) if @schema
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
module DeployCouch
|
4
|
+
|
5
|
+
describe DeltaLoader, "load all delta" do
|
6
|
+
|
7
|
+
it "should load all YAML files from the deltas folder" do
|
8
|
+
|
9
|
+
map_function = "function map(doc) { doc.address = \"some address\"; return 'update'; }"
|
10
|
+
rollback_function = "function map(doc) { delete doc.address; return 'update'; }"
|
11
|
+
|
12
|
+
delta_loader = DeltaLoader.new(File.dirname(__FILE__)+'/deltas')
|
13
|
+
deltas = delta_loader.get_deltas
|
14
|
+
deltas.count.should == 5
|
15
|
+
deltas[1].file_name.should == "1_add_address_to_customer.yml"
|
16
|
+
deltas[1].type.should == "customer"
|
17
|
+
deltas[1].map_function.should == map_function
|
18
|
+
deltas[1].rollback_function.should == rollback_function
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise an error when file is not in deltanumber_description format" do
|
22
|
+
File.new(File.dirname(__FILE__)+'/deltas/invalid_delta_file.yml','w')
|
23
|
+
begin
|
24
|
+
delta_loader = DeltaLoader.new(File.dirname(__FILE__)+'/deltas')
|
25
|
+
lambda { delta_loader.get_deltas }.should raise_error()
|
26
|
+
ensure
|
27
|
+
File.delete(File.dirname(__FILE__)+'/deltas/invalid_delta_file.yml')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should raise an error when two deltas have the same key" do
|
32
|
+
File.new(File.dirname(__FILE__)+'/deltas/11_duplicate_key.yml','w')
|
33
|
+
begin
|
34
|
+
delta_loader = DeltaLoader.new(File.dirname(__FILE__)+'/deltas')
|
35
|
+
lambda { delta_loader.get_deltas }.should raise_error()
|
36
|
+
ensure
|
37
|
+
File.delete(File.dirname(__FILE__)+'/deltas/11_duplicate_key.yml')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should raise an error when file content does not have both type and map_function" do
|
43
|
+
File.new(File.dirname(__FILE__)+'/deltas/100_invalid_delta_file_content.yml','w')
|
44
|
+
begin
|
45
|
+
delta_loader = DeltaLoader.new(File.dirname(__FILE__)+'/deltas')
|
46
|
+
lambda { delta_loader.get_deltas }.should raise_error()
|
47
|
+
ensure
|
48
|
+
File.delete(File.dirname(__FILE__)+'/deltas/100_invalid_delta_file_content.yml')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|