wss_agent 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +201 -0
  7. data/README.md +73 -0
  8. data/Rakefile +10 -0
  9. data/bin/wss_agent +13 -0
  10. data/lib/config/custom_default.yml +5 -0
  11. data/lib/config/default.yml +11 -0
  12. data/lib/wss_agent/cli.rb +49 -0
  13. data/lib/wss_agent/client.rb +59 -0
  14. data/lib/wss_agent/configure.rb +90 -0
  15. data/lib/wss_agent/gem_sha1.rb +76 -0
  16. data/lib/wss_agent/project.rb +45 -0
  17. data/lib/wss_agent/response.rb +57 -0
  18. data/lib/wss_agent/response_inventory.rb +28 -0
  19. data/lib/wss_agent/response_policies.rb +76 -0
  20. data/lib/wss_agent/specifications.rb +150 -0
  21. data/lib/wss_agent/version.rb +4 -0
  22. data/lib/wss_agent.rb +40 -0
  23. data/spec/fixtures/vcr_cassettes/WssAgent_CLI/update/when_not_found_token/should_display_error_message.yml +2984 -0
  24. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/server_error/response_should_be_success.yml +2984 -0
  25. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/server_error/should_response_json_data.yml +2984 -0
  26. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/server_error/should_return_message_response.yml +2984 -0
  27. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/server_error/should_return_status_of_response.yml +2984 -0
  28. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/server_timeout/response_should_be_success.yml +2984 -0
  29. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/server_timeout/should_response_json_data.yml +2984 -0
  30. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/server_timeout/should_return_message_response.yml +2984 -0
  31. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/server_timeout/should_return_status_of_response.yml +2984 -0
  32. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/success/response_should_be_success.yml +2984 -0
  33. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/success/should_response_json_data.yml +2984 -0
  34. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/success/should_return_message_response.yml +2984 -0
  35. data/spec/fixtures/vcr_cassettes/WssAgent_Client/_update/success/should_return_status_of_response.yml +2984 -0
  36. data/spec/fixtures/vcr_cassettes/WssAgent_Specifications/_check_policies/should_check_policies.yml +50 -0
  37. data/spec/fixtures/vcr_cassettes/WssAgent_Specifications/_update/should_update_list_gems_on_server.yml +50 -0
  38. data/spec/fixtures/vcr_cassettes/WssAgent_Specifications/_update/when_check_policies_is_true/and_check_policies_return_a_violation/should_not_update_inventory.yml +2984 -0
  39. data/spec/fixtures/vcr_cassettes/WssAgent_Specifications/_update/when_check_policies_is_true/and_check_policies_returns_without_a_violation/should_update_inventory.yml +2984 -0
  40. data/spec/fixtures/wss_agent.yml +9 -0
  41. data/spec/spec_helper.rb +35 -0
  42. data/spec/wss_agent/cli_spec.rb +57 -0
  43. data/spec/wss_agent/client_spec.rb +137 -0
  44. data/spec/wss_agent/configure_spec.rb +148 -0
  45. data/spec/wss_agent/specifications_spec.rb +137 -0
  46. data/wss_agent.gemspec +38 -0
  47. metadata +390 -0
