artifactory-ruby 0.0.1

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.
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: []