skirnir 0.0.2
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 +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +19 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/ski +72 -0
- data/lib/skirnir.rb +4 -0
- data/lib/skirnir/chef.rb +31 -0
- data/lib/skirnir/node.rb +42 -0
- data/lib/skirnir/site.rb +163 -0
- data/lib/skirnir/version.rb +3 -0
- data/pkg/skirnir-0.0.2.gem +0 -0
- data/skirnir.gemspec +26 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a0e1b499c4beb1871eca335e45ce3d84a596da80
|
4
|
+
data.tar.gz: 55d96459c0281137094fba9155ebc272ba0ebcce
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1f1b164087f21715af27d1b4a34a6c990662a66a4ce11b1a90c0f730c49d21f66fedf678affd7495de3c671bdc3f626426176ab30b57cfff2c845052fb91c0df
|
7
|
+
data.tar.gz: d8236dca09bc58d2e14673e6a3cc8a951a6ce868cedf9a200cadaeb9a85748a744002987229fa532cbe2f96cce0e0bbe07c07035a966d8574196fba9028b6d29
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.idea
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 irontoby
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Skirnir
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'skirnir'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install skirnir
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( https://github.com/[my-github-username]/skirnir/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/ski
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'skirnir'
|
4
|
+
require 'pp'
|
5
|
+
|
6
|
+
def show_box_info node, env
|
7
|
+
#file = File.expand_path('config.yml')
|
8
|
+
|
9
|
+
info = Skirnir::Site.new
|
10
|
+
|
11
|
+
if node.nil?
|
12
|
+
info.read_default
|
13
|
+
else
|
14
|
+
info.read(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
pp info.chef_hash_for_node_name node
|
18
|
+
end
|
19
|
+
|
20
|
+
def list_boxes(env='all')
|
21
|
+
info = Skirnir::Site.new
|
22
|
+
|
23
|
+
if env.nil? || env == '' || env == 'all'
|
24
|
+
info.silent = true
|
25
|
+
|
26
|
+
info.all_environments.each do |env|
|
27
|
+
list_nodes info, env
|
28
|
+
puts "\n"
|
29
|
+
end
|
30
|
+
else
|
31
|
+
list_nodes info, env
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
def list_nodes(info, env)
|
37
|
+
info.read env
|
38
|
+
puts "Nodes in #{env}:"
|
39
|
+
info.nodes.map {|node| puts format(" %8s %s\n", node.name, node.ip_int)}
|
40
|
+
end
|
41
|
+
|
42
|
+
def give_help
|
43
|
+
puts <<-eos
|
44
|
+
ski [command] [node] [env]
|
45
|
+
|
46
|
+
AVAILABLE COMMANDS:
|
47
|
+
show <node> [env] Outputs Chef/node JSON
|
48
|
+
list [env] List node names, or nodes for env
|
49
|
+
help Print this help message.
|
50
|
+
eos
|
51
|
+
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
|
55
|
+
command, node, env = ARGF.argv
|
56
|
+
|
57
|
+
give_help if command.nil?
|
58
|
+
|
59
|
+
case command
|
60
|
+
when 'help'
|
61
|
+
give_help
|
62
|
+
when 'show'
|
63
|
+
show_box_info node, env
|
64
|
+
when 'list'
|
65
|
+
env = node
|
66
|
+
list_boxes env
|
67
|
+
else
|
68
|
+
give_help
|
69
|
+
end
|
70
|
+
|
71
|
+
exit
|
72
|
+
|
data/lib/skirnir.rb
ADDED
data/lib/skirnir/chef.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
class Skirnir::Chef
|
2
|
+
def initialize(defs)
|
3
|
+
@defs = defs
|
4
|
+
end
|
5
|
+
|
6
|
+
def set(role, *path, value)
|
7
|
+
#where = path.join('/')
|
8
|
+
#puts "Set for role #{role}: #{where} = #{value}"
|
9
|
+
|
10
|
+
h = Hash.construct(path, value)
|
11
|
+
@defs[role] = {} unless @defs.has_key?(role)
|
12
|
+
|
13
|
+
@defs[role].deep_merge!(h)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param roles [Array]
|
17
|
+
def get_for_roles(*roles)
|
18
|
+
roles.flatten!
|
19
|
+
|
20
|
+
roles.unshift('all') unless roles.include?('all')
|
21
|
+
|
22
|
+
result = {}
|
23
|
+
|
24
|
+
roles.each do |role|
|
25
|
+
result.deep_merge!(@defs[role]) if @defs.has_key?(role)
|
26
|
+
end
|
27
|
+
|
28
|
+
result
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
data/lib/skirnir/node.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
class Skirnir::Node
|
2
|
+
attr_accessor :name, :roles, :chef, :run_list, :ip_int, :ip_ext
|
3
|
+
|
4
|
+
def initialize(site_name, config)
|
5
|
+
@name = config['name']
|
6
|
+
@roles = config['roles']
|
7
|
+
@run_list = @roles.map{|role| "recipe[#{site_name}::#{role}_box]"}
|
8
|
+
@ip_int = config['ip_int']
|
9
|
+
@ip_ext = config['ip_ext'] || @ip_int
|
10
|
+
|
11
|
+
chef_config = config['chef'] || {}
|
12
|
+
|
13
|
+
@chef = Skirnir::Chef.new({'all' => chef_config})
|
14
|
+
|
15
|
+
to_h.each_pair do |key, value|
|
16
|
+
@chef.set('all', 'box', key, value)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_role?(role)
|
22
|
+
@roles.include? role
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Hash]
|
26
|
+
def to_h
|
27
|
+
{
|
28
|
+
'name' => @name,
|
29
|
+
'roles' => @roles,
|
30
|
+
'ip_int' => @ip_int,
|
31
|
+
'ip_ext' => @ip_ext
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
# returns the chef definitions specific for this node
|
36
|
+
def chef_hash
|
37
|
+
@chef.get_for_roles('all')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
|
data/lib/skirnir/site.rb
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'deep_merge'
|
3
|
+
|
4
|
+
DEFAULT_FILENAME = 'config.yml'
|
5
|
+
LOCAL_FILENAME = 'local.yml'
|
6
|
+
|
7
|
+
class Skirnir::Site
|
8
|
+
attr_reader :info, :nodes, :chef, :vagrant, :config
|
9
|
+
attr_accessor :silent
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@silent = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def read_default
|
16
|
+
env=get_env_from_local_section('vagrant')
|
17
|
+
|
18
|
+
read(env, 'config.yml')
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_for_update
|
22
|
+
env = get_env_from_local_section('update')
|
23
|
+
|
24
|
+
read(env, 'config.yml')
|
25
|
+
end
|
26
|
+
|
27
|
+
def read(env, filename = DEFAULT_FILENAME)
|
28
|
+
all = get_config filename
|
29
|
+
puts "- Section: #{env}\n\n" unless @silent
|
30
|
+
|
31
|
+
config = all['common'].deep_merge!(all[env])
|
32
|
+
|
33
|
+
if File.exists?(LOCAL_FILENAME)
|
34
|
+
local = YAML.load(IO.read(LOCAL_FILENAME))
|
35
|
+
config.deep_merge!(local)
|
36
|
+
end
|
37
|
+
|
38
|
+
@config = config
|
39
|
+
@info = config['info']
|
40
|
+
@vagrant = config['vagrant']
|
41
|
+
|
42
|
+
@chef = Skirnir::Chef.new(config['chef'])
|
43
|
+
@nodes = config['nodes'].map {|node| Skirnir::Node.new(site_name, node)}
|
44
|
+
|
45
|
+
setup_role_chefs
|
46
|
+
|
47
|
+
@nodes
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Array<Node>]
|
51
|
+
def nodes_with_role(role)
|
52
|
+
@nodes.select {|node| node.has_role? role}
|
53
|
+
end
|
54
|
+
|
55
|
+
def chef_hash_for_node_name(name)
|
56
|
+
node = (@nodes.select {|node| node.name == name}).first
|
57
|
+
|
58
|
+
raise "Unknown node name ''#{name}''" if node.nil?
|
59
|
+
|
60
|
+
chef_hash_for_node(node)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param node [Node]
|
64
|
+
def chef_hash_for_node(node)
|
65
|
+
result = chef.get_for_roles(node.roles)
|
66
|
+
result.deep_merge!(node.chef_hash)
|
67
|
+
|
68
|
+
nodes_info = @nodes.map {|n| n.to_h}
|
69
|
+
nodes_hash = Hash.construct(%w(site nodes), nodes_info)
|
70
|
+
result.deep_merge!(nodes_hash)
|
71
|
+
|
72
|
+
result
|
73
|
+
end
|
74
|
+
|
75
|
+
def chef_data_for_all_nodes
|
76
|
+
result = {}
|
77
|
+
|
78
|
+
@nodes.each do |node|
|
79
|
+
name = node.name
|
80
|
+
|
81
|
+
name += @info['node_suffix'] unless @info['node_suffix'].empty?
|
82
|
+
|
83
|
+
attribs = chef_hash_for_node(node)
|
84
|
+
run_list = node.run_list
|
85
|
+
|
86
|
+
result[name] = { 'attributes' => attribs, 'run_list' => run_list}
|
87
|
+
end
|
88
|
+
|
89
|
+
result
|
90
|
+
end
|
91
|
+
|
92
|
+
def site_name
|
93
|
+
@info['site_name']
|
94
|
+
end
|
95
|
+
|
96
|
+
def all_environments(filename = DEFAULT_FILENAME)
|
97
|
+
all = get_config
|
98
|
+
|
99
|
+
all.keys.select {|x| x != 'common'}
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
def get_config(filename = DEFAULT_FILENAME)
|
104
|
+
puts "Reading config from #{filename}\n" unless @silent
|
105
|
+
YAML.load(IO.read(filename))
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_env_from_local_section(section_name)
|
109
|
+
raise "Can't determine default environment; #{LOCAL_FILENAME} missing" unless File.exists?(LOCAL_FILENAME)
|
110
|
+
|
111
|
+
local = YAML.load(IO.read(LOCAL_FILENAME))
|
112
|
+
|
113
|
+
unless local.has_key?(section_name) && local[section_name].has_key?('env')
|
114
|
+
raise "Can't determine default environment; YAML #{section_name}/env entry missing"
|
115
|
+
end
|
116
|
+
|
117
|
+
local[section_name]['env']
|
118
|
+
end
|
119
|
+
|
120
|
+
def setup_role_chefs
|
121
|
+
setup_chef_db_host
|
122
|
+
setup_chef_nginx
|
123
|
+
setup_chef_app_should_migrate
|
124
|
+
end
|
125
|
+
|
126
|
+
def setup_chef_db_host
|
127
|
+
db_nodes = nodes_with_role('db')
|
128
|
+
|
129
|
+
raise "Expected single node with role 'db'; found #{db_nodes.count}" if db_nodes.count != 1
|
130
|
+
|
131
|
+
db_ip = db_nodes[0].ip_int
|
132
|
+
app_nodes = nodes_with_role('app')
|
133
|
+
|
134
|
+
is_local = app_nodes.all? {|node| node.ip_int == db_ip}
|
135
|
+
|
136
|
+
@chef.set('all', %w(site db host), is_local ? 'localhost' : db_ip)
|
137
|
+
@chef.set('all', %w(site db is_local), is_local)
|
138
|
+
@chef.set('db', %w(site db bind_address), is_local ? '127.0.0.1' : db_ip)
|
139
|
+
end
|
140
|
+
|
141
|
+
def setup_chef_nginx
|
142
|
+
# TODO this is no good for staging, need is_local for web too
|
143
|
+
web_ips = nodes_with_role('web').map{|node| node.ip_int}.map{|ip| "#{ip}/32"}
|
144
|
+
|
145
|
+
@chef.set('app', ['nginx'], { 'authorized_ips' => web_ips, 'realip' => { 'addresses' => web_ips}})
|
146
|
+
end
|
147
|
+
|
148
|
+
def setup_chef_app_should_migrate
|
149
|
+
should_migrate = true
|
150
|
+
|
151
|
+
nodes_with_role('app').each do |node|
|
152
|
+
node.chef.set('all', %w(site app should_migrate), should_migrate)
|
153
|
+
should_migrate = false
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
class Hash
|
160
|
+
def self.construct(*path, value)
|
161
|
+
path.flatten.reverse.inject(value) {|a, n| { n => a}}
|
162
|
+
end
|
163
|
+
end
|
Binary file
|
data/skirnir.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'skirnir/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'skirnir'
|
8
|
+
spec.version = Skirnir::VERSION
|
9
|
+
spec.date = '2014-06-16'
|
10
|
+
spec.authors = ['Toby Johnson']
|
11
|
+
spec.email = ['irontoby@gmail.com']
|
12
|
+
spec.summary = 'Tools for working with Chef, Vagrant and Digital Ocean'
|
13
|
+
spec.description = 'Coming soon...'
|
14
|
+
spec.homepage = 'http://rubygems.org/gems/skirnir'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
|
25
|
+
spec.add_runtime_dependency 'deep_merge', '~> 1.0.1'
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: skirnir
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Toby Johnson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
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: deep_merge
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.0.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.1
|
55
|
+
description: Coming soon...
|
56
|
+
email:
|
57
|
+
- irontoby@gmail.com
|
58
|
+
executables:
|
59
|
+
- ski
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- Gemfile
|
65
|
+
- Gemfile.lock
|
66
|
+
- LICENSE.txt
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- bin/ski
|
70
|
+
- lib/skirnir.rb
|
71
|
+
- lib/skirnir/chef.rb
|
72
|
+
- lib/skirnir/node.rb
|
73
|
+
- lib/skirnir/site.rb
|
74
|
+
- lib/skirnir/version.rb
|
75
|
+
- pkg/skirnir-0.0.2.gem
|
76
|
+
- skirnir.gemspec
|
77
|
+
homepage: http://rubygems.org/gems/skirnir
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.2.2
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Tools for working with Chef, Vagrant and Digital Ocean
|
101
|
+
test_files: []
|