The supplied files describe a partially developed Perl/Moo-based toolset for managing DAP application binaries stored in Artifactory and making them available on destination hosts.
At a high level, the project appears intended to:
1. Validate that a named release exists in Artifactory. 2. Read release metadata from Artifactory. 3. Update a local status.xml manifest describing supported products and JDKs. 4. Download product archives such as WebLogic, Tomcat, JBoss and JDK tarballs from Artifactory. 5. Stage or extract those archives onto destination hosts. 6. Optionally process local .dap metadata files to update status.xml.
The main implemented workflows are split between:
- artifactory-release, which is a CLI script for checking a release and updating status.xml. - lib/Dap/Artifactory/Manifest.pm, which reads remote release metadata and rewrites sections of status.xml. - lib/Dap/Artifactory.pm, which downloads and stages/extracts products and JDKs from Artifactory. - lib/Dap/Artifactory/Tx.pm, which provides the Artifactory HTTP/curl transaction layer. - lib/Dap/Artifactory/Dapfile*.pm, which seem intended to process per-package .dap JSON metadata files, although this area is incomplete.
There are several implementation bugs and inconsistencies, so the project should be regarded as incomplete or not yet production-safe.
According to artifactory-release, the first visible use case is:
artifactory-release --release <release-path> --statusxml <status.xml>
has status_xml => ( is => 'rw', required => 1 );
has release => ( is => 'rw', required => 1 );
if (not $self->tx->file_exist($self->release)) {
$self->log->error("RELEASE: " . $self->release . ' NOT FOUND on Artifactory');
exit 1;
}
$self->log->info('RELEASE ' . $self->release . ' OK');
Dap::Artifactory::Manifest->new(
release => $self->release,
status_xml => $self->status_xml,
)->update;
The release metadata itself is expected to live in Artifactory under a path based on:
/dist-private-local/com/db/dap/<release>
as implemented in lib/Dap/Artifactory/Manifest.pm and lib/Dap/Artifactory/Tx.pm.
The second use case, represented by lib/Dap/Artifactory.pm, is installation/staging:
1. Read a manifest. 2. For each product/JDK in the manifest: - Check if it is already installed or staged. - If not, verify the archive exists in Artifactory. - Download it. - For WebLogic, move the archive into a WebLogic staging tarball directory. - For Tomcat/JBoss/JDK, extract the archive into the staging application directory.
The third partial use case, represented by lib/Dap/Artifactory/Dapfile.pm, is discovery of .dap metadata files inside package directories and conversion of that metadata into status.xml entries.
artifactory-release defines package Dap::Artifactory::Release and a main block.
It accepts two command-line options through Dap::Script:
"release|r=s" => \my $release,
"statusxml=s" => \my $status_xml,
The object requires:
has status_xml => ( is => 'rw', required => 1 );
has release => ( is => 'rw', required => 1 );
Its run method does:
if (not $self->tx->file_exist($self->release)) {
$self->log->error("RELEASE: " . $self->release . ' NOT FOUND on Artifactory');
exit 1;
}
$self->log->info('RELEASE ' . $self->release . ' OK');
Dap::Artifactory::Manifest->new(
release => $self->release,
status_xml => $self->status_xml,
)->update;
So the intended behavior is:
1. Confirm the release path exists in Artifactory. 2. Update the provided status.xml using release metadata.
From artifactory-release:
| Input | Required | Description |
|---|---:|---|
| `--release` / `-r` | Yes | Release path/name in Artifactory. |
| `--statusxml` | Yes | Local XML file to update. |
| Environment variables | Yes, indirectly | Artifactory connection details are used by `Dap::Artifactory::Tx`. |
- Logs to Mojo::Log. - Updated status.xml. - Exits with status 1 if release is not found.
This file is intended to define the main deployment/downloader class. However, there is an important typo:
package Dap::Artifatory {
The package name is missing the c in Artifactory. This means the file path lib/Dap/Artifactory.pm does not define Dap::Artifactory; it defines Dap::Artifatory. Unless the rest of the system uses that typo, this module will not load as expected.
This module is intended to:
1. Process JBoss. 2. Process Tomcat. 3. Process WebLogic. 4. Process JDKs.
The run method in lib/Dap/Artifactory.pm does:
$self->process_jboss;
$self->process_tomcat;
$self->process_weblogic;
$self->process_jdks;
It has a force_download flag:
has force_download => ( is => 'rw', default => 0 );
The comments say:
> This option means: ignore staging copy, download remote copy, remove local copy, extract remote copy
process_weblogic, process_tomcat, and process_jboss all call _process_product.
The _process_product method:
1. Iterates over products from the manifest. 2. Filters by technology. 3. Skips if already installed or staged unless force_download is enabled. 4. Checks if the artifact exists in Artifactory. 5. Downloads it. 6. For WebLogic: - Moves the archive to the WebLogic tarball staging directory. 7. For Tomcat/JBoss: - Extracts it under the staging application directory. - Removes the downloaded temporary file.
The relevant code in lib/Dap/Artifactory.pm:
if ($self->tx->file_exist($p->af_file)) {
my $downloaded = $self->tx->download(file => $p->af_file, archive => $p->archive);
if ($p->is_weblogic) {
rename($downloaded, $p->absolute_staging_name)
? $self->log->info("$downloaded -> ".$p->absolute_staging_name)
: $self->log->error("Failed to move $downloaded - $!");
}
else {
$self->tx->extract(dir => $p->verison, file => $p->archive);
unlink($downloaded)
? $self->log->debug("Removing temporary file $downloaded")
: $self->log->error("Failed to cleanup $downloaded - $!");
}
}
There is a typo here:
$p->verison
should probably be:
$p->version
process_jdks in lib/Dap/Artifactory.pm:
1. Iterates over manifest JDKs. 2. Skips JDKs where location is unknown. 3. Skips already installed/staged JDKs unless force_download is enabled. 4. Checks the JDK archive in Artifactory. 5. Downloads and extracts it. 6. Deletes the temporary archive.
Dap::Artifactory::Tx wraps Artifactory operations.
It uses:
use Mojo::UserAgent;
use Dap::Const;
use Dap::Cluster;
It expects Artifactory credentials and base URL from environment variables:
has user => ( is => 'rw', lazy => 1, default => $ENV{ARTIFACTORY_USER} );
has token => ( is => 'rw', lazy => 1, default => $ENV{ARTIFACTORY_TOKEN} );
has url => ( is => 'rw', lazy => 1, default => $ENV{ARTIFACTORY_URL} );
The default Artifactory repository path is:
/dist-private-local/com/db/dap
as defined in lib/Dap/Artifactory/Tx.pm:
has default_artifatory_path => (
is => 'rw',
default => sub { '/dist-private-local/com/db/dap' }
);
Note the attribute name is also misspelled as default_artifatory_path.
Mojo::UserAgent is configured so that every request gets credentials:
$tx->req->url->userinfo(sprintf("%s:%s", $self->user, $self->token));
$tx->req->url->base(Mojo::URL->new($self->url));
file_exist in lib/Dap/Artifactory/Tx.pm calls Artifactory’s storage API:
my $url = $self->url . "/api/storage/dist-private-local/com/db/dap/$file";
$self->ua->get($url)->res->is_success;
So if called with:
$self->tx->file_exist('weblogic/weblogic-14.1.1.0.240628.tar.bz2')
it checks:
$ARTIFACTORY_URL/api/storage/dist-private-local/com/db/dap/weblogic/weblogic-14.1.1.0.240628.tar.bz2
The download method deliberately shells out to curl instead of using Mojo::UserAgent.
The comment in lib/Dap/Artifactory/Tx.pm says:
> For some funny reason Mojo::UserAgent does not download entire file from Artifactory therefore the need to shell out to external curl command to download the archive.
The generated command is approximately:
curl -OJkLu <user>:<token> <ARTIFACTORY_URL>/<path>/<file>
The path defaults to:
/dist-private-local/com/db/dap
The file is downloaded into $const->dap_tmp.
The extract method in lib/Dap/Artifactory/Tx.pm extracts tar archives into the staging apps directory:
/bin/tar --no-same-owner --extract --auto-compress \
--directory=<staging_apps> \
--file=<dap_tmp>/<archive>
Before extraction, it removes any existing staging directory:
rm -fr <staging_apps>/<dir>
The upload method in lib/Dap/Artifactory/Tx.pm PUTs a file to Artifactory using Mojo::UserAgent.
Dap::Artifactory::Manifest is the main metadata updater.
It requires:
has release => ( is => 'rw', required => 1 );
It also has a status_xml path, defaulting to:
$const->dap_etc . '/status.xml'
The XML document is loaded lazily:
XML::LibXML->load_xml(location=>$self->status_xml)
The release URL is computed by:
return $self->tx->url . $self->tx->default_artifatory_path . '/' . $self->release;
So for release foo, the tool expects metadata under:
$ARTIFACTORY_URL/dist-private-local/com/db/dap/foo
update in lib/Dap/Artifactory/Manifest.pm does:
$self->update_products;
$self->update_jdks;
$self->update_jdklist;
$self->save;
So it rewrites three sections of status.xml:
1. <products> 2. <jdks>/<jdk> 3. <jdks>/<jdklist>
Dap::Artifactory::Manifest expects at least three remote resources:
Fetched from:
<release-url>/products
in products:
my $aref = $self->tx->ua->get($self->_release_url . '/products')->res->json;
Expected format: JSON array.
Each product entry is converted to Dap::Artifactory::Manifest::Entry::Product, defined in lib/Dap/Artifactory/Manifest/Entry/Product.pm.
Required product fields are:
upgradedue
name
technology
securitystatus
status
jdklist
version
Optional:
releasedate
Fetched from:
<release-url>/java/jdks
in jdks:
my $res = $self->tx->ua->get($self->_release_url . '/java/jdks')->res;
return c(@{$res->json})
Expected format: JSON array.
Each entry is converted to Dap::Artifactory::Manifest::Entry::Jdk, defined in lib/Dap/Artifactory/Manifest/Entry/Jdk.pm.
Required JDK fields are:
location
upgradedue
securitystatus
status
name
version
Fetched from:
<release-url>/java/jdklist
in jdklist:
my $content = $self->tx->ua->get($self->_release_url . '/java/jdklist')->res->body;
Expected format: plain text.
Blank lines and comments are ignored:
->grep(sub { not m/^\s*$/ and not m/^\s*\#/ })
Each non-comment line is split as:
my ($list, $jdk) = split(/[\s\t]+/);
Example intended format:
java87 java8-openjdk-401
java87 java8-openjdk-402
java1187 java11-openjdk-21
Each line becomes a Dap::Artifactory::Manifest::Entry::Jdklist, defined in lib/Dap/Artifactory/Manifest/Entry/Jdklist.pm.
From lib/Dap/Artifactory/Manifest.pm, the expected XML structure is approximately:
<cluster>
<products>
<dap ... />
<tomcat ... />
<jboss ... />
</products>
<jdks>
<jdk ... />
<jdklist name="java87">
<jdk name="java8-openjdk-401" priority="1" />
<jdk name="java8-openjdk-402" priority="2" />
</jdklist>
</jdks>
</cluster>
update_products removes the existing <products> node under <cluster> and recreates it:
my $node = c($dom->findnodes("//cluster"))->first;
c($node->getChildrenByTagName('products'))->map(sub { $_->unbindNode });
my $products = $dom->createElement('products');
For each remote product, it creates an XML element named after the product technology:
my $el = $dom->createElement($p->technology);
Then sets attributes:
upgradedue
name
technology
securitystatus
status
jdklist
version
update_jdks removes all existing <jdk> children under <cluster>/<jdks> and adds remote JDKs back.
The generated JDK XML elements have attributes:
name
version
location
status
securitystatus
upgradedue
update_jdklist removes all existing <jdklist> children under <cluster>/<jdks> and recreates them based on remote java/jdklist.
Dap::Artifactory::Manifest::Entry::Product represents one application server/product entry.
Required fields:
upgradedue
name
technology
securitystatus
status
jdklist
version
Optional:
releasedate
It uses constants from lib/Dap/Artifactory/Const.pm.
sub is_weblogic {
my $self = shift;
return $self->technology eq WEBLOGIC;
}
Since WEBLOGIC is defined as dap in lib/Dap/Artifactory/Const.pm, WebLogic product entries are expected to have:
"technology": "dap"
For WebLogic:
weblogic-<version>.tar.bz2
For other products, it is intended to be:
<version>.tar.gz
But there is a bug in lib/Dap/Artifactory/Manifest/Entry/Product.pm:
: $_->version . '.tar.gz';
This should almost certainly be:
: $self->version . '.tar.gz';
As written, $_ may be undefined or not what is intended.
For WebLogic:
weblogic/weblogic-<version>.tar.bz2
For others:
<technology>/<version>.tar.gz
Examples:
weblogic/weblogic-14.1.1.0.240628.tar.bz2
tomcat/tomcat-9.0.71.tar.gz
jboss/jboss-eap-7.4.17.tar.gz
Dap::Artifactory::Manifest::Entry::Jdk represents one JDK.
Required fields:
location
upgradedue
securitystatus
status
name
version
Archive naming:
sub archive { shift->location . '.tar.gz' }
Artifactory path:
sub af_file { 'java/' . shift->archive }
So a JDK with location:
openjdk1.17.0_10
maps to:
java/openjdk1.17.0_10.tar.gz
Installation and staging paths are based on $const, from external Dap::Const:
absolute_install_name => $const->dap_apps . '/' . location
absolute_staging_name => $const->staging_apps . '/' . location
Dap::Artifactory::Manifest::Entry::Jdklist is a small value object with:
list
name
priority
It represents one mapping from a JDK list name to a JDK name, for example:
java87 java8-openjdk-401
where:
list => 'java87'
name => 'java8-openjdk-401'
priority => 1
Dap::Artifactory::Const exports technology constants:
sub WEBLOGIC { 'dap' };
sub TOMCAT { 'tomcat' };
sub JBOSS { 'jboss' };
sub JAVA { 'java' };
The important detail is that WebLogic is represented as technology value:
dap
not:
weblogic
This matters in lib/Dap/Artifactory/Manifest/Entry/Product.pm, lib/Dap/Artifactory.pm, and lib/Dap/Artifactory/Dapfile.pm.
Dap::Artifactory::Dapfile is intended to read a .dap JSON file from a directory.
process($dir) sets:
$self->file(path("$dir/.dap"));
If the file does not exist, it logs an error.
If it exists:
1. Slurps JSON. 2. Reads the technology key. 3. Normalizes it with lc(trim(...)). 4. Sets a selector for XML lookup: - tomcat → tomcat - dap / WebLogic → dap - jboss → jboss 5. Constructs a Dap::Artifactory::Dapfile::Generic object.
The selector logic in lib/Dap/Artifactory/Dapfile.pm:
$meta->{selector} =
$meta->{technology} eq TOMCAT ? 'tomcat' :
$meta->{technology} eq WEBLOGIC ? 'dap' :
$meta->{technology} eq JBOSS ? 'jboss' :
undef;
The embedded examples after __END__ in lib/Dap/Artifactory/Dapfile.pm show intended JSON metadata for JDK and Tomcat entries.
Example Tomcat metadata:
{
"technology":"tomcat",
"name":"Tomcat 9.0.71",
"status":"Unsupported",
"version":"tomcat-9.0.71",
"jdklist":"java1187",
"securitystatus":"Insecure High",
"upgradedue":"2023-09-12",
"releasedate":"2023-06-12"
}
There is also a JDK example, but it contains invalid JSON syntax:
"location"="openjdk1.17.0_10"
should be:
"location": "openjdk1.17.0_10"
Dap::Artifactory::Dapfile::Generic updates an XML status file based on .dap metadata.
Required attributes:
jdklist
name
releasedate
securitystatus
status
technology
upgradedue
version
selector
It currently uses a hard-coded XML file:
my $filename = '/home/nedevala/status.xml';
The commented line suggests the intended file was:
$const->dap_etc . '/status.xml'
It loads the XML:
my $dom = XML::LibXML->load_xml(location=>$filename);
Then searches for an existing product node:
my $tc = c($dom->findnodes("//cluster/products/".$self->selector))
->grep(sub{$_->{version} eq $self->version})
->first;
If found, it updates these attributes:
jdklist
securitystatus
status
upgradedue
If not found, it creates a new element under <cluster>/<products> with attributes:
name
status
version
jdklist
securitystatus
upgradedue
It then pretty-prints and writes the XML file.
This is a narrower, local-metadata-based alternative to the release-manifest approach in lib/Dap/Artifactory/Manifest.pm.
Dap::Artifactory::Dapfile::Jdk defines a data model for JDK .dap metadata.
Required fields:
technology
name
priority
jdklist
version
location
status
securitystatus
upgradedue
releasedate
However, the process method is empty:
sub process {
my $self = shift;
}
So JDK-specific .dap processing is not implemented yet.
The example after __END__ in lib/Dap/Artifactory/Dapfile/Jdk.pm again shows the intended JDK metadata shape, but also contains the same invalid JSON syntax for location.
Dap::Artifactory::PrettyPrint is a vendored copy of XML::LibXML::PrettyPrint.
It provides utilities to:
1. Strip insignificant whitespace. 2. Indent XML nodes. 3. Pretty-print XML documents before saving.
It is used by:
- lib/Dap/Artifactory/Manifest.pm - lib/Dap/Artifactory/Dapfile/Generic.pm
For example, in lib/Dap/Artifactory/Manifest.pm:
Dap::Artifactory::PrettyPrint->new->pretty_print($self->dom);
and in lib/Dap/Artifactory/Dapfile/Generic.pm:
Dap::Artifactory::PrettyPrint->new->pretty_print($dom);
The purpose is to keep status.xml human-readable after programmatic modifications.
list.json is an example Artifactory storage API response for the WebLogic directory:
dist-private-local/com/db/dap/weblogic
It contains:
{
"uri": "https://artifactory.intranet.db.com/artifactory/api/storage/dist-private-local/com/db/dap/weblogic",
"files": [...]
}
Each file entry includes:
{
"uri": "/weblogic-14.1.1.0.240628.tar.bz2",
"size": 1428937446,
"lastModified": "2024-08-05T12:24:44.530+02:00",
"folder": false,
"sha1": "...",
"sha2": "..."
}
This confirms the archive naming convention used by lib/Dap/Artifactory/Manifest/Entry/Product.pm:
weblogic-<version>.tar.bz2
For example, list.json contains:
/weblogic-14.1.1.0.240628.tar.bz2
/weblogic-14.1.1.0.231220.tar.bz2
/weblogic-12.2.1.4.231010.tar.bz2
This matches the WebLogic archive method in lib/Dap/Artifactory/Manifest/Entry/Product.pm:
'weblogic-' . $self->version . '.tar.bz2'
Based on all files, the project can be specified as follows.
The system manages binary releases stored in Artifactory and updates destination hosts’ metadata and staging areas.
It supports these technology classes:
| Technology | Constant | XML element | Archive format |
|---|---|---|---|
| WebLogic | `WEBLOGIC` = `dap` | `<dap>` | `weblogic-<version>.tar.bz2` |
| Tomcat | `TOMCAT` = `tomcat` | `<tomcat>` | `<version>.tar.gz` |
| JBoss | `JBOSS` = `jboss` | `<jboss>` | `<version>.tar.gz` |
| Java/JDK | `JAVA` = `java` | `<jdk>` | `<location>.tar.gz` |
The constants are defined in lib/Dap/Artifactory/Const.pm.
Defined mainly in lib/Dap/Artifactory/Tx.pm.
Required environment variables:
| Variable | Description |
|---|---|
| `ARTIFACTORY_USER` | Artifactory username |
| `ARTIFACTORY_TOKEN` | Artifactory API token/password |
| `ARTIFACTORY_URL` | Artifactory base URL |
Default repository path:
/dist-private-local/com/db/dap
Storage API check path:
<ARTIFACTORY_URL>/api/storage/dist-private-local/com/db/dap/<file>
Download path:
<ARTIFACTORY_URL>/dist-private-local/com/db/dap/<file>
A release should live under:
/dist-private-local/com/db/dap/<release>
The following files are expected:
<release>/products
<release>/java/jdks
<release>/java/jdklist
JSON array.
Each object should contain:
{
"technology": "tomcat",
"name": "Tomcat 9.0.71",
"status": "Unsupported",
"version": "tomcat-9.0.71",
"jdklist": "java1187",
"securitystatus": "Insecure High",
"upgradedue": "2023-09-12",
"releasedate": "2023-06-12"
}
Required by lib/Dap/Artifactory/Manifest/Entry/Product.pm:
upgradedue
name
technology
securitystatus
status
jdklist
version
JSON array.
Each object should contain:
{
"name": "java8-openjdk-401",
"version": "17.0.10",
"location": "openjdk1.17.0_10",
"status": "Invest",
"securitystatus": "Secure",
"upgradedue": "2025-12-31"
}
Required by lib/Dap/Artifactory/Manifest/Entry/Jdk.pm:
location
upgradedue
securitystatus
status
name
version
Plain text.
Example:
# list-name jdk-name
java87 java8-openjdk-401
java87 java8-openjdk-402
java1187 java11-openjdk-21
Each non-comment line maps a JDK list to a JDK name. Priority is assigned based on order within the same list, as implemented in lib/Dap/Artifactory/Manifest.pm.
Implemented in lib/Dap/Artifactory/Manifest.pm.
Given a valid release and local XML file:
1. Load status.xml. 2. Remove existing <products> under <cluster>. 3. Create a new <products> element. 4. Add one child element per product. 5. Remove existing <jdk> children under <cluster>/<jdks>. 6. Add one <jdk> element per remote JDK. 7. Remove existing <jdklist> children under <cluster>/<jdks>. 8. Add one <jdklist> per remote JDK list. 9. Pretty-print the XML. 10. Save status.xml.
Implemented in lib/Dap/Artifactory.pm and lib/Dap/Artifactory/Tx.pm.
For each product from the manifest:
1. If already installed, skip. 2. If already staged, skip. 3. Otherwise, check Artifactory. 4. Download the archive into $const->dap_tmp. 5. If WebLogic: - Move the archive into $const->staging_wltarballs. 6. If Tomcat/JBoss: - Extract the archive into $const->staging_apps. - Delete temporary archive.
For each JDK:
1. Ignore entries where location is unknown. 2. If already installed, skip. 3. If already staged, skip. 4. Otherwise, check Artifactory. 5. Download the archive. 6. Extract into $const->staging_apps. 7. Delete temporary archive.
If force_download is enabled, the installed/staged checks are bypassed.
From artifactory-release:
--release / -r
--statusxml
Example:
artifactory-release \
--release release-2024-08 \
--statusxml /opt/dap/etc/status.xml
From lib/Dap/Artifactory/Tx.pm:
ARTIFACTORY_USER
ARTIFACTORY_TOKEN
ARTIFACTORY_URL
From lib/Dap/Artifactory/Manifest.pm:
status.xml
From lib/Dap/Artifactory/Dapfile.pm:
<directory>/.dap
From lib/Dap/Artifactory.pm and lib/Dap/Artifactory/Tx.pm, paths provided by external Dap::Const, such as:
$const->dap_tmp
$const->dap_apps
$const->dap_etc
$const->staging_apps
$const->staging_wltarballs
$const->prog_curl
Dap::Const is not provided in the submitted documents, but it is heavily relied on.
From lib/Dap/Artifactory/Manifest.pm:
<release>/products
<release>/java/jdks
<release>/java/jdklist
From lib/Dap/Artifactory/Manifest/Entry/Product.pm and lib/Dap/Artifactory/Manifest/Entry/Jdk.pm, expected artifact locations include:
weblogic/weblogic-<version>.tar.bz2
tomcat/<version>.tar.gz
jboss/<version>.tar.gz
java/<location>.tar.gz
list.json demonstrates the real Artifactory WebLogic directory layout.
The main output of artifactory-release and lib/Dap/Artifactory/Manifest.pm is an updated status.xml.
The main output of lib/Dap/Artifactory.pm and lib/Dap/Artifactory/Tx.pm is staged software under paths from Dap::Const, for example:
$const->staging_apps/<product-version>
$const->staging_apps/<jdk-location>
$const->staging_wltarballs/weblogic-<version>.tar.bz2
All major classes use Mojo::Log.
Examples:
- artifactory-release - lib/Dap/Artifactory.pm - lib/Dap/Artifactory/Tx.pm - lib/Dap/Artifactory/Dapfile.pm - lib/Dap/Artifactory/Dapfile/Generic.pm - lib/Dap/Artifactory/Manifest.pm
The file declares:
package Dap::Artifatory {
but the expected package from the path is:
Dap::Artifactory
This will cause load/use issues unless all callers use the misspelled name.
In lib/Dap/Artifactory/Manifest.pm:
has release => ( is => 'rw', required => 1 );
But in lib/Dap/Artifactory.pm:
has manifest => (
is => 'rw',
default => sub { Dap::Artifactory::Manifest->new }
);
That will fail because release is required.
Either release needs to be supplied, or the manifest class should support a local-only mode.
In lib/Dap/Artifactory/Manifest/Entry/Product.pm:
: $_->version . '.tar.gz';
should almost certainly be:
: $self->version . '.tar.gz';
In lib/Dap/Artifactory.pm:
$self->tx->extract(dir => $p->verison, file => $p->archive);
should be:
$self->tx->extract(dir => $p->version, file => $p->archive);
In lib/Dap/Artifactory/Manifest.pm, products checks:
$self->tx->file_exist('products')
but then fetches:
$self->_release_url . '/products'
Similarly, jdks checks:
$self->tx->file_exist('java/jdks')
but fetches:
$self->_release_url . '/java/jdks'
That means it checks:
/dist-private-local/com/db/dap/products
/dist-private-local/com/db/dap/java/jdks
but fetches:
/dist-private-local/com/db/dap/<release>/products
/dist-private-local/com/db/dap/<release>/java/jdks
The check probably should include $self->release.
In lib/Dap/Artifactory/Dapfile/Generic.pm:
my $filename = '/home/nedevala/status.xml';
This should likely be configurable or use:
$const->dap_etc . '/status.xml'
as suggested by the commented code.
In both lib/Dap/Artifactory/Dapfile.pm and lib/Dap/Artifactory/Dapfile/Jdk.pm, the sample JDK JSON contains:
"location"="openjdk1.17.0_10"
This should be:
"location": "openjdk1.17.0_10"
In lib/Dap/Artifactory/Tx.pm, download runs:
system(@cmd);
but does not verify success. It then renames and returns the expected path regardless.
A production version should check:
system(@cmd) == 0
and validate the downloaded file exists and has non-zero size.
In lib/Dap/Artifactory/Tx.pm:
system("@cmd");
is used for rm -fr.
This invokes the shell. It would be safer to use list form:
system(@cmd);
or a Perl filesystem library.
In lib/Dap/Artifactory/Manifest.pm:
for my $attr (sort qw/name version location status securitystatus upgradedue/) {
$jdk->setAttribute($attr => $_->$attr);
$jdklist_node->appendChild($jdk);
}
The append should probably happen after the loop:
for my $attr (...) {
$jdk->setAttribute($attr => $_->$attr);
}
$jdklist_node->appendChild($jdk);
Appending the same node repeatedly will not normally duplicate it, but it is semantically wrong and confusing.
lib/Dap/Artifactory/Manifest.pm assumes these nodes exist:
<cluster>
<jdks>
</jdks>
</cluster>
If they are missing, calls like:
$jdklist_node->getChildrenByTagName('jdk')
will fail.
Remote files such as products, java/jdks, and .dap are assumed to contain valid JSON with all required fields. Moo required attributes will catch missing fields, but error reporting may not be user-friendly.
A more formal version of the intended tool could be:
artifactory-release --release RELEASE --statusxml STATUS_XML
1. ARTIFACTORY_USER, ARTIFACTORY_TOKEN, and ARTIFACTORY_URL are set. 2. STATUS_XML exists and has a <cluster> root or descendant containing <products> and <jdks>. 3. Artifactory contains:
/dist-private-local/com/db/dap/RELEASE/products
/dist-private-local/com/db/dap/RELEASE/java/jdks
/dist-private-local/com/db/dap/RELEASE/java/jdklist
1. Validate that the release exists. 2. Load remote product list. 3. Load remote JDK list. 4. Load remote JDK-list mappings. 5. Rewrite relevant sections of STATUS_XML. 6. Pretty-print and save STATUS_XML.
A separate deployment command or object should:
1. Load the same release manifest. 2. For each product and JDK: - Determine expected Artifactory archive. - Determine local install/staging paths. - Skip if already installed/staged unless forced. - Download missing archives. - Extract or stage them.
WebLogic: weblogic/weblogic-<version>.tar.bz2
Tomcat: tomcat/<version>.tar.gz
JBoss: jboss/<version>.tar.gz
JDK: java/<location>.tar.gz
This naming is confirmed by lib/Dap/Artifactory/Manifest/Entry/Product.pm, lib/Dap/Artifactory/Manifest/Entry/Jdk.pm, and the sample Artifactory listing in list.json.
| File | Role |
|---|---|
| `artifactory-release` | CLI script. Validates release exists and updates `status.xml`. |
| `lib/Dap/Artifactory.pm` | Intended main downloader/stager for WebLogic, Tomcat, JBoss, and JDKs. Contains package-name typo. |
| `lib/Dap/Artifactory/Dapfile.pm` | Reads `.dap` JSON metadata and dispatches to a processor. |
| `lib/Dap/Artifactory/Dapfile/Generic.pm` | Updates product entries in `status.xml` from `.dap` metadata. Uses hard-coded XML path. |
| `lib/Dap/Artifactory/Dapfile/Jdk.pm` | Placeholder model for JDK `.dap` metadata. Processing not implemented. |
| `lib/Dap/Artifactory/PrettyPrint.pm` | Vendored XML pretty-printer used before saving XML. |
| `lib/Dap/Artifactory/Tx.pm` | Artifactory transaction layer: existence check, download, upload, extract. |
| `lib/Dap/Artifactory/Manifest.pm` | Core release manifest reader and `status.xml` updater. |
| `lib/Dap/Artifactory/Manifest/Entry/Product.pm` | Product metadata object and archive/path naming logic. Contains bug using `$_`. |
| `lib/Dap/Artifactory/Manifest/Entry/Jdk.pm` | JDK metadata object and archive/path naming logic. |
| `lib/Dap/Artifactory/Manifest/Entry/Jdklist.pm` | JDK-list mapping object. |
| `lib/Dap/Artifactory/Const.pm` | Defines technology constants. |
| `list.json` | Example Artifactory storage API response for WebLogic artifacts. Confirms archive naming and repository layout. |