Initial commit.
commit
6b38243d43
|
|
@ -0,0 +1,5 @@
|
|||
bin/
|
||||
output/
|
||||
outboard/
|
||||
.env
|
||||
.terraform.lock.hcl
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Python: Aktuelle Datei",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"console": "integratedTerminal",
|
||||
"args": [
|
||||
"EMEA_PROD"
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
# TerraformOnboarding
|
||||
The purpose of the exportConfig.py script is to export dynatrace specific services as terraform files. The importConfig.py script is used to additionally also export the states for each exported terraform file, since terraform does not do that by default.
|
||||
|
||||
|
||||
# Setup
|
||||
Run the following command to install all necessary dependencies:
|
||||
|
||||
```python
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
In order to ensure full functionality a `.env` file is necessary with the following format:
|
||||
|
||||
```yml
|
||||
# Environment URLs
|
||||
CN_PREPROD_ENV_URL="https://dynatracemgd-cn.bmwgroup.net/e/ab88c03b-b7fc-45f0-9115-9e9ecc0ced35"
|
||||
CN_PROD_ENV_URL="https://dynatracemgd-cn.bmwgroup.net/e/b921f1b9-c00e-4031-b9d1-f5a0d530757b"
|
||||
EMEA_PREPROD_ENV_URL="https://qqk70169.live.dynatrace.com"
|
||||
EMEA_PROD_ENV_URL="https://xxu26128.live.dynatrace.com"
|
||||
NA_PREPROD_ENV_URL="https://onb44935.live.dynatrace.com"
|
||||
NA_PROD_ENV_URL="https://wgv50241.live.dynatrace.com"
|
||||
|
||||
# Environment Tokens
|
||||
CN_PREPROD_API_TOKEN="<your-token>"
|
||||
CN_PROD_API_TOKEN="<your-token>"
|
||||
EMEA_PREPROD_API_TOKEN="<your-token>"
|
||||
EMEA_PROD_API_TOKEN="<your-token>"
|
||||
NA_PREPROD_API_TOKEN="<your-token>"
|
||||
NA_PROD_API_TOKEN="<your-token>"
|
||||
```
|
||||
Place the `.env` file within the root directory of the project folder:
|
||||
|
||||
```bash
|
||||
TerraformDynatrace Porter # Project Folder
|
||||
├─── res
|
||||
├─── templates
|
||||
├─── .env # Add the environment file
|
||||
├─── .gitignore
|
||||
├─── README.md
|
||||
├─── exportConfig.py
|
||||
├─── imortConfig.py
|
||||
├─── main.tf
|
||||
└─── requirements.txt
|
||||
```
|
||||
|
||||
# Run
|
||||
You can simply run the script by executing the following example command within the projects root directory:
|
||||
|
||||
```python
|
||||
python exportConfig.py
|
||||
python importConfig.py
|
||||
```
|
||||
**Note:** First run the exportConfig.py script and once that is done run the importConfig.py script.
|
||||
|
||||
|
||||
# Version
|
||||
```python
|
||||
Python 3.9.9
|
||||
```
|
||||
|
|
@ -0,0 +1,202 @@
|
|||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import shutil
|
||||
import hcl
|
||||
from dotenv import load_dotenv
|
||||
from glob import glob
|
||||
|
||||
|
||||
# [AA 2021.12.10] Method to set environments
|
||||
def setEnv(env, time, path):
|
||||
os.environ['DYNATRACE_ENV_URL'] = str(os.getenv(env + "_ENV_URL"))
|
||||
os.environ['DYNATRACE_API_TOKEN'] = str(os.getenv(env + "_API_TOKEN"))
|
||||
os.environ['DYNATRACE_TARGET_FOLDER'] = str(path + time + "_" + env)
|
||||
return os.environ
|
||||
|
||||
|
||||
# [AA 2021.12.10] Method to call process synchronously
|
||||
def runProcess(process_name, input_params):
|
||||
process_names = ["Export", "Terraform init"]
|
||||
success = False
|
||||
try:
|
||||
process = subprocess.Popen(input_params)
|
||||
process.wait(timeout=60*10) # 10 minutes
|
||||
success = True
|
||||
print("[DEBUG]", "Process:", process_name, "Success:", success)
|
||||
# print("[DEBUG]", "Process return code:", outs)
|
||||
except subprocess.TimeoutExpired:
|
||||
print("[DEBUG]", "Exception occured:", subprocess.TimeoutExpired)
|
||||
print("[DEBUG]", "Killing process:", process_name)
|
||||
process.kill()
|
||||
success = False
|
||||
print("[DEBUG]", "Process:", process_name, "Success:", success)
|
||||
except:
|
||||
if process_name in process_names and success == False:
|
||||
print("[DEBUG]", "Process:", process_name, "Success:", success)
|
||||
print("[DEBUG]", "Exiting program.")
|
||||
process.kill()
|
||||
success = False
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("[FAILED]", input_params)
|
||||
|
||||
|
||||
# [AA 2021.12.13] Fill dictionary
|
||||
def readFile(path):
|
||||
with open(path, 'r', encoding='utf8') as cfg:
|
||||
|
||||
# [AA 2021.12.01] Load the content of the particular resource file in eg: management_zones
|
||||
obj = hcl.load(cfg)
|
||||
|
||||
# [AA, EW 2021.12.01] Store resource type and resource name of that file into a dictionary
|
||||
key = list(obj['resource'].keys())[0]
|
||||
val = list(obj['resource'][key].keys())[0]
|
||||
return key, val
|
||||
|
||||
|
||||
# [AA, EW 2022.01.17] Load all resources and add them to a dictionary
|
||||
def createResourceDict():
|
||||
files = [os.path.normpath(f).replace('\\', '/') for f in glob(targetFolder + "**/**.tf", recursive=True)]
|
||||
for index, file in enumerate(files):
|
||||
filedir = "./"+("./"+os.path.dirname(file)).replace(targetFolder, "")
|
||||
splittedFilename = os.path.basename(file).split(".")
|
||||
|
||||
if len(splittedFilename) == 5:
|
||||
resourceID = splittedFilename[1]
|
||||
moduleName, resourceName = readFile(file)
|
||||
|
||||
if not filedir in myDict.keys():
|
||||
myDict.setdefault(filedir, {})
|
||||
|
||||
if not moduleName in myDict[filedir].keys():
|
||||
myDict[filedir].setdefault(moduleName, [])
|
||||
|
||||
resourceValue = {"resourceName": resourceName,
|
||||
"resourceID": resourceID}
|
||||
myDict[filedir][moduleName].append(resourceValue)
|
||||
|
||||
|
||||
# [AA, EW 2022.01.17] Copy main.tf into the target folder
|
||||
def copyMainTemplate():
|
||||
shutil.copyfile(templatesFolder + "main.tf", targetFolder + "main.tf")
|
||||
|
||||
|
||||
# [AA 2022.01.17] Copy module.tf in all folders and subfolders except where main.tf is
|
||||
def copyModuleTemplate():
|
||||
dirs = glob(targetFolder + "**/", recursive=True)
|
||||
for index, dir in enumerate(dirs):
|
||||
if index != 0:
|
||||
shutil.copyfile(templatesFolder + "module.tf", dir + "module.tf")
|
||||
|
||||
|
||||
# [AA 2021.12.13] Append correct configuration path
|
||||
def writeFile(k, d):
|
||||
with open(".\\main.tf", "a") as mf:
|
||||
mf.writelines("\n" + "module \"" + k + "\" { source = \"" + d + "\" }")
|
||||
|
||||
|
||||
# [AA, EW 2022.01.17] Adjust the resource module name
|
||||
def getModuleTag(str):
|
||||
return str.replace("./", "").replace("/", "_")
|
||||
|
||||
|
||||
# [AA, EW 2022.01.17] Set the resource names
|
||||
def editMainTF():
|
||||
with open(targetFolder + "main.tf", "a") as mf:
|
||||
for index, (filedir, value) in enumerate(myDict.items()):
|
||||
mf.writelines("\n" + "module \"" + getModuleTag(filedir) +
|
||||
"\" { source = \"" + filedir + "\" }")
|
||||
|
||||
|
||||
# [AA, EW 2022.01.17] Start importing
|
||||
def importStates():
|
||||
os.chdir(targetFolder)
|
||||
input_params = ["terraform", "init"]
|
||||
runProcess("Terraform init",input_params)
|
||||
|
||||
for filedir, resourceV in myDict.items():
|
||||
for resource, valueArray in resourceV.items():
|
||||
for rObject in valueArray:
|
||||
input_params = ["terraform", "import", "module."+getModuleTag(
|
||||
filedir)+"."+resource+"."+rObject["resourceName"], rObject["resourceID"]]
|
||||
runProcess("Import", input_params)
|
||||
# terraform import module.alerting_profiles.dynatrace_alerting_profiles.CD_ABC 9348098098safs9f8
|
||||
os.chdir(cwd)
|
||||
|
||||
|
||||
# [AA 2022.01.17] Arguments passed
|
||||
if(len(sys.argv) == 2):
|
||||
|
||||
# [AA 2021.11.29] Load enviroment file
|
||||
load_dotenv()
|
||||
|
||||
# [AA 2022.01.17] Set available resources
|
||||
Resources = [
|
||||
# "dynatrace_custom_service",
|
||||
# "dynatrace_dashboard",
|
||||
# "dynatrace_management_zone",
|
||||
# "dynatrace_maintenance_window",
|
||||
# "dynatrace_request_attribute",
|
||||
"dynatrace_alerting_profile",
|
||||
"dynatrace_notification",
|
||||
# "dynatrace_autotag"
|
||||
# "dynatrace_aws_credentials",
|
||||
# "dynatrace_azure_credentials",
|
||||
# "dynatrace_k8s_credentials",
|
||||
# "dynatrace_service_anomalies",
|
||||
# "dynatrace_application_anomalies",
|
||||
# "dynatrace_host_anomalies",
|
||||
# "dynatrace_database_anomalies",
|
||||
# "dynatrace_custom_anomalies",
|
||||
# "dynatrace_disk_anomalies",
|
||||
# "dynatrace_calculated_service_metric", #issue -> bug: windows specific due to path length limit
|
||||
# "dynatrace_service_naming",
|
||||
# "dynatrace_host_naming",
|
||||
# "dynatrace_processgroup_naming",
|
||||
# "dynatrace_slo", # issue -> bug: whitespace issue
|
||||
# "dynatrace_span_entry_point",
|
||||
# "dynatrace_span_capture_rule",
|
||||
# "dynatrace_span_context_propagation",
|
||||
# "dynatrace_resource_attributes",
|
||||
# "dynatrace_span_attribute",
|
||||
# "dynatrace_mobile_application",
|
||||
# "dynatrace_credentials", #issue -> bug: unknown issue? not supported?
|
||||
# "dynatrace_browser_monitor",
|
||||
# "dynatrace_http_monitor",
|
||||
]
|
||||
|
||||
# [AA, EW 2022.01.17] Set global variables
|
||||
global timestamp, templatesFolder, outputFolder, targetFolder, myDict, cwd
|
||||
# timestamp = time.strftime("%Y%m%d-%H%M%S")
|
||||
timestamp = "20220120-084944"
|
||||
cwd = os.getcwd()
|
||||
outputFolder = "./output/"
|
||||
targetFolder = outputFolder + timestamp + "_" + sys.argv[1] + "/"
|
||||
templatesFolder = "./templates/"
|
||||
myDict = {}
|
||||
|
||||
# [AA, EW 2022.01.17] Set env varibales
|
||||
setEnv(sys.argv[1], timestamp, outputFolder)
|
||||
|
||||
# [AA, EW 2022.01.17] Download resource files
|
||||
# runProcess("Export", [".\\bin\\terraform-provider-dynatrace_v1.9.1.exe", "export"] + Resources)
|
||||
|
||||
# [AA, EW 2022.01.17] Create a dictionary to store information of resources
|
||||
createResourceDict()
|
||||
|
||||
# [AA, EW 2022.01.17] Copy main.tf file and add module.tf files
|
||||
# copyMainTemplate()
|
||||
# copyModuleTemplate()
|
||||
|
||||
# [AA, EW 2022.01.17] Print the module names with their associated module path into the main.tf file
|
||||
# editMainTF()
|
||||
|
||||
# [AA, EW 2022.01.17] Import the states for each module
|
||||
# importStates()
|
||||
print("Finished!")
|
||||
else:
|
||||
print("Usage example: ")
|
||||
print("List of available environments: CN_PREPROD, CN_PROD, EMEA_PREPROD, EMEA_PROD, NA_PREPROD, NA_PROD")
|
||||
print("python .\exportConfig.py EMEA_PROD ")
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
dynatrace = {
|
||||
version = "1.9.1"
|
||||
source = "dynatrace-oss/dynatrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# module "configDir" {
|
||||
# source = "git::https://github.com/arnauagithub/DynatraceTerraformConfiguration.git?ref=20211130-151123"
|
||||
# }
|
||||
|
||||
|
||||
module "m1" { source = "./output/20220117-132316_EMEA_PROD/anomalies" }
|
||||
module "m2" { source = "./output/20220117-132316_EMEA_PROD/credentials" }
|
||||
module "dynatrace_custom_service" { source = "./output/20220117-132316_EMEA_PROD/custom_services" }
|
||||
module "dynatrace_service_naming" { source = "./output/20220117-132316_EMEA_PROD/naming/services" }
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
python-dotenv
|
||||
pyhcl
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import subprocess
|
||||
import sys
|
||||
|
||||
if(len(sys.argv) == 1):
|
||||
try:
|
||||
process = subprocess.Popen(["terraform", "init"])
|
||||
outs = process.wait(timeout=10*60)
|
||||
print("[DEBUG]", "Process return code:", outs)
|
||||
except subprocess.TimeoutExpired:
|
||||
print("[DEBUG]", "Exception occured:", subprocess.TimeoutExpired)
|
||||
print("[DEBUG]", "Killing process.")
|
||||
process.kill()
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
dynatrace = {
|
||||
version = "1.9.1"
|
||||
source = "dynatrace-oss/dynatrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
import subprocess
|
||||
process = subprocess.Popen([".\\bin\\terraform-provider-dynatrace_v1.9.1.exe", "export", "dynatrace_alerting_profile"])
|
||||
print(process.returncode)
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
dynatrace = {
|
||||
version = "1.9.1"
|
||||
source = "dynatrace-oss/dynatrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# module "configDir" {
|
||||
# source = "git::https://github.com/arnauagithub/DynatraceTerraformConfiguration.git?ref=20211130-151123"
|
||||
# }
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
dynatrace = {
|
||||
version = "1.9.1"
|
||||
source = "dynatrace-oss/dynatrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue