wss_agent 0.0.15

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