"""
AzureInstance
=============
The following Azure Instance related parsers are placed in this module:
AzureInstanceID - 'vmId' of Azure Instance
------------------------------------------
AzureInstanceType - 'vmSize' of Azure Instance
----------------------------------------------
AzureInstancePlan - 'plan' of Azure Instance
--------------------------------------------
AzurePublicIpv4Addresses - list of public IPv4 addresses
--------------------------------------------------------
"""
import json
from insights.core import CommandParser
from insights.core.exceptions import ParseException, SkipComponent
from insights.core.plugins import parser
from insights.specs import Specs
def validate_content(content):
if not content or 'curl: ' in content[0]:
raise SkipComponent()
[docs]@parser(Specs.azure_instance_id)
class AzureInstanceID(CommandParser):
"""
Class for parsing the Azure Instance type returned by command
``curl -s -H Metadata:true http://169.254.169.254/metadata/instance/compute/vmId?api-version=2021-12-13&format=text``,
Typical output of this command is::
f904ece8-c6c1-4b5c-881f-309b50f25e50
Raises:
SkipComponent: When content is empty or no parse-able content.
Attributes:
id (str): The instance ID of the VM instance in Azure.
Examples:
>>> azure_id.id
'f904ece8-c6c1-4b5c-881f-309b50f25e50'
"""
[docs] def parse_content(self, content):
validate_content(content)
self.id = content[0].strip()
def __repr__(self):
return "<instance_id: {i}>".format(i=self.id)
[docs]@parser(Specs.azure_instance_type)
class AzureInstanceType(CommandParser):
"""
Class for parsing the Azure Instance type returned by command
``curl -s -H Metadata:true http://169.254.169.254/metadata/instance/compute/vmSize?api-version=2021-12-13&format=text``,
Typical output of this command is::
Standard_L64s_v2
Raises:
SkipComponent: When content is empty or no parse-able content.
ParseException: When type cannot be recognized.
Attributes:
type (str): The type of VM instance in Azure, e.g: Standard
size (str): The size of VM instance in Azure, e.g: L64s, NC12s
version (str): The version of VM instance in Azure, e.g: v2, v3, `None` for non-version
raw (str): The fully type string returned by the ``curl`` command
Examples:
>>> azure_type.type
'Standard'
>>> azure_type.size
'L64s'
>>> azure_type.version
'v2'
>>> azure_type.raw
'Standard_L64s_v2'
"""
[docs] def parse_content(self, content):
validate_content(content)
self.raw = self.type = self.size = self.version = None
# Ignore any curl stats that may be present in data
for l in content:
l_strip = l.strip()
if ' ' not in l_strip and '_' in l_strip:
self.raw = l_strip
type_sp = l_strip.split('_')
self.type, self.size = type_sp[0], type_sp[1]
if len(type_sp) >= 3:
self.version = type_sp[2]
if not self.type:
raise ParseException('Unrecognized type: "{0}"', content[0])
def __repr__(self):
return "<azure_type: {t}, size: {s}, version: {v}, raw: {r}>".format(
t=self.type, s=self.size, v=self.version, r=self.raw)
[docs]@parser(Specs.azure_instance_plan)
class AzureInstancePlan(CommandParser):
"""
Class for parsing the Azure Instance Plan returned by command
``curl -s -H Metadata:true http://169.254.169.254/metadata/instance/compute/plan?api-version=2021-12-13&format=json``,
Typical Output of this command is::
{
"name": "planName",
"product": "planProduct",
"publisher": "planPublisher"
},
Raises:
SkipComponent: When content is empty or no parse-able content.
Attributes:
name (str): The name of the plan for the VM Instance in Azure, e.g: rhel7
product (str): The product of the plan for the VM Instance in Azure, e.g: RHEL
publisher (str): The publisher of the plan for the VM Instance in Azure, e.g: Red hat
raw (str): The full JSON of the plan returned by the ``curl`` command
Examples:
>>> azure_plan.name == 'planName'
True
>>> azure_plan.product == 'planProduct'
True
>>> azure_plan.publisher == 'planPublisher'
True
"""
[docs] def parse_content(self, content):
validate_content(content)
try:
plan = json.loads(content[0])
except:
raise ParseException("Unable to parse JSON")
self.raw = content[0]
self.name = plan["name"] if plan["name"] != "" else None
self.product = plan["product"] if plan["product"] != "" else None
self.publisher = plan["publisher"] if plan["publisher"] != "" else None
def __repr__(self):
return "<azure_plan_name: {n}, product: {pr}, publisher: {pu}, raw: {r}".format(
n=self.name, pr=self.product, pu=self.publisher, r=self.raw
)
[docs]@parser(Specs.azure_load_balancer)
class AzurePublicIpv4Addresses(CommandParser, list):
"""
Class for parsing the Azure load balancer JSON data returned by command
curl -sH "Metadata:true" --connect-timeout 5 \
"http://169.254.169.254/metadata/loadbalancer?api-version=2021-12-13&format=json"
Typical Output of this command is::
{
"loadbalancer": {
"publicIpAddresses": [
{
"frontendIpAddress": "137.116.118.209",
"privateIpAddress": "10.0.0.4"
}
],
"inboundRules": [],
"outboundRules": []
}
}
Raises:
SkipComponent: When content is empty or curl returned an error.
ParseException: On JSON parsing error.
"""
[docs] def parse_content(self, content):
validate_content(content)
try:
plan = json.loads(' '.join(content))
for pair in plan["loadbalancer"]["publicIpAddresses"]:
self.append(pair["frontendIpAddress"])
except:
raise ParseException("Unable to parse JSON")