niman 0.0.5 → 0.0.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0dd2e66a5efe87391ae8ea496cf819c14cc611bb
4
- data.tar.gz: 51bddf363cae6f579f3906cb2a86e62a13243e8d
3
+ metadata.gz: cec92b45c738e4089f9d9dd278f4c6f84b86e161
4
+ data.tar.gz: bbbfe3217ab77454b7339aefc5826bf4b5443c91
5
5
  SHA512:
6
- metadata.gz: 09b62fb72deb43fdb3455b3b11460bdc66eaf3dafd74f9f891481ffd35c4a981e659385d0e3336f241251afc80bd4fffe1ce6531f41b2d55a892ffdabb716603
7
- data.tar.gz: 519dbe2cf887550e5c498c5c8a5af914c23cb4b90516155e3ce36650e00149be3ef2e33efa66a06937614cdf43fa917d4cef93247e1bbaf0805d6500c790fcda
6
+ metadata.gz: 7233e582d4389918020a9ffb1a6ba067841c1d0101bc6fc562f8d1d55fb473786b0bf88617b1294cb124401591d6b0c78575e31e0e6fd4b2b9e41d574de962db
7
+ data.tar.gz: 9c5a3030863723f7df305f0c26dc390af35c6f59f53af716b906585d8f0eebcc0db1f11fb58e9e3faa5ecf7036e36f64dca26eeb742c255373922ad5febfb829
data/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Niman
2
2
  [![Build Status](https://travis-ci.org/schultyy/Niman.svg?branch=master)](https://travis-ci.org/schultyy/Niman)
3
+ [![Code Climate](https://codeclimate.com/github/schultyy/Niman/badges/gpa.svg)](https://codeclimate.com/github/schultyy/Niman)
3
4
 
4
5
  Niman is a proof-of-concept provisioner.
5
6
 
@@ -34,6 +35,24 @@ This places a new file `hello.txt` in `/home/bob` with rights 0600.
34
35
 
35
36
  A `Nimanfile` contains all necessary commands for `niman` to run.
36
37
 
38
+ ### Commands
39
+
40
+ Niman has support to execute arbitrary commands on the host system:
41
+
42
+ ```ruby
43
+ Niman::Recipe.configure do |config|
44
+ config.exec "touch ~/hello.txt"
45
+ end
46
+ ```
47
+
48
+ Or if you need sudo privileges:
49
+
50
+ ```ruby
51
+ Niman::Recipe.configure do |config|
52
+ config.exec :sudo, "apt-get update"
53
+ end
54
+ ```
55
+
37
56
  ### Packages
38
57
 
39
58
  Use a concrete package in your script:
@@ -42,7 +61,6 @@ Use a concrete package in your script:
42
61
  Niman::Recipe.configure do |config|
43
62
  config.package do |package|
44
63
  package.name = "vim"
45
- package.version = "7.4"
46
64
  end
47
65
  end
48
66
  ```
@@ -56,8 +74,8 @@ Package description:
56
74
  #packages/ruby.rb
57
75
  require 'niman'
58
76
  class RubyPackage < Niman::Package
59
- package :ubuntu, "ruby1.9.1"
60
- package :centos, "ruby1.9.1"
77
+ package_name :ubuntu, "ruby1.9.1"
78
+ package_name :centos, "ruby1.9.1"
61
79
  end
62
80
  ```
63
81
  In your `Nimanfile`:
@@ -72,14 +90,14 @@ A custom package can have one or more configuration files inside of it:
72
90
  ```ruby
73
91
  #packages/nginx
74
92
  class NginxPackage < Niman::Package
75
- package :ubuntu, 'nginx'
93
+ package_name :ubuntu, 'nginx'
76
94
 
77
- configuration '/etc/nginx/nginx.conf' do |config|
95
+ file '/etc/nginx/nginx.conf' do |config|
78
96
  #general nginx configuration goes here
79
97
  config.content = '...'
80
98
  end
81
99
 
82
- configuration '/etc/nginx/sites-available/example.com' do |config|
100
+ file '/etc/nginx/sites-available/example.com' do |config|
83
101
  config.content = '...'
84
102
  end
85
103
  end
@@ -30,7 +30,7 @@ module Niman
30
30
 
31
31
  resolver = Niman::PackageResolver.new(config.instructions)
32
32
  filehandler = Niman::FileHandler.new(client_shell)
33
- provisioner = Niman::Provisioner.new(installer, filehandler, resolver.resolve)
33
+ provisioner = Niman::Provisioner.new(installer, filehandler, @client_shell, resolver.resolve)
34
34
  this = self
35
35
  provisioner.run do |instruction|
36
36
  this.say "Executing task #{instruction.description}" unless @silent
@@ -0,0 +1,26 @@
1
+ module Niman
2
+ module Library
3
+ class Command
4
+ include Virtus.model
5
+
6
+ attribute :command, String
7
+ attribute :use_sudo, Symbol, default: :no_sudo
8
+
9
+ def valid?
10
+ !command.empty? && [:no_sudo, :sudo].include?(use_sudo)
11
+ end
12
+
13
+ def errors
14
+ "command must not be empty"
15
+ end
16
+
17
+ def description
18
+ if use_sudo == :sudo
19
+ "sudo #{command}"
20
+ else
21
+ command
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -2,7 +2,7 @@ module Niman
2
2
  module Library
3
3
  class CustomPackage
4
4
  class << self
5
- attr_reader :package_names, :files
5
+ attr_reader :package_names, :files, :commands
6
6
 
7
7
  def valid?
8
8
  !package_names.nil? &&
@@ -26,6 +26,11 @@ module Niman
26
26
  ''
27
27
  end
28
28
 
29
+ def exec(sudo=:no_sudo, command)
30
+ @commands ||= []
31
+ @commands << Niman::Library::Command.new(use_sudo: sudo, command: command)
32
+ end
33
+
29
34
  def errors
30
35
  return [] if self.valid?
31
36
  package_names.keys.map do |key|
@@ -1,4 +1,5 @@
1
1
  require 'niman/library/file'
2
+ require 'niman/library/command'
2
3
 
3
4
  module Niman
4
5
  class Nimanfile
@@ -20,5 +21,9 @@ module Niman
20
21
  yield(package) if block_given?
21
22
  @instructions.push(package)
22
23
  end
24
+
25
+ def exec(use_sudo = :no_sudo, command)
26
+ @instructions.push(Niman::Library::Command.new(command: command, use_sudo: use_sudo))
27
+ end
23
28
  end
24
29
  end
@@ -4,9 +4,10 @@ module Niman
4
4
  class Provisioner
5
5
  attr_reader :instructions
6
6
 
7
- def initialize(installer, filehandler, instructions)
7
+ def initialize(installer, filehandler, shell, instructions)
8
8
  @installer = installer
9
9
  @filehandler = filehandler
10
+ @shell = shell
10
11
  @instructions = Array(instructions)
11
12
  end
12
13
 
@@ -23,16 +24,42 @@ module Niman
23
24
  @instructions.each do |instruction|
24
25
  yield(instruction) if block_given?
25
26
  if instruction.respond_to?(:files)
26
- instruction.files.each do |file|
27
- @filehandler.run(file)
28
- end
27
+ custom_package_files(instruction)
28
+ end
29
+ if instruction.respond_to?(:commands)
30
+ custom_package_exec(instruction)
29
31
  end
30
32
  if instruction.respond_to?(:run)
31
33
  @filehandler.run(instruction)
34
+ elsif instruction.respond_to?(:command)
35
+ command(instruction)
32
36
  else
33
37
  @installer.install(instruction)
34
38
  end
35
39
  end
36
40
  end
41
+
42
+ private
43
+
44
+ def custom_package_exec(instruction)
45
+ return if instruction.commands.nil?
46
+ instruction.commands.each { |cmd| command(cmd) }
47
+ end
48
+
49
+ def custom_package_files(instruction)
50
+ instruction.files.each do |file|
51
+ @filehandler.run(file)
52
+ end
53
+ end
54
+
55
+ def command(instruction)
56
+ mode = case instruction.use_sudo
57
+ when :sudo
58
+ true
59
+ when :no_sudo
60
+ false
61
+ end
62
+ @shell.exec(instruction.command, mode)
63
+ end
37
64
  end
38
65
  end
@@ -18,12 +18,10 @@ module VagrantPlugins
18
18
 
19
19
  def exec(command, use_sudo=false)
20
20
  @machine.ui.info(command, {color: :green})
21
- opts = { error_check: false, elevated: true }
22
- @channel.sudo(command, opts) do |type, data|
21
+ opts = { error_check: false, elevated: use_sudo }
22
+ handler = Proc.new do |type, data|
23
23
  if [:stderr, :stdout].include?(type)
24
- #Output the data with the proper color based on the stream.
25
24
  color = type == :stdout ? :green : :red
26
- # Clear out the newline since we add one
27
25
  data = data.chomp
28
26
  next if data.empty?
29
27
  options = {}
@@ -31,6 +29,11 @@ module VagrantPlugins
31
29
  @machine.ui.info(data.chomp, options)
32
30
  end
33
31
  end
32
+ if use_sudo
33
+ @channel.sudo(command, opts, &handler)
34
+ else
35
+ @channel.execute(command, opts, &handler)
36
+ end
34
37
  end
35
38
 
36
39
  def print(message, type)
@@ -42,20 +45,13 @@ module VagrantPlugins
42
45
  end
43
46
  end
44
47
 
45
- def create_file(path, content)
48
+ def create_file(path, content, use_sudo=false)
46
49
  if content.include?("\n")
47
50
  cmd = "cat > #{path} << EOL\n#{content}\nEOL"
48
51
  else
49
52
  cmd = "echo #{content} > #{path}"
50
53
  end
51
- @channel.sudo(cmd) do |type, data|
52
- color = type == :stdout ? :green : :red
53
- data = data.chomp
54
- next if data.empty?
55
- options = {}
56
- options[:color] = :green
57
- @machine.ui.info(data.chomp, options)
58
- end
54
+ self.exec(cmd, use_sudo)
59
55
  end
60
56
 
61
57
  private
data/lib/niman/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Niman
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -18,6 +18,55 @@ describe Niman::CLI::Application do
18
18
  File.delete(Niman::Recipe::DEFAULT_FILENAME)
19
19
  end
20
20
 
21
+ describe "commands" do
22
+ def write_file(body)
23
+ nimanfile = <<-EOS
24
+ Niman::Recipe.configure do |config|
25
+ #{body}
26
+ end
27
+ EOS
28
+ File.open(Niman::Recipe::DEFAULT_FILENAME, "w") {|h| h.write(nimanfile)}
29
+ end
30
+
31
+ context 'without sudo' do
32
+ it 'is passed to shell' do
33
+ allow(shell).to receive(:exec)
34
+ write_file("config.exec 'touch hello.txt'")
35
+ application.apply
36
+ expect(shell).to have_received(:exec).with("touch hello.txt", false)
37
+ end
38
+
39
+ it 'does not execute when argument is empty' do
40
+ write_file("config.exec ''")
41
+ allow(shell).to receive(:print).with(any_args)
42
+ application.apply
43
+ expect(shell).to have_received(:print).with(any_args)
44
+ end
45
+ end
46
+ context 'with sudo' do
47
+ it 'is passed to shell' do
48
+ allow(shell).to receive(:exec)
49
+ write_file("config.exec :sudo, 'apt-get update'")
50
+ application.apply
51
+ expect(shell).to have_received(:exec).with('apt-get update', true)
52
+ end
53
+
54
+ it 'does not execute when argument is empty' do
55
+ write_file("config.exec :sudo, ''")
56
+ allow(shell).to receive(:print).with(any_args)
57
+ application.apply
58
+ expect(shell).to have_received(:print).with(any_args)
59
+ end
60
+
61
+ it 'does not execute when sudo_mode is unknown' do
62
+ write_file("config.exec :foo, 'apt-get update'")
63
+ allow(shell).to receive(:print).with(any_args)
64
+ application.apply
65
+ expect(shell).to have_received(:print).with(any_args)
66
+ end
67
+ end
68
+ end
69
+
21
70
  describe "create files" do
22
71
  before do
23
72
  nimanfile = <<-EOS
@@ -82,15 +131,18 @@ describe Niman::CLI::Application do
82
131
  context 'is existant' do
83
132
  before do
84
133
  nginx_package = <<-EOS
85
- require 'niman'
134
+ require 'niman'
135
+
136
+ class Nginx < Niman::Library::CustomPackage
137
+ package_name :debian, 'nginx'
86
138
 
87
- class Nginx < Niman::Library::CustomPackage
88
- package_name :debian, 'nginx'
139
+ file '/etc/nginx/nginx.conf' do |config|
140
+ config.content = 'foo bar'
141
+ end
89
142
 
90
- file '/etc/nginx/nginx.conf' do |config|
91
- config.content = 'foo bar'
92
- end
93
- end
143
+ exec :sudo, 'ln -s /etc/nginx/sites-available/example.org /etc/nginx/sites-enabled/example.org'
144
+ exec 'touch ~/install_notes.txt'
145
+ end
94
146
  EOS
95
147
 
96
148
  nimanfile = <<-EOS
@@ -119,6 +171,14 @@ describe Niman::CLI::Application do
119
171
  it 'writes /etc/nginx/nginx.conf' do
120
172
  expect(shell).to have_received(:create_file).with('/etc/nginx/nginx.conf', 'foo bar')
121
173
  end
174
+
175
+ it 'links /etc/nginx/sites-available/example.org' do
176
+ expect(shell).to have_received(:exec).with('ln -s /etc/nginx/sites-available/example.org /etc/nginx/sites-enabled/example.org', true)
177
+ end
178
+
179
+ it 'creates install_notes.txt in home directory' do
180
+ expect(shell).to have_received(:exec).with('touch ~/install_notes.txt', false)
181
+ end
122
182
  end
123
183
  end
124
184
  end
@@ -4,6 +4,7 @@ require 'niman/installer'
4
4
  require 'niman/exceptions'
5
5
 
6
6
  describe Niman::Provisioner do
7
+ let(:shell) { double('Shell') }
7
8
  let(:file) { Niman::Library::File.new(path: '~/hello.txt', content: 'ohai') }
8
9
  let(:vim_package) { Niman::Library::Package.new(name: 'vim') }
9
10
  let(:nginx_package) { Class.new(Niman::Library::CustomPackage) do
@@ -15,7 +16,7 @@ describe Niman::Provisioner do
15
16
  let(:instructions) { [file,vim_package, nginx_package] }
16
17
  let(:installer) { double(Niman::Installer) }
17
18
  let(:filehandler) { double(Niman::FileHandler) }
18
- subject(:provisioner) { Niman::Provisioner.new(installer, filehandler, instructions) }
19
+ subject(:provisioner) { Niman::Provisioner.new(installer, filehandler, shell, instructions) }
19
20
 
20
21
  describe "#initialize" do
21
22
  it 'accepts a list of instructions' do
@@ -23,7 +24,7 @@ describe Niman::Provisioner do
23
24
  end
24
25
 
25
26
  it 'accepts a single instruction' do
26
- provisioner = Niman::Provisioner.new(installer, filehandler, file)
27
+ provisioner = Niman::Provisioner.new(installer, filehandler, shell, file)
27
28
  expect(provisioner.instructions).to eq [file]
28
29
  end
29
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: niman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
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-17 00:00:00.000000000 Z
11
+ date: 2015-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -143,6 +143,7 @@ files:
143
143
  - lib/niman/exceptions.rb
144
144
  - lib/niman/filehandler.rb
145
145
  - lib/niman/installer.rb
146
+ - lib/niman/library/command.rb
146
147
  - lib/niman/library/custom_package.rb
147
148
  - lib/niman/library/file.rb
148
149
  - lib/niman/library/package.rb