Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6133 dpurdie 1
########################################################################
6177 dpurdie 2
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
6133 dpurdie 3
#
4
# Module name   : jats_generate_deployable.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats build system
8
#
9
# Description   : Extracts current package version list from release manager
10
#                 based on the 'IS_DEPOLYABLE' flag in a given Release
11
#                 and copies resultant packages to release specific
12
#                 directory.
13
#                 
14
#                 Based on jats_update_release.pl and jats_gen_bom.pl but it is 
15
#                 intended to be used by the PULSE digital distribution process
16
#......................................................................#
17
 
18
require 5.008_002;
19
use File::Basename;
20
use File::Copy;
21
use File::Path;
22
use strict;
23
use warnings;
24
use JatsEnv;
25
use JatsError;
26
use JatsRmApi;
27
use ArrayHashUtils;
28
use FileUtils;
29
use DBI;
30
use Getopt::Long;
31
use Pod::Usage;                             # required for help support
32
use JSON;
33
 
34
#
35
#   Config Options
36
#
37
my $VERSION = "1.0.0";                      # Update this
38
my $opt_help = 0;
39
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
40
my $opt_rtagid;
41
my $opt_rootdir = '.';
42
my $opt_test;
43
my $opt_showFilters;
44
my @opt_addFilters;
45
my @opt_delFilters;
46
my $opt_showFiles;
47
my @opt_addFiles;
48
my @opt_delFiles;
49
 
50
 
51
#
52
#   Constants
53
#
54
my $CONFFILE = '.bomGen';
6177 dpurdie 55
my $BOMFILE = '.bomCots';
6133 dpurdie 56
my $MANIFEST = 'MANIFEST.json';
57
my $TFVARS   = 'MANIFEST.tf';
58
 
59
#
60
#   Globals
61
#
62
my $DM_DB;              # Data Base Interface
63
my %bomList;            # All files in the BOM
64
my $bomInfo;            # Sbom meta data
6177 dpurdie 65
my %baseList;           # List of files in bin
6133 dpurdie 66
 
67
#
68
#   Configuration file vars
69
#
70
my @confFilters;
71
my @confFiles;
72
my %filtersUsed;
73
 
74
#-------------------------------------------------------------------------------
75
# Function        : Main
76
#
77
# Description     : Main entry point
78
#                   Parse user options
79
#
80
# Inputs          :
81
#
82
# Returns         :
83
#
84
 
85
my $result = GetOptions (
86
                "help:+"            => \$opt_help,              # flag, multiple use allowed
87
                "manual:3"          => \$opt_help,              # flag, multiple use allowed
88
                "verbose:+"         => \$opt_verbose,           # flag
89
                "rtagid|rtag_id=s"  => \$opt_rtagid,            # Number
90
                "rootdir=s"         => \$opt_rootdir,           # string
91
 
92
                "addfilter=s"       => \@opt_addFilters,        # multiple strings
93
                "delfilter=s"       => \@opt_delFilters,        # multiple strings
94
                "showfilters"       => \$opt_showFilters,       # flag
95
 
96
                "addfiles=s"       => \@opt_addFiles,           # multiple strings
97
                "delfiles=s"       => \@opt_delFiles,           # multiple strings
98
                "showfiles"        => \$opt_showFiles,          # flag
99
 
100
                "test"              => \$opt_test,              # flag
101
                );
102
 
103
#
104
#   Process help and manual options
105
#
106
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
107
pod2usage(-verbose => 1)  if ($opt_help == 2 );
108
pod2usage(-verbose => 2)  if ($opt_help > 2);
109
 
110
ErrorConfig( 'name'    => 'GenDeploy',
111
             'verbose' => $opt_verbose );
112
 
113
#
114
#   Sanity tests
115
#
116
 
117
# Supplied rootdir must exists as a directory
118
Error("Root dir not specified") 
119
    unless defined $opt_rootdir;
120
Error("Root dir not a valid directory: ", $opt_rootdir )
121
    unless( -d $opt_rootdir );
122
 
123
    # Environment var GBE_DPKG must exists as a directory
124
Error("GBE_DPKG Environment var is not a directory")
125
    unless ( -d $ENV{GBE_DPKG} );
126
 
127
LoadFilterConfig();
128
ProcessFilterArgs();
129
 
130
#   Non Filter operations
131
#   Must supply an rtagid
132
Error("Need --rtagid", "Example: -rtagid=2362" )
133
    unless ($opt_rtagid);
134
 
6177 dpurdie 135
Error("No Filters defined.", "Add filters before creating BOM") 
136
    unless ( @confFilters );
