solokit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ree-1.8.7-2010.02@solokit --create
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/LICENCE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Joakim Kolsjö
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1 @@
1
+ Extracting out some code I use to provision servers with chef-solo. Only supports ubuntu.
data/lib/chef.rb ADDED
@@ -0,0 +1,57 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'ssh.rb'))
2
+
3
+ class Chef
4
+ def initialize(ip, name, env, debug_ssh, user = 'root')
5
+ @ip, @name, @env = ip, name, env
6
+ @ssh = SSH.new(ip, user, debug_ssh)
7
+ end
8
+
9
+ def install
10
+ return true if installed?
11
+ puts "#{@name} (#{@env}): Installing chef..."
12
+ @ssh.run('export DEBIAN_FRONTEND=noninteractive; apt-get update && apt-get upgrade -y && apt-get install ruby ruby1.8-dev libopenssl-ruby wget rsync build-essential -y && wget http://production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz && tar xfz rubygems-1.3.7.tgz && cd rubygems-1.3.7 && ruby setup.rb && cd .. && rm -rf rubygems-1.3.7* && ln -s /usr/bin/gem1.8 /usr/bin/gem && gem install chef ohai --no-ri --no-rdoc')
13
+ end
14
+
15
+ def upload(root = "/")
16
+ @ssh.run("rm -rf #{root}var/chef-solo", false) &&
17
+ @ssh.run("rm -rf #{root}etc/chef", false) &&
18
+ upload_files("cookbooks/upstream/", "#{root}var/chef-solo/upstream-cookbooks") &&
19
+ upload_files("cookbooks/site/", "#{root}var/chef-solo/site-cookbooks") &&
20
+ (File.exists?("envs/#{@env}/cookbooks") ?
21
+ upload_files("envs/#{@env}/cookbooks/*", "#{root}var/chef-solo/site-cookbooks") :
22
+ true) &&
23
+ upload_files("chef/*", "#{root}etc/chef") &&
24
+ upload_files("envs/#{@env}/chef/", "#{root}etc/chef")
25
+ end
26
+
27
+ def run(debug = false, root = "/")
28
+ puts "\n#{@name} (#{@env}): Running chef..."
29
+ if debug
30
+ @ssh.run("#{custom_ruby_path(root)} chef-solo -c #{root}etc/chef/solo.rb -j #{root}etc/chef/#{@name}.json -l debug", false)
31
+ else
32
+ @ssh.run("#{custom_ruby_path(root)} chef-solo -c #{root}etc/chef/solo.rb -j #{root}etc/chef/#{@name}.json", false)
33
+ end
34
+ end
35
+
36
+ def self.provision!(env, host, config)
37
+ chef = Chef.new(host, "server", env, config.debug_ssh)
38
+ chef.install || raise("Chef install failed on #{env}")
39
+ chef.upload || raise("Chef upload failed on #{env}")
40
+ chef.run(config.debug_chef) || raise("Chef failed on #{env}")
41
+ end
42
+
43
+ private
44
+
45
+ def custom_ruby_path(root)
46
+ "PATH=\"#{root}ruby/bin:/sbin:$PATH\""
47
+ end
48
+
49
+ def upload_files(from, to)
50
+ @ssh.run("mkdir -p #{to}") &&
51
+ @ssh.rsync(from, to, true)
52
+ end
53
+
54
+ def installed?
55
+ @ssh.run('gem list chef | grep chef')
56
+ end
57
+ end
@@ -0,0 +1,19 @@
1
+ require 'ostruct'
2
+
3
+ class Configuration < OpenStruct
4
+ def initialize(*envs)
5
+ shared_config = YAML.load_file("config.yml")
6
+
7
+ config = shared_config
8
+ envs.each do |env|
9
+ env_config_file = "envs/#{env}/config.yml"
10
+
11
+ config = File.exists?(env_config_file) ?
12
+ YAML.load_file(env_config_file).merge(config) :
13
+ config
14
+ end
15
+
16
+ super(config)
17
+ end
18
+ end
19
+
@@ -0,0 +1,3 @@
1
+ module Solokit
2
+ VERSION = "0.0.1"
3
+ end
data/lib/solokit.rb ADDED
@@ -0,0 +1,4 @@
1
+ require File.join(File.dirname(__FILE__), "chef.rb")
2
+ require File.join(File.dirname(__FILE__), "user_json_generator.rb")
3
+ require File.join(File.dirname(__FILE__), "configuration.rb")
4
+
data/lib/ssh.rb ADDED
@@ -0,0 +1,33 @@
1
+ class SSH
2
+ def initialize(ip, user, debug)
3
+ @ip, @user, @debug = ip, user, debug
4
+ end
5
+
6
+ def run(command, quiet = true)
7
+ run_command("ssh #{ssh_opts} #{@user}@#{@ip} '#{command}' #{supress_output(quiet)}")
8
+ end
9
+
10
+ def rsync(source, target, quiet = false)
11
+ run_command("rsync -e 'ssh #{ssh_opts}' -az #{source} #{@user}@#{@ip}:#{target} #{supress_output(quiet)}")
12
+ end
13
+
14
+ private
15
+
16
+ def supress_output(hide_stdout)
17
+ if @debug
18
+ ""
19
+ else
20
+ "#{hide_stdout ? '2> /dev/null 1> /dev/null' : '2> /dev/null'}"
21
+ end
22
+ end
23
+
24
+ def run_command(cmd)
25
+ puts "SSH | #{cmd}" if @debug
26
+ system(cmd)
27
+ end
28
+
29
+ def ssh_opts
30
+ "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
31
+ end
32
+ end
33
+
@@ -0,0 +1,100 @@
1
+ require 'yaml'
2
+ require 'active_support'
3
+ require 'active_support/json/encoding'
4
+
5
+ class UserJsonGenerator
6
+
7
+ def initialize(key_path, env, opts = {})
8
+ @key_path = key_path
9
+
10
+ data = YAML.load_file("users.yml")
11
+
12
+ @default_hash = data["default_hash"]
13
+ @users = data["users"]
14
+ @groups = data["groups"]
15
+ @env = data["envs"][env]
16
+ @opts = { :home => "/home" }.merge(opts)
17
+ end
18
+
19
+ def generate(target)
20
+ if ENV['DEBUG_USER_JSON']
21
+ require 'pp'
22
+ ::PP.pp generate_json
23
+ exit 0
24
+ end
25
+ File.open(target, 'w') { |f| f.write(generate_json) }
26
+ end
27
+
28
+ def self.generate!(env, opts = {})
29
+ UserJsonGenerator.new("public_keys", env, opts).generate("envs/#{env}/chef/roles/users.json")
30
+ end
31
+
32
+ private
33
+
34
+ def generate_json
35
+ {
36
+ :name => "Users",
37
+ :chef_type => "role",
38
+ :json_class => "Chef::Role",
39
+ :override_attributes => {
40
+ :users => env_users.inject({}) { |h, user|
41
+ h[user] = {
42
+ :password => (@users[user] || {})["hash"] || @default_hash,
43
+ :home => (user == 'root' ? '/root' : [ @opts[:home], user ].join('/')),
44
+ :hidden_home => !!(@users[user] || {})["hidden_home"]
45
+ }; h
46
+ },
47
+ :ssh_keys => env_users.inject({}) { |h, user|
48
+ h[user] = get_keys(user); h
49
+ },
50
+ :authorization => {
51
+ :sudo => { :users => env_sudo_users }
52
+ }
53
+ },
54
+ :run_list => [ "recipe[users]", "recipe[sudo]" ]
55
+ }.send(ENV['DEBUG_USER_JSON'] ? 'to_hash' : 'to_json')
56
+ #.gsub(/\{/, "{\n").gsub(/\}/, "}\n")
57
+ end
58
+
59
+ def env_users
60
+ resolve_users(@env["users"].split)
61
+ end
62
+
63
+ def env_sudo_users
64
+ @env["sudo"] && resolve_users(@env["sudo"].split)
65
+ end
66
+
67
+ def resolve_users(list)
68
+ list.map { |item|
69
+ if item.include?("group")
70
+ fetch_group_users(item)
71
+ else
72
+ item
73
+ end
74
+ }.flatten
75
+ end
76
+
77
+ def get_keys(user)
78
+ (@users[user] || {})["keys"].to_s.split.map do |key_name|
79
+ if key_name.include?("group")
80
+ keys_from_group(key_name)
81
+ else
82
+ key_file = "#{@key_path}/#{key_name}.pub"
83
+ if File.exists?(key_file)
84
+ File.read(key_file).chomp
85
+ else
86
+ raise "Could not find key file: #{key_file}."
87
+ end
88
+ end
89
+ end.join("\n")
90
+ end
91
+
92
+ def fetch_group_users(name)
93
+ @groups[name.split('/').last].split
94
+ end
95
+
96
+ def keys_from_group(name)
97
+ @groups[name.split("/").last].split.map { |user| get_keys(user) }
98
+ end
99
+ end
100
+
data/solokit.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "solokit/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "solokit"
7
+ s.version = Solokit::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Joakim Kolsjö"]
10
+ s.email = ["joakim.kolsjo@gmail.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{}
13
+ s.description = %q{}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency "activesupport", ">= 3.0.0"
21
+ s.add_development_dependency "bundler"
22
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: solokit
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - "Joakim Kolsj\xC3\xB6"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-25 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activesupport
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 0
34
+ version: 3.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 3
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ type: :development
50
+ version_requirements: *id002
51
+ description: ""
52
+ email:
53
+ - joakim.kolsjo@gmail.com
54
+ executables: []
55
+
56
+ extensions: []
57
+
58
+ extra_rdoc_files: []
59
+
60
+ files:
61
+ - .rvmrc
62
+ - Gemfile
63
+ - LICENCE
64
+ - README
65
+ - lib/chef.rb
66
+ - lib/configuration.rb
67
+ - lib/solokit.rb
68
+ - lib/solokit/version.rb
69
+ - lib/ssh.rb
70
+ - lib/user_json_generator.rb
71
+ - solokit.gemspec
72
+ has_rdoc: true
73
+ homepage: ""
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options: []
78
+
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.6.2
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: ""
106
+ test_files: []
107
+