@@ -0,0 +1,57 @@
1
+ module WssAgent
2
+ class Response
3
+ SUCCESS_STATUS = 1
4
+ BAD_REQUEST_STATUS = 2
5
+ SERVER_ERROR_STATUS = 3
6
+
7
+ attr_reader :response, :status, :message, :response_data, :data
8
+
9
+ def initialize(response)
10
+ @response = response
11
+ if response.is_a?(Faraday::Error::ClientError)
12
+ parse_error
13
+ else
14
+ parse_response
15
+ end
16
+ end
17
+
18
+ def parse_error
19
+ @status = SERVER_ERROR_STATUS
20
+ @message = response.message
21
+ end
22
+
23
+ def parse_response
24
+ if response.success?
25
+ begin
26
+ @response_data = Oj.load(response.body)
27
+ @status = @response_data['status'].to_i
28
+ @message = @response_data['message']
29
+ rescue
30
+ @status = SERVER_ERROR_STATUS
31
+ @message = response.body
32
+ end
33
+ else
34
+ @status = SERVER_ERROR_STATUS
35
+ @message = response.body
36
+ end
37
+ end
38
+
39
+ def response_success?
40
+ if response.is_a?(Faraday::Error::ClientError)
41
+ false
42
+ else
43
+ response.success?
44
+ end
45
+ end
46
+
47
+ def success?
48
+ response_success? && status == SUCCESS_STATUS
49
+ end
50
+
51
+ def data
52
+ @data ||= Oj.load(response_data['data'])
53
+ rescue
54
+ response_data && response_data.key?('data') ? response_data['data'] : nil
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ module WssAgent
2
+ class ResponseInventory < Response
3
+
4
+ def message
5
+ if success?
6
+ @message = "White Source update results: \n"
7
+ @message << " White Source organization: #{data['organization']} \n"
8
+
9
+ unless data['createdProjects'].empty?
10
+ @message << " #{data['createdProjects'].size} newly created projects: "
11
+ @message << data['createdProjects'].join(' ')
12
+ else
13
+ @message << " No new projects found \n"
14
+ end
15
+
16
+ unless data['updatedProjects'].empty?
17
+ @message << " #{data['updatedProjects'].size} existing projects were updated: "
18
+ @message << data['updatedProjects'].join(' ')
19
+ else
20
+ @message << "\n No projects were updated \n"
21
+ end
22
+ @message
23
+ else
24
+ super
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,76 @@
1
+ module WssAgent
2
+ class ResponsePolicies < Response
3
+ REJECT_ACTION = 'Reject'
4
+
5
+ def parse_response
6
+ if response.success?
7
+ begin
8
+ @response_data = Oj.load(response.body)
9
+ @status = @response_data['status'].to_i
10
+ @message = @response_data['message']
11
+ check_new_projects
12
+ check_existing_projects
13
+ rescue
14
+ @status = SERVER_ERROR_STATUS
15
+ @message = response.body
16
+ end
17
+ else
18
+ @status = SERVER_ERROR_STATUS
19
+ @message = response.body
20
+ end
21
+ end
22
+
23
+
24
+ def message
25
+ if success?
26
+ if policy_violations?
27
+ @message = [
28
+ 'Some dependencies do not conform with open source policies',
29
+ 'List of violations:'
30
+ ]
31
+ @message << policy_violations.each_with_index.map { |j, i|
32
+ "#{i+1}. Package: #{j['resource']['displayName']} - #{j['policy']['displayName']}"
33
+ }.join("\n")
34
+ @message.join("\n")
35
+ else
36
+ "All dependencies conform with open source policies"
37
+ end
38
+ end
39
+ end
40
+
41
+ def policy_violations
42
+ @policy_violations || []
43
+ end
44
+
45
+ def policy_violations?
46
+ !policy_violations.nil? &&
47
+ !policy_violations.empty? &&
48
+ policy_violations.size > 0
49
+ end
50
+
51
+ def check_existing_projects
52
+ data['existingProjects'].each { |_proj_name, resource| check(resource) }
53
+ end
54
+
55
+ def check_new_projects
56
+ data['newProjects'].each { |_proj_name, resource| check(resource) }
57
+ end
58
+
59
+ def add_resource(resource)
60
+ @policy_violations ||= []
61
+ @policy_violations << resource
62
+ end
63
+
64
+ def check(resource)
65
+ if resource.key?('resource') && resource.key?('policy') &&
66
+ (resource['policy']['actionType'] == REJECT_ACTION)
67
+ add_resource({'resource' => resource['resource'],
68
+ 'policy' => resource['policy']})
69
+ end
70
+
71
+ if resource.key?('children') && resource['children'].is_a?(Array)
72
+ resource['children'].each { |j| check(j) }
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,150 @@
1
+ require "digest"
2
+
3
+ module WssAgent
4
+ class Specifications
5
+
6
+ class << self
7
+ # Get dependencies
8
+ #
9
+ # @param [Hash]
10
+ # @option options [Boolean] 'all' if true then get all dependencies (include development dependencies)
11
+ # @option options [String] 'excludes' list gem name which need to exclude from end list
12
+ def specs(options = {})
13
+ list_gems = Bundler.load.specs.to_a
14
+ if options['all']
15
+ # get all gems
16
+ list = {}
17
+ list_gems.each { |j| list[j.name] = j }
18
+ list_gems.each { |j|
19
+ list = gem_dependencies(list, j.dependencies, options)
20
+ }
21
+
22
+ list_gems = list.values
23
+ end
24
+ list_gems
25
+ end
26
+
27
+ # Display list dependencies
28
+ #
29
+ # @param (see Specifications#specs)
30
+ def list(options = {})
31
+ new(specs(options)).call
32
+ end
33
+
34
+ # Send gem list to server
35
+ #
36
+ # @param (see Specifications#specs)
37
+ def update(options = {})
38
+ wss_client = WssAgent::Client.new
39
+ if WssAgent::Configure['check_policies']
40
+ policy_results = wss_client.check_policies(WssAgent::Specifications.list(options))
41
+ if policy_results.success? && policy_results.policy_violations?
42
+ puts policy_results.message
43
+ return false
44
+ end
45
+ end
46
+
47
+ result = wss_client.update(WssAgent::Specifications.list(options))
48
+ if result.success?
49
+ WssAgent.logger.debug result.data
50
+ puts result.message
51
+ else
52
+ ap "synchronization errors occur: status: #{result.status}, message: #{result.message}"
53
+ end
54
+
55
+ result.success?
56
+ end
57
+
58
+ # checking dependencies that they conforms with company policy.
59
+ #
60
+ # @param (see Specifications#specs)
61
+ def check_policies(options = {})
62
+ wss_client = WssAgent::Client.new
63
+ result = wss_client.check_policies(WssAgent::Specifications.list(options))
64
+ if result.success?
65
+ WssAgent.logger.debug result.data
66
+ puts result.message
67
+ else
68
+ ap "check policies errors occur: #{result.status}, message: #{result.message}, data: #{result.data}"
69
+ end
70
+ end
71
+
72
+ # Get all dependencies includes development
73
+ #
74
+ # @param [Array<Spec>] array for gems
75
+ # @param [Array<Dependencies>]
76
+ # @param [Hash]
77
+ # @options options [String] :excludes list gems to exclude
78
+ #
79
+ # @return [Array<Spec>] list
80
+ def gem_dependencies(list, gem_dependencies, options = {})
81
+ gem_dependencies.each do |gd|
82
+ if options['excludes'] && options['excludes'].to_s.split(',').include?(gd.name)
83
+ next
84
+ end
85
+ gs = gd.matching_specs.first
86
+ if gs
87
+ unless list[gs.name]
88
+ list[gs.name] = gs
89
+ unless gs.dependencies.empty?
90
+ list = gem_dependencies(list, gs.dependencies, options)
91
+ end
92
+ end
93
+ else
94
+ unless list[gd.name]
95
+ list[gd.name] = Gem::Specification.new(gd.name,
96
+ gd.requirements_list.last.scan(/[\d\.\w]+/).first)
97
+ rm_dep = remote_dependencies(gd.name, gd.requirements_list.last)
98
+ unless rm_dep.empty?
99
+ list = gem_dependencies(list, rm_dep, options)
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ list
106
+ end
107
+
108
+ # Load dependencies from rubygems
109
+ #
110
+ # @param gem_name [String] name gem
111
+ # @params version [String] version gem
112
+ #
113
+ # @return [Array<Gem::Dependency>] list gem dependencies
114
+ def remote_dependencies(gem_name, version)
115
+ conn = Faraday.new(url: 'https://rubygems.org') do |h|
116
+ h.headers[:content_type] = 'application/x-www-form-urlencoded'
117
+ h.request :url_encoded
118
+ h.adapter :excon
119
+ end
120
+ response = conn.get("/api/v1/gems/#{gem_name}.json")
121
+ dep_list = Oj.load(response.body)
122
+ dep_list['dependencies'].values.flatten.
123
+ map { |j| Gem::Dependency.new(j['name'], Gem::Requirement.new(j['requirements'].split(','))) }
124
+ end
125
+ end # end class << self
126
+
127
+ def initialize(gem_specs)
128
+ @gem_specs = gem_specs
129
+ end
130
+
131
+ def call
132
+ @gem_specs.map do |spec|
133
+ next if spec.name == WssAgent::NAME
134
+ gem_item(spec)
135
+ end.compact
136
+ end
137
+
138
+ def gem_item(spec)
139
+ {
140
+ 'groupId' => spec.name,
141
+ 'artifactId' => spec.file_name,
142
+ 'version' => spec.version.to_s,
143
+ 'sha1' => GemSha1.new(spec).sha1,
144
+ 'optional' => false,
145
+ 'children' => [],
146
+ 'exclusions' => []
147
+ }
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,4 @@
1
+ module WssAgent
2
+ VERSION = "0.0.15"
3
+ NAME = 'wss_agent'
4
+ end
data/lib/wss_agent.rb ADDED
@@ -0,0 +1,40 @@
1
+ require 'thor'
2
+ require 'net/http'
3
+ require 'awesome_print'
4
+ require 'yaml'
5
+ require 'oj'
6
+ require 'faraday'
7
+ require 'faraday_middleware'
8
+ require 'yell'
9
+ require 'wss_agent/version'
10
+ require 'wss_agent/specifications'
11
+ require 'wss_agent/configure'
12
+ require 'wss_agent/cli'
13
+ require 'wss_agent/response'
14
+ require 'wss_agent/response_policies'
15
+ require 'wss_agent/response_inventory'
16
+ require 'wss_agent/client'
17
+ require 'wss_agent/gem_sha1'
18
+ require 'wss_agent/project'
19
+
20
+
21
+ module WssAgent
22
+ # Your code goes here...
23
+
24
+ class WssAgentError < StandardError
25
+ def self.status_code(code)
26
+ define_method(:status_code) { code }
27
+ end
28
+ end
29
+
30
+ class TokenNotFound < WssAgentError; status_code(10) ; end
31
+ class ApiUrlNotFound < WssAgentError; status_code(11) ; end
32
+
33
+ def self.logger
34
+ @logger ||= Yell.new STDOUT, level: [:info]
35
+ end
36
+
37
+ def self.enable_debug!
38
+ @logger ||= Yell.new STDOUT, level: [:debug, :info, :warn, :error, :fatal, :unknown]
39
+ end
40
+ end