serverkit 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +6 -0
- data/README.md +8 -5
- data/lib/readable_validator.rb +9 -0
- data/lib/required_validator.rb +9 -0
- data/lib/serverkit/actions/validate.rb +15 -0
- data/lib/serverkit/command.rb +8 -0
- data/lib/serverkit/errors/base.rb +6 -0
- data/lib/serverkit/errors/invalid_recipe_type.rb +16 -0
- data/lib/serverkit/errors/invalid_resources_type.rb +16 -0
- data/lib/serverkit/recipe.rb +62 -14
- data/lib/serverkit/resources/base.rb +19 -7
- data/lib/serverkit/resources/file.rb +7 -21
- data/lib/serverkit/resources/git.rb +4 -15
- data/lib/serverkit/resources/homebrew_cask.rb +2 -7
- data/lib/serverkit/resources/package.rb +2 -7
- data/lib/serverkit/resources/symlink.rb +3 -12
- data/lib/serverkit/version.rb +1 -1
- data/serverkit.gemspec +2 -1
- metadata +24 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3973baadffe8fb3a024c183ff1736bce8f48c719
|
4
|
+
data.tar.gz: aac29f5ee26cc9c77d644b9c6dd7f2cd9c22eebd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6e93dd18c08bb32e80d57ea3b59e28b1eece1e0d93a438e51bcfbb3d8aae8c2fe17cfb7a36e1a279bd46b648bc40365d3f540b2dfe3c8668402f7701b64b606e
|
7
|
+
data.tar.gz: 33152a234df68bcd557b6ef38f0df5a58b29d0ac192315ab7b87cd87c2aa69449e1893ad91b19bab124b623c9d5137a2e8e02987f84d9794138bc0a1f509ea1f
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
# Serverkit [![Build Status](https://travis-ci.org/r7kamura/serverkit.svg)](https://travis-ci.org/r7kamura/serverkit) [![Code Climate](https://codeclimate.com/github/r7kamura/serverkit/badges/gpa.svg)](https://codeclimate.com/github/r7kamura/serverkit)
|
2
|
-
Configuration management toolkit for
|
2
|
+
Configuration management toolkit for your infrastructure.
|
3
3
|
|
4
4
|
## Usage
|
5
5
|
```sh
|
6
6
|
# Write your recipe
|
7
7
|
vi recipe.yml
|
8
8
|
|
9
|
-
#
|
10
|
-
|
9
|
+
# Validate recipe
|
10
|
+
serverkit validate --recipe=recipe.yml
|
11
11
|
|
12
|
-
#
|
13
|
-
|
12
|
+
# Check differences
|
13
|
+
serverkit check --recipe=recipe.yml
|
14
|
+
|
15
|
+
# Apply migration
|
16
|
+
serverkit apply --recipe=recipe.yml
|
14
17
|
```
|
15
18
|
|
16
19
|
### Example
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "serverkit/actions/base"
|
2
|
+
|
3
|
+
module Serverkit
|
4
|
+
module Actions
|
5
|
+
class Validate < Base
|
6
|
+
def call
|
7
|
+
if recipe.valid?
|
8
|
+
puts "Success"
|
9
|
+
else
|
10
|
+
abort recipe.errors.map { |error| "Error: #{error}" }.join("\n")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/serverkit/command.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require "serverkit/actions/apply"
|
2
2
|
require "serverkit/actions/check"
|
3
|
+
require "serverkit/actions/validate"
|
3
4
|
require "slop"
|
4
5
|
|
5
6
|
module Serverkit
|
@@ -7,6 +8,7 @@ module Serverkit
|
|
7
8
|
ACTION_NAMES = %w(
|
8
9
|
apply
|
9
10
|
check
|
11
|
+
validate
|
10
12
|
)
|
11
13
|
|
12
14
|
# @param [Array<String>] argv
|
@@ -24,6 +26,8 @@ module Serverkit
|
|
24
26
|
apply
|
25
27
|
when action_name == "check"
|
26
28
|
check
|
29
|
+
when action_name == "validate"
|
30
|
+
validate
|
27
31
|
end
|
28
32
|
rescue Slop::MissingOptionError => exception
|
29
33
|
abort "Error: #{exception}"
|
@@ -67,5 +71,9 @@ module Serverkit
|
|
67
71
|
on "-r", "--recipe=", "Path to recipe file", required: true
|
68
72
|
end
|
69
73
|
end
|
74
|
+
|
75
|
+
def validate
|
76
|
+
Actions::Validate.new(options).call
|
77
|
+
end
|
70
78
|
end
|
71
79
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "serverkit/errors/base"
|
2
|
+
|
3
|
+
module Serverkit
|
4
|
+
module Errors
|
5
|
+
class InvalidRecipeType < Base
|
6
|
+
# @param [Class] type
|
7
|
+
def initialize(type)
|
8
|
+
@type = type
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"Recipe data must be a Hash, not #{@type}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "serverkit/errors/base"
|
2
|
+
|
3
|
+
module Serverkit
|
4
|
+
module Errors
|
5
|
+
class InvalidResourcesType < Base
|
6
|
+
# @param [Class] type
|
7
|
+
def initialize(type)
|
8
|
+
@type = type
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
"resources property must be an Array, not #{@type}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/serverkit/recipe.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require "active_support/core_ext/string/inflections"
|
2
|
+
require "serverkit/errors/invalid_recipe_type"
|
3
|
+
require "serverkit/errors/invalid_resources_type"
|
2
4
|
require "serverkit/resources/file"
|
3
5
|
require "serverkit/resources/git"
|
4
6
|
require "serverkit/resources/homebrew"
|
@@ -11,39 +13,85 @@ module Serverkit
|
|
11
13
|
class << self
|
12
14
|
# @param [String] path
|
13
15
|
def load_from_path(path)
|
14
|
-
|
15
|
-
new(
|
16
|
+
recipe_data = YAML.load_file(path)
|
17
|
+
new(recipe_data)
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
21
|
+
attr_reader :recipe_data
|
22
|
+
|
23
|
+
# @param [Hash] recipe_data
|
24
|
+
def initialize(recipe_data)
|
25
|
+
@recipe_data = recipe_data
|
22
26
|
end
|
23
27
|
|
24
|
-
# @return [Array<Serverkit::
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
# @return [Array<Serverkit::Errors::Base>]
|
29
|
+
def errors
|
30
|
+
@errors ||= begin
|
31
|
+
case
|
32
|
+
when !has_valid_typed_recipe_data?
|
33
|
+
errors_for_invalid_typed_recipe_data
|
34
|
+
when !has_valid_typed_resources_property?
|
35
|
+
errors_for_invalid_typed_resources_property
|
36
|
+
else
|
37
|
+
errors_in_resources
|
38
|
+
end
|
29
39
|
end
|
30
40
|
end
|
31
41
|
|
32
42
|
# @return [Array<String>]
|
33
43
|
def hosts
|
34
|
-
@
|
44
|
+
@recipe_data["hosts"]
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Array<Serverkit::Resources::Base>]
|
48
|
+
# @todo Delegate to resource builder
|
49
|
+
def resources
|
50
|
+
@resources ||= resources_property.map do |attributes|
|
51
|
+
Resources.const_get(attributes["type"].camelize, false).new(attributes)
|
52
|
+
end
|
35
53
|
end
|
36
54
|
|
37
55
|
# @return [true, false] Flag to use SSH (default: true)
|
38
56
|
def ssh?
|
39
|
-
@
|
57
|
+
@recipe_data["ssh"] != false
|
58
|
+
end
|
59
|
+
|
60
|
+
def valid?
|
61
|
+
errors.empty?
|
40
62
|
end
|
41
63
|
|
42
64
|
private
|
43
65
|
|
66
|
+
# @return [Array<Serverkit::Errors::Base>]
|
67
|
+
def errors_for_invalid_typed_recipe_data
|
68
|
+
[Errors::InvalidRecipeType.new(@recipe_data.class)]
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Array<Serverkit::Errors::Base>]
|
72
|
+
def errors_for_invalid_typed_resources_property
|
73
|
+
[Errors::InvalidResourcesType.new(resources_property.class)]
|
74
|
+
end
|
75
|
+
|
76
|
+
# @return [Array<Serverkit::Errors::Base>]
|
77
|
+
def errors_in_resources
|
78
|
+
resources.flat_map do |resource|
|
79
|
+
resource.validate
|
80
|
+
resource.errors.to_a
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def has_valid_typed_resources_property?
|
85
|
+
resources_property.is_a?(Array)
|
86
|
+
end
|
87
|
+
|
88
|
+
def has_valid_typed_recipe_data?
|
89
|
+
@recipe_data.is_a?(Hash)
|
90
|
+
end
|
91
|
+
|
44
92
|
# @return [Array<String>]
|
45
|
-
def
|
46
|
-
@
|
93
|
+
def resources_property
|
94
|
+
@recipe_data["resources"] || []
|
47
95
|
end
|
48
96
|
end
|
49
97
|
end
|
@@ -1,16 +1,28 @@
|
|
1
|
+
require "active_model"
|
2
|
+
|
1
3
|
module Serverkit
|
2
4
|
module Resources
|
3
5
|
class Base
|
6
|
+
class << self
|
7
|
+
# @note DSL method to define attribute with its validations
|
8
|
+
def attribute(name, options = {})
|
9
|
+
default = options.delete(:default)
|
10
|
+
define_method(name) do
|
11
|
+
@attributes[name.to_s] || default
|
12
|
+
end
|
13
|
+
validates name, options unless options.empty?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
include ActiveModel::Validations
|
18
|
+
|
4
19
|
attr_accessor :backend
|
5
20
|
|
6
|
-
|
7
|
-
def initialize(properties)
|
8
|
-
@properties = properties
|
9
|
-
end
|
21
|
+
attribute :name, required: true
|
10
22
|
|
11
|
-
# @
|
12
|
-
def
|
13
|
-
@
|
23
|
+
# @param [Hash] attributes
|
24
|
+
def initialize(attributes)
|
25
|
+
@attributes = attributes
|
14
26
|
end
|
15
27
|
|
16
28
|
private
|
@@ -1,9 +1,16 @@
|
|
1
1
|
require "digest"
|
2
|
+
require "readable_validator"
|
3
|
+
require "required_validator"
|
2
4
|
require "serverkit/resources/base"
|
3
5
|
|
4
6
|
module Serverkit
|
5
7
|
module Resources
|
6
8
|
class File < Base
|
9
|
+
attribute :destination, required: true
|
10
|
+
attribute :group
|
11
|
+
attribute :owner
|
12
|
+
attribute :source, readable: true, required: true
|
13
|
+
|
7
14
|
def apply
|
8
15
|
send_file if file_sendable?
|
9
16
|
change_group unless has_valid_group?
|
@@ -25,20 +32,10 @@ module Serverkit
|
|
25
32
|
run_command_from_identifier(:change_file_owner, destination, owner)
|
26
33
|
end
|
27
34
|
|
28
|
-
# @return [String]
|
29
|
-
def destination
|
30
|
-
@properties["destination"]
|
31
|
-
end
|
32
|
-
|
33
35
|
def file_sendable?
|
34
36
|
!has_file? || !has_same_content?
|
35
37
|
end
|
36
38
|
|
37
|
-
# @return [String]
|
38
|
-
def group
|
39
|
-
@properties["group"]
|
40
|
-
end
|
41
|
-
|
42
39
|
def has_file?
|
43
40
|
check_command_from_identifier(:check_file_is_file, destination)
|
44
41
|
end
|
@@ -55,17 +52,11 @@ module Serverkit
|
|
55
52
|
owner.nil? || check_command_from_identifier(:check_file_is_owned_by, destination, owner)
|
56
53
|
end
|
57
54
|
|
58
|
-
# @todo Rescue Errno::ENOENT from File.read
|
59
55
|
# @return [String]
|
60
56
|
def local_file_sha256sum
|
61
57
|
::Digest::SHA256.hexdigest(::File.read(source))
|
62
58
|
end
|
63
59
|
|
64
|
-
# @return [String]
|
65
|
-
def owner
|
66
|
-
@properties["owner"]
|
67
|
-
end
|
68
|
-
|
69
60
|
# @return [String]
|
70
61
|
def remote_file_sha256sum
|
71
62
|
run_command_from_identifier(:get_file_sha256sum, destination).stdout.rstrip
|
@@ -74,11 +65,6 @@ module Serverkit
|
|
74
65
|
def send_file
|
75
66
|
run_command_from_identifier(:send_file, source, destination)
|
76
67
|
end
|
77
|
-
|
78
|
-
# @return [String]
|
79
|
-
def source
|
80
|
-
@properties["source"]
|
81
|
-
end
|
82
68
|
end
|
83
69
|
end
|
84
70
|
end
|
@@ -5,6 +5,10 @@ module Serverkit
|
|
5
5
|
class Git < Base
|
6
6
|
DEFAULT_STATUS = "cloned"
|
7
7
|
|
8
|
+
attribute :path, required: true
|
9
|
+
attribute :repository, required: true
|
10
|
+
attribute :status, default: DEFAULT_STATUS
|
11
|
+
|
8
12
|
def apply
|
9
13
|
clone if clonable?
|
10
14
|
update if updatable?
|
@@ -48,21 +52,6 @@ module Serverkit
|
|
48
52
|
run_command("cd #{path} && git ls-remote origin HEAD").stdout.split.first
|
49
53
|
end
|
50
54
|
|
51
|
-
# @return [String] Where to locate cloned repository
|
52
|
-
def path
|
53
|
-
@properties["path"]
|
54
|
-
end
|
55
|
-
|
56
|
-
# @return [String] Git repository URL
|
57
|
-
def repository
|
58
|
-
@properties["repository"]
|
59
|
-
end
|
60
|
-
|
61
|
-
# @return [String]
|
62
|
-
def status
|
63
|
-
@properties["status"] || DEFAULT_STATUS
|
64
|
-
end
|
65
|
-
|
66
55
|
def updatable?
|
67
56
|
status == "updated" && !updated?
|
68
57
|
end
|
@@ -3,6 +3,8 @@ require "serverkit/resources/base"
|
|
3
3
|
module Serverkit
|
4
4
|
module Resources
|
5
5
|
class HomebrewCask < Base
|
6
|
+
attribute :package, required: true
|
7
|
+
|
6
8
|
def apply
|
7
9
|
run_command("brew cask install #{package}")
|
8
10
|
end
|
@@ -11,13 +13,6 @@ module Serverkit
|
|
11
13
|
def check
|
12
14
|
check_command("/usr/local/bin/brew cask list -1 | grep -E '^#{package}$'")
|
13
15
|
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
# @return [String]
|
18
|
-
def package
|
19
|
-
@properties["package"]
|
20
|
-
end
|
21
16
|
end
|
22
17
|
end
|
23
18
|
end
|
@@ -3,6 +3,8 @@ require "serverkit/resources/base"
|
|
3
3
|
module Serverkit
|
4
4
|
module Resources
|
5
5
|
class Package < Base
|
6
|
+
attribute :package, required: true
|
7
|
+
|
6
8
|
def apply
|
7
9
|
run_command_from_identifier(:install, package)
|
8
10
|
end
|
@@ -11,13 +13,6 @@ module Serverkit
|
|
11
13
|
def check
|
12
14
|
check_command_from_identifier(:check_package_is_installed, package)
|
13
15
|
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
# @return [String]
|
18
|
-
def package
|
19
|
-
@properties["package"]
|
20
|
-
end
|
21
16
|
end
|
22
17
|
end
|
23
18
|
end
|
@@ -3,6 +3,9 @@ require "serverkit/resources/base"
|
|
3
3
|
module Serverkit
|
4
4
|
module Resources
|
5
5
|
class Symlink < Base
|
6
|
+
attribute :destination, required: true
|
7
|
+
attribute :source, required: true
|
8
|
+
|
6
9
|
def apply
|
7
10
|
run_command_from_identifier(:link_file_to, source, destination)
|
8
11
|
end
|
@@ -11,18 +14,6 @@ module Serverkit
|
|
11
14
|
def check
|
12
15
|
check_command_from_identifier(:check_file_is_linked_to, source, destination)
|
13
16
|
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
# @return [String]
|
18
|
-
def destination
|
19
|
-
@properties["destination"]
|
20
|
-
end
|
21
|
-
|
22
|
-
# @return [String]
|
23
|
-
def source
|
24
|
-
@properties["source"]
|
25
|
-
end
|
26
17
|
end
|
27
18
|
end
|
28
19
|
end
|
data/lib/serverkit/version.rb
CHANGED
data/serverkit.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.version = Serverkit::VERSION
|
8
8
|
spec.authors = ["Ryo Nakamura"]
|
9
9
|
spec.email = ["r7kamura@gmail.com"]
|
10
|
-
spec.summary = "Configuration management toolkit for
|
10
|
+
spec.summary = "Configuration management toolkit for your infrastructure."
|
11
11
|
spec.homepage = "https://github.com/r7kamura/serverkit"
|
12
12
|
spec.license = "MIT"
|
13
13
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
@@ -15,6 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
16
|
spec.require_paths = ["lib"]
|
17
17
|
|
18
|
+
spec.add_runtime_dependency "activemodel"
|
18
19
|
spec.add_runtime_dependency "activesupport"
|
19
20
|
spec.add_runtime_dependency "slop", "~> 3.4"
|
20
21
|
spec.add_runtime_dependency "specinfra"
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serverkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activemodel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: activesupport
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -134,17 +148,24 @@ files:
|
|
134
148
|
- ".rspec"
|
135
149
|
- ".rubocop.yml"
|
136
150
|
- ".travis.yml"
|
151
|
+
- CHANGELOG.md
|
137
152
|
- Gemfile
|
138
153
|
- LICENSE.txt
|
139
154
|
- README.md
|
140
155
|
- Rakefile
|
141
156
|
- bin/serverkit
|
142
157
|
- examples/recipe.yml
|
158
|
+
- lib/readable_validator.rb
|
159
|
+
- lib/required_validator.rb
|
143
160
|
- lib/serverkit.rb
|
144
161
|
- lib/serverkit/actions/apply.rb
|
145
162
|
- lib/serverkit/actions/base.rb
|
146
163
|
- lib/serverkit/actions/check.rb
|
164
|
+
- lib/serverkit/actions/validate.rb
|
147
165
|
- lib/serverkit/command.rb
|
166
|
+
- lib/serverkit/errors/base.rb
|
167
|
+
- lib/serverkit/errors/invalid_recipe_type.rb
|
168
|
+
- lib/serverkit/errors/invalid_resources_type.rb
|
148
169
|
- lib/serverkit/recipe.rb
|
149
170
|
- lib/serverkit/resources/base.rb
|
150
171
|
- lib/serverkit/resources/file.rb
|
@@ -178,6 +199,6 @@ rubyforge_project:
|
|
178
199
|
rubygems_version: 2.4.5
|
179
200
|
signing_key:
|
180
201
|
specification_version: 4
|
181
|
-
summary: Configuration management toolkit for
|
202
|
+
summary: Configuration management toolkit for your infrastructure.
|
182
203
|
test_files: []
|
183
204
|
has_rdoc:
|