nexus_cli 0.2.1 → 0.3.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/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