bixby_common 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "multi_json"
4
+ gem "oj"
5
+ gem "curb"
6
+ gem "systemu"
7
+
8
+ group :development do
9
+ gem "yard", "~> 0.8"
10
+ gem "bundler", "~> 1.1"
11
+ gem "jeweler", "~> 1.8.3"
12
+
13
+ gem "simplecov", :platforms => :mri_19
14
+ gem "rcov", :platforms => :mri_18
15
+
16
+ gem "minitest", :platforms => :mri_19
17
+ gem "test-unit", :platforms => :mri_18
18
+
19
+ gem "turn"
20
+ end
21
+
data/Gemfile.lock ADDED
@@ -0,0 +1,45 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ ansi (1.4.2)
5
+ curb (0.8.0)
6
+ git (1.2.5)
7
+ jeweler (1.8.3)
8
+ bundler (~> 1.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rdoc
12
+ json (1.7.3)
13
+ minitest (3.1.0)
14
+ multi_json (1.3.6)
15
+ oj (1.2.11)
16
+ rake (0.9.2.2)
17
+ rcov (1.0.0)
18
+ rdoc (3.12)
19
+ json (~> 1.4)
20
+ simplecov (0.6.4)
21
+ multi_json (~> 1.0)
22
+ simplecov-html (~> 0.5.3)
23
+ simplecov-html (0.5.3)
24
+ systemu (2.5.1)
25
+ test-unit (2.5.0)
26
+ turn (0.9.5)
27
+ ansi
28
+ yard (0.8.2.1)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bundler (~> 1.1)
35
+ curb
36
+ jeweler (~> 1.8.3)
37
+ minitest
38
+ multi_json
39
+ oj
40
+ rcov
41
+ simplecov
42
+ systemu
43
+ test-unit
44
+ turn
45
+ yard (~> 0.8)
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+ require 'jeweler'
14
+
15
+ Jeweler::Tasks.new do |gemspec|
16
+ gemspec.name = "bixby_common"
17
+ gemspec.summary = "Bixby Common"
18
+ gemspec.description = "Bixby Common files/libs"
19
+ gemspec.email = "chetan@pixelcop.net"
20
+ gemspec.homepage = "http://github.com/chetan/devops_common"
21
+ gemspec.authors = ["Chetan Sarva"]
22
+ end
23
+ Jeweler::RubygemsDotOrgTasks.new
24
+
25
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
26
+
27
+ require 'rake/testtask'
28
+ Rake::TestTask.new(:test) do |test|
29
+ test.libs << 'lib' << 'test'
30
+ test.pattern = 'test/**/test_*.rb'
31
+ test.verbose = true
32
+ end
33
+
34
+ if Module.const_defined? :Rcov then
35
+ begin
36
+ require 'rcov/rcovtask'
37
+ Rcov::RcovTask.new do |test|
38
+ test.libs << 'test'
39
+ test.pattern = 'test/**/test_*.rb'
40
+ test.verbose = true
41
+ test.rcov_opts << '--exclude "gems/*"'
42
+ end
43
+ rescue Exception => ex
44
+ end
45
+ end
46
+
47
+ task :default => :test
48
+
49
+ require 'yard'
50
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1,95 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "bixby_common"
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Chetan Sarva"]
12
+ s.date = "2012-07-27"
13
+ s.description = "Bixby Common files/libs"
14
+ s.email = "chetan@pixelcop.net"
15
+ s.files = [
16
+ ".document",
17
+ "Gemfile",
18
+ "Gemfile.lock",
19
+ "Rakefile",
20
+ "VERSION",
21
+ "bixby_common.gemspec",
22
+ "lib/bixby_common.rb",
23
+ "lib/bixby_common/api/base_module.rb",
24
+ "lib/bixby_common/api/bundle_repository.rb",
25
+ "lib/bixby_common/api/json_request.rb",
26
+ "lib/bixby_common/api/json_response.rb",
27
+ "lib/bixby_common/command_response.rb",
28
+ "lib/bixby_common/command_spec.rb",
29
+ "lib/bixby_common/exception/bundle_not_found.rb",
30
+ "lib/bixby_common/exception/command_not_found.rb",
31
+ "lib/bixby_common/util/crypto_util.rb",
32
+ "lib/bixby_common/util/hashify.rb",
33
+ "lib/bixby_common/util/http_client.rb",
34
+ "lib/bixby_common/util/jsonify.rb",
35
+ "test/helper.rb",
36
+ "test/support/test_bundle/bin/cat",
37
+ "test/support/test_bundle/bin/echo",
38
+ "test/support/test_bundle/digest",
39
+ "test/support/test_bundle/manifest.json",
40
+ "test/test_bixby_common.rb",
41
+ "test/test_command_spec.rb",
42
+ "test/test_jsonify.rb",
43
+ "test_guard.rb"
44
+ ]
45
+ s.homepage = "http://github.com/chetan/devops_common"
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = "1.8.24"
48
+ s.summary = "Bixby Common"
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<multi_json>, [">= 0"])
55
+ s.add_runtime_dependency(%q<oj>, [">= 0"])
56
+ s.add_runtime_dependency(%q<curb>, [">= 0"])
57
+ s.add_runtime_dependency(%q<systemu>, [">= 0"])
58
+ s.add_development_dependency(%q<yard>, ["~> 0.8"])
59
+ s.add_development_dependency(%q<bundler>, ["~> 1.1"])
60
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
61
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
62
+ s.add_development_dependency(%q<rcov>, [">= 0"])
63
+ s.add_development_dependency(%q<minitest>, [">= 0"])
64
+ s.add_development_dependency(%q<test-unit>, [">= 0"])
65
+ s.add_development_dependency(%q<turn>, [">= 0"])
66
+ else
67
+ s.add_dependency(%q<multi_json>, [">= 0"])
68
+ s.add_dependency(%q<oj>, [">= 0"])
69
+ s.add_dependency(%q<curb>, [">= 0"])
70
+ s.add_dependency(%q<systemu>, [">= 0"])
71
+ s.add_dependency(%q<yard>, ["~> 0.8"])
72
+ s.add_dependency(%q<bundler>, ["~> 1.1"])
73
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
74
+ s.add_dependency(%q<simplecov>, [">= 0"])
75
+ s.add_dependency(%q<rcov>, [">= 0"])
76
+ s.add_dependency(%q<minitest>, [">= 0"])
77
+ s.add_dependency(%q<test-unit>, [">= 0"])
78
+ s.add_dependency(%q<turn>, [">= 0"])
79
+ end
80
+ else
81
+ s.add_dependency(%q<multi_json>, [">= 0"])
82
+ s.add_dependency(%q<oj>, [">= 0"])
83
+ s.add_dependency(%q<curb>, [">= 0"])
84
+ s.add_dependency(%q<systemu>, [">= 0"])
85
+ s.add_dependency(%q<yard>, ["~> 0.8"])
86
+ s.add_dependency(%q<bundler>, ["~> 1.1"])
87
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
88
+ s.add_dependency(%q<simplecov>, [">= 0"])
89
+ s.add_dependency(%q<rcov>, [">= 0"])
90
+ s.add_dependency(%q<minitest>, [">= 0"])
91
+ s.add_dependency(%q<test-unit>, [">= 0"])
92
+ s.add_dependency(%q<turn>, [">= 0"])
93
+ end
94
+ end
95
+
@@ -0,0 +1,21 @@
1
+
2
+ module Bixby
3
+
4
+ autoload :CommandResponse, "bixby_common/command_response"
5
+ autoload :CommandSpec, "bixby_common/command_spec"
6
+
7
+ autoload :JsonRequest, "bixby_common/api/json_request"
8
+ autoload :JsonResponse, "bixby_common/api/json_response"
9
+
10
+ autoload :BaseModule, "bixby_common/api/base_module"
11
+ autoload :BundleRepository, "bixby_common/api/bundle_repository"
12
+
13
+ autoload :BundleNotFound, "bixby_common/exception/bundle_not_found"
14
+ autoload :CommandNotFound, "bixby_common/exception/command_not_found"
15
+
16
+ autoload :CryptoUtil, "bixby_common/util/crypto_util"
17
+ autoload :HttpClient, "bixby_common/util/http_client"
18
+ autoload :Jsonify, "bixby_common/util/jsonify"
19
+ autoload :Hashify, "bixby_common/util/hashify"
20
+
21
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module Bixby
3
+ class BaseModule
4
+
5
+ class << self
6
+ attr_accessor :agent, :manager_uri
7
+
8
+ include HttpClient
9
+ end
10
+
11
+ end # BaseModule
12
+ end # Bixby
@@ -0,0 +1,12 @@
1
+
2
+ # path should be initialized on Agent or Manager start
3
+
4
+ module Bixby
5
+
6
+ class BundleRepository < BaseModule
7
+ class << self
8
+ attr_accessor :path
9
+ end
10
+ end # BundleRepository
11
+
12
+ end # Bixby
@@ -0,0 +1,25 @@
1
+
2
+ module Bixby
3
+
4
+ # Wraps a JSON Request
5
+ #
6
+ # @attr [String] operation Name of operation
7
+ # @attr [Array] params Array of paramters; must be valid JSON types
8
+ class JsonRequest
9
+
10
+ include Jsonify
11
+ include HttpClient
12
+
13
+ attr_accessor :operation, :params
14
+
15
+ # Create a new JsonRequest
16
+ #
17
+ # @param [String] operation Name of operation
18
+ # @param [Array] params Array of parameters; must ve valid JSON types
19
+ def initialize(operation, params)
20
+ @operation = operation
21
+ @params = params
22
+ end
23
+
24
+ end # JsonRequest
25
+ end # Bixby
@@ -0,0 +1,69 @@
1
+
2
+ module Bixby
3
+
4
+ # Wraps a JSON Response
5
+ #
6
+ # @attr [String] status Status of operaiton ("success" or "fail")
7
+ # @attr [String] message Response message
8
+ # @attr [Hash] data Response data as key/value pairs
9
+ # @attr [FixNum] code Response code
10
+ class JsonResponse
11
+
12
+ include Jsonify
13
+
14
+ attr_accessor :status, :message, :data, :code
15
+
16
+ SUCCESS = "success"
17
+ FAIL = "fail"
18
+
19
+ # Create a new JsonResponse
20
+ #
21
+ # @param [String] status Status of operaiton ("success" or "fail")
22
+ # @param [String] message Response message
23
+ # @param [Hash] data Response data as key/value pairs
24
+ # @param [FixNum] code Response code
25
+ def initialize(status = nil, message = nil, data = nil, code = nil)
26
+ @status = status
27
+ @message = message
28
+ @data = data
29
+ @code = code
30
+ end
31
+
32
+ # Was operation successful?
33
+ #
34
+ # @return [Boolean] True if @status == "success"
35
+ def success?
36
+ @status && @status == SUCCESS
37
+ end
38
+
39
+ # Was operation unsuccessful?
40
+ #
41
+ # @return [Boolean] True if @status != "success"
42
+ def fail?
43
+ @status && @status == FAIL
44
+ end
45
+
46
+ # Create a JsonResponse representing an invalid request
47
+ #
48
+ # @param [String] msg Optional message (default: "invalid request")
49
+ def self.invalid_request(msg = nil)
50
+ new("fail", (msg || "invalid request"), nil, 400)
51
+ end
52
+
53
+ # Create a JsonResponse indicating "bundle not found"
54
+ #
55
+ # @param [String] bundle Name of bundle
56
+ def self.bundle_not_found(bundle)
57
+ new("fail", "bundle not found: #{bundle}", nil, 404)
58
+ end
59
+
60
+ # Create a JsonResponse indicating "command not found"
61
+ #
62
+ # @param [String] command Name of command
63
+ def self.command_not_found(command)
64
+ new("fail", "command not found: #{command}", nil, 404)
65
+ end
66
+
67
+ end # JsonResponse
68
+
69
+ end # Bixby
@@ -0,0 +1,31 @@
1
+
2
+ module Bixby
3
+ class CommandResponse
4
+
5
+ include Jsonify
6
+
7
+ attr_accessor :status, :stdout, :stderr
8
+
9
+ def initialize(params = nil)
10
+ return if params.nil? or params.empty?
11
+ params.each{ |k,v| self.send("#{k}=", v) if self.respond_to? "#{k}=" }
12
+ end
13
+
14
+ def success?
15
+ @status.to_i == 0
16
+ end
17
+
18
+ def error?
19
+ not success?
20
+ end
21
+
22
+ def decode
23
+ MultiJson.load(@stdout)
24
+ end
25
+
26
+ def decode_stderr
27
+ MultiJson.load(@stderr)
28
+ end
29
+
30
+ end # CommandResponse
31
+ end # Bixby
@@ -0,0 +1,149 @@
1
+
2
+ require 'digest'
3
+ require 'tempfile'
4
+
5
+ require 'systemu'
6
+
7
+ module Bixby
8
+ class CommandSpec
9
+
10
+ include Jsonify
11
+ include Hashify
12
+
13
+ attr_accessor :repo, :digest, :bundle, :command, :args, :stdin, :env
14
+
15
+ # Create new CommandSpec
16
+ #
17
+ # @params [Hash] params Hash of attributes to initialize with
18
+ def initialize(params = nil)
19
+ return if params.nil? or params.empty?
20
+ params.each{ |k,v| self.send("#{k}=", v) if self.respond_to? "#{k}=" }
21
+
22
+ digest = load_digest()
23
+ @digest = digest["digest"] if digest
24
+ end
25
+
26
+ # Execute this command
27
+ #
28
+ # @param [String] cmd Command string to execute
29
+ #
30
+ # @return [Array<FixNum, String, String>] status code, stdout, stderr
31
+ def execute
32
+ if @stdin and not @stdin.empty? then
33
+ temp = Tempfile.new("input-")
34
+ temp << @stdin
35
+ temp.flush
36
+ temp.close
37
+ cmd = "sh -c 'cat #{temp.path} | #{self.command_file}"
38
+ else
39
+ cmd = "sh -c '#{self.command_file}"
40
+ end
41
+ cmd += @args ? " #{@args}'" : "'"
42
+
43
+ status, stdout, stderr = system_exec(cmd)
44
+ end
45
+
46
+ # Validate the existence of this Command on the local system
47
+ #
48
+ # @return [Boolean] returns true if available, else raises error
49
+ # @raise [BundleNotFound]
50
+ # @raise [CommandNotFound]
51
+ def validate
52
+ if not bundle_exists? then
53
+ raise BundleNotFound.new("repo = #{@repo}; bundle = #{@bundle}")
54
+ end
55
+
56
+ if not command_exists? then
57
+ raise CommandNotFound.new("repo = #{@repo}; bundle = #{@bundle}; command = #{@command}")
58
+ end
59
+ return true
60
+ end
61
+
62
+ # resolve the given bundle
63
+ def bundle_dir
64
+ if @repo == "local" and Module.constants.include? :AGENT_ROOT then
65
+ # only resolve the special "local" repo for Agents
66
+ return File.expand_path(File.join(AGENT_ROOT, "../repo", @bundle))
67
+ end
68
+ File.join(BundleRepository.path, self.relative_path)
69
+ end
70
+
71
+ def relative_path
72
+ File.join(@repo, @bundle)
73
+ end
74
+
75
+ def bundle_exists?
76
+ File.exists? self.bundle_dir
77
+ end
78
+
79
+ def command_file
80
+ File.join(self.bundle_dir, "bin", @command)
81
+ end
82
+
83
+ def command_exists?
84
+ File.exists? self.command_file
85
+ end
86
+
87
+ def config_file
88
+ command_file + ".json"
89
+ end
90
+
91
+ def load_config
92
+ if File.exists? config_file then
93
+ MultiJson.load(File.read(config_file))
94
+ else
95
+ {}
96
+ end
97
+ end
98
+
99
+ def digest_file
100
+ File.join(self.bundle_dir, "digest")
101
+ end
102
+
103
+ def load_digest
104
+ begin
105
+ return MultiJson.load(File.read(digest_file))
106
+ rescue => ex
107
+ end
108
+ nil
109
+ end
110
+
111
+ def update_digest
112
+
113
+ path = self.bundle_dir
114
+ sha = Digest::SHA2.new
115
+ bundle_sha = Digest::SHA2.new
116
+
117
+ digests = []
118
+ Dir.glob("#{path}/**/*").sort.each do |f|
119
+ next if File.directory? f || File.basename(f) == "digest"
120
+ bundle_sha.file(f)
121
+ sha.reset()
122
+ digests << { :file => f.gsub(/#{path}\//, ''), :digest => sha.file(f).hexdigest() }
123
+ end
124
+
125
+ @digest = { :digest => bundle_sha.hexdigest(), :files => digests }
126
+ File.open(path+"/digest", 'w'){ |f| f.write(MultiJson.dump(@digest, :pretty => true) + "\n") }
127
+
128
+ end
129
+
130
+
131
+ private
132
+
133
+ # Cleanup the ENV before executing command
134
+ #
135
+ # @param [String] cmd Command string to execute
136
+ #
137
+ # @return [Array<FixNum, String, String>] status, stdout, stderr
138
+ def system_exec(cmd)
139
+ rem = [ "BUNDLE_BIN_PATH", "BUNDLE_GEMFILE", "RUBYOPT" ]
140
+ old_env = {}
141
+ rem.each{ |r| old_env[r] = ENV.delete(r) }
142
+ status, stdout, stderr = systemu(cmd)
143
+ rem.each{ |r| ENV[r] = old_env[r] if old_env[r] }
144
+
145
+ return [ status, stdout, stderr ]
146
+ end
147
+
148
+ end # CommandSpec
149
+ end # Bixby