dtk-node-agent 0.7.7 → 0.8.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.
Files changed (94) hide show
  1. checksums.yaml +5 -13
  2. data/README.md +21 -4
  3. data/bin/dtk-node-agent +17 -0
  4. data/lib/config/install.config +2 -2
  5. data/lib/dtk-node-agent/installer.rb +30 -25
  6. data/lib/dtk-node-agent/version.rb +18 -1
  7. metadata +23 -110
  8. data/mcollective_additions/debian.mcollective.init +0 -92
  9. data/mcollective_additions/plugins/README.md +0 -1
  10. data/mcollective_additions/plugins/v1.2/agent/discovery.rb +0 -39
  11. data/mcollective_additions/plugins/v1.2/agent/get_log_fragment.ddl +0 -15
  12. data/mcollective_additions/plugins/v1.2/agent/get_log_fragment.rb +0 -79
  13. data/mcollective_additions/plugins/v1.2/agent/git_access.ddl +0 -9
  14. data/mcollective_additions/plugins/v1.2/agent/git_access.rb +0 -79
  15. data/mcollective_additions/plugins/v1.2/agent/netstat.ddl +0 -9
  16. data/mcollective_additions/plugins/v1.2/agent/netstat.rb +0 -34
  17. data/mcollective_additions/plugins/v1.2/agent/puppet_apply.ddl +0 -9
  18. data/mcollective_additions/plugins/v1.2/agent/puppet_apply.rb +0 -630
  19. data/mcollective_additions/plugins/v1.2/agent/rpcutil.ddl +0 -204
  20. data/mcollective_additions/plugins/v1.2/agent/rpcutil.rb +0 -101
  21. data/mcollective_additions/plugins/v1.2/facts/pbuilder_facts.rb +0 -35
  22. data/mcollective_additions/plugins/v2.2/agent/action_agent.ddl +0 -9
  23. data/mcollective_additions/plugins/v2.2/agent/action_agent.rb +0 -47
  24. data/mcollective_additions/plugins/v2.2/agent/dev_manager.ddl +0 -9
  25. data/mcollective_additions/plugins/v2.2/agent/dev_manager.rb +0 -111
  26. data/mcollective_additions/plugins/v2.2/agent/discovery.rb +0 -39
  27. data/mcollective_additions/plugins/v2.2/agent/dtk_node_agent_git_client.rb +0 -94
  28. data/mcollective_additions/plugins/v2.2/agent/execute_tests.ddl +0 -9
  29. data/mcollective_additions/plugins/v2.2/agent/execute_tests.rb +0 -111
  30. data/mcollective_additions/plugins/v2.2/agent/execute_tests_v2.ddl +0 -9
  31. data/mcollective_additions/plugins/v2.2/agent/execute_tests_v2.rb +0 -131
  32. data/mcollective_additions/plugins/v2.2/agent/get_log_fragment.ddl +0 -15
  33. data/mcollective_additions/plugins/v2.2/agent/get_log_fragment.rb +0 -79
  34. data/mcollective_additions/plugins/v2.2/agent/git_access.ddl +0 -9
  35. data/mcollective_additions/plugins/v2.2/agent/git_access.rb +0 -61
  36. data/mcollective_additions/plugins/v2.2/agent/netstat.ddl +0 -9
  37. data/mcollective_additions/plugins/v2.2/agent/netstat.rb +0 -34
  38. data/mcollective_additions/plugins/v2.2/agent/ps.ddl +0 -9
  39. data/mcollective_additions/plugins/v2.2/agent/ps.rb +0 -37
  40. data/mcollective_additions/plugins/v2.2/agent/puppet_apply.ddl +0 -9
  41. data/mcollective_additions/plugins/v2.2/agent/puppet_apply.rb +0 -818
  42. data/mcollective_additions/plugins/v2.2/agent/puppet_cancel.ddl +0 -10
  43. data/mcollective_additions/plugins/v2.2/agent/puppet_cancel.rb +0 -78
  44. data/mcollective_additions/plugins/v2.2/agent/rpcutil.ddl +0 -204
  45. data/mcollective_additions/plugins/v2.2/agent/rpcutil.rb +0 -101
  46. data/mcollective_additions/plugins/v2.2/agent/ssh_agent.ddl +0 -13
  47. data/mcollective_additions/plugins/v2.2/agent/ssh_agent.rb +0 -97
  48. data/mcollective_additions/plugins/v2.2/agent/sync_agent_code.ddl +0 -10
  49. data/mcollective_additions/plugins/v2.2/agent/sync_agent_code.rb +0 -85
  50. data/mcollective_additions/plugins/v2.2/agent/tail.ddl +0 -11
  51. data/mcollective_additions/plugins/v2.2/agent/tail.rb +0 -67
  52. data/mcollective_additions/plugins/v2.2/audit/logfile.rb +0 -26
  53. data/mcollective_additions/plugins/v2.2/connector/r8stomp.rb +0 -238
  54. data/mcollective_additions/plugins/v2.2/connector/stomp.rb +0 -349
  55. data/mcollective_additions/plugins/v2.2/connector/stomp_em.rb +0 -191
  56. data/mcollective_additions/plugins/v2.2/data/agent_data.ddl +0 -22
  57. data/mcollective_additions/plugins/v2.2/data/agent_data.rb +0 -17
  58. data/mcollective_additions/plugins/v2.2/data/collective_data.ddl +0 -20
  59. data/mcollective_additions/plugins/v2.2/data/collective_data.rb +0 -9
  60. data/mcollective_additions/plugins/v2.2/data/fact_data.ddl +0 -28
  61. data/mcollective_additions/plugins/v2.2/data/fact_data.rb +0 -55
  62. data/mcollective_additions/plugins/v2.2/data/fstat_data.ddl +0 -89
  63. data/mcollective_additions/plugins/v2.2/data/fstat_data.rb +0 -56
  64. data/mcollective_additions/plugins/v2.2/discovery/flatfile.ddl +0 -11
  65. data/mcollective_additions/plugins/v2.2/discovery/flatfile.rb +0 -48
  66. data/mcollective_additions/plugins/v2.2/discovery/mc.ddl +0 -11
  67. data/mcollective_additions/plugins/v2.2/discovery/mc.rb +0 -30
  68. data/mcollective_additions/plugins/v2.2/discovery/stdin.ddl +0 -11
  69. data/mcollective_additions/plugins/v2.2/discovery/stdin.rb +0 -66
  70. data/mcollective_additions/plugins/v2.2/facts/pbuilder_facts.rb +0 -37
  71. data/mcollective_additions/plugins/v2.2/facts/yaml_facts.rb +0 -61
  72. data/mcollective_additions/plugins/v2.2/registration/agentlist.rb +0 -10
  73. data/mcollective_additions/plugins/v2.2/security/sshkey.ddl +0 -9
  74. data/mcollective_additions/plugins/v2.2/security/sshkey.rb +0 -362
  75. data/mcollective_additions/plugins/v2.2/util/puppetrunner.rb +0 -36
  76. data/mcollective_additions/plugins/v2.2/validator/array_validator.ddl +0 -7
  77. data/mcollective_additions/plugins/v2.2/validator/array_validator.rb +0 -9
  78. data/mcollective_additions/plugins/v2.2/validator/ipv4address_validator.ddl +0 -7
  79. data/mcollective_additions/plugins/v2.2/validator/ipv4address_validator.rb +0 -16
  80. data/mcollective_additions/plugins/v2.2/validator/ipv6address_validator.ddl +0 -7
  81. data/mcollective_additions/plugins/v2.2/validator/ipv6address_validator.rb +0 -16
  82. data/mcollective_additions/plugins/v2.2/validator/length_validator.ddl +0 -7
  83. data/mcollective_additions/plugins/v2.2/validator/length_validator.rb +0 -11
  84. data/mcollective_additions/plugins/v2.2/validator/regex_validator.ddl +0 -7
  85. data/mcollective_additions/plugins/v2.2/validator/regex_validator.rb +0 -9
  86. data/mcollective_additions/plugins/v2.2/validator/shellsafe_validator.ddl +0 -7
  87. data/mcollective_additions/plugins/v2.2/validator/shellsafe_validator.rb +0 -13
  88. data/mcollective_additions/plugins/v2.2/validator/typecheck_validator.ddl +0 -7
  89. data/mcollective_additions/plugins/v2.2/validator/typecheck_validator.rb +0 -28
  90. data/mcollective_additions/redhat.mcollective.init +0 -139
  91. data/mcollective_additions/redhat.mcollective.service +0 -14
  92. data/mcollective_additions/server.cfg +0 -22
  93. data/src/etc/logrotate.d/mcollective +0 -10
  94. data/src/etc/mcollective.default +0 -6
@@ -1,204 +0,0 @@
1
- metadata :name => "rpcutil",
2
- :description => "General helpful actions that expose stats and internals to SimpleRPC clients",
3
- :author => "R.I.Pienaar <rip@devco.net>",
4
- :license => "Apache License, Version 2.0",
5
- :version => "1.0",
6
- :url => "http://marionette-collective.org/",
7
- :timeout => 10
8
-
9
- action "collective_info", :description => "Info about the main and sub collectives" do
10
- display :always
11
-
12
- output :main_collective,
13
- :description => "The main Collective",
14
- :display_as => "Main Collective"
15
-
16
- output :collectives,
17
- :description => "All Collectives",
18
- :display_as => "All Collectives"
19
-
20
- summarize do
21
- aggregate summary(:collectives)
22
- end
23
- end
24
-
25
- action "inventory", :description => "System Inventory" do
26
- display :always
27
-
28
- output :agents,
29
- :description => "List of agent names",
30
- :display_as => "Agents"
31
-
32
- output :facts,
33
- :description => "List of facts and values",
34
- :display_as => "Facts"
35
-
36
- output :classes,
37
- :description => "List of classes on the system",
38
- :display_as => "Classes"
39
-
40
- output :version,
41
- :description => "MCollective Version",
42
- :display_as => "Version"
43
-
44
- output :main_collective,
45
- :description => "The main Collective",
46
- :display_as => "Main Collective"
47
-
48
- output :collectives,
49
- :description => "All Collectives",
50
- :display_as => "All Collectives"
51
-
52
- output :data_plugins,
53
- :description => "List of data plugin names",
54
- :display_as => "Data Plugins"
55
- end
56
-
57
- action "get_fact", :description => "Retrieve a single fact from the fact store" do
58
- display :always
59
-
60
- input :fact,
61
- :prompt => "The name of the fact",
62
- :description => "The fact to retrieve",
63
- :type => :string,
64
- :validation => '^[\w\-\.]+$',
65
- :optional => false,
66
- :maxlength => 40
67
-
68
- output :fact,
69
- :description => "The name of the fact being returned",
70
- :display_as => "Fact"
71
-
72
- output :value,
73
- :description => "The value of the fact",
74
- :display_as => "Value"
75
-
76
- summarize do
77
- aggregate summary(:value)
78
- end
79
- end
80
-
81
- action "daemon_stats", :description => "Get statistics from the running daemon" do
82
- display :always
83
-
84
- output :threads,
85
- :description => "List of threads active in the daemon",
86
- :display_as => "Threads"
87
-
88
- output :agents,
89
- :description => "List of agents loaded",
90
- :display_as => "Agents"
91
-
92
- output :pid,
93
- :description => "Process ID of the daemon",
94
- :display_as => "PID"
95
-
96
- output :times,
97
- :description => "Processor time consumed by the daemon",
98
- :display_as => "Times"
99
-
100
- output :validated,
101
- :description => "Messages that passed security validation",
102
- :display_as => "Security Validated"
103
-
104
- output :unvalidated,
105
- :description => "Messages that failed security validation",
106
- :display_as => "Failed Security"
107
-
108
- output :passed,
109
- :description => "Passed filter checks",
110
- :display_as => "Passed Filter"
111
-
112
- output :filtered,
113
- :description => "Didn't pass filter checks",
114
- :display_as => "Failed Filter"
115
-
116
- output :starttime,
117
- :description => "Time the server started",
118
- :display_as => "Start Time"
119
-
120
- output :total,
121
- :description => "Total messages received",
122
- :display_as => "Total Messages"
123
-
124
- output :replies,
125
- :description => "Replies sent back to clients",
126
- :display_as => "Replies"
127
-
128
- output :configfile,
129
- :description => "Config file used to start the daemon",
130
- :display_as => "Config File"
131
-
132
- output :version,
133
- :description => "MCollective Version",
134
- :display_as => "Version"
135
-
136
- output :ttlexpired,
137
- :description => "Messages that did pass TTL checks",
138
- :display_as => "TTL Expired"
139
-
140
- summarize do
141
- aggregate summary(:version)
142
- aggregate summary(:agents)
143
- end
144
- end
145
-
146
- action "agent_inventory", :description => "Inventory of all agents on the server" do
147
- display :always
148
-
149
- output :agents,
150
- :description => "List of agents on the server",
151
- :display_as => "Agents"
152
- end
153
-
154
- action "get_config_item", :description => "Get the active value of a specific config property" do
155
- display :always
156
-
157
- input :item,
158
- :prompt => "Configuration Item",
159
- :description => "The item to retrieve from the server",
160
- :type => :string,
161
- :validation => '^.+$',
162
- :optional => false,
163
- :maxlength => 50
164
-
165
- output :item,
166
- :description => "The config property being retrieved",
167
- :display_as => "Property"
168
-
169
- output :value,
170
- :description => "The value that is in use",
171
- :display_as => "Value"
172
-
173
- summarize do
174
- aggregate summary(:value)
175
- end
176
- end
177
-
178
- action "get_data", :description => "Get data from a data plugin" do
179
- display :always
180
-
181
- input :source,
182
- :prompt => "Data Source",
183
- :description => "The data plugin to retrieve information from",
184
- :type => :string,
185
- :validation => '^\w+$',
186
- :optional => false,
187
- :maxlength => 50
188
-
189
- input :query,
190
- :prompt => "Query",
191
- :description => "The query argument to supply to the data plugin",
192
- :type => :string,
193
- :validation => '^.+$',
194
- :optional => true,
195
- :maxlength => 50
196
- end
197
-
198
- action "ping", :description => "Responds to requests for PING with PONG" do
199
- display :always
200
-
201
- output :pong,
202
- :description => "The local timestamp",
203
- :display_as => "Timestamp"
204
- end
@@ -1,101 +0,0 @@
1
- module MCollective
2
- module Agent
3
- class Rpcutil<RPC::Agent
4
- # Basic system inventory, same as the basic discovery agent
5
- action "inventory" do
6
- reply[:agents] = Agents.agentlist
7
- reply[:facts] = PluginManager["facts_plugin"].get_facts
8
- reply[:version] = MCollective.version
9
- reply[:classes] = []
10
- reply[:main_collective] = config.main_collective
11
- reply[:collectives] = config.collectives
12
- reply[:data_plugins] = PluginManager.grep(/_data$/)
13
-
14
- cfile = Config.instance.classesfile
15
- if File.exist?(cfile)
16
- reply[:classes] = File.readlines(cfile).map {|i| i.chomp}
17
- end
18
- end
19
-
20
- # Retrieve a single fact from the node
21
- action "get_fact" do
22
- validate :fact, String
23
-
24
- reply[:fact] = request[:fact]
25
- reply[:value] = Facts[request[:fact]]
26
- end
27
-
28
- # Get the global stats for this mcollectied
29
- action "daemon_stats" do
30
- stats = PluginManager["global_stats"].to_hash
31
-
32
- reply[:threads] = stats[:threads]
33
- reply[:agents] = stats[:agents]
34
- reply[:pid] = stats[:pid]
35
- reply[:times] = stats[:times]
36
- reply[:configfile] = Config.instance.configfile
37
- reply[:version] = MCollective.version
38
-
39
- reply.data.merge!(stats[:stats])
40
- end
41
-
42
- # Builds an inventory of all agents on teh machine
43
- # including license, version and timeout information
44
- action "agent_inventory" do
45
- reply[:agents] = []
46
-
47
- Agents.agentlist.sort.each do |target_agent|
48
- agent = PluginManager["#{target_agent}_agent"]
49
- actions = agent.methods.grep(/_agent/)
50
-
51
- agent_data = {:agent => target_agent,
52
- :license => "unknown",
53
- :timeout => agent.timeout,
54
- :description => "unknown",
55
- :name => target_agent,
56
- :url => "unknown",
57
- :version => "unknown",
58
- :author => "unknown"}
59
-
60
- agent_data.merge!(agent.meta)
61
-
62
- reply[:agents] << agent_data
63
- end
64
- end
65
-
66
- # Retrieves a single config property that is in effect
67
- action "get_config_item" do
68
- validate :item, String
69
-
70
- reply.fail! "Unknown config property #{request[:item]}" unless config.respond_to?(request[:item])
71
-
72
- reply[:item] = request[:item]
73
- reply[:value] = config.send(request[:item])
74
- end
75
-
76
- # Responds to PING requests with the local timestamp
77
- action "ping" do
78
- reply[:pong] = Time.now.to_i
79
- end
80
-
81
- # Returns all configured collectives
82
- action "collective_info" do
83
- config = Config.instance
84
- reply[:main_collective] = config.main_collective
85
- reply[:collectives] = config.collectives
86
- end
87
-
88
- action "get_data" do
89
- validate :source, String
90
-
91
- query = Data.ddl_transform_input(Data.ddl(request[:source]), request[:query].to_s)
92
-
93
- data = Data[ request[:source] ].lookup(query)
94
-
95
- data.keys.each do |key|
96
- reply[key] = data[key]
97
- end
98
- end
99
- end
100
- end
101
- end
@@ -1,35 +0,0 @@
1
- require 'open-uri'
2
- require 'timeout'
3
- require 'yaml'
4
-
5
- module MCollective
6
- module Facts
7
- # A factsource for pbuilder
8
- class Pbuilder_facts < Base
9
-
10
- def load_facts_from_source
11
- ret = {"pbuilderid" => get_pbuilderid()}
12
- yaml_file = '/etc/mcollective/facts.yaml'
13
- if File.exists?(yaml_file)
14
- yaml_facts = YAML.load_file(yaml_file)
15
- ret.merge!(yaml_facts)
16
- end
17
- ret
18
- end
19
-
20
- def get_pbuilderid()
21
- ret = nil
22
- begin
23
- addr = "169.254.169.254"
24
- wait_sec = 2
25
- Timeout::timeout(wait_sec) {open("http://#{addr}:80/")}
26
- ret = OpenURI.open_uri("http://#{addr}/2008-02-01/meta-data/instance-id").read
27
- rescue Timeout::Error
28
- rescue
29
- #TODO: unexpected; write to log what error is
30
- end
31
- ret
32
- end
33
- end
34
- end
35
- end
@@ -1,9 +0,0 @@
1
- metadata :name => "action agent",
2
- :description => "Action Agent allows us to run native bash commands on target system",
3
- :author => "Reactor8",
4
- :license => "",
5
- :version => "",
6
- :url => "",
7
- :timeout => 0
8
- action "run_command", :description => "Run provided command on system" do
9
- end
@@ -1,47 +0,0 @@
1
- require 'json'
2
- require 'cgi'
3
-
4
- module MCollective
5
- module Agent
6
- class Action_agent < RPC::Agent
7
- action "run_command" do
8
- #validate :action_agent_request, String
9
-
10
- payload = request[:action_agent_request].to_json
11
- Log.info "Run command has been started with params: "
12
- Log.info payload
13
-
14
- # we encode payload
15
- encoded_payload = CGI.escape(payload)
16
- result = `/opt/puppet-omnibus/embedded/bin/dtk-action-agent '#{encoded_payload}'`
17
-
18
- json_result = JSON.parse(result)
19
- reply[:results] = json_result['results']
20
- reply[:errors] = json_result['errors']
21
-
22
- Log.info "Results: "
23
- Log.info reply[:results]
24
-
25
- Log.info "Errors: "
26
- Log.info reply[:errors]
27
-
28
-
29
- reply[:pbuilderid] = Facts["pbuilderid"]
30
-
31
- if reply[:errors].empty?
32
- Log.info "DTK Action Agent has finished successfully sending proper response"
33
- reply[:status] = :ok
34
- else
35
- reply[:status] = :failed
36
- reply[:statusmsg] = :failed
37
- reply[:statuscode] = 1
38
-
39
- Log.error "DTK Action Agent has errors:"
40
- reply[:errors].each { |a| Log.error a }
41
- end
42
-
43
- end
44
-
45
- end
46
- end
47
- end
@@ -1,9 +0,0 @@
1
- metadata :name => "development manager",
2
- :description => "Manager which allows manipulation of nodes",
3
- :author => "Reactor8",
4
- :license => "",
5
- :version => "",
6
- :url => "",
7
- :timeout => 60
8
- action "inject_agent", :description => "Injects agent content and restarts mcollective" do
9
- end
@@ -1,111 +0,0 @@
1
- require 'base64'
2
- require 'tmpdir'
3
- require 'fileutils'
4
-
5
- module MCollective
6
- module Agent
7
- class Dev_manager < RPC::Agent
8
-
9
- AGENT_MCOLLECTIVE_LOCATION = "#{::MCollective::Config.instance.libdir.join}/mcollective/agent/"
10
- DTK_AA_TEMP_DIR = File.join(Dir.tmpdir(), 'dtk-action-agent')
11
-
12
- action "inject_agent" do
13
- begin
14
-
15
- ret ||= Response.new()
16
-
17
- # make sure default `service` command paths are set
18
- ENV['PATH'] += ":/usr/sbin:/sbin"
19
-
20
- (request[:agent_files]||[]).each do |k,v|
21
- if v == :deleted
22
- File.delete("#{AGENT_MCOLLECTIVE_LOCATION}#{k}")
23
- next
24
- end
25
- content = Base64.decode64(v)
26
- File.open("#{AGENT_MCOLLECTIVE_LOCATION}#{k}",'w') do |file|
27
- file << content
28
- end
29
- end
30
-
31
- ret.set_status_succeeded!()
32
-
33
- dtk_aa_url = request[:action_agent_remote_url]
34
- dtk_aa_branch = request[:action_agent_branch]
35
-
36
- # DTK Action Agent Sync
37
- if dtk_aa_url && dtk_aa_branch
38
- begin
39
- Log.instance.info("Started DTK Action Agent sync, temp dir '#{DTK_AA_TEMP_DIR}'")
40
- output = `git clone #{dtk_aa_url} -b #{dtk_aa_branch} #{DTK_AA_TEMP_DIR}`
41
- result = $?
42
-
43
- if result.success?
44
- Log.instance.info("Cloned latest code from branch '#{dtk_aa_branch}' for DTK Action Agent.")
45
-
46
- output = `cd #{DTK_AA_TEMP_DIR} && /opt/puppet-omnibus/embedded/bin/gem build #{DTK_AA_TEMP_DIR}/dtk-action-agent.gemspec && /opt/puppet-omnibus/embedded/bin/gem install #{DTK_AA_TEMP_DIR}/dtk-action-agent-*.gem --no-ri --no-rdoc`
47
- result = $?
48
- if result.success?
49
- Log.instance.info("DTK Action Agent has been successfully update from branch '#{dtk_aa_branch}'")
50
- else
51
- Log.instance.error("DTK Action Agent could not be updated, reason: #{output}")
52
- end
53
- else
54
- Log.instance.error("Not able to clone latest code from '#{dtk_aa_url} branch #{dtk_aa_branch}', aborting DTK Action Agent Sync. #{output}")
55
- end
56
- ensure
57
- FileUtils.rm_rf DTK_AA_TEMP_DIR
58
- end
59
- end
60
-
61
- t1 = Thread.new do
62
- sleep(2)
63
- Log.instance.info "Initiating mcollective restart..."
64
- system("#{service_command} restart")
65
- end
66
-
67
- def self.service_command
68
- cmd = `which service`.chomp
69
- cmd.empty? ? "/etc/init.d/mcollective" : "#{cmd} mcollective"
70
- end
71
-
72
- return ret
73
-
74
- rescue Exception => e
75
- Log.instance.error e
76
- ret.set_status_failed!()
77
- error_info = { :error => { :message => "Error syncing agents: #{e}" } }
78
- ret.merge!(error_info)
79
- end
80
-
81
- return ret
82
- end
83
- end
84
- #TODO: this should be common accross Agents
85
- class Response < Hash
86
- def initialize(hash={})
87
- super()
88
- self.merge!(hash)
89
- self[:status] = :unknown unless hash.has_key?(:status)
90
- end
91
-
92
- def to_hash()
93
- Hash.new.merge(self)
94
- end
95
-
96
- def failed?()
97
- self[:status] == :failed
98
- end
99
-
100
- def set_status_failed!()
101
- self[:status] = :failed
102
- end
103
- def set_status_succeeded!()
104
- self[:status] = :succeeded
105
- end
106
- def set_dynamic_attributes!(dynamic_attributes)
107
- self[:dynamic_attributes] = dynamic_attributes
108
- end
109
- end
110
- end
111
- end