aubergine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []