veye 0.0.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.
Files changed (63) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +2 -0
  3. data/Gemfile.lock +51 -0
  4. data/README.md +271 -0
  5. data/README.rdoc +6 -0
  6. data/Rakefile +44 -0
  7. data/bin/veye +390 -0
  8. data/lib/veye/api/base_resource.rb +29 -0
  9. data/lib/veye/api/json_response.rb +56 -0
  10. data/lib/veye/api/resource.rb +22 -0
  11. data/lib/veye/api.rb +3 -0
  12. data/lib/veye/package/follow.rb +50 -0
  13. data/lib/veye/package/info.rb +50 -0
  14. data/lib/veye/package/info_csv.rb +18 -0
  15. data/lib/veye/package/info_json.rb +14 -0
  16. data/lib/veye/package/info_pretty.rb +27 -0
  17. data/lib/veye/package/info_table.rb +29 -0
  18. data/lib/veye/package/search.rb +46 -0
  19. data/lib/veye/package/search_csv.rb +33 -0
  20. data/lib/veye/package/search_json.rb +19 -0
  21. data/lib/veye/package/search_pretty.rb +35 -0
  22. data/lib/veye/package/search_table.rb +40 -0
  23. data/lib/veye/package.rb +23 -0
  24. data/lib/veye/pagination/pagination_csv.rb +17 -0
  25. data/lib/veye/pagination/pagination_json.rb +12 -0
  26. data/lib/veye/pagination/pagination_pretty.rb +22 -0
  27. data/lib/veye/pagination/pagination_table.rb +22 -0
  28. data/lib/veye/pagination/show.rb +26 -0
  29. data/lib/veye/pagination.rb +7 -0
  30. data/lib/veye/project/check.rb +147 -0
  31. data/lib/veye/project/licence.rb +48 -0
  32. data/lib/veye/project/project_csv.rb +28 -0
  33. data/lib/veye/project/project_dependency_csv.rb +25 -0
  34. data/lib/veye/project/project_dependency_json.rb +12 -0
  35. data/lib/veye/project/project_dependency_pretty.rb +30 -0
  36. data/lib/veye/project/project_dependency_table.rb +27 -0
  37. data/lib/veye/project/project_json.rb +13 -0
  38. data/lib/veye/project/project_licence_csv.rb +19 -0
  39. data/lib/veye/project/project_licence_json.rb +12 -0
  40. data/lib/veye/project/project_licence_pretty.rb +23 -0
  41. data/lib/veye/project/project_licence_table.rb +29 -0
  42. data/lib/veye/project/project_pretty.rb +28 -0
  43. data/lib/veye/project/project_table.rb +30 -0
  44. data/lib/veye/project.rb +11 -0
  45. data/lib/veye/service.rb +14 -0
  46. data/lib/veye/user/favorite_csv.rb +28 -0
  47. data/lib/veye/user/favorite_json.rb +14 -0
  48. data/lib/veye/user/favorite_pretty.rb +25 -0
  49. data/lib/veye/user/favorite_table.rb +28 -0
  50. data/lib/veye/user/me.rb +75 -0
  51. data/lib/veye/user/profile_csv.rb +21 -0
  52. data/lib/veye/user/profile_json.rb +14 -0
  53. data/lib/veye/user/profile_pretty.rb +31 -0
  54. data/lib/veye/user/profile_table.rb +34 -0
  55. data/lib/veye/user.rb +7 -0
  56. data/lib/veye/version.rb +13 -0
  57. data/lib/veye.rb +82 -0
  58. data/test/default_test.rb +14 -0
  59. data/test/files/Gemfile +20 -0
  60. data/test/files/maven-1.0.1.pom +128 -0
  61. data/test/test_helper.rb +9 -0
  62. data/veye.rdoc +5 -0
  63. metadata +229 -0
