nexus_cli 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/VERSION +1 -1
- data/lib/nexus_cli/errors.rb +12 -5
- data/lib/nexus_cli/remote.rb +56 -42
- data/lib/nexus_cli/tasks.rb +71 -14
- data/spec/remote_spec.rb +5 -0
- metadata +4 -4
data/.gitignore
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/nexus_cli/errors.rb
CHANGED
@@ -25,16 +25,16 @@ module NexusCli
|
|
25
25
|
def initialize(key)
|
26
26
|
@missing_setting = key
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def message
|
30
|
-
"The .nexus_cli file
|
30
|
+
"The .nexus_cli file or your overrides are missing the value: #{@missing_setting}"
|
31
31
|
end
|
32
32
|
status_code(102)
|
33
33
|
end
|
34
34
|
|
35
35
|
class MissingSettingsFileException < NexusCliError
|
36
36
|
def message
|
37
|
-
"The .nexus_cli file is missing or corrupt."
|
37
|
+
"The .nexus_cli file is missing or corrupt. You can either fix the .nexus_cli file or pass the --overrides hash."
|
38
38
|
end
|
39
39
|
status_code(103)
|
40
40
|
end
|
@@ -48,7 +48,7 @@ module NexusCli
|
|
48
48
|
|
49
49
|
class CouldNotConnectToNexusException < NexusCliError
|
50
50
|
def message
|
51
|
-
"Could not connect to Nexus. Please ensure the url
|
51
|
+
"Could not connect to Nexus. Please ensure the url you are using is reachable."
|
52
52
|
end
|
53
53
|
status_code(105)
|
54
54
|
end
|
@@ -65,8 +65,15 @@ module NexusCli
|
|
65
65
|
%{Your request was denied by the Nexus server due to a bad request and your artifact has not been uploaded.
|
66
66
|
This could mean several things:
|
67
67
|
Your .nexus_cli['repository'] is invalid.
|
68
|
-
The artifact with this identifier
|
68
|
+
The artifact with this identifier already exists inside the repository and that repository does not allow multiple deployments.}
|
69
69
|
end
|
70
70
|
status_code(107)
|
71
71
|
end
|
72
|
+
|
73
|
+
class NotNexusProException < NexusCliError
|
74
|
+
def message
|
75
|
+
"You cannot use this feature unless you are using Nexus Professional."
|
76
|
+
end
|
77
|
+
status_code(108)
|
78
|
+
end
|
72
79
|
end
|
data/lib/nexus_cli/remote.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'restclient'
|
2
|
+
require 'rexml/document'
|
2
3
|
require 'yaml'
|
3
4
|
require 'open3'
|
4
5
|
|
@@ -7,38 +8,42 @@ module NexusCli
|
|
7
8
|
class << self
|
8
9
|
|
9
10
|
def configuration=(config = {})
|
10
|
-
validate_config(config)
|
11
11
|
@configuration = config
|
12
12
|
end
|
13
13
|
|
14
14
|
def configuration
|
15
15
|
return @configuration if @configuration
|
16
|
-
begin
|
17
|
-
config = YAML::load_file(File.expand_path("~/.nexus_cli"))
|
18
|
-
rescue Errno::ENOENT
|
19
|
-
raise MissingSettingsFileException
|
20
|
-
end
|
21
|
-
validate_config(config)
|
22
|
-
@configuration = config
|
23
16
|
end
|
24
17
|
|
25
18
|
def nexus
|
26
19
|
@nexus ||= RestClient::Resource.new configuration["url"], :user => configuration["username"], :password => configuration["password"]
|
27
20
|
end
|
28
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
|
+
|
29
34
|
def pull_artifact(artifact, destination, overrides)
|
30
|
-
parse_overrides(overrides)
|
31
35
|
split_artifact = artifact.split(":")
|
32
36
|
if(split_artifact.size < 4)
|
33
37
|
raise ArtifactMalformedException
|
34
38
|
end
|
39
|
+
group_id, artifact_id, version, extension = split_artifact
|
35
40
|
begin
|
36
|
-
fileData = nexus['service/local/artifact/maven/redirect'].get ({params: {r: configuration['repository'], g:
|
41
|
+
fileData = nexus['service/local/artifact/maven/redirect'].get ({params: {r: configuration['repository'], g: group_id, a: artifact_id, v: version, e: extension}})
|
37
42
|
rescue RestClient::ResourceNotFound
|
38
43
|
raise ArtifactNotFoundException
|
39
44
|
end
|
40
45
|
artifact = nil
|
41
|
-
destination = File.join(File.expand_path(destination || "."), "#{
|
46
|
+
destination = File.join(File.expand_path(destination || "."), "#{artifact_id}-#{version}.#{extension}")
|
42
47
|
artifact = File.open(destination, 'w')
|
43
48
|
artifact.write(fileData)
|
44
49
|
artifact.close()
|
@@ -46,29 +51,21 @@ module NexusCli
|
|
46
51
|
end
|
47
52
|
|
48
53
|
def push_artifact(artifact, file, insecure, overrides)
|
49
|
-
#Build up the pieces that will make up the PUT request
|
50
|
-
parse_overrides(overrides)
|
51
54
|
split_artifact = artifact.split(":")
|
52
55
|
if(split_artifact.size < 4)
|
53
56
|
raise ArtifactMalformedException
|
54
57
|
end
|
55
|
-
artifact_id = split_artifact
|
56
|
-
group_id
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
Open3.popen3("curl -I #{insecure ? "-k" : ""} -T #{file} #{File.join(configuration['url'], put_string)} -u #{configuration['username']}:#{configuration['password']}") do |stdin, stdout, stderr, wait_thr|
|
61
|
-
exit_code = wait_thr.value.exitstatus
|
62
|
-
standard_out = stdout.read
|
63
|
-
if (standard_out.match('403 Forbidden') || standard_out.match('401 Unauthorized'))
|
64
|
-
raise PermissionsException
|
65
|
-
elsif standard_out.match('400 Bad Request')
|
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
|
66
63
|
raise BadUploadRequestException
|
67
|
-
|
68
|
-
|
69
|
-
when
|
70
|
-
raise
|
71
|
-
when
|
64
|
+
when 401
|
65
|
+
raise PermissionsException
|
66
|
+
when 403
|
67
|
+
raise PermissionsException
|
68
|
+
when 404
|
72
69
|
raise CouldNotConnectToNexusException
|
73
70
|
end
|
74
71
|
end
|
@@ -79,16 +76,15 @@ module NexusCli
|
|
79
76
|
if(split_artifact.size < 4)
|
80
77
|
raise ArtifactMalformedException
|
81
78
|
end
|
82
|
-
|
83
|
-
|
79
|
+
group_id = split_artifact[0].gsub(".", "/")
|
80
|
+
artifact_id = split_artifact[1].gsub(".", "/")
|
84
81
|
version = split_artifact[2]
|
85
82
|
|
86
|
-
delete_string = "content/repositories/releases/#{
|
83
|
+
delete_string = "content/repositories/releases/#{group_id}/#{artifact_id}/#{version}"
|
87
84
|
Kernel.quietly {`curl --request DELETE #{File.join(configuration['url'], delete_string)} -u #{configuration['username']}:#{configuration['password']}`}
|
88
85
|
end
|
89
86
|
|
90
87
|
def get_artifact_info(artifact, overrides)
|
91
|
-
parse_overrides(overrides)
|
92
88
|
split_artifact = artifact.split(":")
|
93
89
|
if(split_artifact.size < 4)
|
94
90
|
raise ArtifactMalformedException
|
@@ -99,19 +95,37 @@ module NexusCli
|
|
99
95
|
raise ArtifactNotFoundException
|
100
96
|
end
|
101
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
|
102
115
|
|
103
116
|
private
|
104
|
-
|
105
|
-
|
106
|
-
["url", "repository", "username","password"].each do |key|
|
107
|
-
raise InvalidSettingsException.new(key) unless configuration.has_key?(key)
|
108
|
-
end
|
117
|
+
def running_nexus_pro?
|
118
|
+
return status['edition_long'] == "Professional" ? true : false
|
109
119
|
end
|
110
120
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
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>"
|
115
129
|
end
|
116
130
|
end
|
117
131
|
end
|
data/lib/nexus_cli/tasks.rb
CHANGED
@@ -6,14 +6,32 @@ module NexusCli
|
|
6
6
|
base.send :include, ::Thor::Actions
|
7
7
|
base.class_eval do
|
8
8
|
|
9
|
+
map 'pull' => :pull_artifact
|
10
|
+
map 'push' => :push_artifact
|
11
|
+
map 'info' => :get_artifact_info
|
12
|
+
map 'custom' => :get_artifact_custom_info
|
13
|
+
map 'config' => :get_nexus_configuration
|
14
|
+
map 'status' => :get_nexus_status
|
15
|
+
|
16
|
+
class_option :overrides,
|
17
|
+
:type => :hash,
|
18
|
+
:default => {},
|
19
|
+
:desc => "A hashed list of overrides. Available options are 'url', 'repository', 'username', and 'password'."
|
20
|
+
|
21
|
+
def initialize(*args)
|
22
|
+
super
|
23
|
+
begin
|
24
|
+
set_remote_configuration(options[:overrides])
|
25
|
+
rescue NexusCliError => e
|
26
|
+
say e.message, :red
|
27
|
+
exit e.status_code
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
9
31
|
method_option :destination,
|
10
32
|
:type => :string,
|
11
33
|
:default => nil,
|
12
34
|
:desc => "A different folder other than the current working directory."
|
13
|
-
method_option :overrides,
|
14
|
-
:type => :hash,
|
15
|
-
:default => {},
|
16
|
-
:desc => "A hashed list of overrides. Available options are 'url', 'repository', 'username', and 'password'."
|
17
35
|
desc "pull_artifact artifact", "Pulls an artifact from Nexus and places it on your machine."
|
18
36
|
def pull_artifact(artifact)
|
19
37
|
begin
|
@@ -29,10 +47,6 @@ module NexusCli
|
|
29
47
|
:type => :boolean,
|
30
48
|
:default => false,
|
31
49
|
:desc => "Overrides any failures because of an 'insecure' SSL conncetion."
|
32
|
-
method_option :overrides,
|
33
|
-
:type => :hash,
|
34
|
-
:default => {},
|
35
|
-
:desc => "A hashed list of overrides. Available options are 'url', 'repository', 'username', and 'password'."
|
36
50
|
desc "push_artifact artifact file", "Pushes an artifact from your machine onto the Nexus."
|
37
51
|
def push_artifact(artifact, file)
|
38
52
|
begin
|
@@ -44,11 +58,7 @@ module NexusCli
|
|
44
58
|
end
|
45
59
|
end
|
46
60
|
|
47
|
-
|
48
|
-
:type => :hash,
|
49
|
-
:default => {},
|
50
|
-
:desc => "A hashed list of overrides. Available options are 'url', 'repository', 'username', and 'password'."
|
51
|
-
desc "get_artifact_info artifact", "Gets and returns the XML information about a particular artifact."
|
61
|
+
desc "get_artifact_info artifact", "Gets and returns the metadata in XML format about a particular artifact."
|
52
62
|
def get_artifact_info(artifact)
|
53
63
|
begin
|
54
64
|
say Remote.get_artifact_info(artifact, options[:overrides]), :green
|
@@ -58,11 +68,21 @@ module NexusCli
|
|
58
68
|
end
|
59
69
|
end
|
60
70
|
|
71
|
+
desc "get_artifact_custom_info artifact", "Gets and returns the custom metadata in XML format about a particular artifact."
|
72
|
+
def get_artifact_custom_info(artifact)
|
73
|
+
begin
|
74
|
+
say Remote.get_artifact_custom_info(artifact, options[:overrides]), :green
|
75
|
+
rescue NexusCliError => e
|
76
|
+
say e.message, :red
|
77
|
+
exit e.status_code
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
61
81
|
desc "get_nexus_configuration", "Prints out configuration from the .nexus_cli file that helps inform where artifacts will be uploaded."
|
62
82
|
def get_nexus_configuration
|
63
83
|
begin
|
64
84
|
config = Remote.configuration
|
65
|
-
say "*********Reading
|
85
|
+
say "********* Reading CLI configuration from #{File.expand_path('~/.nexus_cli')} *********", :blue
|
66
86
|
say "Nexus URL: #{config['url']}", :blue
|
67
87
|
say "Nexus Repository: #{config['repository']}", :blue
|
68
88
|
rescue NexusCliError => e
|
@@ -70,6 +90,43 @@ module NexusCli
|
|
70
90
|
exit e.status_code
|
71
91
|
end
|
72
92
|
end
|
93
|
+
|
94
|
+
desc "get_nexus_status", "Prints out information about the Nexus instance."
|
95
|
+
def get_nexus_status
|
96
|
+
begin
|
97
|
+
data = Remote.status
|
98
|
+
say "********* Getting Nexus status from #{data['base_url']} *********", :blue
|
99
|
+
say "Application Name: #{data['app_name']}", :blue
|
100
|
+
say "Version: #{data['version']}", :blue
|
101
|
+
say "Edition: #{data['edition_long']}", :blue
|
102
|
+
say "State: #{data['state']}", :blue
|
103
|
+
say "Started At: #{data['started_at']}", :blue
|
104
|
+
say "Base URL: #{data['base_url']}", :blue
|
105
|
+
rescue NexusCliError => e
|
106
|
+
say e.message, :red
|
107
|
+
exit e.status_code
|
108
|
+
end
|
109
|
+
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
|
73
130
|
end
|
74
131
|
end
|
75
132
|
end
|
data/spec/remote_spec.rb
CHANGED
@@ -35,4 +35,9 @@ describe NexusCli do
|
|
35
35
|
RestClient::Resource.any_instance.stub(:get).and_raise(RestClient::ResourceNotFound)
|
36
36
|
expect {NexusCli::Remote.get_artifact_info "com.something:something:1.0.0:tgz"}.to raise_error(NexusCli::ArtifactNotFoundException)
|
37
37
|
end
|
38
|
+
|
39
|
+
it "gives you errors when you attempt to get an artifact's custom info and it cannot be found" do
|
40
|
+
RestClient::Resource.any_instance.stub(:get).and_raise(RestClient::ResourceNotFound)
|
41
|
+
expect {NexusCli::Remote.get_artifact_custom_info "com.something:something:1.0.0:tgz"}.to raise_error(NexusCli::ArtifactNotFoundException)
|
42
|
+
end
|
38
43
|
end
|
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.
|
4
|
+
version: 0.2.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-
|
12
|
+
date: 2012-07-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
@@ -149,7 +149,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
149
149
|
version: '0'
|
150
150
|
segments:
|
151
151
|
- 0
|
152
|
-
hash:
|
152
|
+
hash: 3449401773214889774
|
153
153
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
154
|
none: false
|
155
155
|
requirements:
|
@@ -158,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
158
158
|
version: '0'
|
159
159
|
segments:
|
160
160
|
- 0
|
161
|
-
hash:
|
161
|
+
hash: 3449401773214889774
|
162
162
|
requirements: []
|
163
163
|
rubyforge_project:
|
164
164
|
rubygems_version: 1.8.21
|