nexus_cli 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.3.0
@@ -0,0 +1,49 @@
1
+ Feature: Use the Nexus CLI
2
+ As a CLI user
3
+ I need commands to get Nexus status, push, pull
4
+
5
+ Scenario: Get Nexus Status
6
+ When I call the nexus "status" command
7
+ Then the output should contain:
8
+ """
9
+ Application Name: Sonatype Nexus
10
+ Version: 2.0.5
11
+ """
12
+ And the exit status should be 0
13
+
14
+ Scenario: Push an Artifact
15
+ When I push an artifact with the GAV of "com.test:mytest:1.0.0:tgz"
16
+ Then the output should contain:
17
+ """
18
+ Artifact com.test:mytest:1.0.0:tgz has been successfully pushed to Nexus.
19
+ """
20
+ And the exit status should be 0
21
+
22
+ Scenario: Pull an artifact
23
+ When I call the nexus "pull com.test:mytest:1.0.0:tgz" command
24
+ Then the output should contain:
25
+ """
26
+ Artifact has been retrived and can be found at path:
27
+ """
28
+ And the exit status should be 0
29
+
30
+ Scenario: Pull an artifact to a specific place
31
+ When I pull an artifact with the GAV of "com.test:mytest:1.0.0:tgz" to a temp directory
32
+ Then I should have a copy of the "mytest-1.0.0.tgz" artifact in a temp directory
33
+
34
+ Scenario: Get an artifact's info
35
+ When I call the nexus "info com.test:mytest:1.0.0:tgz" command
36
+ Then the output should contain:
37
+ """
38
+ <groupId>com.test</groupId>
39
+ """
40
+ And the exit status should be 0
41
+
42
+ Scenario: Attempt to delete an artifact
43
+ When I delete an artifact with the GAV of "com.test:mytest:1.0.0:tgz"
44
+ And I call the nexus "info com.test:mytest:1.0.0:tgz" command
45
+ Then the output should contain:
46
+ """
47
+ The artifact you requested information for could not be found. Please ensure it exists inside the Nexus.
48
+ """
49
+ And the exit status should be 101
@@ -1,32 +1,26 @@
1
- When /^I get the artifact "([^"]*)"$/ do |arg1|
2
- NexusCli::Remote.pull_artifact arg1, nil
3
- end
4
-
5
- Then /^I should have a copy of the "([^"]*)" artifact on my computer$/ do |arg1|
6
- File.exists?(arg1).should be_true
7
- end
1
+ require 'aruba/api'
2
+ World(Aruba::Api)
8
3
 
9
- When /^I want the artifact "([^"]*)" in a temp directory$/ do |arg1|
10
- NexusCli::Remote.pull_artifact arg1, ENV["TMPDIR"]
4
+ When /^I call the nexus "(.*?)" command$/ do |command|
5
+ step "I run `nexus-cli #{command} --overrides=#{get_overrides}`"
11
6
  end
12
7
 
13
- Then /^I should have a copy of the "([^"]*)" artifact in a temp directory$/ do |arg1|
14
- path = File.join(ENV["TMPDIR"], arg1)
15
- File.exists?(path).should be_true
8
+ When /^I push an artifact with the GAV of "(.*)"$/ do |gav|
9
+ groupId, artifactId, version, extension = gav.split(":")
10
+ file = File.new(File.join(temp_dir, "#{artifactId}-#{version}.#{extension}"), 'w')
11
+ file.puts "some data"
12
+ file.close
13
+ step "I run `nexus-cli push #{gav} #{file.path}`"
16
14
  end
17
15
 
18
- Then /^I should expect an error because I need more colon separated values$/ do
19
- assert_exit_status(100)
16
+ When /^I pull an artifact with the GAV of "(.*?)" to a temp directory$/ do |gav|
17
+ step "I run `nexus-cli pull #{gav} --destination #{temp_dir}`"
20
18
  end
21
19
 
22
- When /^I push an artifact into the Nexus$/ do
23
- file = File.new("myFile.tgz", 'w')
24
- file.puts "some data"
25
- file.close
26
- file = File.open("myFile.tgz", 'r')
27
- NexusCli::Remote.push_artifact "com.foo.bar:myFile:1.0.0:tgz", file
20
+ Then /^I should have a copy of the "(.*?)" artifact in a temp directory$/ do |fileName|
21
+ File.exists?(File.join(temp_dir, fileName)).should == true
28
22
  end
