CSV-Powered Tagging Recipes for Azure & OCI
No-fuss CSV tagging scripts for Azure RGs & OCI compartments—serve up tags with a single file.
Overview
Think of these CSV-powered tagging tools as your FinOps sous-chefs—just feed them a simple CSV and they’ll sprinkle the five essential tags (Environment, Owner, CostCenter, Project, Application) onto your Azure RGs and OCI compartments, keeping your cloud kitchen organized and cost-savvy.
CloudCostChefs Azure RG Tag Chef
Whip up consistent tags across all your Azure Resource Groups in a snap—just feed it a CSV and watch the magic happen.
CloudCostChefs OCI Compartment Tag Chef
Serve up standardized tags across all your OCI compartments—just feed it a CSV and watch it cook up consistency and cost clarity.
Sure, the portals have tagging buttons—but these scripts let you:
- 🔄 Tag dozens of resources in one swoop
- ✅ Keep tags uniform across your entire organization
- 🤖 Bake tagging into your automation pipelines
- 📝 Capture every tag change in detailed logs
Key Features
CSV-Driven
A plain CSV means even non-techy teammates can update tags—no code wizardry needed.
Core Tag Ingredients
We zero in on the five must-have tags—Environment, Owner, CostCenter, Project, and Application—to keep your cloud costs in check and your resources well-seasoned.
Minimal Dependencies
All you need is pandas and the Azure or OCI SDK—no extra garnish, quick to install, and ready to run.
Detailed Logging
Every tagging action is logged to both console and file—so you’ll have a clear audit trail and troubleshooting breadcrumbs whenever you need them.
Tag Merger Magic
Keeps your old tags intact and blends in new ones—no empty-handed tag overwrites here.
Error Resilience
If one resource throws a tantrum, the script keeps cooking—no full-stop failures here.
Prerequisites
Azure Prerequisites
- Python 3.6+ installed on your system
- Required Python packages:bash
pip install pandas azure-identity azure-mgmt-resource
- Azure CLI installed and configured with appropriate permissions:bash
# Login to Azure az login # Verify you have the correct permissions az account show
- Permissions: You need at least Reader and Tag Contributor role on the resource groups you want to tag
OCI Prerequisites
- Python 3.6+ installed on your system
- Required Python packages:bash
pip install pandas oci
- OCI SDK Configuration: Set up your OCI config file:bash
# Default location: ~/.oci/config # Format: [DEFAULT] user=ocid1.user.oc1..aaaaaaaa... fingerprint=aa:bb:cc:dd:ee:ff:gg:hh:ii:jj:kk:ll:mm:nn:oo:pp key_file=~/.oci/oci_api_key.pem tenancy=ocid1.tenancy.oc1..aaaaaaaa... region=us-ashburn-1
- Permissions: You need permissions to manage tags on compartments (typically requires admin privileges)
- Tag Namespace: The script uses "CloudCostChefs" as the tag namespace. Ensure this namespace exists in your tenancy or modify the script to use your existing namespace.
CSV Format
Azure CSV Format
Create a CSV file named ResourceGroup_Tags.csv
with the following columns:
ResourceGroupName,SubscriptionId,Environment,Owner,CostCenter,Project,Application
Example entries:
rg-finance-prod,12345678-1234-1234-1234-123456789012,Production,jane.doe@example.com,FIN1234,ERP-Migration,ERP-App rg-devops-dev,87654321-4321-4321-4321-987654321098,Development,john.smith@example.com,ENG5678,CI-CD,Build-Pipeline
Only ResourceGroupName
and SubscriptionId
are required. The tag columns (Environment, Owner, CostCenter, Project, Application) are optional, but you should include at least one tag column for the script to be useful.
OCI CSV Format
Create a CSV file named Compartment_Tags.csv
with the following columns:
CompartmentName,Environment,Owner,CostCenter,Project,Application
Example entries:
FinanceComp,Production,jane.doe@example.com,FIN1234,ERP-Migration,ERP-App DevOpsComp,Development,john.smith@example.com,ENG5678,CI-CD,Build-Pipeline
Only CompartmentName
is required. The tag columns (Environment, Owner, CostCenter, Project, Application) are optional, but you should include at least one tag column for the script to be useful.
Installation & Setup
Azure Setup
- Download the Azure Resource Group Tagger script:
- Create a directory for your tagging operations:bash
mkdir -p azure-tagging/logs
- Place the script in the directory:bash
mv azure_rg_tagger.py azure-tagging/
- Create your CSV file (see CSV Format section) and place it in the same directory:bash
# Example: Create a simple CSV echo 'ResourceGroupName,SubscriptionId,Environment,Owner,CostCenter,Project,Application' > azure-tagging/ResourceGroup_Tags.csv echo 'rg-example,12345678-1234-1234-1234-123456789012,Production,admin@example.com,IT001,Core-Infra,Monitoring' >> azure-tagging/ResourceGroup_Tags.csv
- Make the script executable:bash
chmod +x azure-tagging/azure_rg_tagger.py
OCI Setup
- Download the OCI Compartment Tagger script:
- Create a directory for your tagging operations:bash
mkdir -p oci-tagging/logs
- Place the script in the directory:bash
mv oci_compartment_tagger.py oci-tagging/
- Create your CSV file (see CSV Format section) and place it in the same directory:bash
# Example: Create a simple CSV echo 'CompartmentName,Environment,Owner,CostCenter,Project,Application' > oci-tagging/Compartment_Tags.csv echo 'ExampleComp,Production,admin@example.com,IT001,Core-Infra,Monitoring' >> oci-tagging/Compartment_Tags.csv
- Make the script executable:bash
chmod +x oci-tagging/oci_compartment_tagger.py
- Ensure your OCI config file is set up correctly (typically at
~/.oci/config
)
Usage
Running the Azure Tagger
- Navigate to your script directory:bash
cd azure-tagging
- Run the script:bash
./azure_rg_tagger.py
- Check the output in the console and the log file:bash
cat logs/azure_rg_tagger.log
Environment Variables
You can customize the script behavior with these environment variables:
RESOURCE_GROUP_CSV_PATH
- Path to your CSV file (default:./ResourceGroup_Tags.csv
)LOG_DIR
- Directory for log files (default:./logs
)
Example with Custom CSV Path
RESOURCE_GROUP_CSV_PATH=/path/to/my/custom_tags.csv ./azure_rg_tagger.py
Running the OCI Tagger
- Navigate to your script directory:bash
cd oci-tagging
- Run the script:bash
./oci_compartment_tagger.py
- Check the output in the console and the log file:bash
cat logs/oci_compartment_tagger.log
Environment Variables
You can customize the script behavior with these environment variables:
COMPARTMENT_CSV_PATH
- Path to your CSV file (default:./Compartment_Tags.csv
)LOG_DIR
- Directory for log files (default:./logs
)OCI_CONFIG_PATH
- Path to your OCI config file (default:~/.oci/config
)OCI_PROFILE
- OCI config profile to use (default:DEFAULT
)
Example with Custom Config
OCI_CONFIG_PATH=~/.oci/custom_config OCI_PROFILE=PRODUCTION ./oci_compartment_tagger.py
Customization
Customizing the Azure Tagger
Adding Custom Tags
To add custom tags beyond the default five, modify the prepare_tags
function in the script:
def prepare_tags(row): # Original tags tags = {} if pd.notnull(row.get('Environment')): tags['Environment'] = str(row['Environment']).strip() if pd.notnull(row.get('Owner')): tags['Owner'] = str(row['Owner']).strip() if pd.notnull(row.get('CostCenter')): tags['CostCenter'] = str(row['CostCenter']).strip() if pd.notnull(row.get('Project')): tags['Project'] = str(row['Project']).strip() if 'Application' in row and pd.notnull(row.get('Application')): tags['Application'] = str(row['Application']).strip() # Add your custom tag if 'Department' in row and pd.notnull(row.get('Department')): tags['Department'] = str(row['Department']).strip() return tags
Changing Log Format
To modify the logging format, update the logging.basicConfig
call:
logging.basicConfig( filename=LOG_FILENAME, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s' # Custom format )
Adding Email Notifications
To add email notifications when tagging is complete, add this function and call it at the end of main()
:
import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart def send_notification_email(log_file, recipients): # Read the log file with open(log_file, 'r') as f: log_content = f.read() # Create email msg = MIMEMultipart() msg['Subject'] = 'Azure Resource Group Tagging Complete' msg['From'] = 'your-email@example.com' msg['To'] = ', '.join(recipients) body = f''' Azure Resource Group tagging process has completed. Summary: {log_content[-500:]} # Last 500 characters of log Full log attached. ''' msg.attach(MIMEText(body, 'plain')) # Add log as attachment attachment = MIMEText(log_content) attachment.add_header('Content-Disposition', 'attachment', filename='tagging_log.txt') msg.attach(attachment) # Send email try: server = smtplib.SMTP('smtp.example.com', 587) server.starttls() server.login('your-email@example.com', 'your-password') server.send_message(msg) server.quit() logging.info(f'Notification email sent to {recipients}') except Exception as e: logging.error(f'Failed to send notification email: {e}')
Customizing the OCI Tagger
Changing the Tag Namespace
To use a different tag namespace, modify the prepare_tags
function:
def prepare_tags(row): # Change this line to use your namespace namespace = 'YourCustomNamespace' defined_tags = {namespace: {}} # Rest of the function remains the same if pd.notnull(row.get('Environment')): defined_tags[namespace]['Environment'] = str(row['Environment']).strip() # ...
Adding Custom Tags
To add custom tags beyond the default five, modify the prepare_tags
function:
def prepare_tags(row): namespace = 'CloudCostChefs' defined_tags = {namespace: {}} # Original tags if pd.notnull(row.get('Environment')): defined_tags[namespace]['Environment'] = str(row['Environment']).strip() if pd.notnull(row.get('Owner')): defined_tags[namespace]['Owner'] = str(row['Owner']).strip() if pd.notnull(row.get('CostCenter')): defined_tags[namespace]['CostCenter'] = str(row['CostCenter']).strip() if pd.notnull(row.get('Project')): defined_tags[namespace]['Project'] = str(row['Project']).strip() if 'Application' in row and pd.notnull(row.get('Application')): defined_tags[namespace]['Application'] = str(row['Application']).strip() # Add your custom tag if 'Department' in row and pd.notnull(row.get('Department')): defined_tags[namespace]['Department'] = str(row['Department']).strip() # If no common tags found, return empty dict if not defined_tags[namespace]: return {} return defined_tags
Troubleshooting
Azure Troubleshooting
Authentication Errors
If you see authentication errors:
- Ensure you're logged in with Azure CLI:
az login
- Check if your credentials have expired and re-login if necessary
- Verify you have the correct permissions on the target subscriptions
Resource Group Not Found
If you see "Resource Group not found" errors:
- Verify the resource group name is spelled correctly in your CSV
- Check that the subscription ID is correct
- Confirm the resource group exists in the specified subscription
CSV Format Issues
If you see CSV parsing errors:
- Ensure your CSV has the correct headers
- Check for special characters or encoding issues in your CSV
- Try opening and resaving the CSV in a text editor with UTF-8 encoding
OCI Troubleshooting
Authentication Errors
If you see authentication errors:
- Verify your OCI config file exists and has the correct format
- Check that the key file path in your config is correct
- Ensure your API key is still active in the OCI console
- Confirm the permissions for your config and key files (should be 600)
Compartment Not Found
If you see "Compartment not found" errors:
- Verify the compartment name is spelled correctly in your CSV
- Check that you have access to the compartment
- Confirm the compartment exists in your tenancy
Tag Namespace Issues
If you see errors related to tag namespaces:
- Verify the "CloudCostChefs" tag namespace exists in your tenancy
- If it doesn't exist, create it in the OCI console or modify the script to use an existing namespace
- Ensure the tag keys (Environment, Owner, etc.) are defined in your tag namespace
Best Practices
Consistent Naming
Use consistent tag values across your organization:
- Standardize environment names (e.g., "Production", "Development", "Testing")
- Use email addresses for Owner tags
- Use established cost center codes
Automation Integration
Integrate tagging into your workflows:
- Run the script as part of your CI/CD pipeline
- Schedule regular tagging updates
- Combine with tag enforcement policies
CSV Management
Maintain your CSV files effectively:
- Store CSV files in version control
- Document the purpose and owner of each CSV
- Consider using a central database or spreadsheet as the source of truth
Validation & Testing
Ensure your tagging operations are reliable:
- Test on non-production resources first
- Validate CSV data before running the script
- Review logs after each run to catch any issues
Remember that in both Azure and OCI, tags are not automatically inherited by child resources. Consider implementing additional tagging strategies for individual resources if needed.
Next Steps
After implementing these tagging tools, consider these next steps to enhance your cloud cost management:
Tag-Based Reporting
Leverage your tags for cost analysis:
- Create cost reports grouped by Environment, CostCenter, or Project
- Set up dashboards to visualize spending by tag
- Share reports with stakeholders based on their tags
Tag Enforcement
Ensure consistent tagging across your organization:
- Implement Azure Policy or OCI policies to require tags
- Set up alerts for non-compliant resources
- Create automated remediation for missing tags
Was this documentation helpful?
Have suggestions for improving this documentation? Contact us.