bixby_common 0.2.0

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.
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