serverkit 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +21 -11
- data/example/recipes/dotfiles.yml.erb +4 -4
- data/lib/readable_validator.rb +1 -1
- data/lib/serverkit/actions/apply.rb +14 -12
- data/lib/serverkit/actions/base.rb +34 -16
- data/lib/serverkit/actions/check.rb +10 -8
- data/lib/serverkit/actions/inspect.rb +2 -7
- data/lib/serverkit/actions/validate.rb +2 -6
- data/lib/serverkit/command.rb +1 -1
- data/lib/serverkit/loaders/base_loader.rb +0 -1
- data/lib/serverkit/loaders/recipe_loader.rb +7 -20
- data/lib/serverkit/variables.rb +11 -3
- data/lib/serverkit/version.rb +1 -1
- data/serverkit.gemspec +1 -0
- metadata +15 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 612a45453d00dd4da8b327be21c8513dfb920292
|
4
|
+
data.tar.gz: 4beb20763b868203c302697f114b508c5f5f4cd8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4172b07769a11c4002e67caff3cb009262912e188b583893e4a9bf00a3a9432934088ae1c2c4df5bcf433a9e8621eaa1e33c122aab7547d03f118b39d0511ae6
|
7
|
+
data.tar.gz: 5068bbb81ac75922f293ff2061a41a22de161acfadf5fb64efd3100906e37014202fedec6604ecd748d1a5b716e3834e303e113be12b27c78ccee969d5610093
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
- Support multiple hosts
|
3
|
+
- Change `--host=` option to `--hosts=`
|
4
|
+
- Change variables use on ERB template
|
5
|
+
- Force recipe validation on all actions
|
6
|
+
|
1
7
|
## 0.1.0
|
2
8
|
- Support execution over SSH with --host option
|
3
9
|
- Remove --recipe=... option and require recipe path in 2nd command-line argument
|
data/README.md
CHANGED
@@ -62,12 +62,12 @@ Shows the difference between your recipe and the state of the target host.
|
|
62
62
|
|
63
63
|
```
|
64
64
|
$ serverkit check recipe.yml
|
65
|
-
[OK] install_mysql
|
66
|
-
[OK] install_redis
|
67
|
-
[OK] install_licecap
|
68
|
-
[OK] install_alfred
|
69
|
-
[NG] clone_dotfiles
|
70
|
-
[NG] symlink_zshrc
|
65
|
+
[ OK ] install_mysql
|
66
|
+
[ OK ] install_redis
|
67
|
+
[ OK ] install_licecap
|
68
|
+
[ OK ] install_alfred
|
69
|
+
[ NG ] clone_dotfiles
|
70
|
+
[ NG ] symlink_zshrc
|
71
71
|
```
|
72
72
|
|
73
73
|
### serverkit apply
|
@@ -83,6 +83,16 @@ $ serverkit apply recipe.yml
|
|
83
83
|
[DONE] symlink_zshrc
|
84
84
|
```
|
85
85
|
|
86
|
+
### SSH support
|
87
|
+
Use `--hosts=` option to execute serverkit over SSH.
|
88
|
+
Serverkit does not require any installation on server-side.
|
89
|
+
If you want to specify SSH configuration, write it into your ~/.ssh/config.
|
90
|
+
|
91
|
+
```
|
92
|
+
$ serverkit apply recipe.yml --hosts=alpha.example.com
|
93
|
+
$ serverkit apply recipe.yml --hosts=alpha.example.com,bravo.example.com
|
94
|
+
```
|
95
|
+
|
86
96
|
## Recipe
|
87
97
|
A recipe describes the desired state of your server.
|
88
98
|
It is mostly a collection of resources, defined using certain patterns.
|
@@ -115,7 +125,7 @@ $ serverkit apply recipes/
|
|
115
125
|
When using ERB recipe, you can also give optional variables file
|
116
126
|
that defines configurations in a Hash object for ERB template.
|
117
127
|
It supports similar format variation with Recipe.
|
118
|
-
In ERB template, you can use given variables via
|
128
|
+
In ERB template, you can use given variables via methods named after its keys.
|
119
129
|
|
120
130
|
### Example
|
121
131
|
This is an example recipe to install some packages, clone a git repository, and create a symlink.
|
@@ -137,12 +147,12 @@ resources:
|
|
137
147
|
name: redis
|
138
148
|
- id: clone_dotfiles
|
139
149
|
type: git
|
140
|
-
repository: git@github.com:<%=
|
141
|
-
path: /Users/<%=
|
150
|
+
repository: git@github.com:<%= dotfiles_repository %>.git
|
151
|
+
path: /Users/<%= user %>/src/github.com/<%= dotfiles_repository %>
|
142
152
|
- id: symlink_zshrc
|
143
153
|
type: symlink
|
144
|
-
source: /Users/<%=
|
145
|
-
destination: /Users/<%=
|
154
|
+
source: /Users/<%= user %>/.zshrc
|
155
|
+
destination: /Users/<%= user %>/src/github.com/<%= dotfiles_repository %>/.zshrc
|
146
156
|
```
|
147
157
|
|
148
158
|
## Resource
|
@@ -1,9 +1,9 @@
|
|
1
1
|
resources:
|
2
2
|
- id: clone_dotfiles
|
3
3
|
type: git
|
4
|
-
repository: git@github.com:<%=
|
5
|
-
path: /Users/<%=
|
4
|
+
repository: git@github.com:<%= dotfiles_github_repository %>.git
|
5
|
+
path: /Users/<%= user %>/src/github.com/<%= dotfiles_github_repository %>
|
6
6
|
- id: symlink_zshrc
|
7
7
|
type: symlink
|
8
|
-
source: /Users/<%=
|
9
|
-
destination: /Users/<%=
|
8
|
+
source: /Users/<%= user %>/.zshrc
|
9
|
+
destination: /Users/<%= user %>/src/github.com/<%= dotfiles_github_repository %>/linked/.zshrc
|
data/lib/readable_validator.rb
CHANGED
@@ -2,7 +2,7 @@ require "active_model"
|
|
2
2
|
|
3
3
|
class ReadableValidator < ActiveModel::EachValidator
|
4
4
|
def validate_each(record, attribute, value)
|
5
|
-
|
5
|
+
if !value.nil? && !File.readable?(value)
|
6
6
|
record.errors.add(attribute, "can't be unreadable path")
|
7
7
|
end
|
8
8
|
end
|
@@ -1,22 +1,24 @@
|
|
1
1
|
require "serverkit/actions/base"
|
2
|
+
require "thread"
|
2
3
|
|
3
4
|
module Serverkit
|
4
5
|
module Actions
|
5
6
|
class Apply < Base
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
def run
|
8
|
+
backends.map do |backend|
|
9
|
+
Thread.new do
|
10
|
+
recipe.resources.map(&:dup).each do |resource|
|
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
|
17
19
|
end
|
18
20
|
end
|
19
|
-
end
|
21
|
+
end.each(&:join)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -14,48 +14,65 @@ module Serverkit
|
|
14
14
|
@argv = argv
|
15
15
|
end
|
16
16
|
|
17
|
+
def call
|
18
|
+
setup
|
19
|
+
run
|
20
|
+
end
|
21
|
+
|
17
22
|
private
|
18
23
|
|
19
24
|
def abort_with_errors
|
20
25
|
abort recipe.errors.map { |error| "Error: #{error}" }.join("\n")
|
21
26
|
end
|
22
27
|
|
23
|
-
# @return [Specinfra::Backend::Base]
|
24
|
-
def
|
25
|
-
|
28
|
+
# @return [Array<Specinfra::Backend::Base>]
|
29
|
+
def backends
|
30
|
+
if options[:hosts]
|
31
|
+
hosts.map do |host|
|
32
|
+
backend_class.new(
|
33
|
+
disable_sudo: true,
|
34
|
+
host: host,
|
35
|
+
ssh_options: {
|
36
|
+
user: ssh_user_for(host),
|
37
|
+
},
|
38
|
+
)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
[backend_class.new]
|
42
|
+
end
|
26
43
|
end
|
27
44
|
|
28
45
|
def backend_class
|
29
|
-
if
|
46
|
+
if options[:hosts]
|
30
47
|
Specinfra::Backend::Ssh
|
31
48
|
else
|
32
49
|
Specinfra::Backend::Exec
|
33
50
|
end
|
34
51
|
end
|
35
52
|
|
36
|
-
def
|
37
|
-
|
38
|
-
disable_sudo: true,
|
39
|
-
host: host,
|
40
|
-
ssh_options: {
|
41
|
-
user: ssh_user,
|
42
|
-
},
|
43
|
-
}
|
53
|
+
def hosts
|
54
|
+
options[:hosts].split(",")
|
44
55
|
end
|
45
56
|
|
46
|
-
|
47
|
-
|
57
|
+
# @param [Specinfra::Backend::Base]
|
58
|
+
# @return [String]
|
59
|
+
def host_for(backend)
|
60
|
+
backend.get_config(:host) || "localhost"
|
48
61
|
end
|
49
62
|
|
50
63
|
# @return [Slop] Command-line options
|
51
64
|
def options
|
52
65
|
@options ||= Slop.parse!(@argv, help: true) do
|
53
66
|
banner "Usage: serverkit ACTION [options]"
|
54
|
-
on "--
|
67
|
+
on "--hosts=", "Pass hostname to execute command over SSH"
|
55
68
|
on "--variables=", "Path to variables file for ERB recipe"
|
56
69
|
end
|
57
70
|
end
|
58
71
|
|
72
|
+
def setup
|
73
|
+
abort_with_errors unless recipe.valid?
|
74
|
+
end
|
75
|
+
|
59
76
|
# @return [Serverkit::Recipe]
|
60
77
|
def recipe
|
61
78
|
@recipe ||= Loaders::RecipeLoader.new(recipe_path, variables_path: options[:variables]).load
|
@@ -66,8 +83,9 @@ module Serverkit
|
|
66
83
|
@argv[1] or raise Errors::MissingRecipePathArgumentError
|
67
84
|
end
|
68
85
|
|
86
|
+
# @param [String] host
|
69
87
|
# @return [String] User name used on SSH
|
70
|
-
def
|
88
|
+
def ssh_user_for(host)
|
71
89
|
Net::SSH::Config.for(host)[:user] || Etc.getlogin
|
72
90
|
end
|
73
91
|
end
|
@@ -1,17 +1,19 @@
|
|
1
1
|
require "serverkit/actions/base"
|
2
|
+
require "thread"
|
2
3
|
|
3
4
|
module Serverkit
|
4
5
|
module Actions
|
5
6
|
class Check < Base
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
def run
|
8
|
+
backends.map do |backend|
|
9
|
+
Thread.new do
|
10
|
+
recipe.resources.map(&:dup).each do |resource|
|
11
|
+
resource.backend = backend
|
12
|
+
result = resource.check ? "OK" : "NG"
|
13
|
+
puts "[ #{result} ] #{resource.id} on #{host_for(backend)}"
|
14
|
+
end
|
13
15
|
end
|
14
|
-
end
|
16
|
+
end.each(&:join)
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -1,15 +1,10 @@
|
|
1
1
|
require "serverkit/actions/base"
|
2
|
-
require "yaml"
|
3
2
|
|
4
3
|
module Serverkit
|
5
4
|
module Actions
|
6
5
|
class Inspect < Base
|
7
|
-
def
|
8
|
-
|
9
|
-
puts JSON.pretty_generate(recipe.to_hash)
|
10
|
-
else
|
11
|
-
abort_with_errors
|
12
|
-
end
|
6
|
+
def run
|
7
|
+
puts JSON.pretty_generate(recipe.to_hash)
|
13
8
|
end
|
14
9
|
end
|
15
10
|
end
|
data/lib/serverkit/command.rb
CHANGED
@@ -28,7 +28,7 @@ module Serverkit
|
|
28
28
|
else
|
29
29
|
raise Errors::UnknownActionNameError
|
30
30
|
end
|
31
|
-
rescue Errors::Base, Slop::MissingOptionError => exception
|
31
|
+
rescue Errors::Base, Slop::MissingArgumentError, Slop::MissingOptionError => exception
|
32
32
|
abort "Error: #{exception}"
|
33
33
|
end
|
34
34
|
|
@@ -5,7 +5,7 @@ require "serverkit/recipe"
|
|
5
5
|
module Serverkit
|
6
6
|
module Loaders
|
7
7
|
class RecipeLoader < BaseLoader
|
8
|
-
|
8
|
+
DEFAULT_VARIABLES_DATA = {}
|
9
9
|
|
10
10
|
# @param [String] path
|
11
11
|
# @param [String, nil] variables_path
|
@@ -17,8 +17,9 @@ module Serverkit
|
|
17
17
|
private
|
18
18
|
|
19
19
|
# @note Override
|
20
|
+
# @return [Binding]
|
20
21
|
def binding_for_erb
|
21
|
-
|
22
|
+
variables.to_mash.binding
|
22
23
|
end
|
23
24
|
|
24
25
|
# @note Override to pass @variables_path
|
@@ -45,30 +46,16 @@ module Serverkit
|
|
45
46
|
Serverkit::Recipe
|
46
47
|
end
|
47
48
|
|
48
|
-
# @return [
|
49
|
-
def
|
49
|
+
# @return [Serverkit::Variables]
|
50
|
+
def variables
|
50
51
|
@variables ||= begin
|
51
52
|
if has_variables_path?
|
52
|
-
load_variables
|
53
|
+
load_variables
|
53
54
|
else
|
54
|
-
|
55
|
+
Variables.new(DEFAULT_VARIABLES_DATA.dup)
|
55
56
|
end
|
56
57
|
end
|
57
58
|
end
|
58
|
-
|
59
|
-
class ErbBindingContext
|
60
|
-
attr_reader :variables
|
61
|
-
|
62
|
-
# @param [hash] variables
|
63
|
-
def initialize(variables)
|
64
|
-
@variables = variables
|
65
|
-
end
|
66
|
-
|
67
|
-
# @note Change method visibility to public
|
68
|
-
def binding
|
69
|
-
super
|
70
|
-
end
|
71
|
-
end
|
72
59
|
end
|
73
60
|
end
|
74
61
|
end
|
data/lib/serverkit/variables.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "active_support/core_ext/hash/deep_merge"
|
2
|
+
require "hashie/mash"
|
2
3
|
|
3
4
|
module Serverkit
|
4
5
|
class Variables
|
@@ -23,9 +24,16 @@ module Serverkit
|
|
23
24
|
)
|
24
25
|
end
|
25
26
|
|
26
|
-
# @return [
|
27
|
-
def
|
28
|
-
@variables_data.dup
|
27
|
+
# @return [Hashie::Mash]
|
28
|
+
def to_mash
|
29
|
+
BindableMash.new(@variables_data.dup)
|
30
|
+
end
|
31
|
+
|
32
|
+
class BindableMash < Hashie::Mash
|
33
|
+
# @note Override visibility from private to public
|
34
|
+
def binding
|
35
|
+
super
|
36
|
+
end
|
29
37
|
end
|
30
38
|
end
|
31
39
|
end
|
data/lib/serverkit/version.rb
CHANGED
data/serverkit.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
|
19
19
|
spec.add_runtime_dependency "activemodel"
|
20
20
|
spec.add_runtime_dependency "activesupport"
|
21
|
+
spec.add_runtime_dependency "hashie"
|
21
22
|
spec.add_runtime_dependency "highline"
|
22
23
|
spec.add_runtime_dependency "slop", "~> 3.4"
|
23
24
|
spec.add_runtime_dependency "specinfra"
|
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.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: hashie
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: highline
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|