137
 
6133 dpurdie 138
#
139
#   This command is destined to be used in a directory where group permissions
140
#   are important. Ensure that the user is not killing group access
141
#
142
umask 0002;
143
 
144
#
145
#   Body of the processing
146
#       Save generation time into the meta data
147
my $now = time;
148
$bomInfo->{version} = "2.0.0";
149
$bomInfo->{timestamp}{epoch} = $now;
150
$bomInfo->{timestamp}{utc} = gmtime($now);
151
 
152
Message("Copying packages from $ENV{GBE_DPKG} to $opt_rootdir");
153
 
154
#
155
#   Processing
156
#
157
connectRM(\$DM_DB);
158
GetReleaseInfo();               # Get Release Metadata
159
GetPackageData();               # Get RM Data
160
RemoveDuplicates();             # Need P or D, but not both
161
CopyInNew();                    # Copy new files
162
RemoveExcess();                 # Remove files no longer required
163
GenFileData();                  # Generate file metadata
164
WriteManifest();                # Save out meta data
165
exit 0;
166
 
167
#-------------------------------------------------------------------------------
168
# Function        : GenFileData 
169
#
170
# Description     : Generate meta data on each file
171
#                   Much of this is a guess.
172
#                   Assume files look like:
173
#                   
174
#                       VIXcryptoKeyManager-1.0.2061.cr-WIN32.exe
175
#                       erg-pkgmnt_1.0.3010.cr_UBUNTU16_P.deb
176
#                       erg-pkgmnt_1.0.3010.cr_RHEL7_P.rpm
177
#                       xxxxxx.sh - bit trickier
178
#
179
# Inputs          : None
180
#
181
# Returns         : Populates $bomInfo
182
#
183
sub GenFileData
184
{
185
    my @elist;
186
    my @edup;
187
    foreach my $file (sort keys %bomList)
188
    {
189
        my $data;
190
        my $alias;
191
 
192
        $bomList{$file}{version} =~ m~(.*)\.([a-z]+)$~;
193
        my $pvfull = $1;
194
        my $proj = $2;
195
        my $pv = $pvfull;
196
        $pv =~ s~\.\d+$~~;
197
 
198
        if ($file =~ m~^(.*)-(.*)\.(.*)-(WIN.*)\.(exe)$~i)
199
        {
200
            $data->{name} = $1;
201
            $data->{version} = $2;
202
            $data->{prj} = $3;
203
            $data->{arch} = $4;
204
            $data->{type} = $5;
205
        }
206
        elsif ( $file =~ m~^(.*)_(.*)\.([^_]+)_(.*)\.(deb|tgz|rpm)$~i)
207
        {
208
            $data->{name} = $1;
209
            $data->{version} = $2;
210
            $data->{prj} = $3;
211
            $data->{arch} = $4;
212
            $data->{type} = $5;
213
            $data->{arch} =~ s~_[PD]~~;
214
        }
215
        elsif ( $file =~ m~^(.*)-($pv)\.(.*)\.(rpm)$~i)
216
        {
217
            # COTS package
218
            $data->{name} = $1;
219
            $data->{version} = $2;
220
            $data->{arch} = $3;
221
            $data->{type} = $4;
222
            $data->{prj} = $proj;
223
        }
224
        elsif ( $file =~ m~^(.*)_($pv)\.(tgz)$~i)
225
        {
226
            # COTS package
227
            $data->{name} = $1;
228
            $data->{version} = $2;
229
            $data->{arch} = 'UNKNOWN';
230
            $data->{type} = $3;
231
            $data->{prj} = $proj;
232
        }
233
        elsif ( $file =~ m~^(.*)-($pv)\.(.*)\.(deb)$~i)
234
        {
235
            # COTS package
236
            $data->{name} = $1;
237
            $data->{version} = $2;
238
            $data->{arch} = $3;
239
            $data->{type} = $4;
240
            $data->{prj} = $proj;
241
        }
242
        elsif ( $file =~ m~^(.*)\.(sh|zip|msi|tar\.gz)$~i)
243
        {
244
            $data->{name} = $1;
245
            $data->{arch} = 'NOARCH';
246
            $data->{type} = $2;
247
 
248
            $data->{version} = $pvfull;
249
            $data->{prj} = $proj;
250
        }
251
 
252
        unless ($data && $data->{name} && $data->{prj} && $data->{type}) {
253
            push @elist, $file;
254
            next;
255
        }
256
        $data->{fullname} = $file;
257
 
258
        #
259
        #   Create a nice alias
260
        #       ERG -> VIX  (not done)
261
        #       All lowercase
262
        #
263
        $alias = join ('.', $data->{name}, $data->{prj}, $data->{type});
264
        $alias = lc ($alias);
265
        #$alias =~ s~^erg~vix~;
266
        #$alias =~ s~^vix~vix-~;
267
        #$alias =~ s~^vix--~vix-~;
268
        push (@edup, join( ' : ', $alias, $file ,$bomInfo->{files}{$alias}{fullname})  ) if exists $bomInfo->{files}{$alias};
269
 
270
        delete $data->{type};
271
        $bomInfo->{files}{$alias} = $data;
272
    }
273
 
274
    ReportError ("Cannot extract file metadata from:", @elist)  if (@elist);
275
    ReportError ("Duplicate aliases for:", @edup)  if (@edup);
276
    ErrorDoExit();
277
}
278
 
