Note:
- This tutorial requires access to Oracle Cloud. To sign up for a free account, see Get started with Oracle Cloud Infrastructure Free Tier.
- It uses example values for Oracle Cloud Infrastructure credentials, tenancy, and compartments. When completing your lab, substitute these values with ones specific to your cloud environment.
Automate Patching for Apache Tomcat or a Third-Party Technology with OCI Fleet Application Management
Introduction
Oracle Cloud Infrastructure (OCI) Fleet Application Management service enables IT teams to automate software discovery and patch operations for any software deployed in OCI. The service provides prebuilt runbooks for discovering and patching Oracle technologies, including Oracle WebLogic Server, Oracle Linux, and more. Also, the custom runbooks and Bring Your Own Product capabilities enable you to define your product or technologies to be automatically discovered and patched by the service.
In this tutorial, we are using Apache Tomcat as an example of a popular third-party technology you might often need to patch. The following sections provide step-by-step instructions and reusable code samples to guide you on adding Apache Tomcat to be automatically discovered and applying patches using OCI Fleet Application Management. You can use the same process for any third-party product you want to patch with the service.
Note: We are describing the process using the OCI Console, but you can also use the Oracle Cloud Infrastructure Command Line Interface (OCI CLI) or API. For information about OCI Fleet Application Management, see Fleet Application Management.
Get Started with Patching Apache Tomcat
The Bring Your Own Product capability facilitates the integration of new products within OCI Fleet Application Management, such as third-party software, technologies, or application components. This capability enables the centralization of patch compliance and other lifecycle operations across these various components by using the service.
Using Bring Your Own Product capability, you will first create your custom product in the service along with its compliance policy, and available patches. Next, using custom runbooks, you will create both the discovery and the patching runbooks, enabling you to automate compliance management moving forward.
Objectives
- Automate patching for Apache Tomcat or a third-party technology with OCI Fleet Application Management.
Task 1: Create a Product
-
Log in to the OCI Console, navigate to Observability & Management, and select Fleet Application Management.
-
Click Administration.
-
Under Metadata management, click Products and Create product.
-
Enter the following information for the new product.
- Product Name: Enter the product name, avoiding any confidential information such as keys, and so on.
- Version(s): Enter the version.
- Patch Types (Optional): Select the patch type.
- Compatible products (Optional): Add compatible products.
- Components (Optional): Select components.
- Credential names (Optional): Select the credential name.
Task 2: Define a Patch Compliance Policy Rule
A software patch compliance policy is created automatically for each new product. The default policy does not contain any policy rules. You can edit the policy to add rules to specify the condition to evaluate if a specific target is compliant (if true) or non-compliant (else). You can use various product attributes to define the rules, such as product version, patch type, patch severity, patch selection criteria, and grace period. The patch compliance status is reported as indeterminate if you do not create policy rules.
-
Go to the OCI Console, navigate to Administration, and click Compliance Policy.
-
Select the compliance policy of the product you need to modify. (Syntax: Product name Compliance Policy).
-
Click Create policy rule.
-
Enter the product version and other attributes to be used in the condition.
For example, the policy rules can have the following definition:
- Rule name: Enter
Apache Tomcat
. - Product Version: Select 10.1 and above.
- Patch type: Select Critical Patch.
- Severity: Select CriticalPatch.
- Patch selection: Select Patch Level.
- Rule name: Enter
Task 3: Create Patch Metadata and Upload the Patch
Create the patch metadata to make future patching easier for the product you have added. You should then upload the available patches to OCI Object Storage. Depending on the technology and the types of available patches for your new product, you can upload a generic patch or specific packages for different operating system configurations.
-
Go to the OCI Console, navigate to Fleet Application Management, click Lifecycle Management, then Patches.
-
Click Upload Patch.
-
Enter the following information.
- Patch name: Enter a name.
- Product: Select a product.
- Severity: Select a severity.
- Select Dependent patches to specify the dependent patches that will be patched along with the current patch. For example, in case of Apache Tomcat, the following patch can be downloaded as
apache-tomcat-10.1.25.tar.gz
from here: Central Repository: org/apache/tomcat/tomcat/10.1.25.
Task 4: Create a Discovery Runbook for a Product
The service uses a discovery runbook to identify the software and version of the added product. For example, in the case of Apache Tomcat, the runbook script in Python for discovering and gathering details about Apache Tomcat instances on a system can be as follows:
Tasks in the Discovery Runbook Script
The script performs the following tasks:
- Scans the filesystem to locate Apache Tomcat instances.
- Method (
_get_all_tomcats()
): Locates Apache Tomcat instances.- Uses the find command to search the filesystem for directories named webapps, which is characteristic of Apache Tomcat installations.
- Removes the
/webapps
suffix to get the root of the Apache Tomcat path. - Filters out paths containing backup to avoid redundant or irrelevant results.
- Output: Returns a list of Apache Tomcat installation paths.
- Extracts version details and metadata for each instance.
- Builds a detailed instance dictionary for an Apache Tomcat instance.
- Discovers and aggregates all Apache Tomcat instances.
- Collects information about the associated Java environment.
- Returns all data in JSON format that you can use for reporting or further processing.
- Handles errors.
Breakdown of Key Tasks
-
Locate Apache Tomcat Instances.
-
Extract Apache Tomcat version details.
- Method (
_get_details(path)
):- Runs the
version.sh
script in the bin directory of each of the Apache Tomcat path. - Parses the output to extract key details (for example, version number) into a dictionary.
- Handles errors: Any exceptions during the execution or parsing are silently ignored.
- Runs the
- Output: Returns a dictionary of Apache Tomcat metadata (for example, server number).
- Method (
-
Retrieve file modification timestamp.
- Method
_get_timestamp(file_path)
:- Checks if a given file exists and retrieves its last modification time.
- Formats the timestamp in
dd-MMM-yyyy
HH:mm:ss
format.
- Output: Returns the formatted timestamp.
- Method
-
Gather Java environment details.
- Method
_get_java_details()
:- Uses system commands to fetch Java version and Java home path.
- Java version: Obtained with
java -version
. - Java home path: Extracted from the java runtime properties.
- Java version: Obtained with
- Uses system commands to fetch Java version and Java home path.
- Output: Returns a dictionary with
java_version
andjava_home
.
- Method
-
Build a detailed instance dictionary.
- Method
_instance(path)
:- Constructs a dictionary representing a single Apache Tomcat instance.
- Product details: Name, version, target path, and so on.
- Installed patches: Includes version and last modified date of the directory.
- Java properties: Includes
java_version
andjava_home
.
- Constructs a dictionary representing a single Apache Tomcat instance.
- Output: Returns a structured dictionary for the Apache Tomcat instance.
- Method
-
Discover and aggregate all instances.
- Method
_discovery_tomcat()
:- Calls
_get_all_tomcats()
to find Apache Tomcat paths. - Iterates over each path and calls
_instance(path)
to gather details. - Aggregates all instances into a targets list.
- Calls
- Output: Returns a dictionary with all discovered targets.
- Method
-
Generate output.
- Writes the discovered Apache Tomcat details to a JSON file.
- Location:
/opt/fams/.scripts/tomcat_discovery.json
. - Format: Pretty-printed JSON.
- Location:
- Also prints the JSON object to the console for immediate visibility.
- Writes the discovered Apache Tomcat details to a JSON file.
Script Flow
-
Locate Apache Tomcat instances: The
_get_all_tomcats()
method scans the filesystem. -
Retrieve details for each instance: The
_get_details()
and_instance()
methods extract relevant metadata. -
Collect Java details: The
_get_java_details()
method fetches the Java environment properties. -
Aggregate data: The
_discovery_tomcat()
method combines the information for all instances. -
Generate output: The results are saved in JSON format and printed.
Example Output:
{ "targets": [ { "product": "Tomcat", "version": "9.0", "target\_name": "/usr/local/tomcat", "resource\_name": "", "components": [], "available\_patches": [], "installed\_patches": [ { "patch\_name": "9.0.50", "patch\_applied\_dt": "19-Nov-2024 12:45:30", "patch\_description": "", "patch\_type": "", "severity": "" } ], "properties": [ { "property\_name": "java\_home", "property\_value": "/usr/lib/jvm/java-11-openjdk" }, { "property\_name": "java\_version", "property\_value": "11" } ] } ] }
-
Error handling:
- Silent failure for most exceptions (for example, missing files, command errors).
- This approach prevents the script from terminating prematurely but might obscure errors during execution.
Example: Apache Tomcat Discovery Script in Python
import json
import os
import subprocess
import datetime
class TOMCAT:
def \_get\_all\_tomcats(self):
command = ['find', '/', '-type', 'd', '-name', 'webapps']
sp = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
tomcat\_paths = sp.stdout.decode("utf-8").strip().replace('/webapps', '').split('\n')
tomcat\_paths=[path for path in tomcat\_paths if not 'backup' in path]
return tomcat\_paths
def \_get\_details(self, path):
tomcat\_details = dict()
try:
command = f'{path}/bin/version.sh'
sp = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = sp.communicate(timeout=10)
info\_list = stdout.decode("utf-8")
for line in info\_list.splitlines():
if ':' in line:
key, value = line.split(':', 1)
tomcat\_details[key.strip()] = value.strip()
return tomcat\_details
except Exception as E:
pass
def \_get\_timestamp(self, file\_path):
if os.path.exists(file\_path):
timestamp = os.path.getmtime(file\_path)
modified\_date = datetime.datetime.fromtimestamp(timestamp).strftime("%d-%b-%Y %H:%M:%S %z")
return modified\_date
def \_get\_java\_details(self):
try:
java\_details = dict()
command = "java -version 2>&1 | head -n 1"
sp = subprocess.run(command, shell=True, stdout=subprocess.PIPE)
java\_version = sp.stdout.decode("utf-8").split('"')[1]
# Getting Java Home
command = "java -XshowSettings:properties -version 2>&1 | sed '/^[[:space:]]\*java\.home/!d;s/^[[:space:]]\*java\.home[[:space:]]\*=[[:space:]]\*//'"
sp = subprocess.run(command, shell=True, stdout=subprocess.PIPE)
java\_home = sp.stdout.decode("utf-8").replace("\n", '')
java\_details['java\_home'] = java\_home
java\_details['java\_version'] = java\_version.split('\_')[0]
return java\_details
except Exception as E:
pass
def \_instance(self, path):
properties = []
tomcat\_details = self.\_get\_details(path)
instance = {"product": "Tomcat"}
instance.update({"version": '.'.join(tomcat\_details['Server number'].split('.')[:2])})
instance.update({"target\_name": path})
instance.update({"resource\_name": ""})
instance.update({"components": []})
instance.update({"available\_patches": []})
installed\_patches = [
{
"patch\_name": tomcat\_details['Server number'],
"patch\_applied\_dt": self.\_get\_timestamp(path),
"patch\_description": "",
"patch\_type": "",
"severity": ""
}
]
instance.update({"installed\_patches": installed\_patches})
for key, value in self.\_get\_java\_details().items():
properties.append({"property\_name": key, "property\_value": value})
instance.update({"properties": properties})
return instance
def \_discovery\_tomcat(self):
targets = []
tomcat\_paths = self.\_get\_all\_tomcats()
for path in tomcat\_paths:
instances = targets.append(self.\_instance(path))
discovery\_output = ({"targets": targets})
return discovery\_output
if \_\_name\_\_ == "\_\_main\_\_":
SCRIPTS\_DIR = "/opt/fams/.scripts"
os.makedirs(SCRIPTS\_DIR, exist\_ok=True)
tomcat = TOMCAT()
tomcat\_output = tomcat.\_discovery\_tomcat()
json\_obj = json.dumps(tomcat\_output, indent=4)
print(json\_obj)
with open("{}/tomcat\_discovery.json".format(SCRIPTS\_DIR), 'wb') as outfile:
outfile.write(json\_obj.encode())
After handling all errors, the products are associated with a fleet or several fleets to automate discovery and operations. Once a product is on the list of allowed users for a fleet, its default discovery runbook will automatically find and update the software inventory with targets of the deployed product across all managed resources.
To create a runbook, follow the steps:
-
Go to the OCI Console, navigate to Fleet Application Management, and click Actions and Controls.
-
Click Runbooks and Create runbook.
-
Enter Name, Description, Lifecycle operation, Runbook type, and select Operating System (OS) type and Estimated completion time.
-
Create your runbook by using the visual designer, upload a YAML or JSON file, or reference your existing automation script through Bash or Python script tasks within the runbook. For example, the sample provided is a runbook to discover Apache Tomcat.
-
For runbooks of type discovery, select Mark this as discovery output task to allow the service to read and parse the output of the task to populate the software inventory.
Note: The service can parse the output only if the format of the output is based on the discovery output template.
The following is the JSON output (
runbook\_Apache Tomcat\_discovery.json
) for the product.{ "id": "ocid1.famsrunbook.oc1.eu-frankfurt-1.xxxxxxxx", "displayName": "Apache Tomcat\_discovery", "description": null, "type": "USER\_DEFINED", "runbookRelevance": "PRODUCT", "operation": "DISCOVERY", "osType": "LINUX", "platform": "Apache Tomcat", "isDefault": false, "estimatedTime": "1", "lifecycleState": "INACTIVE", "lifecycleDetails": "{\"subState\":\"DRAFT\",\"message\":\"Draft runbook\"}", "timeCreated": "2024-11-19T13:03:20.376Z", "timeUpdated": "2024-11-19T13:03:20.376Z", "associations": { "tasks": [ { "stepName": "Apache\_Tomcat\_discovery\_task", "associationType": "TASK", "taskRecordDetails": { "scope": "LOCAL", "executionDetails": { "executionType": "SCRIPT", "variables": null, "content": { "sourceType": "OBJECT\_STORAGE\_BUCKET", "namespaceName": "xxxxxx", "namespaceName": "xxxxxx", "bucketName": "demo\_bucket", "objectName": "apache\_tomcat\_discovery\_demo.zip", "checksum": "xxxxxxxxxxxxx" }, "command": "unzip -o -q apache\_tomcat\_discovery\_demo.zip; chmod +x apache\_tomcat\_discovery.py ; python apache\_tomcat\_discovery.py", "credentials": [] }, "description": null, "platform": "Apache Tomcat", "isCopyToLibraryEnabled": false, "osType": "LINUX", "properties": { "numRetries": 0, "timeoutInSeconds": 3000 }, "isDiscoveryOutputTask": true, "isApplySubjectTask": false, "name": "Apache Tomcat\_discovery\_task" }, "stepProperties": { "runOn": null, "condition": null, "actionOnFailure": "ABORT", "pauseDetails": null, "notificationPreferences": null }, "outputVariableMappings": [] } ], "groups": [ { "type": "PARALLEL\_RESOURCE\_GROUP", "name": "Parallel\_resource\_container", "properties": { "runOn": null, "condition": null, "actionOnFailure": "ABORT", "pauseDetails": null, "notificationPreferences": null } } ], "executionWorkflowDetails": { "workflow": [ { "groupName": "Parallel\_resource\_container", "type": "PARALLEL\_RESOURCE\_GROUP", "steps": [ { "type": "TASK", "stepName": "Apache\_Tomcat\_discovery\_task" } ] } ] }, "rollbackWorkflowDetails": null, "version": "1.0" }, "compartmentId": "xxxxxx", "region": "xxxxxxx", "freeformTags": {}, "definedTags": { "Oracle-Tags": { "CreatedBy": "xxxxxx", "CreatedOn": "2024-11-08T15:48:59.329Z" } }, "systemTags": {} }
-
Add more tasks to customize your runbook as needed.
Task 5: Create a Runbook for Applying a Patch
Refer to Task 4 to create a custom runbook with your patching sequence.
After creating a product with its available patches and default discovery logic, you can now create a runbook for patching that includes the automation sequence specific to this technology and your organization’s IT process. Then, you will define a maintenance schedule to define when the runbook would be triggered to patch non-compliant targets that are identified in your fleet.
The Bash script (apache_tomcat_patching.sh
) that automates the process of upgrading an Apache Tomcat installation is as follows. Also, you can find the tasks associated with the script.
-
Initialize Variables
target_path
: This extract from atarget.json
file in theDATA_DIR
directory usingjq
.patches_file
: This variable can be used to dynamically identifies the latestpatches.json
file in the system.patch_url
: This specifies the directory for patches (/opt/fams/wls_patch
).
-
Display and Parse Patch Details: Read the content of the
patches.json
file for the following:- To extract the required patch version (
required_version
). - To determines the filename of the patch (
file_name
).
- To extract the required patch version (
-
Check Required Files
apache_tomcat_functions.sh
:- Ensure the presence of a helper script (
apache_tomcat_functions.sh
). - If the file is missing, the script exits with an error.
- Ensure the presence of a helper script (
- Target Path Validation:
- Verify that the
target_path
directory exists. - If it does not exist, the script exits with an error.
- Verify that the
-
Check the Current Version: Run Apache Tomcat’s
version.sh
script to fetch the currently installed version (curr_version
). -
Prepare for an Upgrade
- Back up Existing Installation: Call
create_backup
to back up the existing Apache Tomcat installation. - Stop Tomcat: Stop Apache Tomcat using a function (
stop_tomcat
).
- Back up Existing Installation: Call
-
Upgrade Apache Tomcat Installation
- Extract a New Version: Extract the new Apache Tomcat package (
file_name
) into the target directory. - Copy Configuration Files:
- Copy critical files (for example, configuration, logs) from the old installation to a new one by using
copy_main_files
. - Handle errors during this step by restoring the backup.
- Copy critical files (for example, configuration, logs) from the old installation to a new one by using
- Rename and Finalize: Rename the new directory to replace the old installation directory.
- Extract a New Version: Extract the new Apache Tomcat package (
-
Validate and Restart
- Verify the Upgrade: Check the upgraded version by running
version.sh
again. - Restart Apache Tomcat: Start Apache Tomcat using
start_tomcat
.
- Verify the Upgrade: Check the upgraded version by running
-
Handle Error
- Provide meaningful error messages at various stages (for example, missing files, directory not found, upgrade failures).
- Roll back changes if critical operations fail (for example, copying files or renaming directories).
Key Functions Used Are:
stop_tomcat
: Stops the Tomcat service.create_backup
: Creates a backup of the existing Tomcat directory.copy_main_files
: Transfers necessary files from the old installation to the new one.start_tomcat
: Starts the upgraded Tomcat service.
What Does It Accomplish?
The script provides a structured and automated approach for upgrading an Apache Tomcat instance, minimizing downtime, and ensuring a rollback mechanism in case of a failure. It relies on the predefined functions (apache_tomcat_functions.sh
) to manage tasks such as stopping or starting Apache Tomcat and file handling.
The following is the sample Bash (apache\_tomcat\_patching.sh
) script with the methods for applying patches.
\#
target\_path=$(cat ${DATA\_DIR}/target.json | jq -r '.target.target\_name')
patches\_file="$(find / -type f -name 'patches.json' | tail -1)"
patch\_url=/opt/fams/wls\_patch
\#
echo "Details of patches.json from path $patches\_file"
cat $patches\_file
required\_version=$(jq -r '.patches[0].name' $patches\_file)
file\_name=$(jq -r '.patches[0].location.object\_name' $patches\_file)
echo "Checking for tomcat\_functions.sh file "
if [ -f ./apache\_tomcat\_functions.sh ]; then
source ./apache\_tomcat\_functions.sh
echo -e "apache\_tomcat\_functions.sh file exists \n"
else
echo "apache\_tomcat\_functions.sh file does not exist..Exiting"
exit 1
fi
echo "Checking if Target Path $target\_path exists"
if [ ! -d "$target\_path" ]; then
echo "$target\_path doesnt exist.....Exiting"
exit 1
else
echo "$target\_path exists"
fi
script\_dir=/opt/fams/.scripts/
echo "Target Directory: " $target\_path
echo "Target Version Download location: " $patch\_url
echo "Target Patch: " $required\_version
\# directories where tomcat is installed
curr\_version=$(sh $target\_path/bin/version.sh | grep 'Server number:' | awk '{print $3}')
echo "\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*"
tomcat\_vars
if [ $curr\_version != "" ]; then
echo -e "Version $curr\_version is currently installed in Target Path $target\_path \n"
dir\_path=$(basename "$target\_path") #old tomcat directory
#file\_name=$(basename "$patch\_url") #zip filename for new version
#Stopping tomcat
stop\_tomcat $target\_path
#killing process
#kill\_tomcat
echo "\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*"
echo -e "Upgrading Tomcat $curr\_version to patch $required\_version.................\n"
# Backing old tomcat
cd $target\_path/..
create\_backup $dir\_path
# Downloading New Tomcat Version
# echo -e "Downloading Tomcat version $required\_version.......................\n"
# download\_required\_version $patch\_url
# echo "\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*"
# # Extracting tomcat directories
echo -e "Extracting Tomcat version from $file\_name file ......................."
tar -xf "$patch\_url/$file\_name"
echo -e " COMPLETED : Extracted successfully \n"
# Copying important files from old tomcat to new tomcat directories
tomcat\_dir=$(basename "$file\_name" .tar.gz) # new tomcat directory
echo -e "Copying important files from $dir\_path directory to $tomcat\_dir ......................."
copy\_main\_files $backup\_dir $tomcat\_dir
status=$?
if [ $status -eq 0 ]; then
# Renaming tomcat directory
echo -e "Renaming $tomcat\_dir directory to $dir\_path......................."
mv $tomcat\_dir $target\_path
else
echo -e "Process failed while Copying important files from $dir\_path directory to $tomcat\_dir.\n"
mv $backup\_dir $dir\_path
exit 1
fi
if [ $? -eq 0 ]; then
upgraded\_version=$(sh $target\_path/bin/version.sh | grep 'Server number:' | awk '{print $3}')
echo -e " COMPLETED : Renaming directory \n"
echo -e "Successfully upgraded tomcat to $upgraded\_version from $curr\_version \n"
# Starting tomcat
echo -e "Starting Tomcat......................."
start\_tomcat $target\_path
else
echo -e "Process failed while renaming $tomcat\_dir directory to $target\_path.\n"
exit 1
fi
else
echo -e "Required version is empty, Exiting \n"
exit 1
fi
#done
stop\_tomcat(){
tomcat\_dir=$1
echo "Stopping Tomcat Service"
sh $tomcat\_dir/bin/shutdown.sh
}
start\_tomcat(){
tomcat\_dir=$1
echo "Starting Tomcat Service"
sh $tomcat\_dir/bin/startup.sh
}
kill\_tomcat(){
myarray=( `ps aux | grep tomcat | awk '{print $2}'` )
for i in "${myarray[@]}"
do
echo "Killing Process $i"
kill -9 $i
done
}
tomcat\_vars(){
\# curr\_ver=$(jq --arg ident "$dir" -r '.targets[] | select(.target\_name == $ident) |.version' $script\_dir/tomcat\_discovery.json)
\# echo "Current Version: "$curr\_version
tomcat\_home=$(jq -r '.targets[].target\_name' $script\_dir/tomcat\_discovery.json)
echo "Tomcat Home: "$tomcat\_home
}
create\_backup(){
dir\_path=$1
\# curr\_version=$2
echo " Backing up directory: $dir\_path"
prefix=backup
backup\_dir="${dir\_path}\_${prefix}"
mkdir -p "$backup\_dir"
cp -r "$dir\_path"/\* "$backup\_dir"/
if [ "$?" -eq 0 ]; then
echo -e " COMPLETED : Backup directory $backup\_dir created \n"
rm -r "$dir\_path"
fi
}
download\_required\_version(){
download\_url=$1
wget -nc $download\_url
}
copy\_main\_files(){
old\_tomcat=$1
new\_tomcat=$2
cp -r ./$old\_tomcat/conf/\* ./$new\_tomcat/conf/
cp -r ./$old\_tomcat/webapps/\* ./$new\_tomcat/webapps/
if [ "$?" -eq 0 ]; then
echo -e " COMPLETED : Copying files into directory \n"
return 0 # Success
else
return 1 # Failure
fi
}
copy\_rollback\_files(){
old\_tomcat=$1
new\_tomcat=$2
cp -r $old\_tomcat/conf/\* /$new\_tomcat/conf/
cp -r $old\_tomcat/webapps/\* /$new\_tomcat/webapps/
echo -e " COMPLETED : Copying files into directory \n"
}
create\_rollback\_backup(){
curr\_tomcat=$1
rollback\_tomcat=$2
echo " Backing up directory: $dir\_path"
prefix=$curr\_version
backup\_dir="${curr\_tomcat}\_${prefix}"
mkdir -p "$backup\_dir"
cp -r "$dir\_path"/\* "$backup\_dir"/
echo -e " COMPLETED : Backup directory $backup\_dir created \n"
rm -r "$dir\_path"
}
Task 6: Create a Fleet
Create a fleet and get your product on the related allow list to discover its software inventory, know about the software patch compliance status, and fix the software patch compliance.
-
Go to the OCI Console, navigate to Fleet Application Management, Fleets, and click Create Fleet.
-
Enter the Name and Description for the fleet and add resources.
-
Enable automatic confirmation of the target’s resources.
Task 7: Fix the Software Patch Compliance
Click Fix now to fix software patch compliance for a fleet on its details page or create a schedule from the Schedules page of Lifecycle management.
If you click Fix now, the compliance job will run in the next 15 minutes, whereas if you select the schedule option from the Schedules page, you can create a job for the future or set a recursive schedule. By defining a maintenance schedule, specify when the runbook would be triggered to patch non-compliant targets identified in your fleet.
Acknowledgments
- Authors - Shabbir Hussain (Consulting Member Technical Staff), Fabio Bonisoli (Fleet Application Management Product Manager)
More Learning Resources
Explore other labs on docs.oracle.com/learn or access more free learning content on the Oracle Learning YouTube channel. Additionally, visit education.oracle.com/learning-explorer to become an Oracle Learning Explorer.
For product documentation, visit Oracle Help Center.
Automate Patching for Apache Tomcat or a Third-Party Technology with OCI Fleet Application Management
G23538-01
December 2024