serverkit 0.2.3 → 0.2.4

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: e5b26c6d22c758ec66cc5435e50d8289c591da71
4
- data.tar.gz: 3324355b6866cbff2a99117b0643449617f54eb0
3
+ metadata.gz: c2ffa547528d62052da5018705e1f1d1e048a586
4
+ data.tar.gz: 199bc68d2e3378ff9d5f30c0dcc2fc744ea09053
5
5
  SHA512:
6
- metadata.gz: 5a7e75d9406ddfc9266015b7cf210bf25069bc5142747f06e99bb51ee72c3df1342ed644d099114fd9354c05e82a6ea3bc396a33d4d7d1c3deb11ab78a248052
7
- data.tar.gz: 50816a5d8ad6bccadf3e1359edc4a3d4c0280cbcb72231be70bd6aa2dc6873c6d30692b134da1f146f8a97ad2ad35b72ac38ed58317b42b847722362440f19f9
6
+ metadata.gz: 027930d6d1455a60425664686b809f6e428f001c070149e0861019718ae1dd40a5f58bb308a43758d97112d795bf105542a50ef7370da197d036a7279ab36d0d
7
+ data.tar.gz: d7ffaf6db341a8b14a65a3283a516806c5de94c9878ba6f0dc6cbcbf9b511b633cd7c69e407ffdae86f95b33e9d7146177ebc5e3fa6aa2bfe7a8b345eb84b28b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.2.4
2
+ - Add new feature: Handlers
3
+ - Add command resource type
4
+ - Change id attribute to optional
5
+ - Improve validation error message on missing type case
6
+
1
7
  ## 0.2.3
2
8
  - Support multiple types on TypeValidator
3
9
  - Fix validation bug on missing type resource
