App-FargateStack

 view release on metacpan or  search on metacpan

lib/App/FargateStack/Builder/Utils.pm  view on Meta::CPAN

package App::FargateStack::Builder::Utils;

use strict;
use warnings;

BEGIN {
  use Log::Log4perl;
  # this register ths package as a wrapper class helps resolve
  # callstack issue when covering Log4perl methods.
  Log::Log4perl->wrapper_register(__PACKAGE__);
}

use Carp;
use Data::Dumper;
use Date::Parse qw(str2time);
use English qw(no_match_vars);
use JSON;
use List::Util qw(any none);
use Scalar::Util qw(blessed reftype refaddr looks_like_number);
use Term::ANSIColor;
use Time::Piece;
use Time::HiRes qw(time);
use Text::Diff;

use JSON;

use Role::Tiny;
use parent qw(Exporter Class::Accessor::Fast);

__PACKAGE__->follow_best_practice;
__PACKAGE__->mk_accessors(qw(_var_pool));

our @EXPORT = qw(
  ToCamelCase
  choose
  common_args
  confirm
  display_diffs
  dmp
  elapsed_time
  jmespath_mapping
  log_die
  normalize_name
  normalize_time_range
  normalize_timestamp
  toCamelCase
  slurp_file
  write_json_file
  fetch_acm
  fetch_cloudtrail
  fetch_application_autoscaling
  fetch_ecr
  fetch_ec2
  fetch_ecs
  fetch_ecr
  fetch_elbv2
  fetch_events
  fetch_efs
  fetch_iam
  fetch_logs
  fetch_secrets
  fetch_sts
  fetch_route53
  fetch_cli_api
  fetch_wafv2
);

########################################################################
sub fetch_application_autoscaling { return shift->fetch_cli_api( 'Application-Autoscaling', @_ ); }
sub fetch_acm                     { return shift->fetch_cli_api( 'ACM',                     @_ ); }
sub fetch_cloudtrail              { return shift->fetch_cli_api( 'CloudTrail',              @_ ); }
sub fetch_iam                     { return shift->fetch_cli_api( 'IAM',                     @_ ); }
sub fetch_logs                    { return shift->fetch_cli_api( 'Logs',                    @_ ); }
sub fetch_efs                     { return shift->fetch_cli_api( 'EFS',                     @_ ); }
sub fetch_ecs                     { return shift->fetch_cli_api( 'ECS',                     @_ ); }
sub fetch_ec2                     { return shift->fetch_cli_api( 'EC2',                     @_ ); }
sub fetch_ecr                     { return shift->fetch_cli_api( 'ECR',                     @_ ); }
sub fetch_events                  { return shift->fetch_cli_api( 'Events',                  @_ ); }
sub fetch_sts                     { return shift->fetch_cli_api( 'STS',                     @_ ); }

lib/App/FargateStack/Builder/Utils.pm  view on Meta::CPAN

  return $json ? decode_json($content) : $content;
}

########################################################################
sub section_break { return shift->get_logger->info( q{-} x 80 ) }
########################################################################

########################################################################
sub normalize_name {
########################################################################
  my ( $self, $name ) = @_;

  return join q{}, map {ucfirst} split /[_-]+/xsm, $name;
}

########################################################################
sub abbrev {
########################################################################
  my ( $text, $len, $offset ) = @_;
  $offset //= 0;
  $text   //= q{};

  return sprintf '%s...', substr $text, $offset, $len;
}

########################################################################
sub is_service_running {
########################################################################
  my ( $self, $task_name ) = @_;

  my ( $config, $cluster ) = $self->common_args(qw(config cluster));
  my $cluster_name = $cluster->{name};

  my $ecs = $self->fetch_ecs;

  my $services = $ecs->list_services( $cluster_name, 'serviceArns' );

  croak sprintf "ERROR: could not list services for: [%s]\n%s", $cluster_name, $ecs->get_error
    if !$services;

  return
    if none {/\/$task_name/xsm} @{$services};

  my $status = $ecs->describe_services(
    cluster_name => $cluster_name,
    service_name => $task_name,
    query        => 'services[0].runningCount'
  );

  croak sprintf "ERROR: could not describe services for: [%s/%s]\n%s", $cluster_name, $task_name, $ecs->get_error
    if !defined $status;

  return $status;
}

########################################################################
sub _log {
########################################################################
  my ( $logger, $level, @args ) = @_;

  # If first arg looks like a sprintf format string AND we have more args, call sprintf
  if ( @args > 1 && $args[0] =~ /%/xsm ) {
    return $logger->$level( sprintf shift(@args), @args );
  }
  else {
    return $logger->$level(@args);
  }
}

sub log_info  { return _log( shift->get_logger, 'info',  @_ ) }
sub log_debug { return _log( shift->get_logger, 'debug', @_ ) }
sub log_warn  { return _log( shift->get_logger, 'warn',  @_ ) }
sub log_error { return _log( shift->get_logger, 'error', @_ ) }
sub log_die   { _log( shift->get_logger, 'error', @_ ); die q{}; }
sub log_trace { return _log( shift->get_logger, 'trace', @_ ) }
sub log_fatal { return _log( shift->get_logger, 'fatal', @_ ) }

########################################################################
sub normalize_timestamp {
########################################################################
  my ($ts) = @_;

  return
    if !$ts;

  # Already epoch?
  return int $ts        if $ts =~ /^\d{10}$/xsm;  # seconds
  return int $ts / 1000 if $ts =~ /^\d{13}$/xsm;  # millis

  my $s = "$ts";

  # Common cleanups:
  $s =~ s/,//xsmg;                                # "Aug 12, 2025, 4:55:04 PM" -> "Aug 12 2025 4:55:04 PM"
  $s =~ s/Z$/+0000/xsm;                           # ISO8601Z -> explicit offset
  $s =~ s/([+\-]\d\d):(\d\d)$/$1$2/xsm;           # "+05:30" -> "+0530"
  $s =~ s/[.]\d+(?=(?:Z|[+\-]\d\d:?\d\d)$)//xsm;  # strip fractional seconds if present

  # Some services append " UTC" or similar—strip trailing timezone words
  $s =~ s/\s+UTC$//xsmi;

  my $epoch = str2time($s);

  die "unrecognized timestamp: [$ts]"
    if !defined $epoch;

  return int $epoch;
}

use Readonly;

Readonly::Scalar our $SEC_PER_MIN  => 60;
Readonly::Scalar our $SEC_PER_HOUR => 60 * $SEC_PER_MIN;
Readonly::Scalar our $SEC_PER_DAY  => 24 * $SEC_PER_HOUR;

########################################################################
sub normalize_time_range {
########################################################################
  my ( $start, $end ) = @_;

  return
    if !$start;



( run in 0.797 second using v1.01-cache-2.11-cpan-39bf76dae61 )