nexus_cli 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ .rake_tasks~
3
+ tmp/
4
+ pkg/
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ Author:: Kyle Allan (<kallan@riotgames.com>)
2
+
3
+ Copyright 2011, 2012 Riot Games
4
+
5
+ Licensed under the Apache License, Version 2.0 (the "License");
6
+ you may not use this file except in compliance with the License.
7
+ You may obtain a copy of the License at
8
+
9
+ http://www.apache.org/licenses/LICENSE-2.0
10
+
11
+ Unless required by applicable law or agreed to in writing, software
12
+ distributed under the License is distributed on an "AS IS" BASIS,
13
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ See the License for the specific language governing permissions and
15
+ limitations under the License.
@@ -0,0 +1,57 @@
1
+ Description
2
+ ===========
3
+
4
+ A CLI wrapper around Sonatype Nexus REST calls.
5
+
6
+ Requirements
7
+ ============
8
+
9
+ * Ruby
10
+
11
+ Installation
12
+ ============
13
+
14
+ 1. Install the Gem
15
+ 2. Create a file in your user's home directory named `.nexus_cli`
16
+ 3. Give the file the following information:
17
+
18
+ ```
19
+ url: "http://whatever"
20
+ username: "username"
21
+ password: "password"
22
+ ```
23
+
24
+ Usage
25
+ =====
26
+
27
+ There are two calls that can be made. push\_artifact and pull\_artifact. Both calls will push or pull artifacts from Nexus using the Maven-flavored syntax: `groupId:artifactId:version:extension`
28
+
29
+ Pull Artifact Example
30
+ ---------------------
31
+ ```
32
+ nexus-cli pull_artifact com.mycompany.artifacts:myartifact:1.0.0:tgz
33
+ ```
34
+ Push Artifact Example
35
+ ---------------------
36
+ ```
37
+ nexus-cli push_artifact com.mycompany.artifacts:myartifact:1.0.0:tgz ~/path/to/file/to/push/myartifact.tgz
38
+ ```
39
+
40
+ License and Author
41
+ ==================
42
+
43
+ Author:: Kyle Allan (<kallan@riotgames.com>)
44
+
45
+ Copyright:: 2012 Riot Games Inc.
46
+
47
+ Licensed under the Apache License, Version 2.0 (the "License");
48
+ you may not use this file except in compliance with the License.
49
+ You may obtain a copy of the License at
50
+
51
+ http://www.apache.org/licenses/LICENSE-2.0
52
+
53
+ Unless required by applicable law or agreed to in writing, software
54
+ distributed under the License is distributed on an "AS IS" BASIS,
55
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
56
+ See the License for the specific language governing permissions and
57
+ limitations under the License.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.3
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $:.push File.expand_path("../../lib", __FILE__)
3
+ require 'nexus_cli'
4
+
5
+ NexusCli::Cli.start
@@ -0,0 +1,17 @@
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
@@ -0,0 +1,8 @@
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
@@ -0,0 +1,32 @@
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
8
+
9
+ When /^I want the artifact "([^"]*)" in a temp directory$/ do |arg1|
10
+ NexusCli::Remote.pull_artifact arg1, ENV["TMPDIR"]
11
+ end
12
+
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
16
+ end
17
+
18
+ Then /^I should expect an error because I need more colon separated values$/ do
19
+ assert_exit_status(100)
20
+ end
21
+
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
28
+ end
29
+
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"
32
+ end
@@ -0,0 +1,15 @@
1
+ require 'aruba/cucumber'
2
+
3
+ $:.push "#{File.dirname(__FILE__)}/../../lib/"
4
+ require 'nexus_cli'
5
+ require 'rspec'
6
+
7
+ After do |scenario|
8
+ FileUtils.rm_f("mytar-1.0.3.tgz")
9
+
10
+ tmp_path = File.join(ENV["TMPDIR"], "mytar-1.0.3.tgz")
11
+ FileUtils.rm_f(tmp_path)
12
+
13
+ NexusCli::Remote.delete_artifact('com.foo.bar:myFile:1.0.0:tgz')
14
+ FileUtils.rm_f("myFile.tgz")
15
+ end
@@ -0,0 +1,12 @@
1
+ require "nexus_cli/remote"
2
+ require "nexus_cli/cli"
3
+ require "nexus_cli/errors"
4
+ require "nexus_cli/kernel"
5
+
6
+ module NexusCli
7
+ class << self
8
+ def root
9
+ @root ||= Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,39 @@
1
+ require 'thor'
2
+
3
+ module NexusCli
4
+ module Cli
5
+ def self.included(base)
6
+ base.send :include, ::Thor::Actions
7
+ base.class_eval do
8
+
9
+ desc "pull_artifact artifact", "Pulls an artifact from Nexus and places it on your machine."
10
+ method_option :destination, :default => nil # defaults to the current working directory
11
+ def pull_artifact(artifact)
12
+ begin
13
+ path_to_artifact = Remote.pull_artifact(artifact, options[:destination])
14
+ puts "Artifact has been retrived and can be found at path: #{path_to_artifact}"
15
+ rescue NexusCliError => e
16
+ puts e.message
17
+ exit e.status_code
18
+ end
19
+ end
20
+
21
+ desc "push_artifact artifact file", "Pushes an artifact from your machine onto the Nexus."
22
+ def push_artifact(artifact, file)
23
+ Remote.push_artifact(artifact, file)
24
+ puts "Artifact #{artifact} has been successfully pushed to Nexus."
25
+ end
26
+
27
+ desc "get_artifact_info artifact", "Gets and returns the XML information about a particular artifact."
28
+ def get_artifact_info(artifact)
29
+ begin
30
+ puts Remote.get_artifact_info(artifact)
31
+ rescue NexusCliError => e
32
+ puts e.message
33
+ exit e.status_code
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,41 @@
1
+ module NexusCli
2
+ class NexusCliError < StandardError
3
+ class << self
4
+ def status_code(code)
5
+ define_method(:status_code) { code }
6
+ end
7
+ end
8
+ end
9
+
10
+ class ArtifactMalformedException < NexusCliError
11
+ def message
12
+ "Please submit your request using 4 colon-separated values. `groupId:artifactId:version:extension`"
13
+ end
14
+ status_code(100)
15
+ end
16
+
17
+ class ArtifactNotFoundException < NexusCliError
18
+ def message
19
+ "The artifact you requested information for could not be found. Please ensure it exists inside the Nexus."
20
+ end
21
+ status_code(101)
22
+ end
23
+
24
+ class InvalidSettingsException < NexusCliError
25
+ def initialize(key)
26
+ @missing_setting = key
27
+ end
28
+
29
+ def message
30
+ "The .nexus_cli file is missing the value: #{@missing_setting}"
31
+ end
32
+ status_code(102)
33
+ end
34
+
35
+ class MissingSettingsFile < NexusCliError
36
+ def message
37
+ "The .nexus_cli file is missing or corrupt."
38
+ end
39
+ status_code(103)
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ # From ActiveSupport: https://github.com/rails/rails/blob/c2c8ef57d6f00d1c22743dc43746f95704d67a95/activesupport/lib/active_support/core_ext/kernel/reporting.rb#L39
2
+
3
+ require 'rbconfig'
4
+
5
+ module Kernel
6
+ # Silences any stream for the duration of the block.
7
+ #
8
+ # silence_stream(STDOUT) do
9
+ # puts 'This will never be seen'
10
+ # end
11
+ #
12
+ # puts 'But this will'
13
+ def silence_stream(stream)
14
+ old_stream = stream.dup
15
+ stream.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null')
16
+ stream.sync = true
17
+ yield
18
+ ensure
19
+ stream.reopen(old_stream)
20
+ end
21
+
22
+ # Silences both STDOUT and STDERR, even for subprocesses.
23
+ #
24
+ # quietly { system 'bundle install' }
25
+ #
26
+ def quietly
27
+ silence_stream(STDOUT) do
28
+ silence_stream(STDERR) do
29
+ yield
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,96 @@
1
+ require 'restclient'
2
+ require 'yaml'
3
+
4
+ module NexusCli
5
+ class Remote
6
+ class << self
7
+
8
+ def configuration=(config = {})
9
+ validate_config(config)
10
+ @configuration = config
11
+ end
12
+
13
+ def configuration
14
+ return @configuration if @configuration
15
+ begin
16
+ config = YAML::load_file(File.expand_path("~/.nexus_cli"))
17
+ rescue Errno::ENOENT
18
+ raise MissingSettingsFile
19
+ end
20
+ validate_config(config)
21
+ @configuration = config
22
+ end
23
+
24
+ def nexus
25
+ @nexus ||= RestClient::Resource.new configuration["url"], :user => configuration["username"], :password => configuration["password"]
26
+ end
27
+
28
+ def pull_artifact(artifact, destination)
29
+ split_artifact = artifact.split(":")
30
+ if(split_artifact.size < 4)
31
+ raise ArtifactMalformedException
32
+ end
33
+ begin
34
+ fileData = nexus['service/local/artifact/maven/redirect'].get ({params: {r: configuration['repository'], g: split_artifact[0], a: split_artifact[1], v: split_artifact[2], e: split_artifact[3]}})
35
+ rescue RestClient::ResourceNotFound
36
+ raise ArtifactNotFoundException
37
+ end
38
+ artifact = nil
39
+ destination = File.join(File.expand_path(destination || "."), "#{split_artifact[1]}-#{split_artifact[2]}.#{split_artifact[3]}")
40
+ artifact = File.open(destination, 'w')
41
+ artifact.write(fileData)
42
+ artifact.close()
43
+ File.expand_path(artifact.path)
44
+ end
45
+
46
+ def push_artifact(artifact, file)
47
+ #Build up the pieces that will make up the PUT request
48
+ split_artifact = artifact.split(":")
49
+ if(split_artifact.size < 4)
50
+ raise ArtifactMalformedException
51
+ end
52
+ artifact_id = split_artifact[0].gsub(".", "/")
53
+ group_id = split_artifact[1].gsub(".", "/")
54
+ version = split_artifact[2]
55
+ file_name = "#{split_artifact[1]}-#{version}.#{split_artifact[3]}"
56
+
57
+ put_string = "content/repositories/releases/#{artifact_id}/#{group_id}/#{version}/#{file_name}"
58
+ #nexus[put_string].put File.read(file), :accept => "*/*"
59
+ Kernel.quietly {`curl -T #{file} #{configuration['url']}#{put_string} -u #{configuration['username']}:#{configuration['password']}`}
60
+ end
61
+
62
+ def delete_artifact(artifact)
63
+ split_artifact = artifact.split(":")
64
+ if(split_artifact.size < 4)
65
+ raise ArtifactMalformedException
66
+ end
67
+ artifact_id = split_artifact[0].gsub(".", "/")
68
+ group_id = split_artifact[1].gsub(".", "/")
69
+ version = split_artifact[2]
70
+
71
+ delete_string = "content/repositories/releases/#{artifact_id}/#{group_id}/#{version}"
72
+ Kernel.quietly {`curl --request DELETE #{configuration['url']}#{delete_string} -u #{configuration['username']}:#{configuration['password']}`}
73
+ end
74
+
75
+ def get_artifact_info(artifact)
76
+ split_artifact = artifact.split(":")
77
+ if(split_artifact.size < 4)
78
+ raise ArtifactMalformedException
79
+ end
80
+ begin
81
+ 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]}})
82
+ rescue RestClient::ResourceNotFound => e
83
+ raise ArtifactNotFoundException
84
+ end
85
+ end
86
+
87
+ private
88
+
89
+ def validate_config(configuration)
90
+ ["url", "repository", "username","password"].each do |key|
91
+ raise InvalidSettingsException.new(key) unless configuration.has_key?(key)
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,6 @@
1
+ module NexusCli
2
+ # @return [String]
3
+ def self.version
4
+ @version ||= File.read(File.expand_path("../../../VERSION", __FILE__)).strip
5
+ end
6
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'nexus_cli/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "nexus_cli"
7
+ s.version = NexusCli.version
8
+ s.authors = ["Kyle Allan"]
9
+ s.email = ["kallan@riotgames.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{A command-line wrapper for making REST calls to Sonatype Nexus.}
12
+ s.description = s.summary
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ #s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'thor'
20
+ s.add_dependency 'rest-client'
21
+
22
+ s.add_development_dependency 'rspec'
23
+ s.add_development_dependency 'aruba'
24
+ s.add_development_dependency 'cucumber'
25
+ end
@@ -0,0 +1,38 @@
1
+ require 'nexus_cli'
2
+ require 'restclient'
3
+
4
+ describe NexusCli do
5
+ it "gives you errors when configuration is missing a password" do
6
+ expect {NexusCli::Remote.configuration = {url: "http://somewebsite.com", username: "admin"}}.to raise_error(NexusCli::InvalidSettingsException)
7
+ end
8
+
9
+ it "gives you errors when configuration is missing a username" do
10
+ expect {NexusCli::Remote.configuration = {url: "http://somewebsite.com", password: "admin"}}.to raise_error(NexusCli::InvalidSettingsException)
11
+ end
12
+
13
+ it "gives you errors when you attempt to pull an artifact don't give a valid artifact name" do
14
+ expect {NexusCli::Remote.pull_artifact "com.something:something:1.0.0", nil}.to raise_error(NexusCli::ArtifactMalformedException)
15
+ end
16
+
17
+ it "gives you errors when you attempt to push an artifact don't give a valid artifact name" do
18
+ expect {NexusCli::Remote.push_artifact "com.something:something:1.0.0", nil}.to raise_error(NexusCli::ArtifactMalformedException)
19
+ end
20
+
21
+ it "gives you errors when you attempt to get an artifact's info and don't give a valid artifact name" do
22
+ expect {NexusCli::Remote.get_artifact_info "com.something:something:1.0.0"}.to raise_error(NexusCli::ArtifactMalformedException)
23
+ end
24
+
25
+ it "gives you errors when you attempt to delete an artifact and don't give a valid artifact name" do
26
+ expect {NexusCli::Remote.get_artifact_info "com.something:something:1.0.0"}.to raise_error(NexusCli::ArtifactMalformedException)
27
+ end
28
+
29
+ it "gives you errors when you attempt to pull an artifact and it cannot be found" do
30
+ RestClient::Resource.any_instance.stub(:get).and_raise(RestClient::ResourceNotFound)
31
+ expect {NexusCli::Remote.pull_artifact "com.something:something:1.0.0:tgz", nil}.to raise_error(NexusCli::ArtifactNotFoundException)
32
+ end
33
+
34
+ it "gives you errors when you attempt to get an artifact's info and it cannot be found" do
35
+ RestClient::Resource.any_instance.stub(:get).and_raise(RestClient::ResourceNotFound)
36
+ expect {NexusCli::Remote.get_artifact_info "com.something:something:1.0.0:tgz"}.to raise_error(NexusCli::ArtifactNotFoundException)
37
+ end
38
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nexus_cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kyle Allan
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: thor
16
+ requirement: &70121685045360 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70121685045360
25
+ - !ruby/object:Gem::Dependency
26
+ name: rest-client
27
+ requirement: &70121685044720 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70121685044720
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &70121685060120 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70121685060120
47
+ - !ruby/object:Gem::Dependency
48
+ name: aruba
49
+ requirement: &70121685058960 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70121685058960
58
+ - !ruby/object:Gem::Dependency
59
+ name: cucumber
60
+ requirement: &70121685058340 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70121685058340
69
+ description: A command-line wrapper for making REST calls to Sonatype Nexus.
70
+ email:
71
+ - kallan@riotgames.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - LICENSE
78
+ - README.md
79
+ - Rakefile
80
+ - VERSION
81
+ - bin/nexus-cli
82
+ - features/cli/pull_artifact.feature
83
+ - features/cli/push_artifact.feature
84
+ - features/step_definitions/cli_steps.rb
85
+ - features/support/env.rb
86
+ - lib/nexus_cli.rb
87
+ - lib/nexus_cli/cli.rb
88
+ - lib/nexus_cli/errors.rb
89
+ - lib/nexus_cli/kernel.rb
90
+ - lib/nexus_cli/remote.rb
91
+ - lib/nexus_cli/version.rb
92
+ - nexus_cli.gemspec
93
+ - spec/remote_spec.rb
94
+ homepage: ''
95
+ licenses: []
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ segments:
107
+ - 0
108
+ hash: -1715274154422444014
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ segments:
116
+ - 0
117
+ hash: -1715274154422444014
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.11
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: A command-line wrapper for making REST calls to Sonatype Nexus.
124
+ test_files:
125
+ - features/cli/pull_artifact.feature
126
+ - features/cli/push_artifact.feature
127
+ - features/step_definitions/cli_steps.rb
128
+ - features/support/env.rb
129
+ - spec/remote_spec.rb