#!/usr/bin/env perl # Daniel Bowling # Feb 2020 use strict; use warnings; use Getopt::Long qw(:config no_ignore_case); use Akamai::Edgegrid; use Mozilla::CA; # Lest ye return SSL trust errors use JSON; use open qw(:std :utf8); # Fix "Wide character in print" warning #use Data::Dumper; # For debugging (uncomment as needed) # Parse options GetOptions( 'account-switch-key|a=s' => \my $acctSwKey, 'contract-id|c=s' => \my $ctrId, 'dry-run|D' => \my $dryRun, 'delimiter|d=s' => \my $sep, 'group-id|g=s' => \my $grpId, 'header|H' => \my $head, 'help|h' => \my $help, 'property-version|P=i' => \my $prpVer, 'property-id|p=s' => \my $prpId, 'version|V' => \my $ver, 'verbose|v' => \my $verb ); ## Let's set some variables... ## # Set delimiter default if none specified $sep = "\t" if ! $sep; # Query strings my $acctSwKeyQS = "accountSwitchKey=$acctSwKey" if $acctSwKey; my $ctrIdQS = "contractId=$ctrId" if $ctrId; my $grpIdQS = "groupId=$grpId" if $grpId; my $prpIdQS = "propertyId=$prpId" if $prpId; my $dryRunQS = "dryRun=false"; $dryRunQS = "dryRun=true" if $dryRun; # For request method my $method; # For input file my @input; ## Print some info and exit since this won't require API calls... ## # Version info option if ($ver) { $ver = '0.09'; print "$ver\n"; exit; } # Print help if no request method specified if (! $ARGV[0]) { print "Usage: $0 GET|PUT|HEAD|PATCH \n\n"; die <<'OPTIONS'; Print or commit delivery configuration JSON rule tree(s) via PAPI. -a, --account-switch-key=KEY Specify account switch key -c, --contract-id=ID Specify contract ID -D, --dry-run Dry run (make no real changes) -d, --delimiter=DELIM Change delimiting character (default is TAB) -g, --group-id=ID Specify group ID -H, --header Print header with output -h, --help Print this help message -P, --property-version=NUM Specify property version -p, --property-id=ID Specify property ID -V, --version Print version -v, --verbose Print more verbose output OPTIONS } else { $method = lc($ARGV[0]) # Make lower-case } # Set input file if ($ARGV[1]) { # Declare variables for this bit my ($n, $fh, $line); # In a loop to handle multiple files $n = 1; until (! $ARGV[$n]) { open($fh, '<:encoding(UTF-8)', $ARGV[$n]) || die; while ($line = <$fh>) { push(@input, $line) } ++$n; } } elsif (! -t STDIN) { chomp(@input = ); } ## Set some things up for the request... ## # Set options for request my $agent = Akamai::Edgegrid->new( config_file => "$ENV{HOME}/.edgerc", section => "default", max_body => "131072" # Defaults to 2048 unless specified ); # Set base URL for request my $baseurl = "https://" . $agent->{host}; ## Functions defined... ## # Variables declared for the functions my ($response, $status, $rules, $body, $headers); # Define function to get rule tree sub get_rules { # Make request for rule tree if ($acctSwKey) { $response = $agent->get( "$baseurl/papi/v1/properties/$prpId/versions/$prpVer/rules?" . "$acctSwKeyQS&$ctrIdQS&$grpIdQS" ); } else { $response = $agent->get( "$baseurl/papi/v1/properties/$prpId/versions/$prpVer/rules?" . "$ctrIdQS&$grpIdQS" ); } $status = $response->status_line; # HTTP status code $rules = $response->content; # Rule tree if ($verb) { return $rules . "\n" . $status # Verbose output if -v } else { return $rules # Just the rule tree } } # Define function to head rule tree sub head_rules { # Make request for rule tree if ($acctSwKey) { $response = $agent->head( "$baseurl/papi/v1/properties/$prpId/versions/$prpVer/rules?" . "$acctSwKeyQS&$ctrIdQS&$grpIdQS" ); } else { $response = $agent->head( "$baseurl/papi/v1/properties/$prpId/versions/$prpVer/rules?" . "$ctrIdQS&$grpIdQS" ); } $headers = $response->headers_as_string; return $headers; } # Define function to upload rule tree sub put_rules { # Request body $body = "@_"; # Make request for rule tree if ($acctSwKey) { $response = $agent->put( "$baseurl/papi/v1/properties/$prpId/versions/$prpVer/rules?" . "$acctSwKeyQS&$ctrIdQS&$grpIdQS&validateRules=true&$dryRunQS", "Content-Type" => "application/json", "Content" => $body ); } else { $response = $agent->put( "$baseurl/papi/v1/properties/$prpId/versions/$prpVer/rules?" . "$ctrIdQS&$grpIdQS&validateRules=true&$dryRunQS", "Content-Type" => "application/json", "Content" => $body ); } $status = $response->status_line; # HTTP status code $rules = $response->content; # Rule tree if ($verb) { return $rules . "\n" . $status # Verbose output if -v } else { return $status # Just the status code } } # Define function to patch rule tree sub patch_rules { # Request body $body = @_; # Make request for rule tree if ($acctSwKey) { $response = $agent->patch( "$baseurl/papi/v1/properties/$prpId/versions/$prpVer/rules?" . "$acctSwKeyQS&$ctrIdQS&$grpIdQS&validateRules=true&$dryRunQS", "Content-Type" => "application/json-patch+json", "Content" => $body ); } else { $response = $agent->patch( "$baseurl/papi/v1/properties/$prpId/versions/$prpVer/rules?" . "$ctrIdQS&$grpIdQS&validateRules=true&$dryRunQS", "Content-Type" => "application/json-patch+json", "Content" => $body ); } $status = $response->status_line; # HTTP status code $rules = $response->content; # Rule tree if ($verb) { return $rules . "\n" . $status # Verbose output if -v } else { return $status # Just the status code } } ## Begin the information gathering/API calling bits... ## # Print list of contracts if none specified if (! $ctrId) { # Make request for contracts if ($acctSwKey) { $response = $agent->get( "$baseurl/papi/v1/contracts?$acctSwKeyQS" ); } else { $response = $agent->get( "$baseurl/papi/v1/contracts" ); } my $ctrs = decode_json($response->content); # Parse the returned JSON # Print header if -H if ($head) { print "contractId"; print $sep . "contractTypeName" if $verb; print "\n"; } # Print contracts my $n = 0; until (! $ctrs->{contracts}{items}[$n]{contractId}) { print $ctrs->{contracts}{items}[$n]{contractId}; if ($verb) { print "$sep" . $ctrs->{contracts}{items}[$n]{contractTypeName} } print "\n"; ++$n; } exit; } # Print list of groups if none specified if (! $grpId) { # Make request for groups if ($acctSwKey) { $response = $agent->get( "$baseurl/papi/v1/groups?$acctSwKeyQS" ); } else { $response = $agent->get( "$baseurl/papi/v1/groups" ); } my $grps = decode_json($response->content); # Parse the returned JSON # Print header if -H if ($head) { print "groupId" . $sep . "groupName"; print $sep . "parentGroupId" if $verb; print "\n"; } # Print groups my $n = 0; until (! $grps->{groups}{items}[$n]{groupId}) { print $grps->{groups}{items}[$n]{groupId} . "$sep" . $grps->{groups}{items}[$n]{groupName}; # Groups may not have parents; print if they do AND verbose flag set if ($grps->{groups}{items}[$n]{parentGroupId} && $verb) { print $sep . $grps->{groups}{items}[$n]{parentGroupId} } print "\n"; ++$n; } exit; } # Print list of properties if none specified if (! $prpId) { # Make request for properties if ($acctSwKey) { $response = $agent->get( "$baseurl/papi/v1/properties?$acctSwKeyQS&$ctrIdQS&$grpIdQS" ); } else { $response = $agent->get( "$baseurl/papi/v1/properties?$ctrIdQS&$grpIdQS" ); } my $prps = decode_json($response->content); # Parse the returned JSON # Print header if -H if ($head) { print "propertyId" . $sep . "propertyName"; print $sep . "latestVersion" if $verb; print "\n"; } # Print properties my $n = 0; until (! $prps->{properties}{items}[$n]{propertyId}) { print $prps->{properties}{items}[$n]{propertyId} . "$sep" . $prps->{properties}{items}[$n]{propertyName}; if ($verb) { print $sep . $prps->{properties}{items}[$n]{latestVersion}; } print "\n"; ++$n; } exit; } # Print list of property versions if none specified if (! $prpVer) { # Make request for property versions if ($acctSwKey) { $response = $agent->get( "$baseurl/papi/v1/properties/$prpId/versions?$acctSwKeyQS&" . "$ctrIdQS&$grpIdQS" ); } else { $response = $agent->get( "$baseurl/papi/v1/properties/$prpId/versions?$ctrIdQS&$grpIdQS" ); } my $versions = decode_json($response->content); # Parse the returned JSON # Print header if -H if ($head) { print "propertyVersion" . $sep . "updatedDate" . $sep. "updatedByUser"; print $sep . "note" if $verb; print "\n"; } # Print property versions my $n = 0; until (! $versions->{versions}{items}[$n]{propertyVersion}) { print $versions->{versions}{items}[$n]{propertyVersion} . "$sep" . $versions->{versions}{items}[$n]{updatedDate} . "$sep" . $versions->{versions}{items}[$n]{updatedByUser}; # Notes don't always exist; print if they do AND verbose flag set if ($versions->{versions}{items}[$n]{note} && $verb) { print $sep . $versions->{versions}{items}[$n]{note} } print "\n"; ++$n; } exit; } ## If we've made it this far then we have enough info to dig in... ## # Begin request for rule tree print get_rules() if $method eq "get"; print head_rules() if $method eq "head"; print put_rules(@input) . "\n" if $method eq "put"; print patch_rules(@input) . "\n" if $method eq "patch";