data/README.md CHANGED
@@ -22,33 +22,27 @@ $ serverkit inspect recipe.yml
22
22
  {
23
23
  "resources": [
24
24
  {
25
- "id": "install_mysql",
26
25
  "type": "homebrew",
27
26
  "name": "mysql"
28
27
  },
29
28
  {
30
- "id": "install_redis",
31
29
  "type": "homebrew",
32
30
  "name": "redis"
33
31
  },
34
32
  {
35
- "id": "install_licecap",
36
33
  "type": "homebrew_cask",
37
34
  "name": "licecap"
38
35
  },
39
36
  {
40
- "id": "install_alfred",
41
37
  "type": "homebrew_cask",
42
38
  "name": "alfred"
43
39
  },
44
40
  {
45
- "id": "clone_dotfiles",
46
41
  "type": "git",
47
42
  "repository": "git@github.com:r7kamura/dotfiles.git",
48
43
  "path": "/Users/r7kamura/src/github.com/r7kamura/dotfiles"
49
44
  },
50
45
  {
51
- "id": "symlink_zshrc",
52
46
  "type": "symlink",
53
47
  "source": "/Users/r7kamura/.zshrc",
54
48
  "destination": "/Users/r7kamura/src/github.com/r7kamura/dotfiles/linked/.zshrc"
@@ -130,27 +124,23 @@ In ERB template, you can use given variables via methods named after its keys.
130
124
  ### Example
131
125
  This is an example recipe to install some packages, clone a git repository, and create a symlink.
132
126
 
133
- ```yaml
127
+ ```yml
134
128
  # variables.yml
135
129
  dotfiles_repository: r7kamura/dotfiles
136
130
  user: r7kamura
137
131
  ```
138
132
 
139
- ```yaml
133
+ ```yml
140
134
  # recipe.yml.erb
141
135
  resources:
142
- - id: install_mysql
143
- type: package
136
+ - type: package
144
137
  name: mysql
145
- - id: install_redis
146
- type: package
138
+ - type: package
147
139
  name: redis
148
- - id: clone_dotfiles
149
- type: git
140
+ - type: git
150
141
  repository: git@github.com:<%= dotfiles_repository %>.git
151
142
  path: /Users/<%= user %>/src/github.com/<%= dotfiles_repository %>
152
- - id: symlink_zshrc
153
- type: symlink
143
+ - type: symlink
154
144
  source: /Users/<%= user %>/.zshrc
155
145
  destination: /Users/<%= user %>/src/github.com/<%= dotfiles_repository %>/.zshrc
156
146
  ```
@@ -161,10 +151,12 @@ A resource is a statement of configuration policy that describes the desired sta
161
151
  ### Type
162
152
  A resource must have a type property. Currently the following types are available:
163
153
 
154
+ - command
164
155
  - file
165
156
  - git
166
157
  - homebrew
167
158
  - homebrew_cask
159
+ - nothing
168
160
  - package
169
161
  - recipe
170
162
  - service
@@ -173,11 +165,37 @@ A resource must have a type property. Currently the following types are availabl
173
165
  - [rbenv_ruby](https://github.com/r7kamura/serverkit-rbenv)
174
166
 
175
167
  ### Example
176
- An example package resource that has id, type, and name attributes.
168
+ An example package resource that has type and name attributes.
177
169
 
178
- ```yaml
170
+ ```yml
179
171
  resources:
180
- - id: install_mysql # id attirbute (This resource is identified by this unique id)
181
- type: package # type attribute (Serverkit::Resources::Package class is used for this)
182
- name: mysql # name attribute (package resource requires name attribute)
172
+ - type: package
173
+ name: mysql
174
+ ```
175
+
176
+ ## Handlers
177
+ When any changes are successfully applied to a resource and it has notify property,
178
+ it notifies handlers that are referenced by their id.
179
+ The notified handlers will run only once after all resources finished their applications.
180
+ Here's an example of restarting Dock on Mac OS X when its preferences change.
181
+
182
+ ```yml
183
+ resources:
184
+ - type: defaults
185
+ domain: com.apple.dock
186
+ key: autohide
187
+ value: 1
188
+ notify:
189
+ - restart_dock
190
+ - id: empty_dock
191
+ type: defaults
192
+ domain: com.apple.dock
193
+ key: persistent-apps
194
+ value: []
195
+ notify:
196
+ - restart_dock
197
+ handlers:
198
+ - id: restart_dock
199
+ type: command
200
+ script: killall Dock
183
201
  ```
@@ -1,9 +1,7 @@
1
1
  resources:
2
- - id: clone_dotfiles
3
- type: git
2
+ - type: git
4
3
  repository: git@github.com:<%= dotfiles_github_repository %>.git
5
4
  path: /Users/<%= user %>/src/github.com/<%= dotfiles_github_repository %>
6
- - id: symlink_zshrc
7
- type: symlink
5
+ - type: symlink
8
6
  source: /Users/<%= user %>/.zshrc
9
7
  destination: /Users/<%= user %>/src/github.com/<%= dotfiles_github_repository %>/linked/.zshrc
@@ -1,7 +1,5 @@
1
1
  resources:
2
- - id: install_mysql
3
- type: homebrew
2
+ - type: homebrew
4
3
  name: mysql
5
- - id: install_redis
6
- type: homebrew
4
+ - type: homebrew
7
5
  name: redis
@@ -1,7 +1,5 @@
1
1
  resources:
2
- - id: install_licecap
3
- type: homebrew_cask
2
+ - type: homebrew_cask
4
3
  name: licecap
5
- - id: install_alfred
6
- type: homebrew_cask
4
+ - type: homebrew_cask
7
5
  name: alfred
@@ -1,19 +1,16 @@
1
1
  {
2
2
  "resources": [
3
3
  {
4
- "id": "install_homebrew_packages",
5
4
  "type": "recipe",
6
5
  "path": "example/recipes/homebrew.yml"
7
6
  },
8
7
  {
9
- "id": "install_homebrew_cask_packages",
10
8
  "type": "recipe",
11
9
  "path": "example/recipes/homebrew_cask.yml"
12
10
  },
13
11
  {
14
- "id": "install_dotfiles",
15
12
  "type": "recipe",
16
13
  "path": "example/recipes/dotfiles.yml.erb"
17
14
  }
18
15
  ]
19
- }
16
+ }
@@ -1,10 +1,16 @@
1
1
  resources:
2
- - id: install_homebrew_packages
3
- type: recipe
2
+ - type: recipe
4
3
  path: example/recipes/homebrew.yml
5
- - id: install_homebrew_cask_packages
6
- type: recipe
4
+ - type: recipe
7
5
  path: example/recipes/homebrew_cask.yml
8
- - id: install_dotfiles
9
- type: recipe
6
+ - type: recipe
10
7
  path: example/recipes/dotfiles.yml.erb
8
+ - type: nothing
9
+ notify:
10
+ - handler_test
11
+ - type: nothing
12
+ notify:
13
+ - handler_test
14
+ handlers:
15
+ - id: handler_test
16
+ type: nothing
@@ -7,15 +7,15 @@ module Serverkit
7
7
  def run
8
8
  backends.map do |backend|
9
9
  Thread.new do
10
- recipe.resources.map(&:dup).each do |resource|
10
+ recipe.resources.map(&:dup).map do |resource|
11
11
  resource.backend = backend
12
- if resource.check
13
- puts "[SKIP] #{resource.id} on #{host_for(backend)}"
14
- else
15
- resource.apply
16
- result = resource.check ? "DONE" : "FAIL"
17
- puts "[#{result}] #{resource.id} on #{host_for(backend)}"
18
- end
12
+ resource.run_apply
13
+ puts resource.inspect_apply_result
14
+ resource
15
+ end.select(&:notifiable?).flat_map(&:handlers).uniq.map(&:dup).each do |handler|
16
+ handler.backend = backend
17
+ handler.run_apply
18
+ puts handler.inspect_apply_result
19
19
  end
20
20
  end
21
21
  end.each(&:join)
@@ -59,12 +59,6 @@ module Serverkit
59
59
  options[:hosts].split(",")
60
60
  end
61
61
 
62
- # @param [Specinfra::Backend::Base]
63
- # @return [String]
64
- def host_for(backend)
65
- backend.get_config(:host) || "localhost"
66
- end
67
-
68
62
  # @return [Slop] Command-line options
69
63
  def options
70
64
  @options ||= Slop.parse!(@argv, help: true) do
@@ -9,8 +9,8 @@ module Serverkit
9
9
  Thread.new do
10
10
  recipe.resources.map(&:dup).each do |resource|
11
11
  resource.backend = backend
12
- result = resource.check ? "OK" : "NG"
13
- puts "[ #{result} ] #{resource.id} on #{host_for(backend)}"
12
+ resource.run_check
13
+ puts resource.inspect_check_result
14
14
  end
15
15
  end
16
16
  end.each(&:join)
@@ -0,0 +1,12 @@
1
+ require "serverkit/errors/base"
2
+
3
+ module Serverkit
4
+ module Errors
5
+ class MissingResourceTypeError < Base
6
+ # @return [String]
7
+ def to_s
8
+ "Missing resource type"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -28,6 +28,13 @@ module Serverkit
28
28
  end
29
29
  end
30
30
 
31
+ # @return [Array<Serverkit::Resource>]
32
+ def handlers
33
+ @handlers ||= Array(handlers_property).flat_map do |attributes|
34
+ ResourceBuilder.new(self, attributes).build.to_a
35
+ end
36
+ end
37
+
31
38
  # @param [Serverkit::Recipe] recipe
32
39
  # @return [Serverkit::Recipe]
33
40
  def merge(recipe)
@@ -76,6 +83,11 @@ module Serverkit
76
83
  resources.flat_map(&:all_errors)
77
84
  end
78
85
 
86
+ # @return [Array<String>, nil]
87
+ def handlers_property
88
+ @recipe_data["handlers"]
89
+ end
90
+
79
91
  def has_valid_typed_resources_property?
80
92
  resources_property.is_a?(Array)
81
93
  end
@@ -1,8 +1,12 @@
1
1
  require "active_support/core_ext/string/inflections"
2
+ require "serverkit/resources/command"
2
3
  require "serverkit/resources/file"
3
4
  require "serverkit/resources/git"
4
5
  require "serverkit/resources/homebrew_cask"
5
6
  require "serverkit/resources/homebrew"
7
+ require "serverkit/resources/missing"
8
+ require "serverkit/resources/nothing"
9
+ require "serverkit/resources/package"
6
10
  require "serverkit/resources/recipe"
7
11
  require "serverkit/resources/service"
8
12
  require "serverkit/resources/symlink"
@@ -30,7 +34,10 @@ module Serverkit
30
34
 
31
35
  # @return [Class]
32
36
  def resource_class
33
- if has_known_type?
37
+ case
38
+ when type.nil?
39
+ Resources::Missing
40
+ when has_known_type?
34
41
  Resources.const_get(resource_class_name, false)
35
42
  else
36
43
  Resources::Unknown
@@ -39,9 +46,7 @@ module Serverkit
39
46
 
40
47
  # @return [String] (e.g. "File", "Symlink")
41
48
  def resource_class_name
42
- if type.is_a?(String)
43
- type.camelize
44
- end
49
+ type.to_s.camelize
45
50
  end
46
51
 
47
52
  # @note Expected to return String in normal case
@@ -24,7 +24,9 @@ module Serverkit
24
24
 
25
25
  attr_reader :attributes, :recipe
26
26
 
27
- attribute :id, required: true, type: String
27
+ attribute :id, type: String
28
+ attribute :notify, type: Array
29
+ attribute :type, type: String
28
30
 
29
31
  # @param [Serverkit::Recipe] recipe
30
32
  # @param [Hash] attributes
@@ -33,23 +35,73 @@ module Serverkit
33
35
  @recipe = recipe
34
36
  end
35
37
 
36
- # @note For override use
38
+ # @note For override
37
39
  # @return [Array<Serverkit::Errors::Base>]
38
40
  def all_errors
39
41
  attribute_validation_errors
40
42
  end
41
43
 
44
+ # @return [Array<Serverkit::Resource>]
45
+ def handlers
46
+ @handlers ||= notify.map do |id|
47
+ recipe.handlers.find do |handler|
48
+ handler.id == id
49
+ end
50
+ end.compact
51
+ end
52
+
53
+ # @note For logging and notifying
54
+ # @return [String]
55
+ def id
56
+ @attributes["id"] || default_id
57
+ end
58
+
59
+ # @return [String]
60
+ def inspect_apply_result
61
+ case @recheck_result
62
+ when nil
63
+ "[SKIP] #{result_inspection_suffix}"
64
+ when false
65
+ "[FAIL] #{result_inspection_suffix}"
66
+ else
67
+ "[DONE] #{result_inspection_suffix}"
68
+ end
69
+ end
70
+
71
+ # @return [String]
72
+ def inspect_check_result
73
+ if @check_result
74
+ "[ OK ] #{result_inspection_suffix}"
75
+ else
76
+ "[ NG ] #{result_inspection_suffix}"
77
+ end
78
+ end
79
+
80
+ # @return [true, false] True if this resource should call any handler
81
+ def notifiable?
82
+ @recheck_result == true && !handlers.nil?
83
+ end
84
+
85
+ # @note #check and #apply wrapper
86
+ def run_apply
87
+ unless run_check
88
+ apply
89
+ @recheck_result = recheck
90
+ end
91
+ end
92
+
93
+ # @note #check wrapper
94
+ # @return [true, false]
95
+ def run_check
96
+ @check_result = check
97
+ end
98
+
42
99
  # @note recipe resource will override to replace itself with multiple resources
43
100
  # @return [Array<Serverkit::Resources::Base>]
44
101
  def to_a
45
102
  [self]
46
103
  end
47
104
 
48
- # @return [String]
49
- def type
50
- @attributes["type"]
51
- end
52
-
53
105
  private
54
106
 
55
107
  # @return [Array<Serverkit::Errors::AttributeValidationError>]
@@ -60,6 +112,11 @@ module Serverkit
60
112
  end
61
113
  end
62
114
 
115
+ # @return [String]
116
+ def backend_host
117
+ backend.get_config(:host) || "localhost"
118
+ end
119
+
63
120
  # @return [true, false]
64
121
  def check_command(*args)
65
122
  run_command(*args).success?
@@ -70,6 +127,23 @@ module Serverkit
70
127
  run_command_from_identifier(*args).success?
71
128
  end
72
129
 
130
+ # @note For override
131
+ # @return [String]
132
+ def default_id
133
+ type
134
+ end
135
+
136
+ # @note For override
137
+ # @return [true, false]
138
+ def recheck
139
+ check
140
+ end
141
+
142
+ # @return [String]
143
+ def result_inspection_suffix
144
+ "#{type} #{id} on #{backend_host}"
145
+ end
146
+
73
147
  # @return [Specinfra::CommandResult]
74
148
  def run_command(*args)
75
149
  backend.run_command(*args)
@@ -0,0 +1,24 @@
1
+ require "serverkit/resources/base"
2
+
3
+ module Serverkit
4
+ module Resources
5
+ class Command < Base
6
+ attribute :script, required: true, type: String
7
+
8
+ # @note Override
9
+ def apply
10
+ run_command(script)
11
+ end
12
+
13
+ # @note Override
14
+ def check
15
+ false
16
+ end
17
+
18
+ # @note Override
19
+ def recheck
20
+ true
21
+ end
22
+ end
23
+ end
24
+ end
@@ -9,13 +9,14 @@ module Serverkit
9
9
  attribute :owner, type: String
10
10
  attribute :source, readable: true, required: true, type: String
11
11
 
12
+ # @note Override
12
13
  def apply
13
14
  send_file if file_sendable?
14
15
  change_group unless has_valid_group?
15
16
  change_owner unless has_valid_owner?
16
17
  end
17
18
 
18
- # @return [true, false]
19
+ # @note Override
19
20
  def check
20
21
  has_file? && has_same_content? && has_valid_group? && has_valid_owner?
21
22
  end
@@ -30,6 +31,11 @@ module Serverkit
30
31
  run_command_from_identifier(:change_file_owner, destination, owner)
31
32
  end
32
33
 
34
+ # @note Override
35
+ def default_id
36
+ destination
37
+ end
38
+
33
39
  def file_sendable?
34
40
  !has_file? || !has_same_content?
35
41
  end
@@ -9,12 +9,13 @@ module Serverkit
9
9
  attribute :repository, required: true, type: String
10
10
  attribute :status, default: DEFAULT_STATUS, type: String
11
11
 
12
+ # @note Override
12
13
  def apply
13
14
  clone if clonable?
14
15
  update if updatable?
15
16
  end
16
17
 
17
- # @return [true, false]
18
+ # @note Override
18
19
  def check
19
20
  has_git? && cloned? && !updatable?
20
21
  end
@@ -33,6 +34,11 @@ module Serverkit
33
34
  check_command_from_identifier(:check_file_is_directory, git_path)
34
35
  end
35
36
 
37
+ # @note Override
38
+ def default_id
39
+ repository
40
+ end
41
+
36
42
  # @return [String] Path to .git directory in the cloned repository
37
43
  def git_path
38
44
  ::File.join(path, ".git")
@@ -5,14 +5,22 @@ module Serverkit
5
5
  class HomebrewCask < Base
6
6
  attribute :name, required: true, type: String
7
7
 
8
+ # @note Override
8
9
  def apply
9
10
  run_command("brew cask install #{name}")
10
11
  end
11
12
 
12
- # @return [true, false]
13
+ # @note Override
13
14
  def check
14
15
  check_command("/usr/local/bin/brew cask list -1 | grep -E '^#{name}$'")
15
16
  end
17
+
18
+ private
19
+
20
+ # @note Override
21
+ def default_id
22
+ name
23
+ end
16
24
  end
17
25
  end
18
26
  end
@@ -0,0 +1,13 @@
1
+ require "serverkit/errors/missing_resource_type_error"
2
+ require "serverkit/resources/base"
3
+
4
+ module Serverkit
5
+ module Resources
6
+ class Missing < Base
7
+ # @return [Array<Serverkit::Errors::MissingResourceTypeError>]
8
+ def all_errors
9
+ [Errors::MissingResourceTypeError.new]
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ require "serverkit/resources/base"
2
+
3
+ module Serverkit
4
+ module Resources
5
+ # A class to do nothing for debugging.
6
+ class Nothing < Base
7
+ # @note Override
8
+ def apply
9
+ end
10
+
11
+ # @note Override for #apply to be always called
12
+ def check
13
+ false
14
+ end
15
+
16
+ private
17
+
18
+ # @note Override to always pass rechecking
19
+ def recheck
20
+ true
21
+ end
22
+ end
23
+ end
24
+ end
@@ -5,14 +5,22 @@ module Serverkit
5
5
  class Package < Base
6
6
  attribute :name, required: true, type: String
7
7
 
8
+ # @note Override
8
9
  def apply
9
10
  run_command_from_identifier(:install_package, name)
10
11
  end
11
12
 
12
- # @return [true, false]
13
+ # @note Override
13
14
  def check
14
15
  check_command_from_identifier(:check_package_is_installed, name)
15
16
  end
17
+
18
+ private
19
+
20
+ # @note Override
21
+ def default_id
22
+ name
23
+ end
16
24
  end
17
25
  end
18
26
  end
@@ -5,13 +5,22 @@ module Serverkit
5
5
  class Service < Base
6
6
  attribute :name, required: true, type: String
7
7
 
8
+ # @note Override
8
9
  def apply
9
10
  run_command_from_identifier(:start, name)
10
11
  end
11
12
 
13
+ # @note Override
12
14
  def check
13
15
  check_command_from_identifier(:check_service_is_running, name)
14
16
  end
17
+
18
+ private
19
+
20
+ # @note Override
21
+ def default_id
22
+ name
23
+ end
15
24
  end
16
25
  end
17
26
  end
@@ -6,14 +6,22 @@ module Serverkit
6
6
  attribute :destination, required: true, type: String
7
7
  attribute :source, required: true, type: String
8
8
 
9
+ # @note Override
9
10
  def apply
10
11
  run_command_from_identifier(:link_file_to, source, destination)
11
12
  end
12
13
 
13
- # @return [true, false]
14
+ # @note Override
14
15
  def check
15
16
  check_command_from_identifier(:check_file_is_linked_to, source, destination)
16
17
  end
18
+
19
+ private
20
+
21
+ # @note Override
22
+ def default_id
23
+ destination
24
+ end
17
25
  end
18
26
  end
19
27
  end
@@ -13,15 +13,7 @@ module Serverkit
13
13
  # @param [Serverkit::Variables] variables
14
14
  # @return [Serverkit::Variables]
15
15
  def merge(variables)
16
- self.class.new(
17
- variables_data.deep_merge(variables.variables_data) do |key, a, b|
18
- if a.is_a?(Array)
19
- a | b
20
- else
21
- b
22
- end
23
- end
24
- )
16
+ self.class.new(variables_data.deep_merge(variables.variables_data))
25
17
  end
26
18
 
27
19
  # @return [Hashie::Mash]
@@ -1,3 +1,3 @@
1
1
  module Serverkit
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serverkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
@@ -204,6 +204,7 @@ files:
204
204
  - lib/serverkit/errors/invalid_resources_type_error.rb
205
205
  - lib/serverkit/errors/missing_action_name_argument_error.rb
206
206
  - lib/serverkit/errors/missing_recipe_path_argument_error.rb
207
+ - lib/serverkit/errors/missing_resource_type_error.rb
207
208
  - lib/serverkit/errors/non_existent_path_error.rb
208
209
  - lib/serverkit/errors/unknown_action_name_error.rb
209
210
  - lib/serverkit/errors/unknown_resource_type_error.rb
@@ -213,10 +214,13 @@ files:
213
214
  - lib/serverkit/recipe.rb
214
215
  - lib/serverkit/resource_builder.rb
215
216
  - lib/serverkit/resources/base.rb
217
+ - lib/serverkit/resources/command.rb
216
218
  - lib/serverkit/resources/file.rb
217
219
  - lib/serverkit/resources/git.rb
218
220
  - lib/serverkit/resources/homebrew.rb
219
221
  - lib/serverkit/resources/homebrew_cask.rb
222
+ - lib/serverkit/resources/missing.rb
223
+ - lib/serverkit/resources/nothing.rb
220
224
  - lib/serverkit/resources/package.rb
221
225
  - lib/serverkit/resources/recipe.rb
222
226
  - lib/serverkit/resources/service.rb
@@ -251,3 +255,4 @@ signing_key:
251
255
  specification_version: 4
252
256
  summary: Configuration management toolkit for IT automation.
253
257
  test_files: []
258
+ has_rdoc: