dm-chef-adapter 0.1.0 → 0.2.0
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/lib/dm-chef-adapter/adapter.rb +27 -9
- data/lib/dm-chef-adapter/adapter.rb~ +204 -0
- data/lib/dm-chef-adapter/version.rb +1 -1
- metadata +22 -10
@@ -2,6 +2,7 @@ require 'json'
|
|
2
2
|
require 'chef'
|
3
3
|
require 'dm-core'
|
4
4
|
require 'uuidtools'
|
5
|
+
|
5
6
|
module DataMapper
|
6
7
|
class Property
|
7
8
|
class DocId < String
|
@@ -47,8 +48,10 @@ module DataMapper
|
|
47
48
|
data = {"id" => resource.key.join('_')}
|
48
49
|
data.merge! Chef::JSONCompat.from_json(resource.to_json)
|
49
50
|
databag_item.raw_data = data
|
50
|
-
#binding.pry
|
51
51
|
databag_item.create
|
52
|
+
if !@cache.nil?
|
53
|
+
@cache.delete(resource.class.storage_name)
|
54
|
+
end
|
52
55
|
else
|
53
56
|
raise "DataBagItem #{resource.class.storage_name}/#{resource.key.join('_')} already exists."
|
54
57
|
end
|
@@ -81,6 +84,9 @@ module DataMapper
|
|
81
84
|
databag_item = Chef::DataBagItem.load collection.storage_name, doc["id"]
|
82
85
|
databag_item.raw_data.merge! Chef::JSONCompat.from_json(fields.to_json)
|
83
86
|
databag_item.save
|
87
|
+
if !@cache.nil?
|
88
|
+
@cache.delete(collection.storage_name)
|
89
|
+
end
|
84
90
|
end
|
85
91
|
end
|
86
92
|
|
@@ -89,6 +95,9 @@ module DataMapper
|
|
89
95
|
read(collection.query).each do |doc|
|
90
96
|
databag_item = Chef::DataBagItem.load collection.storage_name, doc["id"]
|
91
97
|
databag_item.destroy collection.storage_name, doc["id"]
|
98
|
+
if !@cache.nil?
|
99
|
+
@cache.delete(collection.storage_name)
|
100
|
+
end
|
92
101
|
end
|
93
102
|
end
|
94
103
|
|
@@ -107,9 +116,14 @@ module DataMapper
|
|
107
116
|
def initialize(name, opts = {})
|
108
117
|
super
|
109
118
|
Chef::Config.configuration[:node_name] = opts["node_name"]
|
110
|
-
|
111
|
-
|
112
|
-
|
119
|
+
Chef::Config.configuration[:client_key] = opts["client_key"]
|
120
|
+
Chef::Config.configuration[:chef_server_url] = opts["chef_server_url"] if !opts["chef_server_url"].nil?
|
121
|
+
if opts["memcache"]
|
122
|
+
require 'dalli'
|
123
|
+
@cache = Dalli::Client.new(opts["memcache_url"])
|
124
|
+
else
|
125
|
+
@cache = nil
|
126
|
+
end
|
113
127
|
@uuid = UUIDTools::UUID
|
114
128
|
end
|
115
129
|
|
@@ -139,15 +153,19 @@ module DataMapper
|
|
139
153
|
#
|
140
154
|
# @api private
|
141
155
|
def records_for(model)
|
142
|
-
|
143
|
-
|
144
|
-
|
156
|
+
if !@cache.nil?
|
157
|
+
return @cache.get(model) if !@cache.get(model).nil?
|
158
|
+
end
|
159
|
+
records = []
|
160
|
+
databag = chef_databag(model)
|
161
|
+
if !databag.nil?
|
145
162
|
chef_databag(model).keys.each do |key|
|
146
163
|
records << Chef::DataBagItem.load(model, key).raw_data
|
147
164
|
end
|
148
165
|
end
|
149
|
-
records
|
150
|
-
|
166
|
+
@cache.set(model, records, 60) if !@cache.nil?
|
167
|
+
return records
|
168
|
+
end
|
151
169
|
|
152
170
|
# Writes all records to a databag
|
153
171
|
#
|
@@ -0,0 +1,204 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef'
|
3
|
+
require 'dm-core'
|
4
|
+
require 'uuidtools'
|
5
|
+
require 'pry'
|
6
|
+
|
7
|
+
module DataMapper
|
8
|
+
class Property
|
9
|
+
class DocId < String
|
10
|
+
key true
|
11
|
+
writer false
|
12
|
+
default ''
|
13
|
+
# @api private
|
14
|
+
def to_child_key
|
15
|
+
Property::String
|
16
|
+
end
|
17
|
+
|
18
|
+
end # class DocId
|
19
|
+
end # module Property
|
20
|
+
module Is
|
21
|
+
module Chef
|
22
|
+
def is_chef(options={})
|
23
|
+
require 'dm-serializer'
|
24
|
+
property :id, DataMapper::Property::DocId
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
module Adapters
|
29
|
+
class ChefAdapter < AbstractAdapter
|
30
|
+
# @api semipublic
|
31
|
+
def create(resources)
|
32
|
+
resources.collect do |resource|
|
33
|
+
if !Chef::DataBag.list.keys.include?(resource.class.storage_name)
|
34
|
+
databag = Chef::DataBag.new
|
35
|
+
databag.name resource.class.storage_name
|
36
|
+
databag.create
|
37
|
+
end
|
38
|
+
begin
|
39
|
+
resource.id = @uuid.sha1_create(
|
40
|
+
UUIDTools::UUID_DNS_NAMESPACE,
|
41
|
+
("%10.6f#{resource.class.storage_name}" % Time.now.to_f)
|
42
|
+
)
|
43
|
+
rescue
|
44
|
+
resource.send :instance_variable_set, :@id, resource.key
|
45
|
+
end
|
46
|
+
if !Chef::DataBag.load(resource.class.storage_name).keys.include?(resource.key.join('_'))
|
47
|
+
databag_item = Chef::DataBagItem.new
|
48
|
+
databag_item.data_bag resource.class.storage_name
|
49
|
+
data = {"id" => resource.key.join('_')}
|
50
|
+
data.merge! Chef::JSONCompat.from_json(resource.to_json)
|
51
|
+
databag_item.raw_data = data
|
52
|
+
databag_item.create
|
53
|
+
else
|
54
|
+
raise "DataBagItem #{resource.class.storage_name}/#{resource.key.join('_')} already exists."
|
55
|
+
end
|
56
|
+
end.count
|
57
|
+
end
|
58
|
+
|
59
|
+
# @api semipublic
|
60
|
+
def read(query)
|
61
|
+
records = records_for(query.model.storage_name)
|
62
|
+
ret = []
|
63
|
+
query.links.reverse.each do |link|
|
64
|
+
children = records_for(link.child_model.storage_name)
|
65
|
+
parents = records_for(link.parent_model.storage_name)
|
66
|
+
children.each do |child|
|
67
|
+
parents.each do |parent|
|
68
|
+
if child[link.child_key.first.name.to_s] == parent[link.parent_key.first.name.to_s]
|
69
|
+
records.each do |record|
|
70
|
+
ret << child.merge(record)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
query.filter_records(ret+records)
|
77
|
+
end
|
78
|
+
|
79
|
+
def update(attributes, collection)
|
80
|
+
fields = attributes_as_fields(attributes)
|
81
|
+
read(collection.query).each do |doc|
|
82
|
+
databag_item = Chef::DataBagItem.load collection.storage_name, doc["id"]
|
83
|
+
databag_item.raw_data.merge! Chef::JSONCompat.from_json(fields.to_json)
|
84
|
+
databag_item.save
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# @api semipublic
|
89
|
+
def delete(collection)
|
90
|
+
read(collection.query).each do |doc|
|
91
|
+
databag_item = Chef::DataBagItem.load collection.storage_name, doc["id"]
|
92
|
+
databag_item.destroy collection.storage_name, doc["id"]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# @api semipublic
|
97
|
+
def attributes_as_fields(attributes)
|
98
|
+
pairs = attributes.map do |property, value|
|
99
|
+
dumped = value.kind_of?(Module) ? value.name : property.dump(value)
|
100
|
+
[ property.field, dumped ]
|
101
|
+
end
|
102
|
+
Hash[pairs]
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
# @api semipublic
|
108
|
+
def initialize(name, opts = {})
|
109
|
+
super
|
110
|
+
Chef::Config.configuration[:node_name] = opts["node_name"]
|
111
|
+
Chef::Config.configuration[:client_key] = opts["client_key"]
|
112
|
+
Chef::Config.configuration[:chef_server_url] = opts["chef_server_url"] if !opts["chef_server_url"].nil?
|
113
|
+
if !opts["cache"].nil?
|
114
|
+
Chef::Config.configuration[:dm_cache] = opts["cache"]
|
115
|
+
else
|
116
|
+
Chef::Config.configuration[:dm_cache] = 60
|
117
|
+
end
|
118
|
+
@cache = {}
|
119
|
+
@chef = Chef::REST.new(Chef::Config[:chef_server_url])
|
120
|
+
@uuid = UUIDTools::UUID
|
121
|
+
end
|
122
|
+
|
123
|
+
# Retrieves all records for a model and yields them to a block.
|
124
|
+
#
|
125
|
+
# The block should make any changes to the records in-place. After
|
126
|
+
# the block executes all the records are dumped back to the databag.
|
127
|
+
#
|
128
|
+
# @param [Model, #to_s] model
|
129
|
+
# Used to determine which file to read/write to
|
130
|
+
#
|
131
|
+
# @yieldparam [Hash]
|
132
|
+
# A hash of record.key => record pairs retrieved from the databag
|
133
|
+
#
|
134
|
+
# @api private
|
135
|
+
def update_records(model)
|
136
|
+
records = records_for(model)
|
137
|
+
result = yield records
|
138
|
+
write_records(model, records)
|
139
|
+
result
|
140
|
+
end
|
141
|
+
|
142
|
+
# Read all records from a databag for a model
|
143
|
+
#
|
144
|
+
# @param [#storage_name] model
|
145
|
+
# The model/name to retieve records for
|
146
|
+
#
|
147
|
+
# @api private
|
148
|
+
def records_for(model)
|
149
|
+
if !@cache[model].nil? && (Time.now - @cache[model][:timestamp]) < Chef::Config.configuration[:dm_cache]
|
150
|
+
return @cache[model][:records]
|
151
|
+
else
|
152
|
+
records = []
|
153
|
+
databag = chef_databag(model)
|
154
|
+
if !databag.nil?
|
155
|
+
chef_databag(model).keys.each do |key|
|
156
|
+
records << Chef::DataBagItem.load(model, key).raw_data
|
157
|
+
end
|
158
|
+
end
|
159
|
+
@cache[model] = {}
|
160
|
+
@cache[model][:timestamp] = Time.now
|
161
|
+
@cache[model][:records] = records
|
162
|
+
return records
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Writes all records to a databag
|
167
|
+
#
|
168
|
+
# @param [#storage_name] model
|
169
|
+
# The model/name to write the records for
|
170
|
+
#
|
171
|
+
# @param [Hash] records
|
172
|
+
# A hash of record.key => record pairs to be written
|
173
|
+
#
|
174
|
+
# @api private
|
175
|
+
def write_records(model, records)
|
176
|
+
item = Chef::DataBagItem.load(model. records["id"])
|
177
|
+
item.from_hash records
|
178
|
+
item.save
|
179
|
+
end
|
180
|
+
|
181
|
+
# Given a model, gives the databag to be used for record storage
|
182
|
+
#
|
183
|
+
# @example
|
184
|
+
# chef_databag(Article) #=> "Chef::DataBag"
|
185
|
+
#
|
186
|
+
# @param [#storage_name] model
|
187
|
+
# The model to be used to determine the databag.
|
188
|
+
#
|
189
|
+
# @api private
|
190
|
+
def chef_databag(model)
|
191
|
+
begin
|
192
|
+
Chef::DataBag.load model
|
193
|
+
rescue
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
end # class ChefAdapter
|
199
|
+
|
200
|
+
const_added(:ChefAdapter)
|
201
|
+
end # module Adapters
|
202
|
+
Model.append_extensions(Is::Chef)
|
203
|
+
end # module DataMapper
|
204
|
+
|
@@ -1 +1 @@
|
|
1
|
-
DMCHEFADAPTER_VERSION = "0.
|
1
|
+
DMCHEFADAPTER_VERSION = "0.2.0"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-chef-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-03-07 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: chef
|
16
|
-
requirement: &
|
16
|
+
requirement: &9732900 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - =
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.10.8
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *9732900
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: dm-core
|
27
|
-
requirement: &
|
27
|
+
requirement: &9732400 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - =
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.2.0
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *9732400
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: dm-serializer
|
38
|
-
requirement: &
|
38
|
+
requirement: &9731940 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - =
|
@@ -43,7 +43,18 @@ dependencies:
|
|
43
43
|
version: 1.2.1
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *9731940
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: dalli
|
49
|
+
requirement: &9731560 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *9731560
|
47
58
|
description: uses chef databags as a backend for the datamapper ORM
|
48
59
|
email:
|
49
60
|
- ncethier@gmail.com
|
@@ -51,9 +62,10 @@ executables: []
|
|
51
62
|
extensions: []
|
52
63
|
extra_rdoc_files: []
|
53
64
|
files:
|
65
|
+
- lib/dm-chef-adapter.rb
|
54
66
|
- lib/dm-chef-adapter/version.rb
|
55
67
|
- lib/dm-chef-adapter/adapter.rb
|
56
|
-
- lib/dm-chef-adapter.rb
|
68
|
+
- lib/dm-chef-adapter/adapter.rb~
|
57
69
|
- examples/blog.rb
|
58
70
|
homepage: https://github.com/nickethier/dm-chef-adapter
|
59
71
|
licenses:
|
@@ -77,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
77
89
|
version: '0'
|
78
90
|
requirements: []
|
79
91
|
rubyforge_project:
|
80
|
-
rubygems_version: 1.8.
|
92
|
+
rubygems_version: 1.8.15
|
81
93
|
signing_key:
|
82
94
|
specification_version: 3
|
83
95
|
summary: datamapper adapter to use a chef server as a datastore backend
|