bakist 0.7.7
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 +8 -0
- data/Gemfile +3 -0
- data/LICENSE +44 -0
- data/bakist.gemspec +43 -0
- data/bin/bake +4 -0
- data/lib/bakist.rb +2 -0
- data/lib/bakist/cli.rb +178 -0
- data/lib/bakist/config.rb +113 -0
- data/lib/bakist/remote.rb +66 -0
- data/lib/bakist/remote_config.rb +62 -0
- data/lib/bakist/royal_crown.rb +79 -0
- data/lib/bakist/version.rb +3 -0
- metadata +239 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1770832be2cce5d3d56de046d300933eb5c2c6ba
|
4
|
+
data.tar.gz: 55b9f5602369ceca71128fd43b07427d3c233d7a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 63dbe9ceeebc0ca5a2deb30df8ca01d0f13654ce3cd9a0d92401359e8fd92291d30c994373d5e02b72234f7195ccd85769ac71e1d0be35572ad9ad7e9e79fa8e
|
7
|
+
data.tar.gz: 0ede952f221cb5fe6ac36a0dac495bcbcdd45e43f87f90da7071ba3ac6bbf39bf2d5942f73d7db6e4c97dd0e36b407ea8bb52b19297198b7938477c6ae7f48b2
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright (c) 2014 Mike Mackintosh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# ORIGINAL LICENSE
|
24
|
+
#
|
25
|
+
# Copyright (c) 2012 Matthew Kocher and Doc Ritezel
|
26
|
+
#
|
27
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
28
|
+
# a copy of this software and associated documentation files (the
|
29
|
+
# "Software"), to deal in the Software without restriction, including
|
30
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
31
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
32
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
33
|
+
# the following conditions:
|
34
|
+
#
|
35
|
+
# The above copyright notice and this permission notice shall be
|
36
|
+
# included in all copies or substantial portions of the Software.
|
37
|
+
#
|
38
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
39
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
40
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
41
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
42
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
43
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
44
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/bakist.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# From the lovely work of "Matthew Kocher", "Doc Ritezel"
|
3
|
+
# who can be found at "kocher@gmail.com", "ritezel@gmail.com"
|
4
|
+
#
|
5
|
+
# Ported from Soloist
|
6
|
+
#
|
7
|
+
$:.push File.expand_path("../lib", __FILE__)
|
8
|
+
require "bakist/version"
|
9
|
+
|
10
|
+
Gem::Specification.new do |s|
|
11
|
+
s.name = "bakist"
|
12
|
+
s.version = Bakist::VERSION
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.authors = ["Mike Mackintosh"]
|
15
|
+
s.email = ["mike.mackintosh@gmail.com"]
|
16
|
+
s.homepage = "http://github.com/mikemackintosh/bakist"
|
17
|
+
s.summary = "Bakist is a simple way of running chef-solo"
|
18
|
+
s.description = "Makes running chef-solo easy."
|
19
|
+
|
20
|
+
s.rubyforge_project = "bakist"
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
|
27
|
+
s.license = 'MIT'
|
28
|
+
|
29
|
+
s.add_dependency "chef"
|
30
|
+
s.add_dependency "librarian-chef"
|
31
|
+
s.add_dependency "thor"
|
32
|
+
s.add_dependency "hashie", "~> 2.0"
|
33
|
+
s.add_dependency "net-ssh"
|
34
|
+
s.add_dependency "awesome_print"
|
35
|
+
|
36
|
+
s.add_development_dependency "rspec"
|
37
|
+
s.add_development_dependency "guard-rspec"
|
38
|
+
s.add_development_dependency "guard-bundler"
|
39
|
+
s.add_development_dependency "guard-shell"
|
40
|
+
s.add_development_dependency "rb-fsevent"
|
41
|
+
s.add_development_dependency "terminal-notifier-guard"
|
42
|
+
s.add_development_dependency "gem-release"
|
43
|
+
end
|
data/bin/bake
ADDED
data/lib/bakist.rb
ADDED
data/lib/bakist/cli.rb
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
require "librarian/chef/cli"
|
2
|
+
require "bakist/remote_config"
|
3
|
+
require "awesome_print"
|
4
|
+
require "thor"
|
5
|
+
|
6
|
+
class Thor::Shell::Color
|
7
|
+
def say(string, color=:WHITE, nl=true, prefix=true)
|
8
|
+
|
9
|
+
if prefix
|
10
|
+
#super '★', :green, false
|
11
|
+
super ' Bakist ', :white, false
|
12
|
+
#super '★', :green, false
|
13
|
+
super ':: ', :white, false
|
14
|
+
end
|
15
|
+
|
16
|
+
super(string, color, nl)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Bakist
|
21
|
+
|
22
|
+
class CLI < Thor
|
23
|
+
attr_writer :bakist_config
|
24
|
+
default_task :chef
|
25
|
+
|
26
|
+
|
27
|
+
desc "chef", "Run chef-solo"
|
28
|
+
method_option :remote, :aliases => "-r", :desc => "Run chef-solo on user@host"
|
29
|
+
method_option :identity, :aliases => "-i", :desc => "The SSH identity file"
|
30
|
+
def chef
|
31
|
+
#begin
|
32
|
+
say 'Bakist is Fetching Cookbooks', :green, true, false
|
33
|
+
install_cookbooks if cheffile_exists?
|
34
|
+
say 'Bakist is Preparing to Bake', :green, true, false
|
35
|
+
bakist_config.run_chef
|
36
|
+
#rescue Exception => msg
|
37
|
+
# say msg.backtrace.inspect
|
38
|
+
# say ' Your Bakery files were not found. Please make sure ', :RED, false
|
39
|
+
# say '~/.bakery/', :YELLOW, false, false
|
40
|
+
# say ' exists', :RED, true, false
|
41
|
+
# say '', nil, nil, false
|
42
|
+
#end
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "run_recipe [cookbook::recipe, ...]", "Run individual recipes"
|
46
|
+
method_option :remote, :aliases => "-r", :desc => "Run recipes on user@host"
|
47
|
+
method_option :identity, :aliases => "-i", :desc => "The SSH identity file"
|
48
|
+
def run_recipe(*recipes)
|
49
|
+
bakist_config.royal_crown.recipes = recipes
|
50
|
+
chef
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "config", "Dumps configuration data for Bakist"
|
54
|
+
def config
|
55
|
+
Kernel.ap(bakist_config.as_node_json)
|
56
|
+
end
|
57
|
+
|
58
|
+
no_tasks do
|
59
|
+
def install_cookbooks
|
60
|
+
|
61
|
+
Dir.chdir(File.dirname(config_path)) do
|
62
|
+
Librarian::Chef::Cli.with_environment do
|
63
|
+
Librarian::Chef::Cli.new.install
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
if user_config_path
|
68
|
+
say 'Bakist is Fetching User-Specific Cookbooks', :green, true, false
|
69
|
+
begin
|
70
|
+
Dir.chdir(File.dirname(user_config_path)) do
|
71
|
+
Librarian::Chef::Cli.with_environment do
|
72
|
+
libchef = Librarian::Chef::Cli.new.install
|
73
|
+
end
|
74
|
+
end
|
75
|
+
rescue
|
76
|
+
say 'Error getting user-specific cookbooks, scratching.', :red
|
77
|
+
abort
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def bakist_config
|
84
|
+
@bakist_config ||= if options[:remote]
|
85
|
+
Bakist::RemoteConfig.from_file(config_path, remote)
|
86
|
+
else
|
87
|
+
Bakist::Config.from_file(config_path)
|
88
|
+
end.tap do |config|
|
89
|
+
config.merge!(user_config) if user_config_path
|
90
|
+
config.merge!(shop_config) if shop_config_path
|
91
|
+
#config.merge!(shop_managed_user_config) if shop_managed_user_config_path
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def shop_config
|
98
|
+
Bakist::Config.from_file(shop_config_path)
|
99
|
+
end
|
100
|
+
|
101
|
+
def user_config
|
102
|
+
Bakist::Config.from_file(user_config_path)
|
103
|
+
end
|
104
|
+
|
105
|
+
def shop_managed_user_config
|
106
|
+
Bakist::Config.from_file(shop_managed_user_config_path)
|
107
|
+
end
|
108
|
+
|
109
|
+
def remote
|
110
|
+
@remote ||= if options[:identity]
|
111
|
+
Bakist::Remote.from_uri(options[:remote], options[:identity])
|
112
|
+
else
|
113
|
+
Bakist::Remote.from_uri(options[:remote])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def cheffile_exists?
|
118
|
+
File.exists?(File.expand_path("~/.bakery/Cheffile"))
|
119
|
+
end
|
120
|
+
|
121
|
+
def config_path
|
122
|
+
@config_path ||= File.expand_path("~/.bakery/bakeryrc")
|
123
|
+
end
|
124
|
+
|
125
|
+
# TODO: Fix librarian cookbook path defaults
|
126
|
+
def shop_managed_user_config_path
|
127
|
+
# current_user = ENV['SUDO_USER'] ||= ENV['USER']
|
128
|
+
# shop_managed_user_config_path = File.expand_path("~/.bakery/bakers/#{current_user}/bakeryrc")
|
129
|
+
# if File.exists?(shop_managed_user_config_path)
|
130
|
+
# @shop_managed_user_config_path ||= shop_managed_user_config_path
|
131
|
+
# end
|
132
|
+
end
|
133
|
+
|
134
|
+
def user_config_path
|
135
|
+
user_config_path = File.expand_path("~/.bakist/bakistrc")
|
136
|
+
if File.exists?(user_config_path)
|
137
|
+
@user_config_path ||= user_config_path
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def shop_config_path
|
142
|
+
shop_config_path = File.expand_path("~/.bakery/shoprc")
|
143
|
+
if File.exists?(shop_config_path)
|
144
|
+
@shop_config_path ||= shop_config_path
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def logo
|
149
|
+
say ' ', :green, true, false
|
150
|
+
say ' kkkkk ', :green, true, false
|
151
|
+
say ' kbbbaaaaaaaabk kkkkk ', :green, true, false
|
152
|
+
say ' kaabkbaaabkbaaaak baaaak ', :green, true, false
|
153
|
+
say ' kaaak kaaaab kaabb kaaaab ', :green, true, false
|
154
|
+
say ' kbaab kbaaaak kbaab kkbbbkkbbbb baaaak kbbk kkbbbbk kbbbkkkkbbk kbbbk kbbbbk ', :green, true, false
|
155
|
+
say ' kabab kaaaaabaaaab kaaaaaaaaaaab kaaaaa kbaabk baaabbaaakkbaaaaaaaaaabaaaak kbaaabk ', :green, true, false
|
156
|
+
say ' k kbbkkbaaaabaaaaaaak baaaak kbaaaak baaaabbaabk kbaaab kbaakkaaaabkbaabbaaaaa baaaab k ', :green, true, false
|
157
|
+
say ' kbaabk kaaaab kbaaaaakbaaaak kaaaaak kbaaaaaaaaaaak kbaaaakkbaakkbaaaak kkkbaaaak kbaaaak kbaabk ', :green, true, false
|
158
|
+
say ' kaaab baaaak kbaaaakaaaab baaaab kaaaabkbaaaaab baaaaababk kaaaab kaaaaa kaaaab baaak ', :green, true, false
|
159
|
+
say ' k kk kaaaab kaaaabbaaaak kaaaaa kbaaaak baaaak kaaaaakkk kbaaaak kaaaak baaaak kk k ', :green, true, false
|
160
|
+
say ' baaaabbkkkbaaabkaaaaaakbbaaaabkkbaaaab kaaaaabkbaaaaabkkkkbbaaaab baaaabbbaaaab ', :green, true, false
|
161
|
+
say ' kbaaaabaaaaaabk baaaaaaabaaaaaaaaaaaak kaaaaaaabaaaaaaaaabkbaaaak baaaaaabaaaak ', :green, true, false
|
162
|
+
say ' kbbbbkkbbaabk kbbbbk kbbbbkkbbbbk kbbbbbk kbbbbbkk bbbbk kbbbkkaaaaa ', :green, true, false
|
163
|
+
say ' kkkkkkbbbbbbbbbbbbbbbkkkkkkkk kbaaaak ', :green, true, false
|
164
|
+
say ' kkbbbbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbkkk kkkbaaaabk ', :green, true, false
|
165
|
+
say ' kbbaabbbbbaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbaaaaaaaabk ', :green, true, false
|
166
|
+
say ' kkbaabbbbbaaaaaaaaaaaaaaaaaaaabbbbbbbbkkkkkbbbbbbbbbbaaaaaaaaaaaaaaaaaaabkk ', :green, true, false
|
167
|
+
say ' kbaaaabbbaaaaaaaaaaaaaaabbkkkk kkkbbbbbbbbbkkk ', :green, true, false
|
168
|
+
say ' kbbbbbaaaaaaaaaaaaaabbkk ', :green, true, false
|
169
|
+
say ' kkbbaaaaaabbkk ', :green, true, false
|
170
|
+
say ' kbaabk ', :green, true, false
|
171
|
+
say ' kk ', :green, true, false
|
172
|
+
say ' ', :green, true, false
|
173
|
+
say 'Preparing... ', :white, true
|
174
|
+
say ' ', :green, true, false
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require "bakist/royal_crown"
|
2
|
+
require "tempfile"
|
3
|
+
|
4
|
+
module Bakist
|
5
|
+
class Config
|
6
|
+
attr_writer :solo_rb_path, :node_json_path
|
7
|
+
attr_reader :royal_crown
|
8
|
+
|
9
|
+
def self.from_file(royal_crown_path)
|
10
|
+
rc = Bakist::RoyalCrown.from_file(royal_crown_path)
|
11
|
+
new(rc)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(royal_crown)
|
15
|
+
@royal_crown = royal_crown
|
16
|
+
end
|
17
|
+
|
18
|
+
def run_chef
|
19
|
+
exec(conditional_sudo("bash -c '#{chef_solo}'"))
|
20
|
+
end
|
21
|
+
|
22
|
+
def chef_solo
|
23
|
+
"chef-solo -c '#{solo_rb_path}' -l '#{log_level}'"
|
24
|
+
end
|
25
|
+
|
26
|
+
def as_solo_rb
|
27
|
+
<<-SOLO_RB
|
28
|
+
file_cache_path "#{chef_cache_path}"
|
29
|
+
cookbook_path #{cookbook_paths.inspect}
|
30
|
+
json_attribs "#{node_json_path}"
|
31
|
+
SOLO_RB
|
32
|
+
end
|
33
|
+
|
34
|
+
def as_node_json
|
35
|
+
compiled.node_attributes.to_hash.merge({ "recipes" => compiled.recipes })
|
36
|
+
end
|
37
|
+
|
38
|
+
def chef_cache_path
|
39
|
+
"/var/chef/cache".tap do |cache_path|
|
40
|
+
system(conditional_sudo("mkdir -p #{cache_path}")) \
|
41
|
+
unless File.directory?(cache_path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def cookbook_paths
|
46
|
+
([royal_crown_cookbooks_directory] + compiled.cookbook_paths).map do |path|
|
47
|
+
File.expand_path(path, royal_crown_path)
|
48
|
+
end.uniq.select do |path|
|
49
|
+
File.directory?(path)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def solo_rb_path
|
54
|
+
@solo_rb_path ||= Tempfile.new(["solo", ".rb"]).tap do |file|
|
55
|
+
puts as_solo_rb if debug?
|
56
|
+
file.write(as_solo_rb)
|
57
|
+
file.close
|
58
|
+
end.path
|
59
|
+
end
|
60
|
+
|
61
|
+
def node_json_path
|
62
|
+
@node_json_path ||= Tempfile.new(["node", ".json"]).tap do |file|
|
63
|
+
puts JSON.pretty_generate(as_node_json) if debug?
|
64
|
+
file.write(JSON.dump(as_node_json))
|
65
|
+
file.close
|
66
|
+
end.path
|
67
|
+
end
|
68
|
+
|
69
|
+
def merge!(other)
|
70
|
+
royal_crown.recipes += other.royal_crown.recipes
|
71
|
+
royal_crown.cookbook_paths += other.royal_crown.cookbook_paths
|
72
|
+
royal_crown.node_attributes.merge!(other.royal_crown.node_attributes)
|
73
|
+
royal_crown.env_variable_switches.merge!(other.royal_crown.env_variable_switches)
|
74
|
+
end
|
75
|
+
|
76
|
+
def compiled
|
77
|
+
@compiled ||= royal_crown.dup.tap do |working_royal_crown|
|
78
|
+
while working_royal_crown["env_variable_switches"]
|
79
|
+
working_royal_crown.delete("env_variable_switches").each do |variable, switch|
|
80
|
+
switch.each do |value, inner|
|
81
|
+
working_royal_crown.merge!(inner) if ENV[variable] == value
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def log_level
|
89
|
+
ENV["LOG_LEVEL"] || "fatal"
|
90
|
+
end
|
91
|
+
|
92
|
+
def debug?
|
93
|
+
log_level == "debug"
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def conditional_sudo(command)
|
98
|
+
root? ? command : "sudo -E #{command}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def root?
|
102
|
+
Process.uid == 0
|
103
|
+
end
|
104
|
+
|
105
|
+
def royal_crown_cookbooks_directory
|
106
|
+
File.expand_path("cookbooks", royal_crown_path)
|
107
|
+
end
|
108
|
+
|
109
|
+
def royal_crown_path
|
110
|
+
File.dirname(royal_crown.path)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "net/ssh"
|
2
|
+
require "shellwords"
|
3
|
+
require "etc"
|
4
|
+
|
5
|
+
module Bakist
|
6
|
+
class RemoteError < RuntimeError; end
|
7
|
+
|
8
|
+
class Remote
|
9
|
+
attr_reader :user, :host, :key, :timeout, :stdout, :stderr, :exitstatus
|
10
|
+
attr_writer :connection
|
11
|
+
|
12
|
+
def self.from_uri(uri, key = "~/.ssh/id_rsa")
|
13
|
+
parsed = URI.parse("ssh://#{uri}")
|
14
|
+
new(parsed.user || Etc.getlogin, parsed.host, key)
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(user, host, key, options = {})
|
18
|
+
@user = user
|
19
|
+
@host = host
|
20
|
+
@key = File.expand_path(key)
|
21
|
+
@timeout = options[:timeout] || 10000
|
22
|
+
end
|
23
|
+
|
24
|
+
def backtick(command)
|
25
|
+
@stdout = ""
|
26
|
+
@stderr = ""
|
27
|
+
exec(command)
|
28
|
+
@stdout
|
29
|
+
end
|
30
|
+
|
31
|
+
def system(command)
|
32
|
+
@stdout = STDOUT
|
33
|
+
@stderr = STDERR
|
34
|
+
exec(command)
|
35
|
+
exitstatus
|
36
|
+
end
|
37
|
+
|
38
|
+
def system!(*command)
|
39
|
+
system(*command).tap do |status|
|
40
|
+
raise RemoteError.new("#{command.join(" ")} exited #{status}") unless status == 0
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def upload(from, to, opts = "--exclude .git")
|
45
|
+
Kernel.system("rsync -e 'ssh -i #{key}' -avz --delete #{from} #{user}@#{host}:#{to} #{opts}")
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def connection
|
50
|
+
@connection ||= Net::SSH.start(host, user, :keys => [key], :timeout => timeout)
|
51
|
+
end
|
52
|
+
|
53
|
+
def exec(*command)
|
54
|
+
connection.open_channel do |channel|
|
55
|
+
channel.exec(*command) do |stream, success|
|
56
|
+
raise RemoteError.new("Could not run #{command.join(" ")}") unless success
|
57
|
+
stream.on_data { |_, data| stdout << data }
|
58
|
+
stream.on_extended_data { |_, type, data| stderr << data }
|
59
|
+
stream.on_request("exit-status") { |_, data| @exitstatus = data.read_long }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
connection.loop
|
63
|
+
@exitstatus ||= 0
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "bakist/config"
|
2
|
+
require "bakist/remote"
|
3
|
+
|
4
|
+
module Bakist
|
5
|
+
class RemoteConfig < Config
|
6
|
+
attr_reader :remote
|
7
|
+
|
8
|
+
def self.from_file(royal_crown_path, remote)
|
9
|
+
rc = Bakist::RoyalCrown.from_file(royal_crown_path)
|
10
|
+
new(rc, remote)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(royal_crown, remote)
|
14
|
+
@royal_crown = royal_crown
|
15
|
+
@remote = remote
|
16
|
+
end
|
17
|
+
|
18
|
+
def run_chef
|
19
|
+
remote.system!(conditional_sudo(%(/bin/bash -lc "#{chef_solo}")))
|
20
|
+
end
|
21
|
+
|
22
|
+
def node_json_path
|
23
|
+
@node_json_path ||= File.expand_path("node.json", chef_config_path).tap do |path|
|
24
|
+
remote.system!(%(echo '#{JSON.dump(as_node_json)}' | #{conditional_sudo("tee #{path}")}))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def solo_rb_path
|
29
|
+
@solo_rb_path ||= File.expand_path("solo.rb", chef_config_path).tap do |path|
|
30
|
+
remote.system!(%(echo '#{as_solo_rb}' | #{conditional_sudo("tee #{path}")}))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def chef_cache_path
|
35
|
+
@chef_cache_path ||= "/var/chef/cache".tap do |cache_path|
|
36
|
+
remote.system!(conditional_sudo("/bin/mkdir -m 777 -p #{cache_path}"))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def chef_config_path
|
41
|
+
@chef_config_path ||= "/etc/chef".tap do |path|
|
42
|
+
remote.system!(conditional_sudo("/bin/mkdir -m 777 -p #{path}"))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def cookbook_paths
|
47
|
+
@cookbook_paths ||= ["/var/chef/cookbooks".tap do |remote_path|
|
48
|
+
remote.system!(conditional_sudo("/bin/mkdir -m 777 -p #{remote_path}"))
|
49
|
+
super.each { |path| remote.upload("#{path}/", remote_path) }
|
50
|
+
end]
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
def conditional_sudo(command)
|
55
|
+
root? ? command : "/usr/bin/sudo -E #{command}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def root?
|
59
|
+
remote.user == "root"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "hashie"
|
2
|
+
|
3
|
+
module Bakist
|
4
|
+
class RoyalCrown < Hashie::Trash
|
5
|
+
property :path
|
6
|
+
property :recipes, :default => []
|
7
|
+
property :cookbook_paths, :default => []
|
8
|
+
property :node_attributes, :default => Hashie::Mash.new,
|
9
|
+
:transform_with => lambda { |v| Hashie::Mash.new(v) }
|
10
|
+
property :env_variable_switches, :default => Hashie::Mash.new,
|
11
|
+
:transform_with => lambda { |v| Hashie::Mash.new(v) }
|
12
|
+
|
13
|
+
def node_attributes=(hash)
|
14
|
+
self["node_attributes"] = Hashie::Mash.new(hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
def merge!(other_royal_crown)
|
18
|
+
merge_recipes(other_royal_crown["recipes"])
|
19
|
+
merge_cookbook_paths(other_royal_crown["cookbook_paths"])
|
20
|
+
self.node_attributes.deep_merge!(other_royal_crown["node_attributes"])
|
21
|
+
self.env_variable_switches = other_royal_crown["env_variable_switches"]
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def merge_recipes(new_recipes = [])
|
26
|
+
merge_array_property("recipes", new_recipes)
|
27
|
+
end
|
28
|
+
|
29
|
+
def merge_cookbook_paths(new_cookbook_paths = [])
|
30
|
+
merge_array_property("cookbook_paths", new_cookbook_paths)
|
31
|
+
end
|
32
|
+
|
33
|
+
def env_variable_switches=(hash)
|
34
|
+
self["env_variable_switches"] ||= Hashie::Mash.new
|
35
|
+
self["env_variable_switches"].merge!(Hashie::Mash.new(hash))
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_yaml
|
39
|
+
to_hash.tap do |hash|
|
40
|
+
hash.delete("path")
|
41
|
+
self.class.nilable_properties.each { |k| hash[k] = nil if hash[k].empty? }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def save
|
46
|
+
return self unless path
|
47
|
+
File.open(path, "w+") { |file| file.write(YAML.dump(to_yaml)) }
|
48
|
+
self
|
49
|
+
end
|
50
|
+
|
51
|
+
def reload
|
52
|
+
self.class.from_file(path)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.from_file(file_path)
|
56
|
+
new(read_config(file_path).merge("path" => file_path))
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.read_config(yaml_file)
|
60
|
+
content = File.read(yaml_file)
|
61
|
+
YAML.load(ERB.new(content).result).tap do |hash|
|
62
|
+
nilable_properties.each do |key|
|
63
|
+
hash.delete(key) if hash[key].nil?
|
64
|
+
end if hash
|
65
|
+
end || {}
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def self.nilable_properties
|
70
|
+
(properties - [:path]).map(&:to_s)
|
71
|
+
end
|
72
|
+
|
73
|
+
def merge_array_property(property_name, values)
|
74
|
+
self[property_name] ||= []
|
75
|
+
self[property_name] += values
|
76
|
+
self[property_name].uniq!
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
metadata
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bakist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.7
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mike Mackintosh
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: chef
|
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: librarian-chef
|
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: thor
|
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: '2.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: net-ssh
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: awesome_print
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
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
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: guard-bundler
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: guard-shell
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rb-fsevent
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - '>='
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: terminal-notifier-guard
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - '>='
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: gem-release
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - '>='
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - '>='
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
description: Makes running chef-solo easy.
|
196
|
+
email:
|
197
|
+
- mike.mackintosh@gmail.com
|
198
|
+
executables:
|
199
|
+
- bake
|
200
|
+
extensions: []
|
201
|
+
extra_rdoc_files: []
|
202
|
+
files:
|
203
|
+
- .gitignore
|
204
|
+
- Gemfile
|
205
|
+
- LICENSE
|
206
|
+
- bakist.gemspec
|
207
|
+
- bin/bake
|
208
|
+
- lib/bakist.rb
|
209
|
+
- lib/bakist/cli.rb
|
210
|
+
- lib/bakist/config.rb
|
211
|
+
- lib/bakist/remote.rb
|
212
|
+
- lib/bakist/remote_config.rb
|
213
|
+
- lib/bakist/royal_crown.rb
|
214
|
+
- lib/bakist/version.rb
|
215
|
+
homepage: http://github.com/mikemackintosh/bakist
|
216
|
+
licenses:
|
217
|
+
- MIT
|
218
|
+
metadata: {}
|
219
|
+
post_install_message:
|
220
|
+
rdoc_options: []
|
221
|
+
require_paths:
|
222
|
+
- lib
|
223
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
224
|
+
requirements:
|
225
|
+
- - '>='
|
226
|
+
- !ruby/object:Gem::Version
|
227
|
+
version: '0'
|
228
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
229
|
+
requirements:
|
230
|
+
- - '>='
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: '0'
|
233
|
+
requirements: []
|
234
|
+
rubyforge_project: bakist
|
235
|
+
rubygems_version: 2.0.14
|
236
|
+
signing_key:
|
237
|
+
specification_version: 4
|
238
|
+
summary: Bakist is a simple way of running chef-solo
|
239
|
+
test_files: []
|