29
23
 
30
- Then /^I should be able to ask the Nexus for information about it and get a result$/ do
31
- NexusCli::Remote.get_artifact_info "com.foo.bar:myFile:1.0.0:tgz"
24
+ When /^I delete an artifact with the GAV of "(.*)"$/ do |gav|
25
+ nexus_remote.delete_artifact(gav)
32
26
  end
@@ -1,15 +1,20 @@
1
1
  require 'aruba/cucumber'
2
-
3
2
  $:.push "#{File.dirname(__FILE__)}/../../lib/"
4
3
  require 'nexus_cli'
5
4
  require 'rspec'
6
5
 
7
- After do |scenario|
8
- FileUtils.rm_f("mytar-1.0.3.tgz")
6
+ def get_overrides
7
+ @overrides ||= {:url => 'http://localhost:8081/nexus', :repository => 'releases', :username => 'deployment', :password => 'deployment123'}
8
+ end
9
9
 
10
- tmp_path = File.join(ENV["TMPDIR"], "mytar-1.0.3.tgz")
11
- FileUtils.rm_f(tmp_path)
10
+ def temp_dir
11
+ @tmpdir ||= Dir.mktmpdir
12
+ end
12
13
 
13
- NexusCli::Remote.delete_artifact('com.foo.bar:myFile:1.0.0:tgz')
14
- FileUtils.rm_f("myFile.tgz")
14
+ def nexus_remote
15
+ @nexus_remote ||= NexusCli::Factory.create(get_overrides)
15
16
  end
17
+
18
+ at_exit do
19
+ FileUtils.rm_rf(temp_dir)
20
+ end
@@ -2,7 +2,9 @@ require 'nexus_cli/tasks'
2
2
  require 'nexus_cli/cli'
3
3
  require 'nexus_cli/errors'
4
4
  require 'nexus_cli/kernel'
5
- require 'nexus_cli/remote'
5
+ require 'nexus_cli/nexus_remote_factory'
6
+ require 'nexus_cli/nexus_oss_remote'
7
+ require 'nexus_cli/nexus_pro_remote'
6
8
 
7
9
  module NexusCli
8
10
  class << self
@@ -76,4 +76,18 @@ This could mean several things:
76
76
  end
77
77
  status_code(108)
78
78
  end
79
+
80
+ class SearchParameterMalformedException < NexusCliError
81
+ def message
82
+ "Submit your search request specifying the search key, type, and value. The available search types are `equal`, `matches`, `bounded`, and `notequal`."
83
+ end
84
+ status_code(109)
85
+ end
86
+
87
+ class BadSearchRequestException < NexusCliError
88
+ def message
89
+ "Your request was denied by the Nexus server due to a bad request. Check that your search parameters contain valid values."
90
+ end
91
+ status_code(110)
92
+ end
79
93
  end
