diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..d799d22 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,6 @@ +Metrics/LineLength: + Max: 200 + AllowURI: true + +Metrics/AbcSize: + Max: 20 diff --git a/README.md b/README.md index 24f7952..a6905e5 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,80 @@ artifactory_rest_gavc_download '/tmp/downloads/commons-io-2.4-sources.jar' do classifier 'sources' end ``` +### artifactory_rest_artifact +Custom Resource for finding an artifact by name or checksum +#### Properties +| Name | Type | Description | Default | Required +| ---- | ---- | ----------- | ------- | -------- +| endpoint | String | artifactory server url | resource name | no +| username | String | artifactory credentials - username | n/a | no +| password | String | artifactory credentials - password | n/a | no +| search_type | String | Search type to find artifact. Valid values are 'name' or any value contained in property checksums | 'name' | yes +| search | String | search term to find artifact. Either the name or checksum, as specified by search_type | n/a | yes +| destination | String | Directory for artifact to be downloaded to | Chef::Config['file_cache_path'] | no +| property_hash | Hash{String => String} | Hash of properties to add or replace if they already exist | n/a | no +| download_path | Identity | Location artifact is downloaded to | destination/artifact.basename | n/a +| checksums | Array[String] |valid values for search_type (other than 'name') | ['md5', 'sha1'] | no + +#### Actions +| Name | Description | Default +| ---- | ----------- | ------- +| :download | Downloads artifact found | yes +| :add_properties | Merges property_hash with the artifact found | no + +#### Usage + +``` ruby +artifact_location = artifactory_rest_artifact 'http://artifactory.mycompany.com' do + username 'my_user' + password 'my_password' + search_type 'sha256' + search '3915ed48d8764758bacb5aa9f15cd276' + destination '/my_artifacts/this_artifact_type' + checksums %w(sha256 sha1 md5) +end + +puts "artifact exists at #{artifact_location.download_path}" +``` + +```ruby +artifactory_rest_artifact 'http://artifactory.mycompany.com' do + username 'my_user' + password 'my_password' + search_type 'sha256' + search '3915ed48d8764758bacb5aa9f15cd276' + property_hash {'chef.cookbook.download_date' => Time.now.utc, 'it.hasbeen.downloaded' => 'true'} + checksums %w(sha256 sha1 md5) + action :update_properties +end +``` +### artifactory_rest_gem + +#### Properties +| Name | Type | Description | Default | Required +| ---- | ---- | ----------- | ------- | -------- +| version | String | Version of the gem or 'latest' | resource name | no +| source | String | Source of the gem | n/a | no + +#### Actions +| Name | Description | Default +| ---- | ----------- | ------- +| :install | Installs the artifactory gem and makes it ready for use immediately at compile time | yes +| :remove | Uninstalls the artifactory gem | no + +Usage + +```ruby +artifactory_rest_gem 'latest' do + source '/my/local/gem/dl' +end +``` +```ruby +artifactory_rest_gem '2.3.0'do + :remove +end +``` ## License and Authors License: See the LICENSE file in this repository. diff --git a/metadata.rb b/metadata.rb index 2e8e5f8..320108b 100644 --- a/metadata.rb +++ b/metadata.rb @@ -4,7 +4,7 @@ license 'MIT' description 'Provides resources for interacting with the artifactory rest API' long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) -version '0.4.0' +version '0.5.0' supports 'windows', '>= 7.0' supports 'centos', '>= 5.0' diff --git a/resources/artifact.rb b/resources/artifact.rb new file mode 100644 index 0000000..949096e --- /dev/null +++ b/resources/artifact.rb @@ -0,0 +1,105 @@ +property :endpoint, String, name_property: true +property :username, String +property :password, String +property :search_type, String, required: true +property :search, String, default: 'name' +property :destination, String, default: Chef::Config['file_cache_path'] +property :property_hash, Hash, required: false +property :download_path, identity: true, desired_state: false +property :checksums, Array, default: %w(md5 sha1) +default_action :download + +def init + require 'artifactory' + require 'net/http' + Chef::Resource.send(:include, Artifactory::Resource) +end + +def set_artifactory + Resource::Artifactory.configure do |config| + config.endpoint = new_resource.endpoint + config.username = new_resource.username + config.password = new_resource.password + end +end + +def artifactory_checksum_search + artifact = Resource::Artifact.checksum_search(search_type.to_sym => search).first + artifact +end + +def artifactory_search + artifact = Resource::Artifact.seach(name: search).first + artifact +end + +def _properties(artifact) + begin + property_list = artifact.properties + rescue Artifactory::Error::HTTPError + property_list = {} + end + property_list.merge!(property_hash) + property_list +end + +def artifact_uri + uri = nil + uri = artifactory_checksum_search.download_uri if checksums.include?(search_type) + uri = artifactory_search.download_uri if search_type == 'name' + log "Artifact search at #{endpoint} for #{search_type}: #{search} returned no results" do + level :error + only_if uri.nil?.to_s + end + uri +end + +def find_artifact + artifact = nil + artifact = artifactory_checksum_search if checksums.include?(search_type) + artifact = artifactory_search if search_type == 'name' + artifact +end + +def form_request(property_list, artifact) + uri = URI.parse(artifact.uri) + uri.query = URI.encode_www_form(property_list) + uri.query.prepend('properties=') + http = Net::HTTP.new(uri.host, uri.port) + puts uri.request_uri + req = Net::HTTP::Put.new(uri.request_uri.tr('&', '|')) + req['Content-Type'] = 'text/plain' + req.basic_auth username, password + response = http.request(req) + response +end + +def update_properties(artifact) + property_list = _properties(artifact) + property_list +end + +action :add_properties do + init + set_artifactory + artifact = find_artifact + property_list = update_properties(artifact) + response = form_request(property_list, artifact) + log 'Unable to update access timestamp in artifactory' do + message "\n#{response.body}" + level :warn + end unless response.body.nil? +end + +action :download do + init + set_artifactory + uri = artifact_uri + download_path = ::File.join(destination, ::File.basename(uri)) + directory ::File.dirname(download_path) do + recursive true + end + remote_file download_path do + source uri + end +end diff --git a/resources/gem.rb b/resources/gem.rb new file mode 100644 index 0000000..8385305 --- /dev/null +++ b/resources/gem.rb @@ -0,0 +1,17 @@ +property :version, String, name_property: true +property :source, String, required: false +default_action :install + +action :install do + chef_gem 'artifactory' do + compile_time true + version new_resource.version unless version == 'latest' + source new_resource.source unless source.nil? + end +end + +action :remove do + chef_gem 'artifactory' do + action :remove + end +end