279
#-------------------------------------------------------------------------------
280
# Function        : CopyInNew 
281
#
282
# Description     : Copy in new files
283
#                   Don't copy in files that already exist - assume that the
284
#                   files don't chnage without a chnage to the file name
285
#
286
# Inputs          : 
287
#
288
# Returns         : 
289
#
290
sub CopyInNew
291
{
292
    #
293
    #   Ensure the output directory exists
294
    #
295
    if ( ! -d $opt_rootdir )
296
    {
297
        if ( defined($opt_test) )
298
        {
299
            Message("mkdir $opt_rootdir");
300
        }
301
        else
302
        {
303
            eval { mkpath($opt_rootdir) };
304
            Error("Failed to make project directory tree $opt_rootdir") if ( $@ || ! -d $opt_rootdir );
305
        }
306
    }
307
 
308
    #
6177 dpurdie 309
    #   Generate a list of all files in the directory
310
    #
311
    foreach my $file ( glob("$opt_rootdir/*") ) {
312
        $baseList{$file}{data} = 1;
313
    }
314
 
315
    #
6133 dpurdie 316
    #   Determine the files to be transferred
317
    #
318
    my @filelist;
319
    foreach my $file ( keys %bomList)
320
    {
321
        push (@filelist, $file) unless ( -f "$opt_rootdir/$file" );
322
    }
323
 
324
    #
325
    #   Perform the actual copy
326
    #
327
    if ( @filelist )
328
    {
329
        #Message("Copying files for package $PKG_NAME version $PKG_VERSION");
330
        if ( defined($opt_test) )
331
        {
332
            Message( map("$_...", @filelist) );
333
        }
334
        else
335
        {
336
            eval { mkpath($opt_rootdir) };
337
            Error("Failed to make destination directory") if ( $@ || ! -d $opt_rootdir );
338
            foreach my $file ( @filelist )
339
            {
340
                Verbose("Copy: $file...");
341
 
342
                my $srcFile = $bomList{$file}{path};
343
                if ( ! copy($srcFile, $opt_rootdir) )
344
                {
345
                    Warning("Failed to copy $file ($!)");
346
                }
347
            }
348
        }
349
    }
350
}
351
 