@@ -0,0 +1,109 @@
1
+ require 'restclient'
2
+ require 'nokogiri'
3
+ require 'yaml'
4
+
5
+ module NexusCli
6
+ class OSSRemote
7
+
8
+ def initialize(overrides)
9
+ @configuration = parse_configuration(overrides)
10
+ end
11
+
12
+ def configuration
13
+ return @configuration if @configuration
14
+ end
15
+
16
+ def nexus
17
+ @nexus ||= RestClient::Resource.new configuration["url"], :user => configuration["username"], :password => configuration["password"]
18
+ end
19
+
20
+ def status
21
+ doc = Nokogiri::XML(nexus['service/local/status'].get).xpath("/status/data")
22
+ data = Hash.new
23
+ data['app_name'] = doc.xpath("appName")[0].text
24
+ data['version'] = doc.xpath("version")[0].text
25
+ data['edition_long'] = doc.xpath("editionLong")[0].text
26
+ data['state'] = doc.xpath("state")[0].text
27
+ data['started_at'] = doc.xpath("startedAt")[0].text
28
+ data['base_url'] = doc.xpath("baseUrl")[0].text
29
+ return data
30
+ end
31
+
32
+ def pull_artifact(artifact, destination)
33
+ group_id, artifact_id, version, extension = parse_artifact_string(artifact)
34
+ begin
35
+ fileData = nexus['service/local/artifact/maven/redirect'].get({:params => {:r => configuration['repository'], :g => group_id, :a => artifact_id, :v => version, :e => extension}})
36
+ rescue RestClient::ResourceNotFound
37
+ raise ArtifactNotFoundException
38
+ end
39
+ artifact = nil
40
+ destination = File.join(File.expand_path(destination || "."), "#{artifact_id}-#{version}.#{extension}")
41
+ artifact = File.open(destination, 'w')
42
+ artifact.write(fileData)
43
+ artifact.close()
44
+ File.expand_path(artifact.path)
45
+ end
46
+
47
+ def push_artifact(artifact, file)
48
+ group_id, artifact_id, version, extension = parse_artifact_string(artifact)
49
+ nexus['service/local/artifact/maven/content'].post({:hasPom => false, :g => group_id, :a => artifact_id, :v => version, :e => extension, :p => extension, :r => configuration['repository'],
50
+ :file => File.new(file)}) do |response, request, result, &block|
51
+ case response.code
52
+ when 400
53
+ raise BadUploadRequestException
54
+ when 401
55
+ raise PermissionsException
56
+ when 403
57
+ raise PermissionsException
58
+ when 404
59
+ raise CouldNotConnectToNexusException
60
+ end
61
+ end
62
+ end
63
+
64
+ def delete_artifact(artifact)
65
+ group_id, artifact_id, version = parse_artifact_string(artifact)
66
+ delete_string = "content/repositories/releases/#{group_id.gsub(".", "/")}/#{artifact_id.gsub(".", "/")}/#{version}"
67
+ Kernel.quietly {`curl --request DELETE #{File.join(configuration['url'], delete_string)} -u #{configuration['username']}:#{configuration['password']}`}
68
+ end
69
+
70
+ def get_artifact_info(artifact)
71
+ group_id, artifact_id, version, extension = parse_artifact_string(artifact)
72
+ begin
73
+ nexus['service/local/artifact/maven/resolve'].get({:params => {:r => configuration['repository'], :g => group_id, :a => artifact_id, :v => version, :e => extension}})
74
+ rescue Errno::ECONNREFUSED => e
75
+ raise CouldNotConnectToNexusException
76
+ rescue RestClient::ResourceNotFound => e
77
+ raise ArtifactNotFoundException
78
+ end
79
+ end
80
+
81
+ private
82
+ def parse_artifact_string(artifact)
83
+ split_artifact = artifact.split(":")
84
+ if(split_artifact.size < 4)
85
+ raise ArtifactMalformedException
86
+ end
87
+ return split_artifact
88
+ end
89
+
90
+ def parse_configuration(overrides)
91
+ begin
92
+ config = YAML::load_file(File.expand_path("~/.nexus_cli"))
93
+ rescue
94
+ end
95
+ if config.nil? && (overrides.nil? || overrides.empty?)
96
+ raise MissingSettingsFileException
97
+ end
98
+ overrides.each{|key, value| config[key] = value} unless overrides.nil? || overrides.empty?
99
+ validate_config(config)
100
+ config
101
+ end
102
+
103
+ def validate_config(configuration)
104
+ ["url", "repository", "username","password"].each do |key|
105
+ raise InvalidSettingsException.new(key) unless configuration.has_key?(key)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,112 @@
1
+ require 'restclient'
2
+ require 'nokogiri'
3
+ require 'tempfile'
4
+ require 'yaml'
5
+
6
+ module NexusCli
7
+ class ProRemote < OSSRemote
8
+
9
+ def get_artifact_custom_info(artifact)
10
+ parse_n3(get_artifact_custom_info_n3(artifact))
11
+ end
12
+
13
+ def get_artifact_custom_info_n3(artifact)
14
+ group_id, artifact_id, version, extension = parse_artifact_string(artifact)
15
+ file_name = "#{artifact_id}-#{version}.#{extension}.n3"
16
+ get_string = "content/repositories/#{configuration['repository']}/.meta/#{group_id.gsub(".", "/")}/#{artifact_id.gsub(".", "/")}/#{version}/#{file_name}"
17
+ begin
18
+ nexus[get_string].get
19
+ rescue RestClient::ResourceNotFound => e
20
+ raise ArtifactNotFoundException
21
+ end
22
+ end
23
+
24
+ def update_artifact_custom_info(artifact, file, insecure)
25
+ # Check if artifact exists before posting custom metadata.
26
+ get_artifact_info(artifact)
27
+ # Update the custom metadata using the n3 file.
28
+ group_id, artifact_id, version, extension = parse_artifact_string(artifact)
29
+ file_name = "#{artifact_id}-#{version}.#{extension}.n3"
30
+ post_string = "content/repositories/#{configuration['repository']}/.meta/#{group_id.gsub(".", "/")}/#{artifact_id.gsub(".", "/")}/#{version}/#{file_name}"
31
+
32
+ # Read in nexus n3 file. If this is a newly-added artifact, there will be no n3 file so escape the exception.
33
+ begin
34
+ nexus_n3 = get_artifact_custom_info_n3(artifact, overrides)
35
+ rescue ArtifactNotFoundException
36
+ nexus_n3 = ""
37
+ end
38
+
39
+ # Read in local n3 file.
40
+ local_n3 = File.open(file).read
41
+
42
+ n3_user_urns = { "head" => "<urn:maven/artifact##{group_id}:#{artifact_id}:#{version}::#{extension}> a <urn:maven#artifact>" }
43
+ # Get all the urn:nexus/user# keys and consolidate.
44
+ # First, get the nexus keys.
45
+ nexus_n3.each_line { |line|
46
+ if line.match(/urn:nexus\/user#/)
47
+ tag, value = parse_n3_line(line)
48
+ n3_user_urns[tag] = "\t<urn:nexus/user##{tag}> \"#{value}\"" unless tag.empty? || value.empty?
49
+ end
50
+ }
51
+ # Next, get the local keys and update the nexus keys.
52
+ local_n3.each_line { |line|
53
+ if line.match(/urn:nexus\/user#/)
54
+ tag, value = parse_n3_line(line)
55
+ # Delete the nexus key if the local key has no value.
56
+ if n3_user_urns.has_key?(tag) && value.empty?
57
+ n3_user_urns.delete(tag)
58
+ else
59
+ n3_user_urns[tag] = "\t<urn:nexus/user##{tag}> \"#{value}\"" unless tag.empty? || value.empty?
60
+ end
61
+ end
62
+ }
63
+
64
+ n3_data = n3_user_urns.values.join(" ;\n") + " ."
65
+ n3_temp = Tempfile.new("nexus_n3")
66
+ begin
67
+ n3_temp.write(n3_data)
68
+ n3_temp.rewind
69
+ Kernel.quietly {`curl -T #{n3_temp.path} #{File.join(configuration['url'], post_string)} -u #{configuration['username']}:#{configuration['password']}`}
70
+ ensure
71
+ n3_temp.close
72
+ n3_temp.unlink
73
+ end
74
+ end
75
+
76
+ def search_artifacts(key, type, value)
77
+ if key.empty? || type.empty? || value.empty?
78
+ raise SearchParameterMalformedException
79
+ end
80
+ begin
81
+ nexus['service/local/search/m2/freeform'].get ({params: {p: key, t: type, v: value}}) do |response, request, result, &block|
82
+ raise BadSearchRequestException if response.code == 400
83
+ doc = Nokogiri::XML(response.body).xpath("/search-results")
84
+ return doc.xpath("count")[0].text.to_i > 0 ? doc.to_s : "No search results."
85
+ end
86
+ rescue RestClient::ResourceNotFound => e
87
+ raise ArtifactNotFoundException
88
+ end
89
+ end
90
+
91
+ private
92
+ def parse_n3(data)
93
+ builder = Nokogiri::XML::Builder.new do |xml|
94
+ xml.send("artifact-resolution") {
95
+ xml.data {
96
+ data.each_line { |line|
97
+ tag, value = parse_n3_line(line)
98
+ xml.send(tag, value) unless tag.empty? || value.empty?
99
+ }
100
+ }
101
+ }
102
+ end
103
+ return builder.doc.root.to_s
104
+ end
105
+
106
+ def parse_n3_line(line)
107
+ tag = line.match(/#(\w*)>/) ? "#{$1}" : ""
108
+ value = line.match(/"([^"]*)"/) ? "#{$1}" : ""
109
+ return tag, value
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,59 @@
1
+ require 'restclient'
2
+ require 'nokogiri'
3
+ require 'yaml'
4
+
5
+ module NexusCli
6
+ class Factory
7
+ class << self
8
+
9
+ def create(overrides)
10
+ @configuration = parse_configuration(overrides)
11
+ running_nexus_pro? ? ProRemote.new(overrides) : OSSRemote.new(overrides)
12
+ end
13
+
14
+ def configuration
15
+ return @configuration if @configuration
16
+ end
17
+
18
+ def nexus
19
+ @nexus ||= RestClient::Resource.new configuration["url"], :user => configuration["username"], :password => configuration["password"]
20
+ end
21
+
22
+ def status
23
+ doc = Nokogiri::XML(nexus['service/local/status'].get).xpath("/status/data")
24
+ data = Hash.new
25
+ data['app_name'] = doc.xpath("appName")[0].text
26
+ data['version'] = doc.xpath("version")[0].text
27
+ data['edition_long'] = doc.xpath("editionLong")[0].text
28
+ data['state'] = doc.xpath("state")[0].text
29
+ data['started_at'] = doc.xpath("startedAt")[0].text
30
+ data['base_url'] = doc.xpath("baseUrl")[0].text
31
+ return data
32
+ end
33
+
34
+ private
35
+ def running_nexus_pro?
36
+ return status['edition_long'] == "Professional" ? true : false
37
+ end
38
+
39
+ def parse_configuration(overrides)
40
+ begin
41
+ config = YAML::load_file(File.expand_path("~/.nexus_cli"))
42
+ rescue
43
+ end
44
+ if config.nil? && (overrides.nil? || overrides.empty?)
45
+ raise MissingSettingsFileException
46
+ end
47
+ overrides.each{|key, value| config[key] = value} unless overrides.nil? || overrides.empty?
48
+ validate_config(config)
49
+ config
50
+ end
51
+
52
+ def validate_config(configuration)
53
+ ["url", "repository", "username","password"].each do |key|
54
+ raise InvalidSettingsException.new(key) unless configuration.has_key?(key)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -21,7 +21,7 @@ module NexusCli
21
21
  def initialize(*args)
22
22
  super
23
23
  begin
24
- set_remote_configuration(options[:overrides])
24
+ @nexus_remote = Factory.create(options[:overrides])
25
25
  rescue NexusCliError => e
26
26
  say e.message, :red
27
27
  exit e.status_code
@@ -35,7 +35,7 @@ module NexusCli
35
35
  desc "pull_artifact artifact", "Pulls an artifact from Nexus and places it on your machine."
36
36
  def pull_artifact(artifact)
37
37
  begin
38
- path_to_artifact = Remote.pull_artifact(artifact, options[:destination], options[:overrides])
38
+ path_to_artifact = @nexus_remote.pull_artifact(artifact, options[:destination])
39
39
  say "Artifact has been retrived and can be found at path: #{path_to_artifact}", :green
40
40
  rescue NexusCliError => e
41
41
  say e.message, :red
@@ -43,14 +43,10 @@ module NexusCli
43
43
  end
44
44
  end
45
45
 
46
- method_option :insecure,
47
- :type => :boolean,
48
- :default => false,
49
- :desc => "Overrides any failures because of an 'insecure' SSL conncetion."
50
46
  desc "push_artifact artifact file", "Pushes an artifact from your machine onto the Nexus."
51
47
  def push_artifact(artifact, file)
52
48
  begin
53
- Remote.push_artifact(artifact, file, options[:insecure], options[:overrides])
49
+ @nexus_remote.push_artifact(artifact, file)
54
50
  say "Artifact #{artifact} has been successfully pushed to Nexus.", :green
55
51
  rescue NexusCliError => e
56
52
  say e.message, :red
@@ -61,7 +57,7 @@ module NexusCli
61
57
  desc "get_artifact_info artifact", "Gets and returns the metadata in XML format about a particular artifact."
62
58
  def get_artifact_info(artifact)
63
59
  begin
64
- say Remote.get_artifact_info(artifact, options[:overrides]), :green
60
+ say @nexus_remote.get_artifact_info(artifact), :green
65
61
  rescue NexusCliError => e
66
62
  say e.message, :red
67
63
  exit e.status_code
@@ -71,7 +67,45 @@ module NexusCli
71
67
  desc "get_artifact_custom_info artifact", "Gets and returns the custom metadata in XML format about a particular artifact."
72
68
  def get_artifact_custom_info(artifact)
73
69
  begin
74
- say Remote.get_artifact_custom_info(artifact, options[:overrides]), :green
70
+ say @nexus_remote.get_artifact_custom_info(artifact), :green
71
+ rescue NexusCliError => e
72
+ say e.message, :red
73
+ exit e.status_code
74
+ end
75
+ end
76
+
77
+ desc "get_artifact_custom_info_n3 artifact", "Gets and returns the custom metadata in Nexus n3 format about a particular artifact."
78
+ def get_artifact_custom_info_n3(artifact)
79
+ begin
80
+ raise NotNexusProException unless @nexus_remote.kind_of? ProRemote
81
+ say @nexus_remote.get_artifact_custom_info_n3(artifact), :green
82
+ rescue NexusCliError => e
83
+ say e.message, :red
84
+ exit e.status_code
85
+ end
86
+ end
87
+
88
+ method_option :insecure,
89
+ :type => :boolean,
90
+ :default => false,
91
+ :desc => "Overrides any failures because of an 'insecure' SSL connection."
92
+ desc "update_artifact_custom_info artifact file", "Updates the artifact custom metadata by pushing the Nexus custom artifact file (n3) from your machine onto the Nexus."
93
+ def update_artifact_custom_info(artifact, file)
94
+ begin
95
+ raise NotNexusProException unless @nexus_remote.kind_of? ProRemote
96
+ @nexus_remote.update_artifact_custom_info(artifact, file, options[:insecure])
97
+ say "Custom metadata for artifact #{artifact} has been successfully pushed to Nexus.", :green
98
+ rescue NexusCliError => e
99
+ say e.message, :red
100
+ exit e.status_code
101
+ end
102
+ end
103
+
104
+ desc "search_artifacts key type value", "Searches for artifacts using artifact metadata and returns the result as a list with items in XML format."
105
+ def search_artifacts(key, type, value)
106
+ begin
107
+ raise NotNexusProException unless @nexus_remote.kind_of? ProRemote
108
+ say @nexus_remote.search_artifacts(key, type, value), :green
75
109
  rescue NexusCliError => e
76
110
  say e.message, :red
77
111
  exit e.status_code
@@ -81,7 +115,7 @@ module NexusCli
81
115
  desc "get_nexus_configuration", "Prints out configuration from the .nexus_cli file that helps inform where artifacts will be uploaded."
82
116
  def get_nexus_configuration
83
117
  begin
84
- config = Remote.configuration
118
+ config = @nexus_remote.configuration
85
119
  say "********* Reading CLI configuration from #{File.expand_path('~/.nexus_cli')} *********", :blue
86
120
  say "Nexus URL: #{config['url']}", :blue
87
121
  say "Nexus Repository: #{config['repository']}", :blue
@@ -94,7 +128,7 @@ module NexusCli
94
128
  desc "get_nexus_status", "Prints out information about the Nexus instance."
95
129
  def get_nexus_status
96
130
  begin
97
- data = Remote.status
131
+ data = @nexus_remote.status
98
132
  say "********* Getting Nexus status from #{data['base_url']} *********", :blue
99
133
  say "Application Name: #{data['app_name']}", :blue
100
134
  say "Version: #{data['version']}", :blue
@@ -107,26 +141,6 @@ module NexusCli
107
141
  exit e.status_code
108
142
  end
109
143
  end
110
-
111
- private
112
- def set_remote_configuration(overrides)
113
- begin
114
- config = YAML::load_file(File.expand_path("~/.nexus_cli"))
115
- rescue
116
- end
117
- if config.nil? && (overrides.nil? || overrides.empty?)
118
- raise MissingSettingsFileException
119
- end
120
- overrides.each{|key, value| config[key] = value} unless overrides.nil? || overrides.empty?
121
- validate_config(config)
122
- Remote.configuration = config
123
- end
124
-
125
- def validate_config(configuration)
126
- ["url", "repository", "username","password"].each do |key|
127
- raise InvalidSettingsException.new(key) unless configuration.has_key?(key)
128
- end
129
- end
130
144
  end
131
145
  end
132
146
  end
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
 
19
19
  s.add_dependency 'thor'
20
20
  s.add_dependency 'rest-client'
21
+ s.add_dependency 'nokogiri'
21
22
 
22
23
  s.add_development_dependency 'rspec'
23
24
  s.add_development_dependency 'aruba'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexus_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-10 00:00:00.000000000 Z
12
+ date: 2012-07-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: nokogiri
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  - !ruby/object:Gem::Dependency
47
63
  name: rspec
48
64
  requirement: !ruby/object:Gem::Requirement
@@ -122,15 +138,16 @@ files:
122
138
  - Rakefile
123
139
  - VERSION
124
140
  - bin/nexus-cli
125
- - features/cli/pull_artifact.feature
126
- - features/cli/push_artifact.feature
141
+ - features/cli/nexus_oss.feature
127
142
  - features/step_definitions/cli_steps.rb
128
143
  - features/support/env.rb
129
144
  - lib/nexus_cli.rb
130
145
  - lib/nexus_cli/cli.rb
131
146
  - lib/nexus_cli/errors.rb
132
147
  - lib/nexus_cli/kernel.rb
133
- - lib/nexus_cli/remote.rb
148
+ - lib/nexus_cli/nexus_oss_remote.rb
149
+ - lib/nexus_cli/nexus_pro_remote.rb
150
+ - lib/nexus_cli/nexus_remote_factory.rb
134
151
  - lib/nexus_cli/tasks.rb
135
152
  - lib/nexus_cli/version.rb
136
153
  - nexus_cli.gemspec
@@ -149,7 +166,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
149
166
  version: '0'
150
167
  segments:
151
168
  - 0
152
- hash: -1507913424416327621
169
+ hash: 3325532431441857534
153
170
  required_rubygems_version: !ruby/object:Gem::Requirement
154
171
  none: false
155
172
  requirements:
@@ -158,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
175
  version: '0'
159
176
  segments:
160
177
  - 0
161
- hash: -1507913424416327621
178
+ hash: 3325532431441857534
162
179
  requirements: []
163
180
  rubyforge_project:
164
181
  rubygems_version: 1.8.21
@@ -166,8 +183,7 @@ signing_key:
166
183
  specification_version: 3
167
184
  summary: A command-line wrapper for making REST calls to Sonatype Nexus.
168
185
  test_files:
169
- - features/cli/pull_artifact.feature
170
- - features/cli/push_artifact.feature
186
+ - features/cli/nexus_oss.feature
171
187
  - features/step_definitions/cli_steps.rb
172
188
  - features/support/env.rb
173
189
  - spec/remote_spec.rb
@@ -1,17 +0,0 @@
1
- @cli
2
- Feature: Pull Artifact
3
- As a CLI user
4
- I need a command to pull artifacts from the Nexus repository
5
- So I have a way to get artifacts from a remote system to my local machine
6
-
7
- Scenario: Pull an artifact
8
- When I get the artifact "com.riotgames.tar:mytar:1.0.3:tgz"
9
- Then I should have a copy of the "mytar-1.0.3.tgz" artifact on my computer
10
-
11
- Scenario: Pull an artifact to a specific place
12
- When I want the artifact "com.riotgames.tar:mytar:1.0.3:tgz" in a temp directory
13
- Then I should have a copy of the "mytar-1.0.3.tgz" artifact in a temp directory
14
-
15
- Scenario: Attempt to pull an artifact with the wrong parameters
16
- When I run `nexus-cli pull_artifact com.riotgames.whatever:something`
17
- Then I should expect an error because I need more colon separated values
@@ -1,8 +0,0 @@
1
- Feature: Push Artifact
2
- As a CLI User
3
- I need a command to push artifacts into the Nexus repository
4
- So I have a way to get artifacts from Nexus when I want them
5
-
6
- Scenario: Push an Artifact
7
- When I push an artifact into the Nexus
8
- Then I should be able to ask the Nexus for information about it and get a result
@@ -1,132 +0,0 @@
1
- require 'restclient'
2
- require 'rexml/document'
3
- require 'yaml'
4
- require 'open3'
5
-
6
- module NexusCli
7
- class Remote
8
- class << self
9
-
10
- def configuration=(config = {})
11
- @configuration = config
12
- end
13
-
14
- def configuration
15
- return @configuration if @configuration
16
- end
17
-
18
- def nexus
19
- @nexus ||= RestClient::Resource.new configuration["url"], :user => configuration["username"], :password => configuration["password"]
20
- end
21
-
22
- def status
23
- doc = REXML::Document.new(nexus['service/local/status'].get).elements['status/data']
24
- data = Hash.new
25
- data['app_name'] = doc.elements['appName'].text
26
- data['version'] = doc.elements['version'].text
27
- data['edition_long'] = doc.elements['editionLong'].text
28
- data['state'] = doc.elements['state'].text
29
- data['started_at'] = doc.elements['startedAt'].text
30
- data['base_url'] = doc.elements['baseUrl'].text
31
- return data
32
- end
33
-
34
- def pull_artifact(artifact, destination, overrides)
35
- split_artifact = artifact.split(":")
36
- if(split_artifact.size < 4)
37
- raise ArtifactMalformedException
38
- end
39
- group_id, artifact_id, version, extension = split_artifact
40
- begin
41
- fileData = nexus['service/local/artifact/maven/redirect'].get({:params => {:r => configuration['repository'], :g => group_id, :a => artifact_id, :v => version, :e => extension}})
42
- rescue RestClient::ResourceNotFound
43
- raise ArtifactNotFoundException
44
- end
45
- artifact = nil
46
- destination = File.join(File.expand_path(destination || "."), "#{artifact_id}-#{version}.#{extension}")
47
- artifact = File.open(destination, 'w')
48
- artifact.write(fileData)
49
- artifact.close()
50
- File.expand_path(artifact.path)
51
- end
52
-
53
- def push_artifact(artifact, file, insecure, overrides)
54
- split_artifact = artifact.split(":")
55
- if(split_artifact.size < 4)
56
- raise ArtifactMalformedException
57
- end
58
- group_id, artifact_id, version, extension = split_artifact
59
- nexus['service/local/artifact/maven/content'].post({:hasPom => false, :g => group_id, :a => artifact_id, :v => version, :e => extension, :p => extension, :r => configuration['repository'],
60
- :file => File.new(file)}) do |response, request, result, &block|
61
- case response.code
62
- when 400
63
- raise BadUploadRequestException
64
- when 401
65
- raise PermissionsException
66
- when 403
67
- raise PermissionsException
68
- when 404
69
- raise CouldNotConnectToNexusException
70
- end
71
- end
72
- end
73
-
74
- def delete_artifact(artifact)
75
- split_artifact = artifact.split(":")
76
- if(split_artifact.size < 4)
77
- raise ArtifactMalformedException
78
- end
79
- group_id = split_artifact[0].gsub(".", "/")
80
- artifact_id = split_artifact[1].gsub(".", "/")
81
- version = split_artifact[2]
82
-
83
- delete_string = "content/repositories/releases/#{group_id}/#{artifact_id}/#{version}"
84
- Kernel.quietly {`curl --request DELETE #{File.join(configuration['url'], delete_string)} -u #{configuration['username']}:#{configuration['password']}`}
85
- end
86
-
87
- def get_artifact_info(artifact, overrides)
88
- split_artifact = artifact.split(":")
89
- if(split_artifact.size < 4)
90
- raise ArtifactMalformedException
91
- end
92
- begin
93
- nexus['service/local/artifact/maven/resolve'].get({:params => {:r => configuration['repository'], :g => split_artifact[0], :a => split_artifact[1], :v => split_artifact[2], :e => split_artifact[3]}})
94
- rescue RestClient::ResourceNotFound => e
95
- raise ArtifactNotFoundException
96
- end
97
- end
98
-
99
- def get_artifact_custom_info(artifact, overrides)
100
- raise NotNexusProException unless running_nexus_pro?
101
- split_artifact = artifact.split(":")
102
- if(split_artifact.size < 4)
103
- raise ArtifactMalformedException
104
- end
105
- group_id, artifact_id, version, extension = split_artifact
106
- file_name = "#{artifact_id}-#{version}.#{extension}"
107
- get_string = "content/repositories/#{configuration['repository']}/.meta/#{group_id.gsub(".", "/")}/#{artifact_id.gsub(".", "/")}/#{version}/#{file_name}.n3"
108
- begin
109
- n3_data = nexus[get_string].get
110
- parse_n3(n3_data)
111
- rescue RestClient::ResourceNotFound => e
112
- raise ArtifactNotFoundException
113
- end
114
- end
115
-
116
- private
117
- def running_nexus_pro?
118
- return status['edition_long'] == "Professional" ? true : false
119
- end
120
-
121
- def parse_n3(data)
122
- result = ""
123
- data.each_line { |item|
124
- tag = item.match(/#(\w*)>/) ? "#{$1}" : ""
125
- value = item.match(/"([^"]*)"/) ? "#{$1}" : ""
126
- result += " <#{tag}>#{value}</#{tag}>\n" unless tag.empty? && value.empty?
127
- }
128
- return "<artifact-resolution>\n <data>\n" + result + " </data>\n</artifact-resolution>"
129
- end
130
- end
131
- end
132
- end