lightchef 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +11 -0
- data/Guardfile +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +78 -0
- data/Rakefile +1 -0
- data/Vagrantfile +23 -0
- data/bin/lightchef +5 -0
- data/example/foo +1 -0
- data/example/node.json +1 -0
- data/example/recipe.rb +11 -0
- data/lib/lightchef.rb +13 -0
- data/lib/lightchef/cli.rb +13 -0
- data/lib/lightchef/logger.rb +19 -0
- data/lib/lightchef/monkey_patch.rb +19 -0
- data/lib/lightchef/node.rb +13 -0
- data/lib/lightchef/recipe.rb +38 -0
- data/lib/lightchef/resources.rb +19 -0
- data/lib/lightchef/resources/base.rb +69 -0
- data/lib/lightchef/resources/file.rb +14 -0
- data/lib/lightchef/resources/package.rb +12 -0
- data/lib/lightchef/runner.rb +39 -0
- data/lib/lightchef/version.rb +3 -0
- data/lightchef.gemspec +29 -0
- data/spec/lib/lightchef/logger_spec.rb +20 -0
- data/spec/lib/lightchef/node_spec.rb +6 -0
- data/spec/lib/lightchef/recipe_spec.rb +6 -0
- data/spec/lib/lightchef/resources/base_spec.rb +76 -0
- data/spec/lib/lightchef/resources/file_spec.rb +20 -0
- data/spec/lib/lightchef/resources/package_spec.rb +18 -0
- data/spec/lib/lightchef/resources_spec.rb +14 -0
- data/spec/lib/lightchef/runner_spec.rb +36 -0
- data/spec/spec_helper.rb +22 -0
- metadata +201 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 70c83b10569b1824d0d30c7b0ad73ef313f23ec6
|
4
|
+
data.tar.gz: 40152fa9a00aee396f36c93e10cbed53b28a2910
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5ac149537d7a1d923994a87a78bff01c84139951ad10309f3d6b9a0ead6590627b84a9ead8372bd9ee0eb8926cfbdffc93eabf34ee5857961883e5e0f98db72a
|
7
|
+
data.tar.gz: 72be9a985c18e6efd7998fcd31219c74260fc482bb9dabf4e67f9611efacb3564ff085553d0885a4d7ca130dccd54df04e90ec26cd0356fa97975a924f88cb32
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
|
9
|
+
# Rails example
|
10
|
+
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
11
|
+
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
|
12
|
+
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
|
13
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
14
|
+
watch('config/routes.rb') { "spec/routing" }
|
15
|
+
watch('app/controllers/application_controller.rb') { "spec/controllers" }
|
16
|
+
|
17
|
+
# Capybara features specs
|
18
|
+
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
|
19
|
+
|
20
|
+
# Turnip features and steps
|
21
|
+
watch(%r{^spec/acceptance/(.+)\.feature$})
|
22
|
+
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
|
23
|
+
end
|
24
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Ryota Arai
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Lightchef [](https://travis-ci.org/ryotarai/lightchef)
|
2
|
+
|
3
|
+
Configuration management tool like Chef which is simpler and lighter than Chef
|
4
|
+
|
5
|
+
## Concept
|
6
|
+
|
7
|
+
* Lighter than Chef
|
8
|
+
* It's just like Chef. No compatibility.
|
9
|
+
* No idempotence
|
10
|
+
* DSL like Chef
|
11
|
+
* Without compilation
|
12
|
+
* All code in recipes will be executed when they are evaluated.
|
13
|
+
* To write recipes easier
|
14
|
+
* Use Ohai
|
15
|
+
* No role, environment and cookbook
|
16
|
+
|
17
|
+
### Examples of Recipes
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
resource "name" do
|
21
|
+
action :action
|
22
|
+
property "value"
|
23
|
+
end
|
24
|
+
```
|
25
|
+
|
26
|
+
### Usage
|
27
|
+
|
28
|
+
```
|
29
|
+
$ sudo lightchef execute -j example/node.json example/recipe.rb
|
30
|
+
D, [2013-12-24T14:05:50.859587 #7156] DEBUG -- : Loading node data from /vagrant/example/node.json ...
|
31
|
+
I, [2013-12-24T14:05:50.862072 #7156] INFO -- : >>> Executing Lightchef::Resources::Package ({:action=>:install, :name=>"git"})...
|
32
|
+
D, [2013-12-24T14:05:51.335070 #7156] DEBUG -- : Command `apt-get -y install git` succeeded
|
33
|
+
D, [2013-12-24T14:05:51.335251 #7156] DEBUG -- : STDOUT> Reading package lists...
|
34
|
+
Building dependency tree...
|
35
|
+
Reading state information...
|
36
|
+
git is already the newest version.
|
37
|
+
0 upgraded, 0 newly installed, 0 to remove and 156 not upgraded.
|
38
|
+
D, [2013-12-24T14:05:51.335464 #7156] DEBUG -- : STDERR>
|
39
|
+
I, [2013-12-24T14:05:51.335531 #7156] INFO -- : <<< Succeeded.
|
40
|
+
I, [2013-12-24T14:05:51.335728 #7156] INFO -- : >>> Executing Lightchef::Resources::File ({:action=>:create, :source=>"foo", :path=>"/home/vagrant/foo"})...
|
41
|
+
D, [2013-12-24T14:05:51.335842 #7156] DEBUG -- : Copying a file from '/vagrant/example/foo' to '/home/vagrant/foo'...
|
42
|
+
I, [2013-12-24T14:05:51.339119 #7156] INFO -- : <<< Succeeded.
|
43
|
+
```
|
44
|
+
|
45
|
+
### TODO
|
46
|
+
|
47
|
+
* `notifies`, `subscribes`
|
48
|
+
|
49
|
+
### Future release
|
50
|
+
|
51
|
+
* Run via SSH too (thanks to specinfra)
|
52
|
+
* Create system info collector instead of Ohai, Facter (They can't execute via SSH)
|
53
|
+
|
54
|
+
## Installation
|
55
|
+
|
56
|
+
Add this line to your application's Gemfile:
|
57
|
+
|
58
|
+
gem 'lightchef'
|
59
|
+
|
60
|
+
And then execute:
|
61
|
+
|
62
|
+
$ bundle
|
63
|
+
|
64
|
+
Or install it yourself as:
|
65
|
+
|
66
|
+
$ gem install lightchef
|
67
|
+
|
68
|
+
## Usage
|
69
|
+
|
70
|
+
TODO: Write usage instructions here
|
71
|
+
|
72
|
+
## Contributing
|
73
|
+
|
74
|
+
1. Fork it
|
75
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
76
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
77
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
78
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/Vagrantfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
|
5
|
+
VAGRANTFILE_API_VERSION = "2"
|
6
|
+
|
7
|
+
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
8
|
+
config.vm.box = "ubuntu/trusty64"
|
9
|
+
|
10
|
+
config.vm.provision :shell, inline: <<-EOC
|
11
|
+
cat /etc/apt/sources.list | sed -e 's|http://[^ ]*|mirror://mirrors.ubuntu.com/mirrors.txt|g' > /tmp/sources.list
|
12
|
+
if !(diff -q /etc/apt/sources.list /tmp/sources.list); then
|
13
|
+
mv /tmp/sources.list /etc/apt/sources.list
|
14
|
+
apt-get update
|
15
|
+
fi
|
16
|
+
|
17
|
+
apt-get -y install ruby2.0 ruby2.0-dev git
|
18
|
+
(gem2.0 list | grep -q 'bundler ') || gem2.0 install bundler
|
19
|
+
cd /vagrant
|
20
|
+
sudo -u vagrant bundle install
|
21
|
+
bundle exec bin/lightchef execute -j example/node.json example/recipe.rb
|
22
|
+
EOC
|
23
|
+
end
|
data/bin/lightchef
ADDED
data/example/foo
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Hello
|
data/example/node.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"file_source": "foo"}
|
data/example/recipe.rb
ADDED
data/lib/lightchef.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "lightchef/version"
|
2
|
+
require "lightchef/runner"
|
3
|
+
require "lightchef/cli"
|
4
|
+
require "lightchef/recipe"
|
5
|
+
require "lightchef/resources"
|
6
|
+
require "lightchef/monkey_patch"
|
7
|
+
require "lightchef/logger"
|
8
|
+
require "lightchef/node"
|
9
|
+
|
10
|
+
module Lightchef
|
11
|
+
# Your code goes here...
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
module Lightchef
|
5
|
+
module Logger
|
6
|
+
def self.logger
|
7
|
+
@logger ||= ::Logger.new($stdout)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.logger=(l)
|
11
|
+
@logger = l
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.method_missing(method, *args, &block)
|
15
|
+
logger.public_send(method, *args, &block)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'net/scp'
|
2
|
+
|
3
|
+
module SpecInfra
|
4
|
+
module Backend
|
5
|
+
class Exec
|
6
|
+
def copy_file(src, dst)
|
7
|
+
FileUtils.cp(src, dst)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Ssh
|
12
|
+
def copy_file(src, dst)
|
13
|
+
scp = Net::SCP.new(SpecInfra.configuration.ssh)
|
14
|
+
scp.upload!(src, dst)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
|
3
|
+
module Lightchef
|
4
|
+
class Recipe
|
5
|
+
attr_reader :path
|
6
|
+
attr_reader :backend
|
7
|
+
attr_reader :current_runner
|
8
|
+
|
9
|
+
def initialize(path)
|
10
|
+
@path = path
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(runner)
|
14
|
+
@current_runner = runner
|
15
|
+
instance_eval(File.read(@path), @path, 1)
|
16
|
+
@current_runner = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def node
|
20
|
+
@current_runner.node
|
21
|
+
end
|
22
|
+
|
23
|
+
def method_missing(method, name = nil, &block)
|
24
|
+
cls = Resources.get_resource_class(method)
|
25
|
+
resource = cls.new(self, name, &block)
|
26
|
+
Logger.info ">>> Executing #{resource.class.name} (#{resource.options})..."
|
27
|
+
begin
|
28
|
+
resource.run
|
29
|
+
rescue Resources::CommandExecutionError
|
30
|
+
Logger.error "<<< Failed."
|
31
|
+
exit 2
|
32
|
+
else
|
33
|
+
Logger.info "<<< Succeeded."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
require 'lightchef/resources/base'
|
3
|
+
require 'lightchef/resources/package'
|
4
|
+
require 'lightchef/resources/file'
|
5
|
+
|
6
|
+
module Lightchef
|
7
|
+
module Resources
|
8
|
+
Error = Class.new(StandardError)
|
9
|
+
CommandExecutionError = Class.new(StandardError)
|
10
|
+
|
11
|
+
def self.get_resource_class_name(method)
|
12
|
+
method.to_s.split('_').map {|part| part.capitalize}.join
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.get_resource_class(method)
|
16
|
+
const_get(get_resource_class_name(method))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
|
3
|
+
module Lightchef
|
4
|
+
module Resources
|
5
|
+
class Base
|
6
|
+
attr_reader :options
|
7
|
+
|
8
|
+
def initialize(recipe, name, &block)
|
9
|
+
@options = {}
|
10
|
+
@recipe = recipe
|
11
|
+
instance_eval(&block) if block_given?
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
action = fetch_option(:action)
|
16
|
+
public_send("#{action}_action".to_sym)
|
17
|
+
end
|
18
|
+
|
19
|
+
def fetch_option(key)
|
20
|
+
@options.fetch(key) do |k|
|
21
|
+
raise Error, "#{k} is not specified."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method, *args)
|
26
|
+
if args.size == 1
|
27
|
+
@options[method] = args.first
|
28
|
+
return
|
29
|
+
end
|
30
|
+
super
|
31
|
+
end
|
32
|
+
|
33
|
+
def run_command(type, *args)
|
34
|
+
command = backend.commands.public_send(type, *args)
|
35
|
+
result = backend.run_command(command)
|
36
|
+
exit_status = result[:exit_status]
|
37
|
+
if exit_status == 0
|
38
|
+
Logger.debug "Command `#{command}` succeeded"
|
39
|
+
Logger.debug "STDOUT> #{(result[:stdout] || "").chomp}"
|
40
|
+
Logger.debug "STDERR> #{(result[:stderr] || "").chomp}"
|
41
|
+
else
|
42
|
+
Logger.error "Command `#{command}` failed. (exit status: #{exit_status})"
|
43
|
+
Logger.error "STDOUT> #{(result[:stdout] || "").chomp}"
|
44
|
+
Logger.error "STDERR> #{(result[:stderr] || "").chomp}"
|
45
|
+
raise CommandExecutionError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def copy_file(src, dst)
|
50
|
+
Logger.debug "Copying a file from '#{src}' to '#{dst}'..."
|
51
|
+
backend.copy_file(src, dst)
|
52
|
+
end
|
53
|
+
|
54
|
+
def node
|
55
|
+
current_runner.node
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
def backend
|
60
|
+
current_runner.backend
|
61
|
+
end
|
62
|
+
|
63
|
+
def current_runner
|
64
|
+
@recipe.current_runner
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
|
3
|
+
module Lightchef
|
4
|
+
module Resources
|
5
|
+
class File < Base
|
6
|
+
def create_action
|
7
|
+
src = ::File.expand_path(fetch_option(:source), ::File.dirname(@recipe.path))
|
8
|
+
dst = fetch_option(:path)
|
9
|
+
copy_file(src, dst)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
require 'specinfra'
|
3
|
+
|
4
|
+
module Lightchef
|
5
|
+
class Runner
|
6
|
+
extend SpecInfra::Helper::Backend
|
7
|
+
extend SpecInfra::Helper::DetectOS
|
8
|
+
|
9
|
+
def self.new_from_options(options)
|
10
|
+
self.new(backend_for(:exec)).tap do |runner|
|
11
|
+
node = if options[:node_json]
|
12
|
+
node_json_path = File.expand_path(options[:node_json])
|
13
|
+
Logger.debug "Loading node data from #{node_json_path} ..."
|
14
|
+
Node.new_from_file(node_json_path)
|
15
|
+
else
|
16
|
+
Node.new
|
17
|
+
end
|
18
|
+
runner.node = node
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.run(recipe_files, options={})
|
23
|
+
runner = new_from_options(options)
|
24
|
+
|
25
|
+
recipe_files.each do |path|
|
26
|
+
recipe = Recipe.new(File.expand_path(path))
|
27
|
+
recipe.run(runner)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_accessor :backend
|
32
|
+
attr_accessor :node
|
33
|
+
|
34
|
+
def initialize(backend)
|
35
|
+
@backend = backend
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
data/lightchef.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'lightchef/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "lightchef"
|
8
|
+
spec.version = Lightchef::VERSION
|
9
|
+
spec.authors = ["Ryota Arai"]
|
10
|
+
spec.email = ["ryota.arai@gmail.com"]
|
11
|
+
spec.summary = %q{Simple Configuration Management Tool}
|
12
|
+
spec.homepage = "https://github.com/ryotarai/lightchef"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_runtime_dependency "thor"
|
21
|
+
spec.add_runtime_dependency "specinfra"
|
22
|
+
spec.add_runtime_dependency "net-scp"
|
23
|
+
spec.add_runtime_dependency "hashie"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "rspec"
|
28
|
+
spec.add_development_dependency "guard-rspec"
|
29
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Lightchef
|
4
|
+
describe Logger do
|
5
|
+
let(:io) { StringIO.new }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Logger.logger = ::Logger.new(io)
|
9
|
+
end
|
10
|
+
|
11
|
+
[:fatal, :error, :warn, :info, :debug].each do |level|
|
12
|
+
describe "##{level}" do
|
13
|
+
it "puts #{level} log" do
|
14
|
+
Logger.public_send(level, "CONTENT")
|
15
|
+
expect(io.string).to include('CONTENT')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
|
3
|
+
module Lightchef
|
4
|
+
describe Resources::Base do
|
5
|
+
let(:commands) { double(:commands) }
|
6
|
+
let(:backend) do
|
7
|
+
double(:backend).tap do |b|
|
8
|
+
b.stub(:commands).and_return(commands)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
let(:runner) do
|
12
|
+
double(:runner).tap do |b|
|
13
|
+
b.stub(:backend).and_return(backend)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
let(:recipe) do
|
17
|
+
double(:recipe).tap do |r|
|
18
|
+
r.stub(:current_runner).and_return(runner)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
subject(:resource) { described_class.new(recipe, "name") }
|
22
|
+
|
23
|
+
describe "#run" do
|
24
|
+
before do
|
25
|
+
subject.action :action_name
|
26
|
+
end
|
27
|
+
it "executes <ACTION_NAME>_action method" do
|
28
|
+
expect(subject).to receive(:action_name_action)
|
29
|
+
subject.run
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#fetch_option" do
|
34
|
+
context "when the option for the key exists" do
|
35
|
+
before do
|
36
|
+
subject.option_key :option_value
|
37
|
+
end
|
38
|
+
it "returns the value" do
|
39
|
+
expect(subject.fetch_option(:option_key)).
|
40
|
+
to eq(:option_value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
context "when the option for the key doesn't exist" do
|
44
|
+
it "raises Resources::Error" do
|
45
|
+
expect do
|
46
|
+
subject.fetch_option(:invalid_option_key)
|
47
|
+
end.to raise_error(Resources::Error)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#run_command" do
|
53
|
+
it "runs specinfra's command by specinfra's backend" do
|
54
|
+
expect(commands).to receive(:cmd).and_return("command")
|
55
|
+
expect(backend).to receive(:run_command).with("command").and_return({exit_status: 0})
|
56
|
+
subject.run_command(:cmd)
|
57
|
+
end
|
58
|
+
context "when the command execution failed" do
|
59
|
+
it "raises CommandExecutionError" do
|
60
|
+
expect(commands).to receive(:cmd).and_return("command")
|
61
|
+
expect(backend).to receive(:run_command).with("command").and_return({exit_status: 1})
|
62
|
+
expect do
|
63
|
+
subject.run_command(:cmd)
|
64
|
+
end.to raise_error(Resources::CommandExecutionError)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "#copy_file" do
|
70
|
+
it "copies a file, using the backend" do
|
71
|
+
expect(backend).to receive(:copy_file).with(:src, :dst)
|
72
|
+
subject.copy_file(:src, :dst)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
|
3
|
+
module Lightchef
|
4
|
+
describe Resources::File do
|
5
|
+
let(:recipe) { double(:recipe) }
|
6
|
+
subject(:resource) { described_class.new(recipe, "name") }
|
7
|
+
|
8
|
+
describe "#create_action" do
|
9
|
+
it "copies a file" do
|
10
|
+
recipe.stub(:path).and_return("/recipe_dir/recipe_file")
|
11
|
+
subject.source "source.file"
|
12
|
+
subject.path "/path/to/dst"
|
13
|
+
expect(subject).to receive(:copy_file).with("/recipe_dir/source.file", "/path/to/dst")
|
14
|
+
subject.create_action
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
|
3
|
+
module Lightchef
|
4
|
+
describe Resources::Package do
|
5
|
+
let(:recipe) { double(:recipe) }
|
6
|
+
subject(:resource) { described_class.new(recipe, "name") }
|
7
|
+
|
8
|
+
describe "#install_action" do
|
9
|
+
it "runs install command of specinfra" do
|
10
|
+
subject.name :package_name
|
11
|
+
expect(subject).to receive(:run_command).with(:install, :package_name)
|
12
|
+
subject.install_action
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Lightchef
|
4
|
+
describe Resources do
|
5
|
+
describe "#get_resource_class_name" do
|
6
|
+
let(:method) { :foo_bar_baz }
|
7
|
+
it "returns camel-cased string" do
|
8
|
+
expect(described_class.get_resource_class_name(method)).
|
9
|
+
to eq("FooBarBaz")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
module Lightchef
|
5
|
+
describe Runner do
|
6
|
+
around do |example|
|
7
|
+
Dir.mktmpdir do |dir|
|
8
|
+
Dir.chdir(dir) do
|
9
|
+
example.run
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ".new_from_options" do
|
15
|
+
before do
|
16
|
+
open('./node.json', 'w') {|f| f.write '{"foo": "bar"}' }
|
17
|
+
end
|
18
|
+
it "returns Runner" do
|
19
|
+
runner = described_class.new_from_options(node_json: "./node.json")
|
20
|
+
expect(runner.node['foo']).to eq 'bar'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe ".run" do
|
25
|
+
let(:recipes) { %w! ./recipe1.rb ./recipe2.rb ! }
|
26
|
+
it "runs each recipe with the runner" do
|
27
|
+
recipes.each do |r|
|
28
|
+
recipe = double(:recipe)
|
29
|
+
Recipe.stub(:new).with(File.expand_path(r)).and_return(recipe)
|
30
|
+
expect(recipe).to receive(:run)
|
31
|
+
end
|
32
|
+
described_class.run(recipes)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'lightchef'
|
2
|
+
|
3
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
4
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
5
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
6
|
+
# loaded once.
|
7
|
+
#
|
8
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run :focus
|
13
|
+
|
14
|
+
# Run specs in random order to surface order dependencies. If you find an
|
15
|
+
# order dependency and want to debug it, you can fix the order by providing
|
16
|
+
# the seed, which is printed after each run.
|
17
|
+
# --seed 1234
|
18
|
+
config.order = 'random'
|
19
|
+
end
|
20
|
+
|
21
|
+
Lightchef::Logger.logger = ::Logger.new(StringIO.new)
|
22
|
+
|
metadata
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lightchef
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryota Arai
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
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'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: specinfra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: net-scp
|
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'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hashie
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.3'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: guard-rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
- ryota.arai@gmail.com
|
128
|
+
executables:
|
129
|
+
- lightchef
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".gitignore"
|
134
|
+
- ".rspec"
|
135
|
+
- ".travis.yml"
|
136
|
+
- Gemfile
|
137
|
+
- Guardfile
|
138
|
+
- LICENSE.txt
|
139
|
+
- README.md
|
140
|
+
- Rakefile
|
141
|
+
- Vagrantfile
|
142
|
+
- bin/lightchef
|
143
|
+
- example/foo
|
144
|
+
- example/node.json
|
145
|
+
- example/recipe.rb
|
146
|
+
- lib/lightchef.rb
|
147
|
+
- lib/lightchef/cli.rb
|
148
|
+
- lib/lightchef/logger.rb
|
149
|
+
- lib/lightchef/monkey_patch.rb
|
150
|
+
- lib/lightchef/node.rb
|
151
|
+
- lib/lightchef/recipe.rb
|
152
|
+
- lib/lightchef/resources.rb
|
153
|
+
- lib/lightchef/resources/base.rb
|
154
|
+
- lib/lightchef/resources/file.rb
|
155
|
+
- lib/lightchef/resources/package.rb
|
156
|
+
- lib/lightchef/runner.rb
|
157
|
+
- lib/lightchef/version.rb
|
158
|
+
- lightchef.gemspec
|
159
|
+
- spec/lib/lightchef/logger_spec.rb
|
160
|
+
- spec/lib/lightchef/node_spec.rb
|
161
|
+
- spec/lib/lightchef/recipe_spec.rb
|
162
|
+
- spec/lib/lightchef/resources/base_spec.rb
|
163
|
+
- spec/lib/lightchef/resources/file_spec.rb
|
164
|
+
- spec/lib/lightchef/resources/package_spec.rb
|
165
|
+
- spec/lib/lightchef/resources_spec.rb
|
166
|
+
- spec/lib/lightchef/runner_spec.rb
|
167
|
+
- spec/spec_helper.rb
|
168
|
+
homepage: https://github.com/ryotarai/lightchef
|
169
|
+
licenses:
|
170
|
+
- MIT
|
171
|
+
metadata: {}
|
172
|
+
post_install_message:
|
173
|
+
rdoc_options: []
|
174
|
+
require_paths:
|
175
|
+
- lib
|
176
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
requirements: []
|
187
|
+
rubyforge_project:
|
188
|
+
rubygems_version: 2.2.2
|
189
|
+
signing_key:
|
190
|
+
specification_version: 4
|
191
|
+
summary: Simple Configuration Management Tool
|
192
|
+
test_files:
|
193
|
+
- spec/lib/lightchef/logger_spec.rb
|
194
|
+
- spec/lib/lightchef/node_spec.rb
|
195
|
+
- spec/lib/lightchef/recipe_spec.rb
|
196
|
+
- spec/lib/lightchef/resources/base_spec.rb
|
197
|
+
- spec/lib/lightchef/resources/file_spec.rb
|
198
|
+
- spec/lib/lightchef/resources/package_spec.rb
|
199
|
+
- spec/lib/lightchef/resources_spec.rb
|
200
|
+
- spec/lib/lightchef/runner_spec.rb
|
201
|
+
- spec/spec_helper.rb
|