352
#-------------------------------------------------------------------------------
353
# Function        : RemoveExcess 
354
#
355
# Description     : Remove excess files from the output directory 
356
#
357
# Inputs          : 
358
#
359
# Returns         : 
360
#
361
sub RemoveExcess
362
{
363
    my @filelist;
364
    my %keepList = map { $_ => 1 } @confFiles;
365
 
366
    #
367
    #   Find all files in the output directory
368
    #   Use the 'keepList' so that we don't pickup files that should
369
    #   be in the directory. README.md, MANIFEST ...
370
    #
371
    foreach my $srcPath ( glob("$opt_rootdir/*") )
372
    {
373
        my $dstFile = basename($srcPath);
374
        next if exists $keepList{$dstFile};
375
        next unless ( -f $srcPath );
376
 
377
        push (@filelist, $dstFile) unless (exists $bomList{$dstFile} );
378
    }
379
 
380
    if ( @filelist)
381
    {
6177 dpurdie 382
        #Message ("Delete execess files", @filelist );
6133 dpurdie 383
        unless ( defined($opt_test) )
384
        {
385
            foreach my $file ( @filelist )
386
            {
387
                Verbose("Delete: $file...");
388
                if ( unlink("$opt_rootdir/$file") ne 1 )
389
                {
390
                    Warning("Failed to delete: $file. ($!)");
391
                }
392
            }
393
        }
394
    }
6177 dpurdie 395
 
396
    #
397
    #   Report changed files
398
    #   Generate a list of all files in the directory
399
    #
400
    foreach my $file ( glob("$opt_rootdir/*") ) {
401
        $baseList{$file}{data} |= 2;
402
    }
403
 
404
    #
405
    #   Determined added, removed and replaced
406
    #       
407
    #
408
    my (@replaced, @added, @removed, @unchanged, %newList);
409
    foreach my $entry ( keys %baseList )
410
    {
411
        (my $key = $entry) =~ s~\d+~z~g;
412
        $baseList{$entry}{key} = $key;
413
 
414
        (my $name = $entry) =~ s~^\./~~;
415
        $newList{$key}{$baseList{$entry}{data}} = $entry;
416
    }
417
 
418
    foreach my $key ( sort keys %newList )
419
    {
420
        if (exists $newList{$key}{1} && exists $newList{$key}{2}  ) {
421
            push @replaced, "$newList{$key}{1}   =>   $newList{$key}{2}";
422
        } elsif (exists $newList{$key}{1}) {
423
            push @removed, $newList{$key}{1};
424
        } elsif (exists $newList{$key}{2}) {
425
            push @added, $newList{$key}{2};
426
        } elsif (exists $newList{$key}{3}) {
427
            push @unchanged, $newList{$key}{3};
428
        }
429
    }
430
 
431
    Message ("Unchanged: " .(@unchanged ? scalar(@unchanged ) : 'None') );
432
    Message ("Replaced: " . (@replaced ?  scalar(@replaced )  : 'None'), @replaced);
433
    Message ("Added: " .    (@added    ?  scalar(@added )     : 'None'), @added);
434
    Message ("Removed: " .  (@removed  ?  scalar(@removed )   : 'None'), @removed);
6133 dpurdie 435
}
436
 
437
#-------------------------------------------------------------------------------
438
# Function        : RemoveDuplicates 
439
#
440
# Description     : Scan the BOM file list and remove duplicate installers
441
#                   Duplicate installers are that that have both a P and a D
442
#                   flavor of the installer
443
#                   
444
#                   This test has some nasty built-in knowledge (assumtions)
445
#                   It assumes that:
446
#                       Windows installers are only created for one flavor
447
#                           Don't need to worry about windoes installers
448
#                       Non windows installers are of the form:
449
#                           Name_Architecture_Type.deb    
450
#
451
# Inputs          : 
452
#
453
# Returns         : 
454
#
455
sub RemoveDuplicates
456
{
457
    my %baseNames;
458
    foreach my $file ( keys %bomList)
459
    {
460
        #
461
        #   Only process files that are of the expected form
462
        #       ie: erg-udcrypt_1.0.3043.vss_UBUNTU16_P.deb
463
        #
464
        if( $file =~ m~(.*)_([PD])(\.(deb|rpm|tgz))$~ )
465
        {
466
            my $base=$1;
467
            my $type=$2;
468
            my $suf=$3;
469
 
470
            if (exists $baseNames{$base} )
471
            {
472
                my $debugName = $base . '_D' . $suf;  
473
                Verbose("Remove debug installer: $file. Kill: $debugName");
474
                delete $bomList{$debugName};
475
            }
476
 
477
            $baseNames{$base} = $type;
478
        }
479
    }
480
}
481
 
482
#-------------------------------------------------------------------------------
483
# Function        : LoadFilterConfig  
484
#
485
# Description     : Load Filter Config
486
#                   Retain filter config for future reference 
487
#
488
# Inputs          : 
489
#
490
# Returns         : 
491
#
492
sub LoadFilterConfig
493
{
494
    if ( -f "$opt_rootdir/$CONFFILE" )
495
    {
496
        Message("Loading Config File");
6177 dpurdie 497
        my $perl_scalar = ReadJsonFile("$opt_rootdir/$CONFFILE");
6133 dpurdie 498
        Error ("Invalid format in Config file")
499
            unless (ref($perl_scalar->{filters}) eq 'ARRAY');
500
 
501
        push (@confFilters, @{$perl_scalar->{filters}});
502
        push (@confFiles, @{$perl_scalar->{keptfiles}}) if exists ($perl_scalar->{keptfiles});
503
    }
504
}
505
 
506
#-------------------------------------------------------------------------------
6177 dpurdie 507
# Function        : ReadJsonFile 
508
#
509
# Description     : Read a JSON file and return the data 
510
#
511
# Inputs          : $fname  - Name of the file to read 
512
#
513
# Returns         : Ref to the JSON 
514
#
515
sub ReadJsonFile
516
{
517
    my ($fname) = @_;
518
    local $/;
519
    open(my $fh, $fname ) || Error("Failed to open $fname. $!");
520
    my $json_text = <$fh>;
521
    my $perl_scalar = decode_json( $json_text );
522
    close($fh);
523
 
524
    return $perl_scalar;
525
}
526
 
