Artifactory-Client
view release on metacpan or search on metacpan
lib/Artifactory/Client.pm view on Meta::CPAN
use JSON::MaybeXS;
use LWP::UserAgent;
use Path::Tiny qw();
use MooseX::StrictConstructor;
use URI::Escape qw(uri_escape);
use File::Basename qw(basename);
use HTTP::Request::StreamingUpload;
use namespace::autoclean;
=head1 NAME
Artifactory::Client - Perl client for Artifactory REST API
=head1 VERSION
Version 1.8.0
=cut
our $VERSION = 'v1.8.0';
=head1 SYNOPSIS
This is a Perl client for Artifactory REST API:
https://www.jfrog.com/confluence/display/RTF/Artifactory+REST+API Every public method provided in this module returns a
HTTP::Response object.
use Artifactory::Client;
my $h = HTTP::Headers->new();
$h->authorization_basic( 'admin', 'password' );
my $ua = LWP::UserAgent->new( default_headers => $h );
my $args = {
artifactory => 'http://artifactory.server.com',
port => 8080,
repository => 'myrepository',
context_root => '/', # Context root for artifactory. Defaults to 'artifactory'.
ua => $ua # Dropping in custom UA with default_headers set. Default is a plain LWP::UserAgent.
};
my $client = Artifactory::Client->new( $args );
my $path = '/foo'; # path on artifactory
# Properties are a hashref of key-arrayref pairs. Note that value must be an arrayref even for a single element.
# This is to conform with Artifactory which treats property values as a list.
my $properties = {
one => ['two'],
baz => ['three'],
};
my $file = '/local/file.xml';
# Name of methods are taken straight from Artifactory REST API documentation. 'Deploy Artifact' would map to
# deploy_artifact method, like below. The caller gets HTTP::Response object back.
my $resp = $client->deploy_artifact( path => $path, properties => $properties, file => $file );
# Custom requests can also be made via usual get / post / put / delete requests.
my $resp = $client->get( 'http://artifactory.server.com/path/to/resource' );
# Repository override for calls that have a repository in the endpoint. The passed-in repository will not persist.
my $resp = $client->calculate_yum_repository_metadata( repository => 'different_repo', async => 1 );
=cut
=head1 Dev Env Setup / Running Tests
carton install
# to run unit tests
prove -r t
=cut
has 'artifactory' => (
is => 'ro',
isa => 'Str',
required => 1,
writer => '_set_artifactory',
);
has 'port' => (
is => 'ro',
isa => 'Int',
default => 80,
);
has 'context_root' => (
is => 'ro',
isa => 'Str',
default => 'artifactory',
);
has 'ua' => (
is => 'rw',
isa => 'LWP::UserAgent',
builder => '_build_ua',
lazy => 1,
);
has 'repository' => (
is => 'ro',
isa => 'Str',
default => '',
writer => '_set_repository',
);
has '_json' => (
is => 'ro',
builder => '_build_json',
lazy => 1,
);
has '_api_url' => (
is => 'ro',
isa => 'Str',
init_arg => undef,
writer => '_set_api_url',
);
has '_art_url' => (
lib/Artifactory/Client.pm view on Meta::CPAN
=cut
sub calculate_bower_index {
my ( $self, %args ) = @_;
my $repository = $args{repository} || $self->repository();
return $self->_handle_repository_reindex("/bower/$repository/reindex");
}
=head2 calculate_helm_chart_index
Calculates Helm chart index on the specified path (local repositories only).
=cut
sub calculate_helm_chart_index {
my ( $self, %args ) = @_;
my $repository = $args{repository} || $self->repository();
return $self->_handle_repository_reindex("/helm/$repository/reindex");
}
=head2 calculate_cran_repository_metadata
Calculates/recalculates the Packages and Release metadata for this repository, based on the CRAN packages in it.
=cut
sub calculate_cran_repository_metadata {
my ( $self, %args ) = @_;
my $repository = $args{repository} || $self->repository();
return $self->_handle_repository_reindex("/cran/reindex/$repository", %args);
}
=head2 calculate_conda_repository_metadata
Calculates/recalculates the Conda packages and release metadata for this repository.
=cut
sub calculate_conda_repository_metadata {
my ( $self, %args ) = @_;
my $repository = $args{repository} || $self->repository();
return $self->_handle_repository_reindex("/conda/reindex/$repository", %args);
}
=head1 SYSTEM & CONFIGURATION
=cut
=head2 system_info
Get general system information
=cut
sub system_info {
my $self = shift;
return $self->_handle_system();
}
=head2 verify_connection( endpoint => 'http://server/foobar', username => 'admin', password => 'password' )
Verifies a two-way connection between Artifactory and another product
=cut
sub verify_connection {
my ( $self, %args ) = @_;
my $url = $self->_api_url() . "/system/verifyconnection";
return $self->post(
$url,
'Content-Type' => 'application/json',
content => $self->_json->encode( \%args )
);
}
=head2 system_health_ping
Get a simple status response about the state of Artifactory
=cut
sub system_health_ping {
my $self = shift;
return $self->_handle_system('ping');
}
=head2 general_configuration
Get the general configuration (artifactory.config.xml)
=cut
sub general_configuration {
my $self = shift;
return $self->_handle_system('configuration');
}
=head2 save_general_configuration( $file )
Save the general configuration (artifactory.config.xml)
=cut
sub save_general_configuration {
my ( $self, $xml ) = @_;
my $file = Path::Tiny::path($xml)->slurp( { binmode => ":raw" } );
my $url = $self->_api_url() . "/system/configuration";
return $self->post(
$url,
'Content-Type' => 'application/xml',
content => $file
);
}
=head2 update_custom_url_base( $url )
Changes the Custom URL base
lib/Artifactory/Client.pm view on Meta::CPAN
=head2 import_repository_content( path => 'foobar', repo => 'repo', metadata => 1, verbose => 0 )
Import one or more repositories
=cut
sub import_repository_content {
my ( $self, %args ) = @_;
my $url = $self->_api_url() . "/import/repositories?";
$url .= $self->_stringify_hash( '&', %args );
return $self->post($url);
}
=head2 import_system_settings_example
Returned default Import Settings JSON
=cut
sub import_system_settings_example {
my $self = shift;
return $self->_handle_system_settings('import');
}
=head2 full_system_import( importPath => '/import/path', includeMetadata => 'false' etc )
Import full system from a server local Artifactory export directory
=cut
sub full_system_import {
my ( $self, %args ) = @_;
return $self->_handle_system_settings( 'import', %args );
}
=head2 export_system_settings_example
Returned default Export Settings JSON
=cut
sub export_system_settings_example {
my $self = shift;
return $self->_handle_system_settings('export');
}
=head2 export_system( exportPath => '/export/path', includeMetadata => 'true' etc )
Export full system to a server local directory
=cut
sub export_system {
my ( $self, %args ) = @_;
return $self->_handle_system_settings( 'export', %args );
}
=head2 ignore_xray_alert( $path )
Sets an alert to be ignored until next time the repository hosting the artifact about which the alert was issued, is scanned. Note that this endpoint does not
affect artifacts that are blocked because they have not been scanned at all.
=cut
sub ignore_xray_alert {
my ( $self, $path ) = @_;
my $url = $self->_api_url() . "/xray/setAlertIgnored?path=$path";
return $self->post($url);
}
=head2 allow_download_of_blocked_artifacts( 'true'|'false' )
When a repository is configured to block downloads of artifacts, you may override that configuration (and allow download of blocked artifacts). Note that this
setting cannot override the blocking of unscanned artifacts.
=cut
sub allow_download_of_blocked_artifacts {
my ( $self, $bool ) = @_;
my $url = $self->_api_url() . "/xray/allowBlockedArtifactsDownload?allow=$bool";
return $self->post($url);
}
=head2 allow_download_when_xray_is_unavailable( 'true'|'false' )
You may configure Artifactory to block downloads of artifacts when the connected Xray instance is unavailable. This endpoint lets you override that
configuration (and allow download of artifacts).
=cut
sub allow_download_when_xray_is_unavailable {
my ( $self, $bool ) = @_;
my $url = $self->_api_url() . "/xray/allowDownloadWhenUnavailable?allow=$bool";
return $self->post($url);
}
=head2 create_bundle( %hash of data structure )
Create a new support bundle
=cut
sub create_bundle {
my ( $self, %args ) = @_;
my $url = $self->_api_url() . '/support/bundles';
%args = () unless %args;
return $self->post(
$url,
"Content-Type" => 'application/json',
Content => $self->_json->encode( \%args )
);
}
=head2 list_bundles
Lists previously created bundle currently stored in the system
=cut
sub list_bundles {
my $self = shift;
my $url = $self->_api_url() . '/support/bundles';
return $self->get( $url, "Content-Type" => 'application/json', );
}
=head2 get_bundle_metadata( $name )
Downloads a previously created bundle currently stored in the system
=cut
sub get_bundle_metadata {
my ( $self, $bundle ) = @_;
my $url = $self->_api_url() . '/support/bundles/' . $bundle;
return $self->get( $url, "Content-Type" => 'application/json', );
}
=head2 get_bundle( $name )
Downloads a previously created bundle currently stored in the system
=cut
sub get_bundle {
my ( $self, $bundle ) = @_;
lib/Artifactory/Client.pm view on Meta::CPAN
$repo =~ s{\/$}{}xi;
my $url =
(%args)
? $self->_api_url() . "/repositories/$repo?"
: $self->_api_url() . "/repositories/$repo";
$url .= $self->_stringify_hash( '&', %args ) if (%args);
if ($payload) {
return $self->$method(
$url,
'Content-Type' => 'application/json',
content => $self->_json->encode($payload)
);
}
return $self->$method($url);
}
sub _handle_system {
my ( $self, $arg ) = @_;
my $url =
($arg)
? $self->_api_url() . "/system/$arg"
: $self->_api_url() . "/system";
return $self->get($url);
}
sub _handle_plugins {
my ( $self, $type ) = @_;
my $url =
($type)
? $self->_api_url() . "/plugins/$type"
: $self->_api_url() . "/plugins";
return $self->get($url);
}
sub _handle_system_settings {
my ( $self, $action, %args ) = @_;
my $url = $self->_api_url() . "/$action/system";
if (%args) {
return $self->post(
$url,
'Content-Type' => 'application/json',
content => $self->_json->encode( \%args )
);
}
return $self->get($url);
}
sub _handle_gpg_key {
my ( $self, $type, $method, %args ) = @_;
my $url = $self->_api_url() . "/gpg/key/$type";
return $self->$method( $url, %args );
}
sub _handle_repository_reindex {
my ( $self, $endpoint, %args ) = @_;
my $url =
(%args)
? $self->_api_url() . $endpoint . "?"
: $self->_api_url() . $endpoint;
$url .= $self->_stringify_hash( '&', %args ) if (%args);
return $self->post($url);
}
sub _handle_multi_push_replication {
my ( $self, $payload, $method ) = @_;
my $url = $self->_api_url() . '/replications/multiple';
return $self->$method(
$url,
"Content-Type" => 'application/json',
Content => $self->_json->encode($payload)
);
}
sub _merge_repo_and_path {
my ( $self, $_path ) = @_;
$_path = '' if not defined $_path;
$_path =~ s{^\/}{}xi;
return join( '/', grep { $_ } $self->repository(), $_path );
}
sub _gather_delete_builds_params {
my ( $self, $buildnumbers, $artifacts, $deleteall ) = @_;
my @params;
if ( ref($buildnumbers) eq 'ARRAY' ) {
my $str = "buildNumbers=";
$str .= join( ",", @{$buildnumbers} );
push @params, $str;
}
push @params, "artifacts=$artifacts" if ( defined $artifacts );
push @params, "deleteAll=$deleteall" if ( defined $deleteall );
return @params;
}
sub _handle_api_key {
my ( $self, $method, %args ) = @_;
my $url = $self->_api_url() . "/apiKey/auth";
return $self->$method(
$url,
'Content-Type' => 'application/json',
content => $self->_json->encode( \%args )
);
}
sub _handle_revoke_api_key {
my ( $self, $endpoint ) = @_;
my $resp = $self->get_api_key();
my $content = $self->_json->decode( $resp->content );
my %header;
$header{'X-Api-Key'} = $content->{apiKey};
my $url = $self->_api_url() . $endpoint;
return $self->delete( $url, %header );
}
sub _handle_block_system_replication {
my ( $self, $ep, %args ) = @_;
my %merged = (
push => 'true',
pull => 'true',
%args # overriding defaults
);
my $repo = $self->repository();
my $url = $self->_api_url() . "/system/replications/$ep?" . $self->_stringify_hash( '&', %merged );
return $self->post($url);
}
__PACKAGE__->meta->make_immutable;
=head1 AUTHOR
Satoshi Yagi, C<< <satoshi.yagi at yahoo.com> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-artifactory-client at
rt.cpan.org>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Artifactory-Client>. I will
be notified, and then you'll automatically be notified of progress on your bug
as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Artifactory::Client
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker (report bugs here)
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Artifactory-Client>
=item * AnnoCPAN: Annotated CPAN documentation
L<http://annocpan.org/dist/Artifactory-Client>
=item * CPAN Ratings
L<http://cpanratings.perl.org/d/Artifactory-Client>
=item * Search CPAN
L<http://search.cpan.org/dist/Artifactory-Client/>
=back
=head1 ACKNOWLEDGEMENTS
=head1 LICENSE AND COPYRIGHT
( run in 1.560 second using v1.01-cache-2.11-cpan-63c85eba8c4 )