@@ -0,0 +1,46 @@
1
+ require_relative 'search_csv.rb'
2
+ require_relative 'search_json.rb'
3
+ require_relative 'search_pretty.rb'
4
+ require_relative 'search_table.rb'
5
+
6
+ module Veye
7
+ module Package
8
+
9
+ class Search
10
+ @@output_formats = {
11
+ 'csv' => SearchCSV.new,
12
+ 'json' => SearchJSON.new,
13
+ 'pretty' => SearchPretty.new,
14
+ 'table' => SearchTable.new
15
+ }
16
+
17
+ def self.search(search_term, language = nil, group_id = nil, page = nil)
18
+ search_api = Veye::API::Resource.new "#{RESOURCE_PATH}/search"
19
+
20
+ search_response = nil
21
+ search_params = {:q => search_term.to_s}
22
+
23
+ search_params[:lang] = Package.encode_language(language) unless language.nil?
24
+ search_params[:g] = group_id unless group_id.nil?
25
+ search_params[:page] = page unless page.nil?
26
+
27
+ request_params = {:params => search_params}
28
+ search_api.resource["/#{search_term}"].get(request_params) do |response, request, result, &block|
29
+ search_response = API::JSONResponse.new(request, result, response)
30
+ end
31
+
32
+ return search_response
33
+ end
34
+
35
+ def self.format(search_results, format = 'pretty', paging = nil)
36
+
37
+ formatter = @@output_formats[format]
38
+ formatter.before
39
+ formatter.format(search_results)
40
+ formatter.after paging
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,33 @@
1
+ module Veye
2
+ module Package
3
+ class SearchCSV
4
+ def before
5
+ printf("nr,name,version,prod_key,version,language,group_id\n")
6
+ end
7
+ def after(paging = nil)
8
+ return if paging.nil?
9
+
10
+ printf("# ------------------------------------------\n")
11
+ printf("current_page,per_page,total_pages,total_entries\n")
12
+ printf("%s,%s,%s,%s\n",
13
+ paging['current_page'],
14
+ paging['per_page'],
15
+ paging['total_pages'],
16
+ paging['total_entries'])
17
+ end
18
+
19
+ def format(results)
20
+ results.each_with_index do |result, index|
21
+ printf("%d,%s,%s,%s,%s,%s,%s\n",
22
+ index + 1,
23
+ result["name"],
24
+ result["version"],
25
+ result["prod_key"],
26
+ result["version"],
27
+ result["language"],
28
+ result["group_id"])
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ module Veye
2
+ module Package
3
+ class SearchJSON
4
+ def before
5
+ @results = {:results => []}
6
+ end
7
+ def after(paging = nil)
8
+ @results[:paging] = paging unless paging.nil?
9
+ printf("%s\n", @results.to_json)
10
+ end
11
+
12
+ def format(results)
13
+ results.each do |result|
14
+ @results[:results] << result
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ require 'rainbow'
2
+
3
+ module Veye
4
+ module Package
5
+ class SearchPretty
6
+ def before; end
7
+ def after(paging = nil)
8
+ return if paging.nil?
9
+
10
+ printf("\n#-- %s\n", "Pagination information".bright)
11
+ printf("\t%-15s: %s\n", "Current page", paging['current_page'])
12
+ printf("\t%-15s: %s\n", "Per page", paging['per_page'])
13
+ printf("\t%-15s: %s\n", "Total pages", paging['total_pages'])
14
+ printf("\t%-15s: %s\n", "Total entries", paging['total_entries'])
15
+
16
+ end
17
+
18
+ def format(results)
19
+ results.each_with_index do |result, index|
20
+ printf("%3d - %s\n",
21
+ index + 1,
22
+ "#{result["name"]}".foreground(:green).bright)
23
+ printf("\t%-15s: %s\n", "Product key", result["prod_key"])
24
+ printf("\t%-15s: %s\n", "Latest version",
25
+ "#{result["version"]}".bright)
26
+ printf("\t%-15s: %s\n", "Language", result["language"])
27
+
28
+ if result.has_key? "group_id" and not result["group_id"].empty?
29
+ printf("\t%-15s: %s\n", "Group id", result["group_id"])
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,40 @@
1
+ require 'terminal-table'
2
+
3
+ module Veye
4
+ module Package
5
+ class SearchTable
6
+ def before
7
+ @@table = Terminal::Table.new :title => "Package search",
8
+ :headings => %w(index name version product_key language group_id)
9
+ @@table.align_column(0, :right)
10
+ end
11
+
12
+ def after(paging = nil)
13
+ unless paging.nil?
14
+ paging_header = ['p', 'current_page', 'per_page', 'total_pages', 'total_entries']
15
+ paging_data = ["p"]
16
+ paging.each_pair do |key, val|
17
+ paging_data << val
18
+ end
19
+
20
+ @@table.add_separator
21
+ @@table << paging_header
22
+ @@table << paging_data
23
+ end
24
+
25
+ puts @@table.to_s
26
+ end
27
+
28
+ def format(results)
29
+ results.each_with_index do |result, index|
30
+ row = [index+1, result["name"], result["version"], result["prod_key"]]
31
+ row << result["language"]
32
+ row << result["group_id"]
33
+
34
+ @@table << row
35
+ end
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'package/info.rb'
2
+ require_relative 'package/search.rb'
3
+ require_relative 'package/follow.rb'
4
+
5
+ # -- define module constants here
6
+ module Veye
7
+ module Package
8
+ RESOURCE_PATH = "/products"
9
+
10
+ def supported_languages
11
+ Set.new ["Clojure", "Java", "Javascript", "Node.JS", "PHP", "Python", "Ruby", "R"]
12
+ end
13
+
14
+ def self.encode_prod_key(prod_key)
15
+ prod_key = prod_key.to_s
16
+ prod_key.gsub(/\//, ":").gsub(/\./, "~")
17
+ end
18
+
19
+ def self.encode_language(lang)
20
+ lang.gsub(/\./, "").downcase
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module Veye
2
+ module Pagination
3
+ class PaginationCSV
4
+ def before
5
+ printf("current_page,per_page,total_pages,total_entries\n")
6
+ end
7
+
8
+ def after; end
9
+
10
+ def format(paging)
11
+ printf("%s,%s,%s,%s\n",
12
+ paging['current_page'], paging['per_page'],
13
+ paging['total_pages'], paging['total_entries'])
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ module Veye
2
+ module Pagination
3
+ class PaginationJSON
4
+ def before; end
5
+ def after; end
6
+
7
+ def format(paging)
8
+ printf("%s\n", {'paging' => paging}.to_json)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,22 @@
1
+ require 'rainbow'
2
+
3
+ module Veye
4
+ module Pagination
5
+ class PaginationPretty
6
+ def before; end
7
+ def after; end
8
+
9
+ def format(paging)
10
+ printf("\t%15s - %s\n",
11
+ "Current page".foreground(:green).bright,
12
+ "#{paging['current_page']}".bright)
13
+ puts "\t-------------------------"
14
+ printf("\t%-15s: %s\n", "Per page", paging['per_page'])
15
+ printf("\t%-15s: %s\n", "Total pages", paging['total_pages'])
16
+ printf("\t%-15s: %s\n", "Total entries", paging['total_entries'])
17
+
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,22 @@
1
+ require 'terminal-table'
2
+
3
+ module Veye
4
+ module Pagination
5
+ class PaginationTable
6
+ def before
7
+ @@table = Terminal::Table.new :title => "Pagination",
8
+ :headings => %w(current_page per_page total_pages total_entries)
9
+ @@table.align_column(0, :right)
10
+ end
11
+
12
+ def after
13
+ puts @@table.to_s
14
+ end
15
+
16
+ def format(paging)
17
+ row = [paging['current_page'], paging['per_page'], paging['total_pages'], paging['total_entries']]
18
+ @@table << row
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'pagination_csv.rb'
2
+ require_relative 'pagination_json.rb'
3
+ require_relative 'pagination_pretty.rb'
4
+ require_relative 'pagination_table.rb'
5
+
6
+ module Veye
7
+ module Pagination
8
+ class Show
9
+ @@pagination_formats = {
10
+ 'csv' => PaginationCSV.new,
11
+ 'json' => PaginationJSON.new,
12
+ 'pretty' => PaginationPretty.new,
13
+ 'table' => PaginationTable.new
14
+ }
15
+
16
+ def self.format(paging, format = 'pretty')
17
+ formatter = @@pagination_formats[format]
18
+
19
+ formatter.before
20
+ formatter.format paging
21
+ formatter.after
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -0,0 +1,7 @@
1
+ require_relative 'pagination/show.rb'
2
+
3
+ module Veye
4
+ module Pagination
5
+ #add module constants here
6
+ end
7
+ end
@@ -0,0 +1,147 @@
1
+ require 'json'
2
+
3
+ require_relative 'project_csv.rb'
4
+ require_relative 'project_json.rb'
5
+ require_relative 'project_pretty.rb'
6
+ require_relative 'project_table.rb'
7
+
8
+ require_relative 'project_dependency_csv.rb'
9
+ require_relative 'project_dependency_json.rb'
10
+ require_relative 'project_dependency_pretty.rb'
11
+ require_relative 'project_dependency_table.rb'
12
+
13
+ module Veye
14
+ module Project
15
+ class Check
16
+ @@output_formats = {
17
+ "csv" => ProjectCSV.new,
18
+ "json" => ProjectJSON.new,
19
+ "pretty" => ProjectPretty.new,
20
+ "table" => ProjectTable.new
21
+ }
22
+
23
+ @@dependency_output_formats = {
24
+ "csv" => ProjectDependencyCSV.new,
25
+ "json" => ProjectDependencyJSON.new,
26
+ "pretty" => ProjectDependencyPretty.new,
27
+ "table" => ProjectDependencyTable.new
28
+ }
29
+
30
+
31
+ def self.get_list(api_key)
32
+ project_api = API::Resource.new(RESOURCE_PATH)
33
+ qparams = {:params => {:api_key => api_key}}
34
+
35
+ project_api.resource.get(qparams) do |response, request, result|
36
+ response_data = API::JSONResponse.new(request, result, response)
37
+ end
38
+ end
39
+
40
+ def self.upload(filename, api_key)
41
+ response_data = {:success => false}
42
+ file_path = File.absolute_path(filename)
43
+
44
+ unless File.exists?(file_path)
45
+ error_msg = sprintf("%s: Cant read file `%s`",
46
+ "Error".foreground(:red),
47
+ "#{filename}".foreground(:yellow)
48
+ )
49
+ exit_now!(error_msg)
50
+ end
51
+
52
+ file_size = File.size(file_path)
53
+ unless file_size != 0 and file_size < MAX_FILE_SIZE
54
+ exit_now!("Size of file is not acceptable: 0kb < x <= #{MAX_FILE_SIZE/1000}kb")
55
+ end
56
+
57
+ project_api = API::Resource.new(RESOURCE_PATH)
58
+ file_obj = File.open(file_path, 'rb')
59
+
60
+ upload_data = {
61
+ :upload => file_obj,
62
+ :api_key => api_key
63
+ }
64
+ project_api.resource.post(upload_data) do |response, request, result, &block|
65
+ response_data = API::JSONResponse.new(request, result, response)
66
+ end
67
+
68
+ return response_data
69
+ end
70
+
71
+ def self.update(project_key, filename, api_key)
72
+ response_data = {:success => false}
73
+ file_path = File.absolute_path(filename)
74
+
75
+ unless File.exists?(file_path)
76
+ error_msg = sprintf("%s: Cant read file `%s`",
77
+ "Error".foreground(:red),
78
+ "#{filename}".foreground(:yellow)
79
+ )
80
+ exit_now!(error_msg)
81
+ end
82
+
83
+ file_size = File.size(file_path)
84
+ unless file_size != 0 and file_size < MAX_FILE_SIZE
85
+ exit_now!(" The size of file is not acceptable: 0kb < x <= #{MAX_FILE_SIZE/1000}kb")
86
+ end
87
+
88
+ project_api = API::Resource.new("#{RESOURCE_PATH}/#{project_key}")
89
+ file_obj = File.open(file_path, 'rb')
90
+ upload_data = {
91
+ :project_file => file_obj,
92
+ :api_key => api_key
93
+ }
94
+ project_api.resource.post(upload_data) do |response, request, result, &block|
95
+ response_data = API::JSONResponse.new(request, result, response)
96
+ end
97
+ end
98
+ def self.get_project(project_key, api_key)
99
+ response_data = nil
100
+ project_api = API::Resource.new(RESOURCE_PATH)
101
+
102
+ if project_key.nil? or project_key.empty?
103
+ error_msg = sprintf("%s: %s",
104
+ "Error".foreground(:red),
105
+ "Not valid project_key: `#{project_key}`")
106
+ exit_now! error_msg
107
+ end
108
+
109
+ project_url = "/#{project_key}"
110
+ qparams = {:params => {:api_key => api_key}}
111
+ project_api.resource[project_url].get(qparams) do |response, request, result|
112
+ response_data = API::JSONResponse.new(request, result, response)
113
+ end
114
+
115
+ return response_data
116
+ end
117
+
118
+ def self.delete_project(project_key, api_key)
119
+ project_api = Veye::API::Resource.new(RESOURCE_PATH)
120
+ qparams = {:params => {:api_key => api_key}}
121
+ response_data = nil
122
+
123
+ project_api.resource["/#{project_key}"].delete(qparams) do |response, request, result|
124
+ response_data = API::JSONResponse.new(request, result, response)
125
+ end
126
+
127
+ return response_data
128
+ end
129
+
130
+ def self.format(results, format = 'pretty')
131
+ formatter = @@output_formats[format]
132
+ formatter.before
133
+ formatter.format results
134
+ formatter.after
135
+ end
136
+
137
+ def self.format_dependencies(results, format = 'pretty')
138
+ formatter = @@dependency_output_formats[format]
139
+ formatter.before
140
+ formatter.format results
141
+ formatter.after
142
+ end
143
+
144
+ end
145
+ end
146
+ end
147
+
@@ -0,0 +1,48 @@
1
+ require 'json'
2
+
3
+ require_relative 'project_licence_csv.rb'
4
+ require_relative 'project_licence_json.rb'
5
+ require_relative 'project_licence_pretty.rb'
6
+ require_relative 'project_licence_table.rb'
7
+
8
+ module Veye
9
+ module Project
10
+ class Licence
11
+ @@output_formats = {
12
+ "csv" => ProjectLicenceCSV.new,
13
+ "json" => ProjectLicenceJSON.new,
14
+ "pretty" => ProjectLicencePretty.new,
15
+ "table" => ProjectLicenceTable.new
16
+ }
17
+
18
+ def self.get_project(project_key, api_key)
19
+ response_data = nil
20
+ project_api = API::Resource.new(RESOURCE_PATH)
21
+
22
+ if project_key.nil? or project_key.empty?
23
+ error_msg = sprintf("%s: %s",
24
+ "Error".foreground(:red),
25
+ "Not valid project_key: `#{project_key}`")
26
+ exit_now! error_msg
27
+ end
28
+
29
+ project_url = "/#{project_key}/licenses"
30
+ qparams = {:params => {:api_key => api_key}}
31
+ project_api.resource[project_url].get(qparams) do |response, request, result|
32
+ response_data = API::JSONResponse.new(request, result, response)
33
+ end
34
+
35
+ return response_data
36
+ end
37
+
38
+ def self.format(results, format = 'pretty')
39
+ formatter = @@output_formats[format]
40
+ formatter.before
41
+ formatter.format results
42
+ formatter.after
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,28 @@
1
+ module Veye
2
+ module Project
3
+ class ProjectCSV
4
+ def before
5
+ printf("nr,name,project_key,private,period,source,dep_number,out_number,created_at\n")
6
+ end
7
+ def after; end
8
+
9
+ def format(results)
10
+ results = [results] if results.is_a? Hash
11
+
12
+ results.each_with_index do |result, index|
13
+ printf("%d,%s,%s,%s,%s,%s,%s,%s,%s\n",
14
+ index + 1,
15
+ result['name'],
16
+ result['project_key'],
17
+ result['private'],
18
+ result['period'],
19
+ result['source'],
20
+ result['dep_number'],
21
+ result['out_number'],
22
+ result['created_at'])
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,25 @@
1
+ module Veye
2
+ module Project
3
+ class ProjectDependencyCSV
4
+ def before
5
+ printf("nr,name,prod_key,outdated,latest,current\n",nil)
6
+ end
7
+ def after; end
8
+
9
+ def format(results)
10
+ results = [results] if results.is_a?(Hash)
11
+
12
+ results.each_with_index do |result, index|
13
+ printf("%d,%s,%s,%s,%s,%s\n",
14
+ index + 1,
15
+ result["name"],
16
+ result["prod_key"],
17
+ result["outdated"],
18
+ result["version_current"],
19
+ result["version_requested"],
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,12 @@
1
+ module Veye
2
+ module Project
3
+ class ProjectDependencyJSON
4
+ def before; end
5
+ def after; end
6
+
7
+ def format(results)
8
+ printf("%s\n", {"dependencies" => results}.to_json)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ require 'rainbow'
2
+
3
+ module Veye
4
+ module Project
5
+ class ProjectDependencyPretty
6
+ def before; end
7
+ def after; end
8
+
9
+ def format(results)
10
+ results = [results] if results.is_a?(Hash)
11
+ results.each_with_index do |result, index|
12
+ project_name = "#{result['name']}".foreground(:green).bright
13
+ printf("%3d - %s\n", index + 1, project_name)
14
+ printf("\t%-15s: %s\n", "Product key", result["prod_key"])
15
+
16
+ color = (result["outdated"] == true) ? :red : :green
17
+ printf("\t%-15s: %s\n", "Outdated",
18
+ "#{result['outdated']}".foreground(color))
19
+
20
+ printf("\t%-15s: %s\n", "Latest version",
21
+ "#{result['version_current']}".foreground(color))
22
+
23
+ printf("\t%-15s: %s\n", "Current version", result["version_requested"])
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,27 @@
1
+ require 'terminal-table'
2
+
3
+ module Veye
4
+ module Project
5
+ class ProjectDependencyTable
6
+ def before
7
+ @@table = Terminal::Table.new :title => "Version check",
8
+ :headings => %w(index name prod_key version_current version_latest)
9
+ @@table.align_column(0, :right)
10
+ end
11
+
12
+ def after
13
+ puts @@table.to_s
14
+ end
15
+
16
+ def format(results)
17
+ results = [results] if results.is_a?(Hash)
18
+
19
+ results.each_with_index do |result, index|
20
+ row = [index + 1, result["name"], result["prod_key"],
21
+ result["version_current"], result["version_requested"]]
22
+ @@table << row
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ module Veye
2
+ module Project
3
+ class ProjectJSON
4
+ def before; end
5
+ def after; end
6
+
7
+ def format(results)
8
+ printf("%s\n", {"projects" => results}.to_json)
9
+ end
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,19 @@
1
+ module Veye
2
+ module Project
3
+ class ProjectLicenceCSV
4
+ def before
5
+ printf("nr,licence,product keys\n")
6
+ end
7
+ def after; end
8
+
9
+ def format(results)
10
+ n = 1
11
+ results["licenses"].each_pair do |licence, prods|
12
+ prod_keys = prods.map {|p| p["prod_key"]}
13
+ printf("%d,%s,%s\n", n, licence, prod_keys.join(','))
14
+ n += 1
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end