527
#-------------------------------------------------------------------------------
528
# Function        : WriteJsonFile 
529
#
530
# Description     : Write data into a file as JSON
531
#
532
# Inputs          : $fname  - Name of file to write
533
#                   $data   - Ref to data to write 
534
#
535
# Returns         : Will not return on error
536
#
537
sub WriteJsonFile
538
{
539
    my ($fname, $data) = @_;
540
    FileCreate ($fname, to_json( $data, { ascii => 1, pretty => 1 }));
541
}
542
 
543
 
544
#-------------------------------------------------------------------------------
6133 dpurdie 545
# Function        : ProcessFilterArgs
546
#
547
# Description     : Process the filter based arguments 
548
#
549
# Inputs          : 
550
#
551
# Returns         : 
552
#
553
sub ProcessFilterArgs
554
{
555
    my $filterArgSeen;
556
    my $writeConf;
557
 
558
 
559
 
560
    if ( @opt_addFilters )
561
    {
562
        Message ("Adding command line filters to the release config file");
563
        foreach my $element (@opt_addFilters) {
564
            UniquePush (\@confFilters, $_ ) foreach  ( split(/,/, $element));
565
        }
566
        $writeConf = 1;
567
    }
568
 
569
    if ( @opt_delFilters )
570
    {
571
        Message ("Deleting command line filters to the release config file");
572
        foreach my $element (@opt_delFilters) {
573
            ArrayDelete (\@confFilters, $_ ) foreach  ( split(/,/, $element));
574
        }
575
        $writeConf = 1;
576
    }
577
 
578
    if ( @opt_addFiles )
579
    {
580
        Message ("Adding command line files to the release config file");
581
        foreach my $element (@opt_addFiles) {
582
            UniquePush (\@confFiles, $_ ) foreach  ( split(/,/, $element));
583
        }
584
        $writeConf = 1;
585
    }
586
 
587
    if ( @opt_delFiles )
588
    {
589
        Message ("Deleting command line files to the release config file");
590
        foreach my $element (@opt_delFiles) {
591
            ArrayDelete (\@confFiles, $_ ) foreach  ( split(/,/, $element));
592
        }
593
        $writeConf = 1;
594
    }
595
 
596
    #
597
    #   Save filter information
598
    #
599
    if ( $writeConf && ! defined($opt_test) )
600
    {
601
        Verbose ("Write config file");
602
 
603
        #
604
        #   Add known files
605
        #
6177 dpurdie 606
        UniquePush (\@confFiles, $CONFFILE, $BOMFILE, $MANIFEST, $TFVARS);
6133 dpurdie 607
 
608
        my $config;
609
        push @{$config->{filters}},@confFilters;
610
        push @{$config->{keptfiles}},@confFiles;
6177 dpurdie 611
        WriteJsonFile("$opt_rootdir/$CONFFILE",$config);
6133 dpurdie 612
    }
613
 
614
    #
615
    #   Display information to the user
616
    #
617
    if ($opt_showFilters)
618
    {
619
        Message ("Configured Filters",@confFilters );
620
        $filterArgSeen = 1;
621
    }
622
 
623
    if ($opt_showFiles)
624
    {
625
        Message ("Configured Files. Keep:",@confFiles );
626
        $filterArgSeen = 1;
627
    }
628
 
629
 
630
    #
631
    #   Terminate program on any filter operations
632
    #
633
    exit 0 if ( $writeConf || $filterArgSeen);
634
}
635
 
636
#-------------------------------------------------------------------------------
637
# Function        : WriteManifest 
638
#
639
# Description     : Save the filter config file if required
640
#
641
# Inputs          : 
642
#
643
# Returns         : 
644
#
645
sub WriteManifest
646
{
647
    return if defined($opt_test);
648
 
649
    #
650
    #   Create JSON metadata
651
    #
652
    Verbose ("Write JSON Manifest");
653
    my $jsonString = to_json( $bomInfo, { ascii => 1, pretty => 1, canonical => 1 } ); 
654
    FileCreate ($opt_rootdir . '/' . $MANIFEST, $jsonString);
655
 
656
    #
657
    #   Create Terraform data
658
    #       Note: Terraform variable cannot have a '.' in them
659
    #   
660
    my @tfData2;
661
 
662
    push @tfData2, "// Terraform variable definitions to map clean package name to full file name";
663
    push @tfData2, "variable vixFileName {";
664
    push @tfData2, "    type = \"map\"";
665
    push @tfData2, "    default = {" ;
666
 
6177 dpurdie 667
    foreach my $item ( sort keys %{$bomInfo->{files}} )
6133 dpurdie 668
    {
669
        push @tfData2, "        \"". $item  ."\" = \"" .$bomInfo->{files}{$item}{fullname} ."\"";
670
    }
671
 
672
    push @tfData2, "    }" ;
673
    push @tfData2, "}" ;
674
 
675
    FileCreate ($opt_rootdir . '/' . $TFVARS, @tfData2);
676
 
677
 
678
}
679
 
680
#-------------------------------------------------------------------------------
681
# Function        : GetReleaseInfo 
682
#
683
# Description     : Get Release Meta Data
684
#
685
# Inputs          : 
686
#
687
# Returns         : Will exit on error 
688
#
689
sub GetReleaseInfo
690
{
691
    my $m_sqlstr = "SELECT p.PROJ_ID, rt.rtag_id, p.PROJ_NAME, rt.RTAG_NAME" .
692
                    " FROM release_tags rt, PROJECTS p" .
693
                    " WHERE p.PROJ_ID = rt.PROJ_ID" .
694
                    " and rt.RTAG_ID = " . $opt_rtagid;
695
 
696
    my $sth = $DM_DB->prepare($m_sqlstr);
697
    if ( defined($sth) )
698
    {
699
        if ( $sth->execute( ) )
700
        {
701
            if ( $sth->rows )
702
            {
703
                while ( my ( $proj_id, $xx, $pname, $rname ) = $sth->fetchrow_array )
704
                {
705
                    my $data;
706
                    $data->{product_id} = $proj_id;
707
                    $data->{product_name} = $pname;
708
                    $data->{release_rtagid} = $opt_rtagid;
709
                    $data->{release_name} = $rname;
710
                    push @{$bomInfo->{release}}, $data;
711
                }
712
            }
713
            else
714
            {
715
                Error("GetReleaseInfo: No rtagid found for " . $opt_rtagid);
716
            }
717
            $sth->finish();
718
        }
719
        else
720
        {
721
            Error("GetReleaseInfo: Execute failure", $sth->errstr(), $m_sqlstr );
722
        }
723
    }
724
    else
725
    {
726
        Error("GetReleaseInfo: Prepare failure", $sth->errstr(), $m_sqlstr );
727
    }
728
}
729
 
730
#-------------------------------------------------------------------------------
731
# Function        : GetPackageData 
732
#
733
# Description     : Extract data from RM based on the provided rtag_id
734
#
735
# Inputs          : 
736
#
737
# Returns         : 
738
#
739
sub GetPackageData
740
{
6177 dpurdie 741
    my $m_sqlstr =  "SELECT p.PKG_NAME, " .
742
                    " pv.PKG_VERSION, " .
743
                    " l.name " .
744
                    "FROM package_versions pv, " .
745
                    " RELEASE_MANAGER.RELEASE_CONTENT rc, " .
746
                    " RELEASE_MANAGER.PACKAGES p, " .
747
                    " RELEASE_MANAGER.LICENCING pl, " .
748
                    " RELEASE_MANAGER.LICENCES l " .
749
                    "WHERE rc.rtag_id     = $opt_rtagid " .
750
                    " AND rc.pv_id         = pv.pv_id " .
751
                    " AND p.PKG_ID         = pv.pkg_id " .
752
                    " AND pv.IS_DEPLOYABLE = 'Y' " .
753
                    " AND pl.PV_ID(+)      = pv.pv_id " .
754
                    " AND pl.LICENCE       = l.LICENCE(+)" ;
6133 dpurdie 755
#                    " and ( pv.IS_DEPLOYABLE = 'Y' or upper( p.PKG_NAME) like 'ERG%' or upper( p.PKG_NAME) like 'VIX%' )";
756
 
6177 dpurdie 757
 
758
 
759
    my ( $PKG_NAME, $PKG_VERSION, $LICENSE );
6133 dpurdie 760
    my $sth = $DM_DB->prepare($m_sqlstr);
761
    if ( defined($sth) )
762
    {
763
        if ( $sth->execute( ) )
764
        {
765
            if ( $sth->rows )
766
            {
6177 dpurdie 767
                while ( ( $PKG_NAME, $PKG_VERSION, $LICENSE ) = $sth->fetchrow_array )
6133 dpurdie 768
                {
769
                    Verbose ("Deployable: $PKG_NAME, $PKG_VERSION");
770
                    my $pkgDir = "$ENV{GBE_DPKG}/$PKG_NAME";
771
                    my $srcDir = "$ENV{GBE_DPKG}/$PKG_NAME/$PKG_VERSION";
772
                    my $dstDir = $opt_rootdir;
773
 
774
                    if ( -d "$srcDir" )
775
                    {
776
                        my $foundFiltered = 0;
777
 
778
                        # for each of the filter rules we glob the rule in the src pkg/version dir
779
                        # and if any of the globbed files dont exist in the dst dir add it to the 
780
                        # the filelist array of files to copy
781
                        foreach my $filter ( @confFilters )
782
                        {
783
                            foreach my $srcPath ( glob("$srcDir/$filter") )
784
                            {
785
                                next unless ( -f $srcPath );
786
                                $foundFiltered = 1;
787
                                $filtersUsed{$filter} = 1;
788
                                my $dstFile = basename($srcPath);
789
                                my $srcFile = $srcPath;
790
                                $srcFile =~ s~^$srcDir/~~;
791
                                $bomList{$srcFile}{path} = $srcPath;
792
                                $bomList{$srcFile}{package} = $PKG_NAME;
793
                                $bomList{$srcFile}{version} = $PKG_VERSION;
6177 dpurdie 794
                                $bomList{$srcFile}{license} = $LICENSE || '';
6133 dpurdie 795
                            }
796
                        }
797
 
798
                        # if no files found using filters then issue warning
799
                        Warning("No Files found for Package Version $PKG_NAME/$PKG_VERSION using supplied filters") 
800
                            unless ( $foundFiltered );
801
 
802
                        if ($foundFiltered)
803
                        {
804
                            $bomInfo->{packages}{$PKG_NAME} = $PKG_VERSION;
805
                        }
806
                    }
807
                    elsif ( ! -d "$pkgDir" )
808
                    {
809
                        # if srcDir and pkgDir dont exist then package is not in dpkg_archive so display message
810
                        Warning("Skipping Package $PKG_NAME/$PKG_VERSION as it does not exist in dpkg_archive");
811
                    }
812
                    else
813
                    {
814
                        # However if srcDir does not exist but pkgDir does exist then the package version is missing which maybe an issue
815
                        Warning("Missing Version $PKG_VERSION for Package $PKG_NAME in dpkg_archive");
816
                    }
817
                }
818
 
819
                #
820
                #   Report filter elements that where not used.
821
                #
822
                my @notUsed;
823
                foreach my $filter ( @confFilters )
824
                {
825
                    next if ( exists $filtersUsed{$filter} );
826
                    push @notUsed, $filter
827
                }
828
                Warning ("Unused filter rules:", @notUsed )
829
                    if ( @notUsed );
830
 
831
            }
832
            else
833
            {
834
                Error("No Packages for rtagid: $opt_rtagid");
835
            }
836
            $sth->finish();
837
        }
838
        else
839
        {
840
            Error("Execute failure", $sth->errstr(), $m_sqlstr );
841
        }
842
    }
843
    else
844
    {
845
        Error("Prepare failure", $sth->errstr(), $m_sqlstr );
846
    }
6177 dpurdie 847
 
848
    #
849
    #   Report Commercial packages
850
    #   Write out a file to contain the list of COTS files
851
    #
852
    my @Commercial;
853
    foreach my $file (sort keys %bomList)
854
    {
855
        next unless ($bomList{$file}{license} =~ m ~^Commercial~);
856
        $bomList{$file}{cots} = 1;
857
        push @Commercial, $file;
858
    }
859
    Message ("Commercial software packages:", @Commercial);
860
    my $data;
861
    $data->{COTS} = \@Commercial;
862
    WriteJsonFile ("$opt_rootdir/$BOMFILE", $data);
6133 dpurdie 863
}
864
 
865
#-------------------------------------------------------------------------------
866
#   Documentation
867
#
868
 
869
=pod
870
 
871
=for htmltoc    DEPLOY::generate_deployable
872
 
873
=head1 NAME
874
 
875
jats_generate_deployable - Extracts current package version list from Release Manager RtagId
876
                and copy resultant packages to a specific directory.
877
 
878
=head1 SYNOPSIS
879
 
880
  jats generate_deployable [options]
881
 
882
 Options:
883
    -help                   - Brief help message
884
    -help -help             - Detailed help message
885
    -man                    - Full documentation
886
    -rtagid=xxx             - Specify the Release Manager RtagId to process
887
    -rootdir=xxx            - Specifies the root of the releases directory
888
 
889
    -showfilters            - Display current filter set and exit
890
    -addfilter=xxx[,yyy]    - Add a new filter to the existing filter set
891
    -delfilter=xxx[,yyy]    - Delete a filter from the existing filter set
892
 
893
    -showfiles              - Display current kept file set and exit
894
    -addfiles=xxx[,yyy]     - Add a new file to the kept file set
895
    -delfiles=xxx[,yyy]     - Delete a file from the kept file set
896
 
897
    -test                   - Just log actions without copying files.
898
    -verbose                - Enable verbose output
899
 
900
=head1 OPTIONS
901
 
902
=over 8
903
 
904
=item B<-help>
905
 
906
Print a brief help message and exits.
907
 
908
=item B<-help -help>
909
 
910
Print a detailed help message with an explanation for each option.
911
 
912
=item B<-man>
913
 
914
Prints the manual page and exits.
915
 
916
=item B<-rtagid=xxx>
917
 
918
This option specifies one or more RTAG_ID's to use as the source of packages that will be copied.
919
The ID will be used to get a unique list of package/versions that can be copied from dpkg_archive.
920
 
921
This option is Mandatory, for non-filter command.
922
 
923
=item B<-rootdir=xxx>
924
 
925
This option specifies the root directory where the packages will be copied to.
926
 
927
The specified directory must exist.
928
 
929
The default value is the current directory.
930
 
931
=item B<-showfilters>
932
 
933
This option will display the current filter set. If it is combined with another filter operation 
934
then the other operations will be performed before the display.
935
 
936
=item B<-addFilter=xxx[,yyy]>
937
 
938
This option allows new filters to be added to the set of filters. This
939
option can be specified multiple times.
940
 
941
This option specifies a comma separated list of shell wildcard filter rule that
942
will be used to determine which files are copied from package version directory in
943
GBE_DPKG to the release directory. This can be supplied multiple times to
944
specify rules for copying.
945
 
946
Filters must be added the first time this command is run against a release 
947
and packages are copied to the project/release directory.  These values are then written to a 
948
config file in the release directory so the same values can be used on subsequent runs.  
949
In these subsequent runs this option need not be specified as the config items will be used, however
950
they can be changed by specifying them again on the command line and the config will be re-written.
951
 
952
The values of these will depend on what builds are required for each project.  Some examples are
953
    --filter='*-WIN32.exe,*.deb'
954
 
955
=item B<-delFilter=xxx[,yyy]>
956
 
957
This option deletes one or more filter rules from an existing set of filters. This
958
option can be specified multiple times.
959
 
960
=item B<-showfiles>
961
 
962
This option will display the current file set. If it is combined with another file operations
963
then the other operations will be performed before the display.
964
 
965
=item B<-addFile=xxx[,yyy]>
966
 
967
This option allows new files to be added to the set of kept files. This
968
option can be specified multiple times.
969
 
970
This option specifies a comma separated list of file names (No wild cards) that
971
will be used to specify a list of files that shold be kept in the directory. These
972
files do not form a part of the manifest, but are not deleted by the tool.
973
 
974
=item B<-delFile=xxx[,yyy]>
975
 
976
This option deletes one or more files from the set of kept files. This
977
option can be specified multiple times.
978
 
979
=item B<-test>
980
 
981
This option will display what would be copied without actually copying anything
982
 
983
=item B<-verbose>
984
 
985
This option will display progress information as the program executes.
986
 
987
=back
988
 
989
=head1 DESCRIPTION
990
 
991
This program is used to update a Distribution 'bin' directory with the versions of
992
packages as indicated by the specified Deployment Manager SBoms.
993
 
994
There are two modes of operation: Filter modification operations and BOM creation.
995
 
996
In 'Filter modification' mode the current filter set will be updated and the program will
997
exit.
998
 
999
In BOM creation mode an sbomid must be provided.
1000
 
1001
The rtagid is used to get all the required information from Release Manager about
1002
which package version are required, as well as the project name and release name.
1003
 
1004
 
1005
In addition to using Release Manager information to determine which Package/Versions are
1006
required to be copied this script also uses a set of shell wildcard filters that are
1007
used to determine which files are actually copied when invoked.
1008
 
1009
The filter rules can be supplied on the command line if available read from a 
1010
configuration file saved in the output diretory the last time the script was run
1011
on this release directory.
1012
 
1013
One or more filter rules must be specified on the command line the first time this command 
1014
is run against a project release directory.  These filter values are then written to a config
1015
file in the output directory so the same values can be used on subsequent runs.  
1016
In subsequent runs the filter rules will be loaded from the config file and need not be specified 
1017
on the command line, however the filter rules in the config file can be changed by specifying 
1018
them again on the command line and the config will be re-written.
1019
 
1020
=cut
1021