mcg 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 97b5139404c248d29de4e559176937bce91edfe6
4
+ data.tar.gz: 9f9387eb45b759cdbf653abe305b30261518324e
5
+ SHA512:
6
+ metadata.gz: e08d97de1c340d660786c494c745c5852168da79e7036a48f7f1008546e77952fff0f4dcf0e5499ccd6593ace64c0b385358fec397f145372eea0b7a42e691be
7
+ data.tar.gz: 1f92bb98dfafa445ae664ac91b8a694b8e591cfc47646c7c551f44ff81659d57714aa0971bf0193ebc1acb2069f44f7f0a44bda85468ca90a082b96ee8bbdd5c
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mcg.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ # MCG
2
+
3
+ MCG is a web daemon that automatically generate file from template and execute commands for web services deployed on Apache Mesos and Marathon.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'mcg'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install mcg
20
+
21
+ ## Usage
22
+
23
+ Create configuration file like this exemple:
24
+
25
+ ```json
26
+ {
27
+ "bind": "127.0.0.1",
28
+ "port": 8000,
29
+ "marathon": "http://localhost:8080",
30
+ "host": "http://127.0.0.1:8000/callback",
31
+ "actions": {
32
+ "apache": {
33
+ "template": "/etc/mgc/apache-template.conf.erb",
34
+ "output": "/etc/apache2/sites-enabled/all_site",
35
+ "reload_command": "apachectl -t && apachectl graceful"
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ and template like this exemple:
42
+
43
+ ```
44
+ <% @data.tasks.each do |name, conf| %>
45
+ # Generated configuration for <%= name %>
46
+
47
+ <VirtualHost *:80>
48
+ ServerAdmin admin@foo.fr
49
+ ServerName <%= name %>
50
+
51
+ ProxyRequests Off
52
+ ProxyPreserveHost On
53
+ SetEnv proxy-sendcl 1
54
+
55
+ <Proxy balancer://<%= name.gsub(/[\.-]/, '_') %>>
56
+ <% conf.each do |c| %>
57
+ BalancerMember <%= c[:host] %>:<%= c[:port] %>
58
+ <% end %>
59
+ </Proxy>
60
+
61
+ ProxyPass / balancer://<%= name.gsub(/[\.-]/, '_') %>/
62
+ ProxyPassReverse / balancer://<%= name.gsub(/[\.-]/, '_') %>/
63
+
64
+ </VirtualHost>
65
+ <% end %>
66
+ ```
67
+
68
+ and start the daemon like this:
69
+
70
+ ```
71
+ mcg -f conf.json
72
+ ```
73
+
74
+ ## Development
75
+
76
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
77
+
78
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
79
+
80
+ ## Contributing
81
+
82
+ 1. Fork it ( https://github.com/pojer-s/mcg/fork )
83
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
84
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
85
+ 4. Push to the branch (`git push origin my-new-feature`)
86
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/mcg ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mcg'
4
+ require 'optparse'
5
+ require 'json'
6
+
7
+ options = {}
8
+
9
+ OptionParser.new do |opts|
10
+ opts.banner = "Usage: example.rb [options]"
11
+
12
+ opts.on("-f FILE", "--config-file FILE", "Config file") do |v|
13
+ options[:config_file] = v
14
+ end
15
+ end.parse!
16
+
17
+ config = JSON.parse(IO.read(options[:config_file]))
18
+
19
+ mcg = MCG.new(config)
20
+ mcg.generate
21
+ mcg.subscribe
22
+ mcg.start
23
+ mcg.unsubscribe
data/lib/mcg.rb ADDED
@@ -0,0 +1,76 @@
1
+ require 'json'
2
+ require 'net/http'
3
+
4
+ require "mcg/version"
5
+ require "mcg/action"
6
+ require "mcg/data"
7
+ require "mcg/server"
8
+
9
+ class MCG
10
+
11
+ def initialize(config=nil)
12
+ @config = {
13
+ "bind" => "127.0.0.1",
14
+ "port" => 8000,
15
+ "marathon" => "http://localhost:8080",
16
+ "actions" => {}
17
+ }
18
+ @config.merge! config
19
+ @data = Data.new(@config["marathon"])
20
+ @actions = {}
21
+ @config["actions"].each do |action_name, action_value|
22
+ add_action(action_name,
23
+ action_value["template"],
24
+ action_value["output"],
25
+ action_value["reload_command"])
26
+ end
27
+ end
28
+
29
+ def add_action(name, template, output, reload_command)
30
+ @actions[name] = Action.new(template, output, reload_command)
31
+ end
32
+
33
+ def generate
34
+ @data.get
35
+ @actions.each do |name, action|
36
+ action.render(@data)
37
+ end
38
+ end
39
+
40
+ def subscribe
41
+ uri = URI.parse(@config["marathon"] + '/v2/eventSubscriptions')
42
+ http = Net::HTTP.new(uri.host, uri.port)
43
+ req = Net::HTTP::Get.new(uri.path, initheader = {'Accept' =>'application/json'})
44
+ resp = http.request(req)
45
+ data = JSON.parse(resp.body)
46
+ if resp.code.to_i == 200
47
+ unless data["callbackUrls"].include?(@config["host"])
48
+ request = Net::HTTP::Post.new(uri.path + "?callbackUrl=#{@config["host"]}")
49
+ request.add_field('Content-Type', 'application/json')
50
+ resp = http.request(request)
51
+ data = JSON.parse(resp.body)
52
+ unless resp.code.to_i == 200
53
+ raise "Cannot subscribe to #{@config["marathon"]}. Error: #{data["message"]}"
54
+ end
55
+ end
56
+ else
57
+ raise "Error: #{data["message"]}"
58
+ end
59
+ end
60
+
61
+ def unsubscribe
62
+ uri = URI.parse(@config["marathon"] + '/v2/eventSubscriptions')
63
+ http = Net::HTTP.new(uri.host, uri.port)
64
+ request = Net::HTTP::Delete.new(uri.path + "?callbackUrl=#{@config["host"]}")
65
+ request.add_field('Content-Type', 'application/json')
66
+ resp = http.request(request)
67
+ data = JSON.parse(resp.body)
68
+ unless resp.code.to_i == 200
69
+ raise "Cannot unsubscribe to #{@config["marathon"]}. Error: #{data["message"]}"
70
+ end
71
+ end
72
+
73
+ def start
74
+ Server.run!({:bind => @config["bind"], :port => @config["port"], :mcg => self})
75
+ end
76
+ end
data/lib/mcg/action.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'erb'
2
+
3
+ class MCG
4
+
5
+ class Action
6
+
7
+ def initialize(template, output, reload_command)
8
+ @template = IO.read(template)
9
+ @output = output
10
+ @reload_command = reload_command
11
+ end
12
+
13
+ def render(data)
14
+ @data = data
15
+ b = binding
16
+ renderer = ERB.new(@template)
17
+ IO.write(@output, renderer.result(b))
18
+ `#{@reload_command}`
19
+ end
20
+
21
+ end
22
+ end
data/lib/mcg/data.rb ADDED
@@ -0,0 +1,41 @@
1
+ require 'json'
2
+ require 'net/http'
3
+
4
+ class MCG
5
+
6
+ class Data
7
+
8
+ attr_reader :data
9
+ attr_reader :tasks
10
+
11
+ def initialize(marathon_url)
12
+ @marathon_url = marathon_url
13
+ @data = nil
14
+ @tasks = nil
15
+ end
16
+
17
+ def get
18
+ uri = URI.parse(@marathon_url + '/v2/tasks')
19
+ http = Net::HTTP.new(uri.host, uri.port)
20
+ req = Net::HTTP::Get.new(uri.path, initheader = {'Accept' =>'application/json'})
21
+ resp = http.request(req)
22
+ @data = JSON.parse(resp.body)
23
+ order_task
24
+ end
25
+
26
+ def order_task
27
+ @tasks = Hash.new { |h, k| h[k] = [] }
28
+
29
+ @data["tasks"].each do |task|
30
+ fqdn = task["appId"][/\/([^\/]+)\//, 1]
31
+ task["ports"].each do |port|
32
+ @tasks[fqdn] << {
33
+ :host => task["host"],
34
+ :port => port
35
+ }
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end
data/lib/mcg/server.rb ADDED
@@ -0,0 +1,16 @@
1
+ require 'sinatra/base'
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+
6
+ class MCG
7
+
8
+ class Server < Sinatra::Base
9
+
10
+ post "/callback" do
11
+ settings.mcg.generate
12
+ "ok"
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ class MCG
2
+ VERSION = "0.1.2"
3
+ end
data/mcg.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 'mcg/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mcg"
8
+ spec.version = MCG::VERSION
9
+ spec.authors = ["Steven Pojer"]
10
+ spec.email = ["steven.pojer@gmail.com"]
11
+
12
+ spec.summary = "MCG is a web daemon that automatically generate file from template and execute commands for web services deployed on Apache Mesos and Marathon."
13
+ spec.description = spec.summary
14
+ spec.homepage = "https://github.com/pojer-s/mgc"
15
+ spec.license = "Apache-2.0"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "bin"
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_runtime_dependency "sinatra", ">= 0"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.9"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mcg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Steven Pojer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
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: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ description: MCG is a web daemon that automatically generate file from template and
56
+ execute commands for web services deployed on Apache Mesos and Marathon.
57
+ email:
58
+ - steven.pojer@gmail.com
59
+ executables:
60
+ - mcg
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - .gitignore
65
+ - .travis.yml
66
+ - Gemfile
67
+ - README.md
68
+ - Rakefile
69
+ - bin/mcg
70
+ - lib/mcg.rb
71
+ - lib/mcg/action.rb
72
+ - lib/mcg/data.rb
73
+ - lib/mcg/server.rb
74
+ - lib/mcg/version.rb
75
+ - mcg.gemspec
76
+ homepage: https://github.com/pojer-s/mgc
77
+ licenses:
78
+ - Apache-2.0
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 2.4.6
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: MCG is a web daemon that automatically generate file from template and execute
100
+ commands for web services deployed on Apache Mesos and Marathon.
101
+ test_files: []