artifactory-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 60b1ba3ee0e3e8e73c67bf3183837ba477edc2c0
4
+ data.tar.gz: 8eb5c22de96241ddd66fdafaf58bdcabd97c8da8
5
+ SHA512:
6
+ metadata.gz: f61eef69170467bd2a829de851d9371da8a76f1b30d76b1a8a261f63f03b7290bec8ed1bfcdb4602caedcf8fa61a5fe2afc701b69afa389a82483a06d7300b3f
7
+ data.tar.gz: c60c0ba0e330be0105acac73f26a0440bfc5c322ee5313eb9d103ce3faf94e61e4c915c7f4932cef9df08d988dfabd2e9b543e8e791a838662fbe8fa0e24dcc2
data/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ Copyright 2017 Matteo Cerutti
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+
8
+ Unless required by applicable law or agreed to in writing, software
9
+ distributed under the License is distributed on an "AS IS" BASIS,
10
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ See the License for the specific language governing permissions and
12
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # Ruby client library for JFrog Artifactory REST API
2
+ This is a simple Ruby client library that allows to interact with the JFrog Artifactory REST API.
3
+
4
+ Pull requests to add additional API features are very welcome. I only implemented what I needed.
5
+
6
+ ## Install
7
+ To install it simply issue the following command:
8
+
9
+ ```
10
+ gem install artifactory-ruby
11
+ ```
12
+
13
+ ## Contact
14
+ Matteo Cerutti - matteo.cerutti@hotmail.co.uk
@@ -0,0 +1,226 @@
1
+ #
2
+ # client.rb
3
+ #
4
+
5
+ require 'net/http'
6
+ require 'uri'
7
+ require 'openssl'
8
+ require 'json'
9
+ require 'time'
10
+
11
+ module Artifactory
12
+ class Client
13
+ attr_reader :uri, :http, :basic_auth, :headers
14
+
15
+ # Initialize an Artifactory client instance
16
+ #
17
+ # @param endpoint [String] Artifactory REST API endpoint
18
+ # @param username [String] Username for HTTP basic authentication
19
+ # @param password [String] Password for HTTP basic authentication
20
+ # @param api_key [String] API key
21
+ # @param ssl_verify [Boolean] Enable/Disable SSL verification
22
+ #
23
+ def initialize(endpoint:, username: nil, password: nil, api_key: nil, ssl_verify: true)
24
+ basic_auth = {}
25
+ uri = URI.parse(endpoint)
26
+ http = Net::HTTP.new(uri.host, uri.port)
27
+
28
+ if (username and api_key) or (username.nil? and api_key.nil?)
29
+ raise RuntimeError, "Either HTTP basic or API key are allowed as authentication methods"
30
+ end
31
+
32
+ headers = {
33
+ 'Content-type' => 'application/json',
34
+ 'Accept' => 'application/json',
35
+ }
36
+
37
+ if username
38
+ basic_auth = {'username' => username, 'password' => password}
39
+ else
40
+ headers['X-JFrog-Art-Api'] = api_key
41
+ end
42
+
43
+ if uri.scheme == 'https'
44
+ http.use_ssl = true
45
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless ssl_verify
46
+ end
47
+
48
+ @uri = uri
49
+ @http = http
50
+ @basic_auth = basic_auth
51
+ @headers = headers
52
+ end
53
+
54
+ # Retrieves the current configuration of a repository. Supported by local, remote and virtual repositories.
55
+ #
56
+ # @param key [String] Repository key
57
+ # @return [Hash] Repository information
58
+ #
59
+ def get_repo(key:)
60
+ api_get("/repositories/#{key}").tap { |h| h.delete('key') }
61
+ end
62
+
63
+ # Returns a list of minimal repository details (unless recurse is enabled) for all repositories of the specified type.
64
+ #
65
+ # @param type [nil, local, remote, virtual] Optionally filter by repository type
66
+ # @param recurse [Boolean] Recursively retrieve repos configuration
67
+ # @return [Hash] List of repositories
68
+ #
69
+ def repos(type: nil, recurse: false)
70
+ ret = {}
71
+ params = []
72
+ params << "type=#{type}" if type
73
+
74
+ api_get(["/repositories", params.join('&')].join('?')).each do |repo|
75
+ ret[repo['key']] = recurse ? self.get_repo(key: repo['key']) : repo.tap { |h| h.delete('key') }
76
+ end
77
+
78
+ ret
79
+ end
80
+
81
+ # Lists all Docker repositories hosted in under an Artifactory Docker repository
82
+ #
83
+ # @param repo_key [String] Repository key
84
+ # @param recurse [Boolean] Recursively retrieve image tags
85
+ # @return [Hash, Array<String>] List of docker images
86
+ #
87
+ def docker_images(repo_key:, recurse: false)
88
+ ret = {}
89
+ repolist = api_get("/docker/#{repo_key}/v2/_catalog")['repositories']
90
+
91
+ if recurse
92
+ api_get("/docker/#{repo_key}/v2/_catalog")['repositories'].each do |name|
93
+ ret[name] = self.docker_tags(repo_key: repo_key, image_name: name)
94
+ end
95
+ else
96
+ ret = repolist
97
+ end
98
+
99
+ images
100
+ end
101
+
102
+ # Retrieve all tags for a docker image
103
+ #
104
+ # @param repo_key [String] Repository key
105
+ # @param image_name [String] Docker image name
106
+ # @return [Array<String>] List of tags
107
+ #
108
+ def docker_tags(repo_key:, image_name:)
109
+ api_get("/docker/#{repo_key}/v2/#{image_name}/tags/list")['tags']
110
+ end
111
+
112
+ # Retrieve a docker image tag manifest
113
+ #
114
+ # @param repo_key [String] Repository key
115
+ # @param image_name [String] Docker image name
116
+ # @param image_tag [String] Docker image tag
117
+ # @return [Hash] Docker manifest describing the tag
118
+ #
119
+ def docker_manifest(repo_key:, image_name:, image_tag:)
120
+ api_get("/docker/#{repo_key}/v2/#{image_name}/manifests/#{image_tag}")
121
+ end
122
+
123
+ # Get a flat (the default) or deep listing of the files and folders (not included by default) within a folder
124
+ #
125
+ # @param repo_key [String] Repository key
126
+ # @param image_name [String] Docker image name
127
+ # @param image_tag [String] Docker image tag
128
+ # @return [Hash] Docker manifest describing the tag
129
+ #
130
+ def file_list(repo_key:, folder_path: '/', deep: false, depth: 0, list_folders: false, md_timestamps: false, include_root_path: false)
131
+ path = ["/storage", repo_key, folder_path].join('/').chomp('/')
132
+ params = ['list']
133
+ params << "deep=#{deep ? 1 : 0}"
134
+ params << "depth=#{depth}" if depth > 0
135
+ params << "listFolders=#{list_folders ? 1 : 0}"
136
+ params << "mdTimestamps=#{md_timestamps ? 1 : 0}"
137
+ params << "includeRootPath=#{include_root_path ? 1 : 0}"
138
+
139
+ files = {}
140
+ api_get([path, params.join('&')].join('?'))['files'].each do |file|
141
+ name = file['uri']
142
+ files[name] = file.tap { |h| h.delete('uri') }
143
+ files[name]['lastModified'] = Time.parse(files[name]['lastModified'])
144
+ end
145
+
146
+ files
147
+ end
148
+
149
+ # Get file statistics like the number of times an item was downloaded, last download date and last downloader.
150
+ #
151
+ # @param repo_key [String] Repository key
152
+ # @param path [String] Path of the file to look up
153
+ # @return [Hash] File statistics
154
+ #
155
+ def file_stat(repo_key:, path:)
156
+ p = File.join("/storage", repo_key, path).chomp('/')
157
+ params = ['stats']
158
+
159
+ ret = {}
160
+ api_get([p, params.join('&')].join('?')).tap { |h| h.delete('uri') }.each do |k, v|
161
+ case k
162
+ when "lastDownloaded", "remoteLastDownloaded"
163
+ ret[k] = Time.at(v/1000) if v > 0
164
+
165
+ else
166
+ ret[k] = v
167
+ end
168
+ end
169
+
170
+ ret
171
+ end
172
+
173
+ # Deletes a file or a folder from the specified destination
174
+ #
175
+ # @param repo_key [String] Repository key
176
+ # @param path [String] Path of the file to delete
177
+ #
178
+ def file_delete(repo_key:, path:)
179
+ api_delete(File.join(repo_key, path))
180
+ end
181
+
182
+ private
183
+ # Dispatch a GET request to the Artifactory API interface
184
+ #
185
+ # @param query [String] HTTP request query
186
+ # @return Response from the server
187
+ #
188
+ def api_get(query)
189
+ begin
190
+ req = Net::HTTP::Get.new(File.join(self.uri.path, 'api', query), self.headers)
191
+ req.basic_auth(self.basic_auth['username'], self.basic_auth['password']) if self.basic_auth
192
+ resp = self.http.request(req)
193
+
194
+ if resp.is_a?(Net::HTTPOK)
195
+ begin
196
+ data = JSON.parse(resp.body)
197
+ rescue JSON::ParserError
198
+ raise Exception, "Failed to decode response message"
199
+ end
200
+ else
201
+ raise Exception, "Query returned a non successful HTTP code (Code: #{resp.code}, Error: #{resp.message})"
202
+ end
203
+ rescue
204
+ raise Exception, "Failed to execute GET request to Artifactory REST API (#{$!})"
205
+ end
206
+
207
+ data
208
+ end
209
+
210
+ # Dispatch a DELETE request to the Artifactory API interface
211
+ #
212
+ # @param query [String] HTTP request query
213
+ #
214
+ def api_delete(query)
215
+ begin
216
+ req = Net::HTTP::Delete.new(File.join(self.uri.path, 'api', query), self.headers)
217
+ req.basic_auth(self.basic_auth['username'], self.basic_auth['password']) if self.basic_auth
218
+ resp = self.http.request(req)
219
+
220
+ raise Exception, "Query returned a non successful HTTP code (Code: #{resp.code}, Error: #{resp.message})" unless resp.is_a?(Net::HTTPNoContent)
221
+ rescue
222
+ raise Exception, "Failed to execute DELETE request to Artifactory REST API (#{$!})"
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,11 @@
1
+ #
2
+ # version.rb
3
+ #
4
+
5
+ module Artifactory
6
+ VERSION = "0.0.1"
7
+
8
+ def self.version
9
+ VERSION
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: artifactory-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Matteo Cerutti
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.7.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.7.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: deep_merge
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.1.0
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: 2.0.0
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.1.0
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: 2.0.0
47
+ description: Ruby client library for Kapacitor JSON REST API
48
+ email: matteo.cerutti@hotmail.co.uk
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - LICENSE
54
+ - README.md
55
+ - lib/artifactory/client.rb
56
+ - lib/artifactory/version.rb
57
+ homepage: https://github.com/m4ce/artifactory-ruby
58
+ licenses:
59
+ - Apache 2.0
60
+ metadata: {}
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.6.8
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Ruby client library that allows to interact with JFrog Artifactory REST API
81
+ test_files: []