aubergine 0.0.1
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/lib/aubergine.rb +19 -0
- data/lib/aubergine/path.rb +28 -0
- data/lib/aubergine/satellite.rb +27 -0
- data/lib/aubergine/server.rb +40 -0
- data/lib/courgette.rb +17 -0
- data/lib/courgette/client.rb +28 -0
- data/lib/courgette/device.rb +31 -0
- data/lib/courgette/executor.rb +24 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 19ec225118a39c85897d5a86b31a684f29cf8b57
|
4
|
+
data.tar.gz: 922c8d730ae1d65c9a43c7b5556e41296296e70f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e858e0d0368e5ee4352c5c7e091d33dcbe5010d2da05b71cde1e53df5e2c7b1168d9e13669a945402bd85d6f67f8f4607a34a8a717cc5b75bcd2e902d01f8c46
|
7
|
+
data.tar.gz: 7c4109b32f987c2e366b0316a163ca06403e3c52aac30c16197b49bd8672fcb54a1cef9719cd0cc4dd6a06a3b0f5cb31e50d5b8f5b43a5a0eb8c8a44c75353c9
|
data/lib/aubergine.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require 'git'
|
5
|
+
|
6
|
+
require_relative './aubergine/satellite.rb'
|
7
|
+
require_relative './aubergine/path.rb'
|
8
|
+
require_relative './aubergine/server.rb'
|
9
|
+
|
10
|
+
module Aubergine
|
11
|
+
def self.register(data)
|
12
|
+
Satellite.all = data
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.run!(repository)
|
16
|
+
Path.configure(repository)
|
17
|
+
Aubergine::Server.run!
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Aubergine
|
2
|
+
class Path
|
3
|
+
def self.repository
|
4
|
+
@@repository
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.configure(repository)
|
8
|
+
@@repository = repository
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(satellite, ip)
|
12
|
+
@satellite = satellite
|
13
|
+
@ip = ip
|
14
|
+
end
|
15
|
+
|
16
|
+
def satellite
|
17
|
+
"#{@@repository}/#{@satellite}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def full
|
21
|
+
"#{@@repository}/#{@satellite}/#{@ip}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def short
|
25
|
+
"#{@satellite}/#{@ip}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Aubergine
|
2
|
+
class Satellite
|
3
|
+
attr_reader :devices
|
4
|
+
|
5
|
+
def initialize(name, devices)
|
6
|
+
@name = name
|
7
|
+
@devices = devices
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.find(key)
|
11
|
+
satellite = @@all.find { |satellite| satellite[:key] == key }
|
12
|
+
if satellite
|
13
|
+
new(satellite[:name], satellite[:devices])
|
14
|
+
else
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
@name
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.all=(data)
|
24
|
+
@@all = data
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Aubergine
|
2
|
+
class Server < Sinatra::Base
|
3
|
+
configure do
|
4
|
+
enable :logging
|
5
|
+
end
|
6
|
+
|
7
|
+
before do
|
8
|
+
@satellite = Satellite.find(request.env['HTTP_COURGETTE'])
|
9
|
+
return status(401) unless @satellite
|
10
|
+
end
|
11
|
+
|
12
|
+
get '/configuration.json' do
|
13
|
+
content_type 'application/json'
|
14
|
+
@satellite.devices.to_json
|
15
|
+
end
|
16
|
+
|
17
|
+
post '/devices/:ip' do
|
18
|
+
path = Path.new(@satellite, params[:ip])
|
19
|
+
|
20
|
+
FileUtils.mkdir_p(path.satellite)
|
21
|
+
File.open(path.full, "w") do |fd|
|
22
|
+
fd.write(params[:configuration])
|
23
|
+
end
|
24
|
+
|
25
|
+
repository = Git.open(Path.repository)
|
26
|
+
shortname = path.short
|
27
|
+
if repository.diff('HEAD', shortname).entries.length > 0
|
28
|
+
repository.add(shortname)
|
29
|
+
repository.commit("Updated #{params[:ip]}")
|
30
|
+
status 202
|
31
|
+
elsif repository.status.untracked.has_key?(shortname)
|
32
|
+
repository.add(shortname)
|
33
|
+
repository.commit("Created #{params[:ip]}")
|
34
|
+
status 201
|
35
|
+
else
|
36
|
+
status 200
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/courgette.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'httparty'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
require 'commutateurs'
|
7
|
+
require 'parallel'
|
8
|
+
|
9
|
+
require_relative './courgette/device.rb'
|
10
|
+
require_relative './courgette/client.rb'
|
11
|
+
require_relative './courgette/executor.rb'
|
12
|
+
|
13
|
+
module Courgette
|
14
|
+
def self.run!(aubergine, token, executors = 4, logger = Logger.new(STDOUT))
|
15
|
+
Executor.new(Client.new(aubergine, token), executors, logger).launch!
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Courgette
|
2
|
+
class Client
|
3
|
+
include HTTParty
|
4
|
+
|
5
|
+
def initialize(aubergine, token)
|
6
|
+
@base = aubergine
|
7
|
+
@headers = { headers: { 'Courgette' => token } }
|
8
|
+
end
|
9
|
+
|
10
|
+
def devices
|
11
|
+
response = self.class.get("#{@base}/configuration.json", @headers)
|
12
|
+
if response.code == 200
|
13
|
+
response.parsed_response.map { |raw| Device.build(raw) }
|
14
|
+
else
|
15
|
+
raise "Configuration not found."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def update_device(ip, configuration)
|
20
|
+
response = self.class.post("#{@base}/devices/#{ip}", @headers.merge(body: { configuration: configuration }))
|
21
|
+
if [200, 201, 202].include?(response.code)
|
22
|
+
{ 200 => "no changes", 201 => "created", 202 => "updated" }[response.code]
|
23
|
+
else
|
24
|
+
raise "Can't push configuration."
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Courgette
|
2
|
+
class Device
|
3
|
+
VENDOR_CLASSES = {
|
4
|
+
'hp' => Commutateurs::HP,
|
5
|
+
'cisco' => Commutateurs::Cisco
|
6
|
+
}
|
7
|
+
|
8
|
+
attr_reader :ip, :vendor
|
9
|
+
|
10
|
+
def initialize(ip, vendor, login, password)
|
11
|
+
@ip = ip
|
12
|
+
@vendor = vendor
|
13
|
+
@login = login
|
14
|
+
@password = password
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.build(hash)
|
18
|
+
new(hash['ip'], hash['vendor'], hash['login'], hash['password'])
|
19
|
+
end
|
20
|
+
|
21
|
+
def fetch
|
22
|
+
credentials = Commutateurs::Credentials.new(@login, @password, @password)
|
23
|
+
|
24
|
+
device = VENDOR_CLASSES[vendor].new(ip, credentials, false)
|
25
|
+
device.connect
|
26
|
+
device.enable
|
27
|
+
|
28
|
+
device.configuration
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Courgette
|
2
|
+
class Executor
|
3
|
+
attr_reader :client, :logger
|
4
|
+
|
5
|
+
def initialize(client, executors, logger)
|
6
|
+
@client = client
|
7
|
+
@executors = executors
|
8
|
+
@logger = logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def launch!
|
12
|
+
Parallel.each(client.devices, in_threads: @executors) do |device|
|
13
|
+
begin
|
14
|
+
status = client.update_device(device.ip, device.fetch)
|
15
|
+
logger.info "#{device.ip} #{status}"
|
16
|
+
rescue Timeout::Error
|
17
|
+
logger.info "#{device.ip} is unreachable (timeout)"
|
18
|
+
rescue Net::SSH::AuthenticationFailed
|
19
|
+
logger.info "#{device.ip} credentials are incorrect"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aubergine
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Guillaume Rose
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: commutateurs
|
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: git
|
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: sinatra
|
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: httparty
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: parallel
|
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
|
+
description: Distributed RANCID - backup your network devices
|
84
|
+
email: guillaume.rose@gmail.com
|
85
|
+
executables: []
|
86
|
+
extensions: []
|
87
|
+
extra_rdoc_files: []
|
88
|
+
files:
|
89
|
+
- lib/aubergine/path.rb
|
90
|
+
- lib/aubergine/satellite.rb
|
91
|
+
- lib/aubergine/server.rb
|
92
|
+
- lib/courgette/client.rb
|
93
|
+
- lib/courgette/device.rb
|
94
|
+
- lib/courgette/executor.rb
|
95
|
+
- lib/aubergine.rb
|
96
|
+
- lib/courgette.rb
|
97
|
+
homepage: http://www.github.com/guillaumerose/aubergine
|
98
|
+
licenses:
|
99
|
+
- MIT
|
100
|
+
metadata: {}
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 2.0.0.rc.2
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: Distributed RANCID - backup your network devices
|
121
|
+
test_files: []
|