bixby-provision 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +29 -0
- data/Gemfile.lock +192 -0
- data/Rakefile +13 -0
- data/VERSION +1 -0
- data/Vagrantfile +64 -0
- data/bin/bixby-provision +6 -0
- data/bixby-provision.gemspec +113 -0
- data/lib/bixby-provision.rb +2 -0
- data/lib/bixby/provision.rb +65 -0
- data/lib/bixby/provision/app.rb +34 -0
- data/lib/bixby/provision/dsl.rb +23 -0
- data/lib/bixby/provision/dsl/base.rb +76 -0
- data/lib/bixby/provision/dsl/bundler.rb +18 -0
- data/lib/bixby/provision/dsl/config.rb +124 -0
- data/lib/bixby/provision/dsl/dir.rb +34 -0
- data/lib/bixby/provision/dsl/file.rb +108 -0
- data/lib/bixby/provision/dsl/inventory.rb +18 -0
- data/lib/bixby/provision/dsl/meteor.rb +30 -0
- data/lib/bixby/provision/dsl/nodejs.rb +73 -0
- data/lib/bixby/provision/dsl/npm.rb +18 -0
- data/lib/bixby/provision/dsl/ntp.rb +41 -0
- data/lib/bixby/provision/dsl/packager/apt.rb +46 -0
- data/lib/bixby/provision/dsl/packager/base.rb +11 -0
- data/lib/bixby/provision/dsl/packager/npm.rb +67 -0
- data/lib/bixby/provision/dsl/packager/yum.rb +100 -0
- data/lib/bixby/provision/dsl/packager/yum/epel.rb +71 -0
- data/lib/bixby/provision/dsl/packager/yum/mongodb.rb +43 -0
- data/lib/bixby/provision/dsl/ruby.rb +21 -0
- data/lib/bixby/provision/dsl/run_control.rb +49 -0
- data/lib/bixby/provision/dsl/scm.rb +34 -0
- data/lib/bixby/provision/dsl/scm/base.rb +11 -0
- data/lib/bixby/provision/dsl/scm/git.rb +89 -0
- data/lib/bixby/provision/dsl/scm/svn.rb +11 -0
- data/lib/bixby/provision/dsl/service.rb +56 -0
- data/lib/bixby/provision/dsl/services/base.rb +11 -0
- data/lib/bixby/provision/dsl/services/init.rb +40 -0
- data/lib/bixby/provision/dsl/system.rb +53 -0
- data/lib/bixby/provision/dsl/util/file.rb +100 -0
- data/lib/bixby/provision/dsl/variable.rb +27 -0
- data/lib/bixby/provision/manifest.rb +49 -0
- data/lib/bixby/provision/manifest/dsl_proxy.rb +17 -0
- data/manifest.rb +31 -0
- data/tasks/coverage.rake +2 -0
- data/tasks/jeweler.rake +21 -0
- data/tasks/test.rake +5 -0
- data/tasks/yard.rake +2 -0
- metadata +244 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
module Bixby
|
3
|
+
module Provision
|
4
|
+
module Packager
|
5
|
+
class Yum < PackagerBase
|
6
|
+
|
7
|
+
module MongoDB
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def install_mongodb(opts)
|
12
|
+
|
13
|
+
file = File.join(YUM_REPOS_D, "mongodb.repo")
|
14
|
+
if File.exists?(file) then
|
15
|
+
logger.info "[yum] mongodb repo already installed"
|
16
|
+
return
|
17
|
+
end
|
18
|
+
|
19
|
+
logger.info "[yum] installing mongodb repo"
|
20
|
+
|
21
|
+
arch = amd64?() ? "x86_64" : "i686"
|
22
|
+
|
23
|
+
File.open(file, 'w') do |f|
|
24
|
+
f.puts <<-EOF
|
25
|
+
[mongodb]
|
26
|
+
name=MongoDB Repository
|
27
|
+
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/#{arch}/
|
28
|
+
gpgcheck=0
|
29
|
+
enabled=1
|
30
|
+
EOF
|
31
|
+
end
|
32
|
+
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
end # MongoDB
|
37
|
+
|
38
|
+
Yum.register_plugin(MongoDB)
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module Bixby
|
3
|
+
module Provision
|
4
|
+
|
5
|
+
class RunControl < Base
|
6
|
+
|
7
|
+
EXPORTS = [:first_boot]
|
8
|
+
|
9
|
+
def first_boot(&block)
|
10
|
+
if first_boot_has_run? then
|
11
|
+
logger.info "first_boot already ran"
|
12
|
+
return
|
13
|
+
end
|
14
|
+
|
15
|
+
logger.info "running first_boot block"
|
16
|
+
begin
|
17
|
+
block.call
|
18
|
+
rescue Exception => ex
|
19
|
+
# TODO fail!
|
20
|
+
raise ex
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
touch_first_boot_state
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def first_boot_has_run?
|
31
|
+
File.exists?(first_boot_state)
|
32
|
+
end
|
33
|
+
|
34
|
+
def first_boot_state
|
35
|
+
Bixby.path("var", "provision", "first_boot")
|
36
|
+
end
|
37
|
+
|
38
|
+
def touch_first_boot_state
|
39
|
+
f = first_boot_state
|
40
|
+
FileUtils.mkdir_p(File.dirname(f))
|
41
|
+
FileUtils.touch(f)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
register_dsl RunControl, "run_control"
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
require "bixby/provision/dsl/scm/base"
|
3
|
+
require "bixby/provision/dsl/scm/git"
|
4
|
+
require "bixby/provision/dsl/scm/svn"
|
5
|
+
|
6
|
+
module Bixby
|
7
|
+
module Provision
|
8
|
+
|
9
|
+
class SCM < Base
|
10
|
+
|
11
|
+
EXPORTS = [:checkout]
|
12
|
+
|
13
|
+
def checkout(uri, opts={})
|
14
|
+
handler(uri).checkout(uri, opts)
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def handler(uri)
|
21
|
+
@handler ||= if uri =~ %r{\.git$} then
|
22
|
+
SCM::Git.new(self)
|
23
|
+
else
|
24
|
+
# TODO add check
|
25
|
+
SCM::SVN.new(self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
register_dsl SCM
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
|
2
|
+
require "git"
|
3
|
+
|
4
|
+
module Bixby
|
5
|
+
module Provision
|
6
|
+
class SCM < Base
|
7
|
+
|
8
|
+
class Git < SCMBase
|
9
|
+
|
10
|
+
def checkout(uri, opts)
|
11
|
+
path = opts.delete(:path)
|
12
|
+
branch = opts.delete(:branch) || "master"
|
13
|
+
|
14
|
+
if path.nil? then
|
15
|
+
# TODO raise
|
16
|
+
end
|
17
|
+
path = File.expand_path(path)
|
18
|
+
if File.directory? File.join(path, ".git") then
|
19
|
+
logger.info "repository already checked out at #{path}"
|
20
|
+
return
|
21
|
+
end
|
22
|
+
dir.create(path)
|
23
|
+
|
24
|
+
# https://github.com/user/repo.git
|
25
|
+
# git@github.com:user/repo.git
|
26
|
+
# ssh://hg@bitbucket.org/user/repo
|
27
|
+
if uri !~ %r{https?://} && uri =~ %r{^(ssh://)?(.*?@)(.*?)[:/]} then
|
28
|
+
ensure_ssh_verify($3)
|
29
|
+
end
|
30
|
+
|
31
|
+
sys.package "git"
|
32
|
+
|
33
|
+
logger.info "[scm] cloning #{uri} into #{path}, branch: #{branch}"
|
34
|
+
g = ::Git.clone(uri, File.basename(path), :path => File.dirname(path))
|
35
|
+
g.checkout(branch) if branch != "master"
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# Ensure that StrictHostKeyChecking is disabled for the given host
|
42
|
+
#
|
43
|
+
# @param [String] host
|
44
|
+
def ensure_ssh_verify(host)
|
45
|
+
|
46
|
+
config = File.expand_path("~/.ssh/config")
|
47
|
+
str = ""
|
48
|
+
str = File.read(config) if File.exists? config
|
49
|
+
|
50
|
+
add = str.empty?
|
51
|
+
if !add then
|
52
|
+
# see if it's already disabled for the given host
|
53
|
+
found_host = false
|
54
|
+
found_strict = false
|
55
|
+
str.split(/n/).each do |l|
|
56
|
+
|
57
|
+
if l =~ /^\s*Host (.*?)/ then
|
58
|
+
if found_host then
|
59
|
+
add = true if !found_strict
|
60
|
+
found_host = false
|
61
|
+
next
|
62
|
+
end
|
63
|
+
if $1 == host then
|
64
|
+
found_host = true
|
65
|
+
end
|
66
|
+
|
67
|
+
elsif found_host && l =~ /StrictHostKeyChecking \s*no/ then
|
68
|
+
found_strict = true
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
return if !add
|
74
|
+
|
75
|
+
logger.info "[scm] disabling StrictHostKeyChecking for #{host}"
|
76
|
+
str += "\n"
|
77
|
+
str += "Host #{host}\n"
|
78
|
+
str += " StrictHostKeyChecking no\n"
|
79
|
+
|
80
|
+
dir.mkdir "~/.ssh", :chmod => "700"
|
81
|
+
File.open(config, 'w'){ |f| f.write(str) }
|
82
|
+
chmod config, "644"
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
require "bixby/provision/dsl/services/base"
|
3
|
+
require "bixby/provision/dsl/services/init"
|
4
|
+
|
5
|
+
module Bixby
|
6
|
+
module Provision
|
7
|
+
|
8
|
+
class Service < Base
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
super
|
12
|
+
@services = if ubuntu? then
|
13
|
+
Services::Init.new(self)
|
14
|
+
elsif centos? or amazon? then
|
15
|
+
Services::Init.new(self)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def start(name, opts={})
|
20
|
+
if !running?(name) || opts[:force] == true then
|
21
|
+
@services.start(name, opts)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def stop(name, opts={})
|
26
|
+
if running?(name) || opts[:force] == true then
|
27
|
+
@services.stop(name, opts)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def restart(name, opts={})
|
32
|
+
@services.restart(name, opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
def reload(name, opts={})
|
36
|
+
@services.reload(name, opts)
|
37
|
+
end
|
38
|
+
|
39
|
+
def running?(name)
|
40
|
+
@services.running?(name)
|
41
|
+
end
|
42
|
+
|
43
|
+
def ensure(name)
|
44
|
+
if centos? or amazon? then
|
45
|
+
logged_sudo("chkconfig --add #{name}")
|
46
|
+
elsif ubuntu? then
|
47
|
+
logged_sudo("update-rc.d #{name} defaults")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
register_dsl Service
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
module Bixby
|
3
|
+
module Provision
|
4
|
+
module Services
|
5
|
+
|
6
|
+
class Init < ServiceBase
|
7
|
+
|
8
|
+
def start(name, opts={})
|
9
|
+
init("#{name} start")
|
10
|
+
end
|
11
|
+
|
12
|
+
def stop(name, opts={})
|
13
|
+
init("#{name} stop")
|
14
|
+
end
|
15
|
+
|
16
|
+
def restart(name, opts={})
|
17
|
+
init("#{name} restart")
|
18
|
+
end
|
19
|
+
|
20
|
+
def reload(name, opts={})
|
21
|
+
init("#{name} reload")
|
22
|
+
end
|
23
|
+
|
24
|
+
def running?(name)
|
25
|
+
cmd = init("#{name} status")
|
26
|
+
return cmd.success? # exit 0 means it's running (usually.. hopefully!)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def init(args)
|
33
|
+
logged_sudo("/etc/init.d/#{args}")
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
require "bixby/provision/dsl/packager/base"
|
3
|
+
require "bixby/provision/dsl/packager/apt"
|
4
|
+
require "bixby/provision/dsl/packager/yum"
|
5
|
+
require "bixby/provision/dsl/packager/npm"
|
6
|
+
|
7
|
+
module Bixby
|
8
|
+
module Provision
|
9
|
+
|
10
|
+
class System < Base
|
11
|
+
|
12
|
+
EXPORTS = [:refresh_packages, :upgrade_system, :package, :repo]
|
13
|
+
|
14
|
+
attr_reader :packager
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
super
|
18
|
+
@packager = if ubuntu? then
|
19
|
+
Packager::Apt.new(self)
|
20
|
+
elsif centos? or amazon? then
|
21
|
+
Packager::Yum.new(self)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def refresh_packages
|
26
|
+
logger.info "[sys] refresh_packages"
|
27
|
+
packager.refresh
|
28
|
+
end
|
29
|
+
|
30
|
+
def upgrade_system
|
31
|
+
logger.info "[sys] upgrade_system"
|
32
|
+
packager.upgrade_system
|
33
|
+
end
|
34
|
+
|
35
|
+
def package(*packages)
|
36
|
+
packages.flatten!
|
37
|
+
logger.info "[sys] installing packages: " + packages.join(" ")
|
38
|
+
packager.install(*packages)
|
39
|
+
end
|
40
|
+
alias_method :packages, :package
|
41
|
+
|
42
|
+
def repo(name, opts={})
|
43
|
+
if packager.install_repo(name, opts) then
|
44
|
+
refresh_packages
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
register_dsl System, "sys"
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
|
2
|
+
module Bixby
|
3
|
+
module Provision
|
4
|
+
module Util
|
5
|
+
module File
|
6
|
+
|
7
|
+
def chown(path, chown, opts={})
|
8
|
+
if chown.nil? then
|
9
|
+
return
|
10
|
+
end
|
11
|
+
chown.strip!
|
12
|
+
return if chown.empty?
|
13
|
+
|
14
|
+
user, group = chown.split(/:/)
|
15
|
+
user = Process.uid if user == "$USER"
|
16
|
+
group = Process.gid if group == "$GROUP"
|
17
|
+
uid = get_uid(user)
|
18
|
+
gid = get_gid(group)
|
19
|
+
|
20
|
+
logger.info "[chown] #{path} -> '#{get_user(uid)}" + (gid ? ":#{get_group(gid)}'" : "'")
|
21
|
+
|
22
|
+
# always as root
|
23
|
+
if opts[:recurse] or opts[:recursively] then
|
24
|
+
logged_sudo("chown -R #{uid}:#{gid} #{path}")
|
25
|
+
else
|
26
|
+
logged_sudo("chown #{uid}:#{gid} #{path}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Change mode of the given path
|
31
|
+
#
|
32
|
+
# @param [String] path
|
33
|
+
# @param [String] mode File mode given as a string, same as the input to the `chmod` command
|
34
|
+
def chmod(path, mode, opts={})
|
35
|
+
return if mode.nil?
|
36
|
+
|
37
|
+
if mode.kind_of? String then
|
38
|
+
mode.strip!
|
39
|
+
return if mode.empty?
|
40
|
+
|
41
|
+
elsif mode.kind_of? Fixnum then
|
42
|
+
# mode should always be a string
|
43
|
+
# convert fixnum to octal
|
44
|
+
mode = sprintf("%o", mode)
|
45
|
+
if mode.length > 4 then
|
46
|
+
# only want the right-most 4 chars
|
47
|
+
# ex: File.stat = mode=0100440 (file r--r-----) => 33056 => "100440" => "0440"
|
48
|
+
mode = mode[mode.length-4, mode.length]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
logger.info "[chmod] #{path} -> '#{mode}'"
|
53
|
+
|
54
|
+
# always as root
|
55
|
+
if opts[:recurse] or opts[:recursively] then
|
56
|
+
logged_sudo("chmod -R #{mode} #{path}")
|
57
|
+
else
|
58
|
+
logged_sudo("chmod #{mode} #{path}")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Get the SHA-256 hex digest of the given file
|
63
|
+
#
|
64
|
+
# @param [String] filename
|
65
|
+
#
|
66
|
+
# @return [String] sha256 hash in hexadecimal form
|
67
|
+
def sha256sum(filename)
|
68
|
+
if ::File.readable? filename then
|
69
|
+
return Digest::SHA2.new(256).file(filename).hexdigest()
|
70
|
+
end
|
71
|
+
|
72
|
+
# read as root
|
73
|
+
if cmd = which("sha256sum") then
|
74
|
+
return logged_sudo("#{cmd} #{filename}").stdout.split(/\s+/).first
|
75
|
+
end
|
76
|
+
|
77
|
+
# use cat - may not work for binaries
|
78
|
+
str = logged_sudo("cat #{filename}").stdout
|
79
|
+
return Digest::SHA2.new(256).update(str).hexdigest()
|
80
|
+
end
|
81
|
+
|
82
|
+
# Locate the given command, if it exists
|
83
|
+
#
|
84
|
+
# @param [String] cmd to locate
|
85
|
+
#
|
86
|
+
# @return [String] path to command if it exists, or nil
|
87
|
+
def which(cmd)
|
88
|
+
ret = systemu("which #{cmd}")
|
89
|
+
if ret.success? then
|
90
|
+
return ret.stdout.strip
|
91
|
+
else
|
92
|
+
return nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
alias_method :command_exists?, :which
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|