niman 0.0.1 → 0.0.3
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 +4 -4
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/.travis.yml +10 -0
- data/Gemfile +8 -0
- data/README.md +56 -2
- data/bin/niman +4 -0
- data/lib/niman/cli/application.rb +48 -0
- data/lib/niman/exceptions.rb +10 -0
- data/lib/niman/installer.rb +18 -0
- data/lib/niman/library/file.rb +24 -0
- data/lib/niman/library/package.rb +18 -0
- data/lib/niman/nimanfile.rb +23 -0
- data/lib/niman/platform.rb +43 -0
- data/lib/niman/provisioner.rb +28 -0
- data/lib/niman/recipe.rb +28 -0
- data/lib/niman/shell.rb +27 -0
- data/lib/niman/vagrant/plugin.rb +10 -0
- data/lib/niman/vagrant/provisioner.rb +24 -0
- data/lib/niman/vagrant/shell.rb +46 -0
- data/lib/niman/version.rb +1 -1
- data/lib/niman.rb +5 -1
- data/niman.gemspec +4 -0
- data/spec/lib/installer_spec.rb +58 -0
- data/spec/lib/library/file_spec.rb +77 -0
- data/spec/lib/library/package_spec.rb +35 -0
- data/spec/lib/nimanfile_spec.rb +40 -0
- data/spec/lib/provisioner_spec.rb +68 -0
- data/spec/lib/recipe_spec.rb +59 -0
- data/spec/spec_helper.rb +89 -0
- metadata +91 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f4b4fbde2c69d5428cdeef5956a0781eded47766
|
4
|
+
data.tar.gz: cc99ba94749c533e2d0a953695a4b03ec0aec32e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25581ac834d6daa7134e5ecf6708a22bd5e7e7bc74568325fd3389bafa7f2e9b7d3079115beed68848f69222933c7da194c70903360a24fae1909595e872c0ea
|
7
|
+
data.tar.gz: a98b0c0aa0417876e61c269aa8c203181ea74ae28194a397f6c79593c0d3ff39bf27af2152d170baf9be62378695e01c394ca538fa92211824abd276da2bc7fc
|
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Niman
|
2
2
|
|
3
|
-
|
3
|
+
Niman is a proof-of-concept provisioner.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -20,7 +20,61 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
It starts with a `Nimanfile`:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
Niman::Recipe.configure do |config|
|
27
|
+
config.file do |file|
|
28
|
+
file.path = '/home/bob/hello.txt'
|
29
|
+
file.content = 'hello from alice'
|
30
|
+
file.mode = '0600'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
```
|
34
|
+
This places a new file `hello.txt` in `/home/bob` with rights 0600.
|
35
|
+
|
36
|
+
A `Nimanfile` contains all necessary commands for `niman` to run.
|
37
|
+
|
38
|
+
### Packages
|
39
|
+
|
40
|
+
Use a concrete package in your script:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
Niman::Recipe.configure do |config|
|
44
|
+
config.package do |package|
|
45
|
+
package.name = "vim"
|
46
|
+
package.version = "7.4"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
50
|
+
|
51
|
+
Custom packages live in `packages/`. Every package gets its own file.
|
52
|
+
Package description:
|
53
|
+
```ruby
|
54
|
+
#packages/ruby.rb
|
55
|
+
require 'niman'
|
56
|
+
class RubyPackage < Niman::Package
|
57
|
+
package :ubuntu, "ruby1.9.1"
|
58
|
+
package :centos, "ruby1.9.1"
|
59
|
+
end
|
60
|
+
```
|
61
|
+
In your `Nimanfile`:
|
62
|
+
```ruby
|
63
|
+
Niman::Recipe.configure do |config|
|
64
|
+
config.package do |package|
|
65
|
+
package.name "ruby"
|
66
|
+
package.path = "packages/ruby"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
### Apply `Nimanfile`
|
72
|
+
|
73
|
+
To apply a `Nimanfile` run:
|
74
|
+
|
75
|
+
```bash
|
76
|
+
$ niman apply
|
77
|
+
```
|
24
78
|
|
25
79
|
## Contributing
|
26
80
|
|
data/bin/niman
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'niman/recipe'
|
3
|
+
require 'niman/provisioner'
|
4
|
+
require "niman/shell"
|
5
|
+
require "niman/installer"
|
6
|
+
|
7
|
+
module Niman
|
8
|
+
module CLI
|
9
|
+
class Application < Thor
|
10
|
+
attr_accessor :client_shell, :silent
|
11
|
+
|
12
|
+
def initialize(*args)
|
13
|
+
super
|
14
|
+
@client_shell= Niman::Shell.new
|
15
|
+
@silent = false
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "apply", "Applies a Nimanfile"
|
19
|
+
def apply
|
20
|
+
Niman::Recipe.from_file
|
21
|
+
config = Niman::Recipe.configuration
|
22
|
+
installer = Niman::Installer.new(shell: client_shell, managers:{
|
23
|
+
debian: 'apt-get -y',
|
24
|
+
redhat: 'yum -y'
|
25
|
+
})
|
26
|
+
provisioner = Niman::Provisioner.new(installer, config.instructions)
|
27
|
+
this = self
|
28
|
+
provisioner.run do |instruction|
|
29
|
+
this.say "Executing task #{instruction.description}" unless @quiet
|
30
|
+
end
|
31
|
+
rescue LoadError => e
|
32
|
+
error e.message
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "setup", "Generates an empty Nimanfile"
|
36
|
+
def setup
|
37
|
+
content = <<-EOS
|
38
|
+
# -*- mode: ruby -*-
|
39
|
+
# vi: set ft=ruby :
|
40
|
+
Niman::Recipe.configure do |config|
|
41
|
+
end
|
42
|
+
EOS
|
43
|
+
File.open(Niman::Recipe::DEFAULT_FILENAME, "w") { |handle| handle.write(content) }
|
44
|
+
say "Created new file #{Niman::Recipe::DEFAULT_FILENAME}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
require 'niman/exceptions'
|
3
|
+
|
4
|
+
module Niman
|
5
|
+
class Installer
|
6
|
+
include Virtus.model
|
7
|
+
|
8
|
+
attribute :managers, Hash[Symbol=>String], default: Hash.new
|
9
|
+
attribute :shell, Object
|
10
|
+
|
11
|
+
def install(packages)
|
12
|
+
package_manager = managers.fetch(shell.os.to_sym) { raise Niman::InstallError, shell.os }
|
13
|
+
Array(packages).each do |package|
|
14
|
+
shell.exec("#{package_manager} install #{package.name}", true)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
|
3
|
+
module Niman
|
4
|
+
module Library
|
5
|
+
class File
|
6
|
+
include Virtus.model
|
7
|
+
|
8
|
+
attribute :path, String, default: ''
|
9
|
+
attribute :content, String, default: ''
|
10
|
+
|
11
|
+
def valid?
|
12
|
+
!self.path.nil? && !self.path.empty?
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
::File.open(::File.expand_path(path), "w") { |handle| handle.write(content) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def description
|
20
|
+
"File #{path}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Niman
|
2
|
+
module Library
|
3
|
+
class Package
|
4
|
+
include Virtus.model
|
5
|
+
|
6
|
+
attribute :name, String, default: ""
|
7
|
+
attribute :version, String, default: ""
|
8
|
+
|
9
|
+
def description
|
10
|
+
name
|
11
|
+
end
|
12
|
+
|
13
|
+
def valid?
|
14
|
+
!name.empty?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'niman/library/file'
|
2
|
+
|
3
|
+
module Niman
|
4
|
+
class Nimanfile
|
5
|
+
attr_reader :instructions
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@instructions = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def file
|
12
|
+
f = Niman::Library::File.new
|
13
|
+
yield(f)
|
14
|
+
@instructions.push(f)
|
15
|
+
end
|
16
|
+
|
17
|
+
def package
|
18
|
+
package = Niman::Library::Package.new
|
19
|
+
yield(package)
|
20
|
+
@instructions.push(package)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Niman
|
2
|
+
class Platform
|
3
|
+
def initialize(platform)
|
4
|
+
@platform = platform
|
5
|
+
end
|
6
|
+
|
7
|
+
def windows?
|
8
|
+
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ @platform) != nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def mac?
|
12
|
+
(/darwin/ =~ @platform) != nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def unix?
|
16
|
+
!windows?
|
17
|
+
end
|
18
|
+
|
19
|
+
def linux?
|
20
|
+
unix? && !mac?
|
21
|
+
end
|
22
|
+
|
23
|
+
def linux_variant(exists_block, read_block)
|
24
|
+
variant = { :distro => nil, :family => nil }
|
25
|
+
|
26
|
+
if exists_block.('/etc/lsb-release')
|
27
|
+
lsb_release = read_block.('/etc/lsb-release')
|
28
|
+
variant = { :distro => $1 } if lsb_release =~ /^DISTRIB_ID=(.*)/
|
29
|
+
end
|
30
|
+
|
31
|
+
if exists_block.('/etc/debian_version')
|
32
|
+
variant[:distro] = :debian if variant[:distro].nil?
|
33
|
+
variant[:family] = :debian if variant[:variant].nil?
|
34
|
+
elsif exists_block.('/etc/redhat-release') or exists_block.('/etc/centos-release')
|
35
|
+
variant[:family] = :redhat if variant[:family].nil?
|
36
|
+
variant[:distro] = :centos if exists_block.('/etc/centos-release')
|
37
|
+
elsif exists_block.('/etc/SuSE-release')
|
38
|
+
variant[:distro] = :sles if variant[:distro].nil?
|
39
|
+
end
|
40
|
+
variant
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'niman/exceptions'
|
2
|
+
|
3
|
+
module Niman
|
4
|
+
class Provisioner
|
5
|
+
attr_reader :instructions
|
6
|
+
|
7
|
+
def initialize(installer, instructions)
|
8
|
+
@installer = installer
|
9
|
+
@instructions = Array(instructions)
|
10
|
+
end
|
11
|
+
|
12
|
+
def valid?
|
13
|
+
@instructions.all?(&:valid?)
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
raise Niman::ConfigError unless self.valid?
|
18
|
+
@instructions.each do |instruction|
|
19
|
+
yield(instruction) if block_given?
|
20
|
+
if instruction.respond_to?(:run)
|
21
|
+
instruction.run
|
22
|
+
else
|
23
|
+
@installer.install(instruction)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/niman/recipe.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'niman/nimanfile'
|
2
|
+
|
3
|
+
module Niman
|
4
|
+
class Recipe
|
5
|
+
DEFAULT_FILENAME = 'Nimanfile'
|
6
|
+
class << self
|
7
|
+
attr_writer :configuration
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.configure
|
11
|
+
@configuration ||= Niman::Nimanfile.new
|
12
|
+
yield(@configuration)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configuration
|
16
|
+
@configuration
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.reset!
|
20
|
+
@configuration = Niman::Nimanfile.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.from_file
|
24
|
+
path = File.join(Dir.pwd, DEFAULT_FILENAME)
|
25
|
+
load DEFAULT_FILENAME
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/niman/shell.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'niman/platform'
|
2
|
+
|
3
|
+
module Niman
|
4
|
+
class Shell
|
5
|
+
def initialize
|
6
|
+
@platform = Niman::Platform.new(RUBY_PLATFORM)
|
7
|
+
end
|
8
|
+
|
9
|
+
def os
|
10
|
+
if @platform.linux?
|
11
|
+
variant = @platform.linux_variant(-> (fn){ File.exists?(fn)},
|
12
|
+
-> (fn){ File.read(fn)})
|
13
|
+
variant[:family]
|
14
|
+
else
|
15
|
+
raise Niman::UnsupportedOSError
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def exec(command, use_sudo=false)
|
20
|
+
if use_sudo
|
21
|
+
`sudo #{command}`
|
22
|
+
else
|
23
|
+
`#{command}`
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "vagrant/util/retryable"
|
2
|
+
require 'niman/vagrant/shell'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
class Provisioner < Vagrant.plugin("2", :provisioner)
|
6
|
+
include Vagrant::Util::Retryable
|
7
|
+
def configure(root_config)
|
8
|
+
end
|
9
|
+
|
10
|
+
def provision
|
11
|
+
require 'niman'
|
12
|
+
@machine.communicate.tap do |comm|
|
13
|
+
vagrant_shell = VagrantPlugins::RemoteShell.new(comm, @machine)
|
14
|
+
app = Niman::CLI::Application.new
|
15
|
+
app.client_shell = vagrant_shell
|
16
|
+
app.silent = true
|
17
|
+
app.apply
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def cleanup
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
class RemoteShell
|
3
|
+
def initialize(communication, machine)
|
4
|
+
@channel = communication
|
5
|
+
@machine = machine
|
6
|
+
@platform = Niman::Platform.new(ruby_platform)
|
7
|
+
end
|
8
|
+
|
9
|
+
def os
|
10
|
+
if @platform.linux?
|
11
|
+
variant = @platform.linux_variant(-> (fn){ @machine.communicate.test("cat #{fn}")},
|
12
|
+
-> (fn){ @channel.execute("cat #{fn}") do |type, data|
|
13
|
+
data.chomp
|
14
|
+
end})
|
15
|
+
variant[:family]
|
16
|
+
else
|
17
|
+
raise Niman::UnsupportedOSError
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def exec(command, use_sudo=false)
|
22
|
+
@machine.ui.info(command, {color: :green})
|
23
|
+
opts = { error_check: false, elevated: true }
|
24
|
+
@channel.sudo(command, opts) do |type, data|
|
25
|
+
if [:stderr, :stdout].include?(type)
|
26
|
+
#Output the data with the proper color based on the stream.
|
27
|
+
color = type == :stdout ? :green : :red
|
28
|
+
# Clear out the newline since we add one
|
29
|
+
data = data.chomp
|
30
|
+
next if data.empty?
|
31
|
+
options = {}
|
32
|
+
options[:color] = :green
|
33
|
+
@machine.ui.info(data.chomp, options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def ruby_platform
|
41
|
+
@channel.execute("ruby -e 'puts RUBY_PLATFORM'") do |type, data|
|
42
|
+
return data.chomp
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/niman/version.rb
CHANGED
data/lib/niman.rb
CHANGED
data/niman.gemspec
CHANGED
@@ -17,6 +17,10 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
+
spec.add_dependency 'thor', '~> 0.19'
|
21
|
+
spec.add_dependency "virtus", "~> 1.0.4"
|
22
|
+
spec.add_development_dependency "fakefs", "~> 0.5"
|
23
|
+
spec.add_development_dependency "rspec", "3.1"
|
20
24
|
spec.add_development_dependency "bundler", "~> 1.7"
|
21
25
|
spec.add_development_dependency "rake", "~> 10.0"
|
22
26
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'niman/installer'
|
3
|
+
|
4
|
+
describe Niman::Installer do
|
5
|
+
describe '#initialize' do
|
6
|
+
it 'accepts a hash of package managers' do
|
7
|
+
managers = {
|
8
|
+
ubuntu: 'apt-get',
|
9
|
+
centos: 'yum'
|
10
|
+
}
|
11
|
+
installer = Niman::Installer.new(managers: managers)
|
12
|
+
expect(installer.managers).to eq managers
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'accepts a shell' do
|
16
|
+
shell = double()
|
17
|
+
installer = Niman::Installer.new(shell: shell)
|
18
|
+
expect(installer.shell).to eq shell
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#managers" do
|
23
|
+
it 'defaults to empty hash' do
|
24
|
+
installer = Niman::Installer.new
|
25
|
+
expect(installer.managers).to eq Hash.new
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#install" do
|
30
|
+
let(:shell) { double() }
|
31
|
+
subject(:installer) { Niman::Installer.new(managers: {
|
32
|
+
debian: 'apt-get',
|
33
|
+
redhat: 'yum'
|
34
|
+
}, shell: shell)}
|
35
|
+
let(:vim_package) { Niman::Library::Package.new(name: 'vim') }
|
36
|
+
let(:ssh_package) { Niman::Library::Package.new(name: 'ssh') }
|
37
|
+
let(:packages) { [vim_package, ssh_package] }
|
38
|
+
|
39
|
+
context 'with valid operating system' do
|
40
|
+
before do
|
41
|
+
allow(shell).to receive(:os).and_return(:debian)
|
42
|
+
allow(shell).to receive(:exec)
|
43
|
+
installer.install(packages)
|
44
|
+
end
|
45
|
+
|
46
|
+
['vim', 'ssh'].each do |package|
|
47
|
+
it "calls shell for #{package}" do
|
48
|
+
expect(shell).to have_received(:exec).with("apt-get install #{package}", true)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'raises for unknown operating system' do
|
54
|
+
allow(shell).to receive(:os).and_return(:freebsd)
|
55
|
+
expect { installer.install(packages) }.to raise_error(Niman::InstallError)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'niman/library/file'
|
3
|
+
require 'fakefs'
|
4
|
+
|
5
|
+
describe Niman::Library::File do
|
6
|
+
subject(:file) { Niman::Library::File.new }
|
7
|
+
[:path, :content].each do |attribute|
|
8
|
+
it "responds to #{attribute}" do
|
9
|
+
expect(file.respond_to?(attribute)).to be true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#initialize' do
|
14
|
+
it 'accepts path' do
|
15
|
+
f = Niman::Library::File.new(path: '/foo/bar')
|
16
|
+
expect(f.path).to eq '/foo/bar'
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'accepts content' do
|
20
|
+
f = Niman::Library::File.new(content: 'Alice likes Bob')
|
21
|
+
expect(f.content).to eq 'Alice likes Bob'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#content' do
|
26
|
+
it 'defaults to empty string' do
|
27
|
+
expect(file.content).to eq ''
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#path' do
|
32
|
+
it 'defaults to empty string' do
|
33
|
+
expect(file.path).to eq ''
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#valid?" do
|
38
|
+
specify 'if it has path' do
|
39
|
+
file.path = '/foo/bar'
|
40
|
+
expect(file.valid?).to be true
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'is not valid when path is empty' do
|
44
|
+
expect(file.valid?).to be false
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'is not valid when path is nil' do
|
48
|
+
file.path = nil
|
49
|
+
expect(file.valid?).to be false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#run" do
|
54
|
+
let(:path) { 'hello.txt' }
|
55
|
+
let(:content) { 'FooBar' }
|
56
|
+
subject(:file) { Niman::Library::File.new(path: path, content: content) }
|
57
|
+
before do
|
58
|
+
file.run
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'creates a file at path' do
|
62
|
+
expect(File.exists?(path)).to be true
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'file has expected content' do
|
66
|
+
expect(File.read(path)).to eq content
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#description" do
|
71
|
+
let(:path) { 'hello.txt' }
|
72
|
+
subject(:file) { Niman::Library::File.new(path: path) }
|
73
|
+
it 'contains path' do
|
74
|
+
expect(file.description).to eq "File #{path}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'niman/library/package'
|
3
|
+
|
4
|
+
describe Niman::Library::Package do
|
5
|
+
subject(:package) { Niman::Library::Package.new }
|
6
|
+
[:name, :version, :description].each do |attribute|
|
7
|
+
it "responds to #{attribute}" do
|
8
|
+
expect(package.respond_to?(attribute)).to be true
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#name" do
|
13
|
+
it "defaults to empty string" do
|
14
|
+
expect(package.name).to eq ""
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#version" do
|
19
|
+
it "defaults to empty string" do
|
20
|
+
expect(package.version).to eq ""
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#valid?' do
|
25
|
+
it 'is true when name is present' do
|
26
|
+
package = Niman::Library::Package.new(name: 'vim')
|
27
|
+
expect(package.valid?).to be true
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'is false when name is not present' do
|
31
|
+
package = Niman::Library::Package.new
|
32
|
+
expect(package.valid?).to be false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'niman/nimanfile'
|
3
|
+
require 'niman/library/file'
|
4
|
+
|
5
|
+
describe Niman::Nimanfile do
|
6
|
+
subject(:niman_file) { Niman::Nimanfile.new }
|
7
|
+
|
8
|
+
it 'has no instructions' do
|
9
|
+
expect(niman_file.instructions.length).to eq 0
|
10
|
+
end
|
11
|
+
|
12
|
+
[:file, :package].each do |attribute|
|
13
|
+
it "has #{attribute} method" do
|
14
|
+
expect(niman_file.respond_to?(attribute)).to be true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
specify 'file calls block with config object' do
|
19
|
+
expect { |b| niman_file.file(&b) }.to yield_with_args(Niman::Library::File)
|
20
|
+
end
|
21
|
+
|
22
|
+
specify 'package calls block with config object' do
|
23
|
+
expect { |b| niman_file.package(&b) }.to yield_with_args(Niman::Library::Package)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#instructions' do
|
27
|
+
before do
|
28
|
+
niman_file.file {}
|
29
|
+
end
|
30
|
+
|
31
|
+
specify 'increases when #file is being called' do
|
32
|
+
expect(niman_file.instructions.length).to eq 1
|
33
|
+
end
|
34
|
+
|
35
|
+
specify 'contains file object' do
|
36
|
+
expect(niman_file.instructions.first).to be_kind_of(Niman::Library::File)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'niman/provisioner'
|
3
|
+
require 'niman/installer'
|
4
|
+
require 'niman/exceptions'
|
5
|
+
|
6
|
+
describe Niman::Provisioner do
|
7
|
+
let(:file) { Niman::Library::File.new(path: '~/hello.txt', content: 'ohai') }
|
8
|
+
let(:vim_package) { Niman::Library::Package.new(name: 'vim') }
|
9
|
+
let(:instructions) { [file, vim_package] }
|
10
|
+
let(:installer) { double(Niman::Installer) }
|
11
|
+
subject(:provisioner) { Niman::Provisioner.new(installer, instructions) }
|
12
|
+
|
13
|
+
describe "#initialize" do
|
14
|
+
it 'accepts a list of instructions' do
|
15
|
+
expect(provisioner.instructions).to eq [file, vim_package]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'accepts a single instruction' do
|
19
|
+
provisioner = Niman::Provisioner.new(installer, file)
|
20
|
+
expect(provisioner.instructions).to eq [file]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#valid?" do
|
25
|
+
context 'with valid instructions' do
|
26
|
+
it 'returns true' do
|
27
|
+
expect(provisioner.valid?).to be true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with invalid instructions' do
|
32
|
+
let(:invalid_file) { Niman::Library::File.new() }
|
33
|
+
let(:instructions) { [file, invalid_file] }
|
34
|
+
it 'returns false' do
|
35
|
+
expect(provisioner.valid?).to be false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#run" do
|
41
|
+
context 'with invalid instructions' do
|
42
|
+
it 'raises when instruction is invalid' do
|
43
|
+
allow(provisioner).to receive(:valid?).and_return(false)
|
44
|
+
expect { provisioner.run }.to raise_error(Niman::ConfigError)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with valid instructions' do
|
49
|
+
before do
|
50
|
+
allow(file).to receive(:run)
|
51
|
+
allow(installer).to receive(:install)
|
52
|
+
provisioner.run
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'calls run for runable instructions' do
|
56
|
+
expect(file).to have_received(:run)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'calls installer for package' do
|
60
|
+
expect(installer).to have_received(:install).with(vim_package)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'calls block for every instruction' do
|
64
|
+
expect { |b| provisioner.run(&b) }.to yield_successive_args(file, vim_package)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'niman/recipe'
|
3
|
+
|
4
|
+
describe Niman::Recipe do
|
5
|
+
describe '.configure' do
|
6
|
+
before do
|
7
|
+
Niman::Recipe.configure do |config|
|
8
|
+
config.file do |file|
|
9
|
+
file.path = '/home/bob/hello.txt'
|
10
|
+
file.content = 'hello from alice'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
specify 'configuration has a file call' do
|
16
|
+
expect(Niman::Recipe.configuration.instructions.length).to eq 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '.reset' do
|
21
|
+
before do
|
22
|
+
Niman::Recipe.configure do |config|
|
23
|
+
config.file do |file|
|
24
|
+
file.path = '/home/bob/hello.txt'
|
25
|
+
file.content = 'hello from alice'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
Niman::Recipe.reset!
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'erases current configuration' do
|
32
|
+
expect(Niman::Recipe.configuration.instructions.length).to eq 0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '.from_file' do
|
37
|
+
before do
|
38
|
+
FakeFS.deactivate!
|
39
|
+
content = <<-EOS
|
40
|
+
Niman::Recipe.configure do |config|
|
41
|
+
config.file do |file|
|
42
|
+
file.path = '/home/bob/hello.txt'
|
43
|
+
file.content = 'hello from alice'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
EOS
|
47
|
+
File.open(Niman::Recipe::DEFAULT_FILENAME, "w") {|handle| handle.write(content) }
|
48
|
+
end
|
49
|
+
after do
|
50
|
+
File.delete(Niman::Recipe::DEFAULT_FILENAME)
|
51
|
+
FakeFS.activate!
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'loads "Nimanfile" by default' do
|
55
|
+
Niman::Recipe.from_file
|
56
|
+
expect(Niman::Recipe.configuration.instructions.length).to eq 1
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# The generated `.rspec` file contains `--require spec_helper` which will cause this
|
4
|
+
# file to always be loaded, without a need to explicitly require it in any files.
|
5
|
+
#
|
6
|
+
# Given that it is always loaded, you are encouraged to keep this file as
|
7
|
+
# light-weight as possible. Requiring heavyweight dependencies from this file
|
8
|
+
# will add to the boot time of your test suite on EVERY test run, even for an
|
9
|
+
# individual file that may not need all of that loaded. Instead, consider making
|
10
|
+
# a separate helper file that requires the additional dependencies and performs
|
11
|
+
# the additional setup, and require it from the spec files that actually need it.
|
12
|
+
#
|
13
|
+
# The `.rspec` file also contains a few flags that are not defaults but that
|
14
|
+
# users commonly want.
|
15
|
+
#
|
16
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
17
|
+
RSpec.configure do |config|
|
18
|
+
# rspec-expectations config goes here. You can use an alternate
|
19
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
20
|
+
# assertions if you prefer.
|
21
|
+
config.expect_with :rspec do |expectations|
|
22
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
23
|
+
# and `failure_message` of custom matchers include text for helper methods
|
24
|
+
# defined using `chain`, e.g.:
|
25
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
26
|
+
# # => "be bigger than 2 and smaller than 4"
|
27
|
+
# ...rather than:
|
28
|
+
# # => "be bigger than 2"
|
29
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
30
|
+
end
|
31
|
+
|
32
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
33
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
34
|
+
config.mock_with :rspec do |mocks|
|
35
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
36
|
+
# a real object. This is generally recommended, and will default to
|
37
|
+
# `true` in RSpec 4.
|
38
|
+
mocks.verify_partial_doubles = true
|
39
|
+
end
|
40
|
+
|
41
|
+
# The settings below are suggested to provide a good initial experience
|
42
|
+
# with RSpec, but feel free to customize to your heart's content.
|
43
|
+
=begin
|
44
|
+
# These two settings work together to allow you to limit a spec run
|
45
|
+
# to individual examples or groups you care about by tagging them with
|
46
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
47
|
+
# get run.
|
48
|
+
config.filter_run :focus
|
49
|
+
config.run_all_when_everything_filtered = true
|
50
|
+
|
51
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
52
|
+
# For more details, see:
|
53
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
54
|
+
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
55
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
56
|
+
config.disable_monkey_patching!
|
57
|
+
|
58
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
59
|
+
# be too noisy due to issues in dependencies.
|
60
|
+
config.warnings = true
|
61
|
+
|
62
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
63
|
+
# file, and it's useful to allow more verbose output when running an
|
64
|
+
# individual spec file.
|
65
|
+
if config.files_to_run.one?
|
66
|
+
# Use the documentation formatter for detailed output,
|
67
|
+
# unless a formatter has already been configured
|
68
|
+
# (e.g. via a command-line flag).
|
69
|
+
config.default_formatter = 'doc'
|
70
|
+
end
|
71
|
+
|
72
|
+
# Print the 10 slowest examples and example groups at the
|
73
|
+
# end of the spec run, to help surface which specs are running
|
74
|
+
# particularly slow.
|
75
|
+
config.profile_examples = 10
|
76
|
+
|
77
|
+
# Run specs in random order to surface order dependencies. If you find an
|
78
|
+
# order dependency and want to debug it, you can fix the order by providing
|
79
|
+
# the seed, which is printed after each run.
|
80
|
+
# --seed 1234
|
81
|
+
config.order = :random
|
82
|
+
|
83
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
84
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
85
|
+
# test failures related to randomization by passing the same `--seed` value
|
86
|
+
# as the one that triggered the failure.
|
87
|
+
Kernel.srand config.seed
|
88
|
+
=end
|
89
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: niman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Schulte
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-08 00:00:00.000000000 Z
|
12
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.19'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.19'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: virtus
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.4
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.0.4
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: fakefs
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.1'
|
13
69
|
- !ruby/object:Gem::Dependency
|
14
70
|
name: bundler
|
15
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -41,18 +97,42 @@ dependencies:
|
|
41
97
|
description:
|
42
98
|
email:
|
43
99
|
- hello@unexpected-co.de
|
44
|
-
executables:
|
100
|
+
executables:
|
101
|
+
- niman
|
45
102
|
extensions: []
|
46
103
|
extra_rdoc_files: []
|
47
104
|
files:
|
48
105
|
- ".gitignore"
|
106
|
+
- ".rspec"
|
107
|
+
- ".travis.yml"
|
49
108
|
- Gemfile
|
50
109
|
- LICENSE.txt
|
51
110
|
- README.md
|
52
111
|
- Rakefile
|
112
|
+
- bin/niman
|
53
113
|
- lib/niman.rb
|
114
|
+
- lib/niman/cli/application.rb
|
115
|
+
- lib/niman/exceptions.rb
|
116
|
+
- lib/niman/installer.rb
|
117
|
+
- lib/niman/library/file.rb
|
118
|
+
- lib/niman/library/package.rb
|
119
|
+
- lib/niman/nimanfile.rb
|
120
|
+
- lib/niman/platform.rb
|
121
|
+
- lib/niman/provisioner.rb
|
122
|
+
- lib/niman/recipe.rb
|
123
|
+
- lib/niman/shell.rb
|
124
|
+
- lib/niman/vagrant/plugin.rb
|
125
|
+
- lib/niman/vagrant/provisioner.rb
|
126
|
+
- lib/niman/vagrant/shell.rb
|
54
127
|
- lib/niman/version.rb
|
55
128
|
- niman.gemspec
|
129
|
+
- spec/lib/installer_spec.rb
|
130
|
+
- spec/lib/library/file_spec.rb
|
131
|
+
- spec/lib/library/package_spec.rb
|
132
|
+
- spec/lib/nimanfile_spec.rb
|
133
|
+
- spec/lib/provisioner_spec.rb
|
134
|
+
- spec/lib/recipe_spec.rb
|
135
|
+
- spec/spec_helper.rb
|
56
136
|
homepage: ''
|
57
137
|
licenses:
|
58
138
|
- MIT
|
@@ -77,4 +157,11 @@ rubygems_version: 2.4.3
|
|
77
157
|
signing_key:
|
78
158
|
specification_version: 4
|
79
159
|
summary: Provisions your machine
|
80
|
-
test_files:
|
160
|
+
test_files:
|
161
|
+
- spec/lib/installer_spec.rb
|
162
|
+
- spec/lib/library/file_spec.rb
|
163
|
+
- spec/lib/library/package_spec.rb
|
164
|
+
- spec/lib/nimanfile_spec.rb
|
165
|
+
- spec/lib/provisioner_spec.rb
|
166
|
+
- spec/lib/recipe_spec.rb
|
167
|
+
- spec/spec_helper.rb
|