#!/usr/bin/perl 
# 
# This program setups up the Alteeve repositories
# 

use strict;
use warnings;

# Catch signals for clean exits.
$SIG{INT}  = \&_catch_sig;
$SIG{TERM} = \&_catch_sig;

my $conf = {
	confirm => 0,
	debug   => 0, 
	key     => "",
	os_repo => "",
};

read_cla($conf);

detect_os($conf);

if ((not $conf->{key}) && (not $conf->{confirm}))
{
	print "\nYou have not specified an Enterprise repo key. This will enable the community\n";
	print "repository. We work quite hard to make it as stable as we possibly can, but it\n";
	print "does lead Enterprise. \n";
	print "Proceed? [y/N]: ";
	my $answer = <STDIN>;
	chomp $answer;
	if (($answer =~ /y/i) or ($answer =~ /yes/i))
	{
		print "- Proceeding!\n";
	}
	else
	{
		print "- Aborting. Please let us know if we can help; https://alteeve.com/w/Support\n";
	}
}

my $repo_body = "";
if ($conf->{key})
{
	$repo_body .= "[anvil-enterprise-".$conf->{os_repo}."]
name=Anvil Enterprise Repository (".$conf->{os_repo}.")
baseurl=https://www.alteeve.com/an-repo/m3/enterprise/".$conf->{os_repo}."/".$conf->{key}."/rpms";
}
else
{
	$repo_body .= "[anvil-community-".$conf->{os_repo}."]
name=Anvil Community Repository (".$conf->{os_repo}.")
baseurl=https://www.alteeve.com/an-repo/m3/community/".$conf->{os_repo}."/rpms";
}
$repo_body .= "
repo_gpgcheck=0
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Alteeve-Official
metadata_expire=24h

";
if ($conf->{key})
{
	$repo_body .= "[anvil-enterprise-".$conf->{os_repo}."-debuginfo]
name=Anvil Enterprise Repository (".$conf->{os_repo}.") - Debug
baseurl=https://www.alteeve.com/an-repo/m3/enterprise/".$conf->{os_repo}."/".$conf->{key}."/debuginfo";
}
else
{
	$repo_body .= "[anvil-community-".$conf->{os_repo}."-debuginfo]
name=Anvil Community Repository (".$conf->{os_repo}.") - Debug
baseurl=https://www.alteeve.com/an-repo/m3/community/".$conf->{os_repo}."/debuginfo";
}
$repo_body .= "
repo_gpgcheck=0
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Alteeve-Official
metadata_expire=24h

";
if ($conf->{key})
{
	$repo_body .= "[anvil-enterprise-".$conf->{os_repo}."-srpms]
name=Anvil Enterprise Repository (".$conf->{os_repo}.") - Sources
baseurl=https://www.alteeve.com/an-repo/m3/enterprise/".$conf->{os_repo}."/".$conf->{key}."/srpms";
}
else
{
	$repo_body .= "[anvil-community-".$conf->{os_repo}."-srpms]
name=Anvil Community Repository (".$conf->{os_repo}.") - Sources
baseurl=https://www.alteeve.com/an-repo/m3/community/".$conf->{os_repo}."/srpms";
}
$repo_body .= "
repo_gpgcheck=0
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Alteeve-Official
metadata_expire=24h
";

my $repo_file = "/etc/yum.repos.d/alteeve-anvil.repo";
if ($conf->{debug})
{
	print __LINE__."; [ Debug ] - Creating the repo: [".$repo_file."] with the body:\n";
	print __LINE__."; [ Debug ] - ====\n";
	print $repo_body;
	print __LINE__."; [ Debug ] - ====\n";
}

print "Writing: [".$repo_file."]...\n";
open(my $file_handle, ">", $repo_file) or die "Failed to write the file: [".$repo_file."]. The error was: [".$!."]\n";
print $file_handle $repo_body;
close $file_handle;

print "Repo: [".$conf->{os_repo}."] created successfuly.\n";

# Add / enable additional repos.
enable_repos($conf);


exit(0);


###############################################################################
# Here be functions.                                                          #
###############################################################################

sub enable_repos
{
	my ($conf) = @_;
	
	# Enable repos as needed.
	if ($conf->{os_repo} eq "rhel-8")
	{
		# Tell the user to enable repos once registered.
		print "\nThis is RHEL 8. Once subscribed, please enable this repo;\n";
		print "# subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms\n\n";
		print "NOTE: On *nodes*, also add the High-Availability Addon repo as well;\n";
		print "# subscription-manager repos --enable rhel-8-for-x86_64-highavailability-rpms\n\n";
	}
	if ($conf->{os_repo} eq "centos-8-stream")
	{
		# Tell the user to enable repos once registered.
		print "Enabling the 'ha' and 'powertools' repositories...\n";
		foreach my $repo ("powertools", "ha")
		{
			my $shell_call = "yum config-manager --set-enabled ".$repo;
			print __LINE__."; [ Debug ] - Calling: [$shell_call]...\n" if $conf->{debug};
			open (my $file_handle, $shell_call." 2>&1 |") or die "Failed to call: [".$shell_call."]. The error was: [".$!."]\n";
			while(<$file_handle>)
			{
				# This should not generate output.
				chomp;
				my $line = $_;
				print __LINE__."; [ Debug ] - Output: [$line]\n" if $conf->{debug};
			}
		}
	}
	if ($conf->{os_repo} eq "almalinux-9")
	{
		# Tell the user to enable repos once registered.
		print "Enabling the 'ha' and 'crb' repositories...\n";
		foreach my $repo ("crb", "highavailability")
		{
			my $shell_call = "dnf config-manager --set-enabled ".$repo;
			print __LINE__."; [ Debug ] - Calling: [$shell_call]...\n" if $conf->{debug};
			open (my $file_handle, $shell_call." 2>&1 |") or die "Failed to call: [".$shell_call."]. The error was: [".$!."]\n";
			while(<$file_handle>)
			{
				# This should not generate output.
				chomp;
				my $line = $_;
				print __LINE__."; [ Debug ] - Output: [$line]\n" if $conf->{debug};
			}
		}
	}
	
	return(0);
}

# This detects the OS type and major version.
sub detect_os
{
	my ($conf) = @_;
	
	my $os_id   = "";
	my $os_name = "";
	my $version = "";
	my $os_file = "/etc/os-release";
	print __LINE__."; [ Debug ] - Reading: [".$os_file."]\n" if $conf->{debug};
	open(my $file_handle, '<', $os_file) or die "Failed to read the OS release file: [".$os_file."], the error was: [".$!."]";
	while(<$file_handle>)
	{
		chomp;
		my $line = $_;
		print __LINE__."; [ Debug ] - line: [".$line."]\n" if $conf->{debug};
		
		if ($line =~ /^ID="(.*?)"$/)
		{
			$os_id = $1;
			print __LINE__."; [ Debug ] - os_id: [".$os_id."]\n" if $conf->{debug};
		}
		if ($line =~ /^NAME="(.*?)"$/)
		{
			$os_name = $1;
			print __LINE__."; [ Debug ] - os_name: [".$os_name."]\n" if $conf->{debug};
		}
		if ($line =~ /^VERSION_ID="(.*?)"$/)
		{
			$version = $1;
			print __LINE__."; [ Debug ] - >> version: [".$version."]\n" if $conf->{debug};
			$version =~ s/^(\d+)\..*/$1/;
			print __LINE__."; [ Debug ] - << version: [".$version."]\n" if $conf->{debug};
		}
	}
	close $file_handle;
	
	# Decide the OS name
	if (($os_id eq "centos") && ($os_name =~ /Stream/i))
	{
		# CentOS Stream
		$conf->{os_repo} = $os_id."-".$version."-stream";
		print __LINE__."; [ Debug ] - os_repo: [".$os_name."]\n" if $conf->{debug};
	}
	else
	{
		# RHEL, Alma, etc
		$conf->{os_repo} = $os_id."-".$version;
		print __LINE__."; [ Debug ] - os_repo: [".$os_name."]\n" if $conf->{debug};
	}
	
	return(0);
}

# This returns the 'help' message.
sub help
{
	my ($conf) = @_;
	
	my $THIS_FILE = ($0 =~ /^.*\/(.*)$/)[0];
	system("man ".$THIS_FILE);
	exit(0);
}

# Read in command line arguments
sub read_cla
{
	my ($conf) = @_;
	
	# Loop through the passed arguments, if any.
	my $set_next = "";
	foreach my $arg (@ARGV)
	{
		# If 'set_next' has a value, push this argument into the 'conf' hash.
		if ($set_next)
		{
			# Record the values.
			$conf->{$set_next} = $arg;
			print __LINE__."; [ Debug ] - '".$set_next."': [".$conf->{$set_next}."]\n" if $conf->{debug};
			
			# Clear it now for the next go-round.
			$set_next = "";
			next;
		}
		
		if ($arg =~ /-h/)
		{
			# Print the help message and then exit.
			help($conf);
		}
		elsif (($arg eq "-k") or ($arg eq "--key"))
		{
			# This is the action to take.
			$set_next = "key";
		}
		elsif (($arg eq "-d") or ($arg eq "--debug"))
		{
			# This is the action to take.
			$conf->{debug} = 1;
			print __LINE__."; [ Debug ] - debug output enabled.\n" if $conf->{debug};
		}
		elsif (($arg eq "-y") or ($arg eq "--yes"))
		{
			# This is the action to take.
			$conf->{confirm} = 1;
			print __LINE__."; [ Debug ] - Will not confirm community repo usage.\n" if $conf->{debug};
		}
		elsif (($arg eq "-h") or ($arg eq "-?") or ($arg eq "--help"))
		{
			help($conf);
		}
		else
		{
			# Bad argument.
			print "Argument: [".$arg."] is not valid arguments. Use '--help' for usage.\n";
			exit(1);
		}
	}
	
	return(0);
}

# Catch SIG, move zig!
sub _catch_sig
{
	my $signame = shift;
	
	print $0." process with PID ".$$." Exiting on SIG".$signame.".\n";
	exit(1);
}
