Skip to content
This repository was archived by the owner on Sep 22, 2024. It is now read-only.

Commit 6c69816

Browse files
committed
Adding current state of project
1 parent dca1140 commit 6c69816

31 files changed

+1735
-0
lines changed

.gitignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
*.pyc
2+
3+
jsons/*
4+
txt/*
5+
variable_sets/*
6+
scripts/*
7+
templates/*
8+
9+
.vscode/
10+
11+
user_variables.py
12+
sandbox_script.py
13+
14+
!variable_sets/template.py
15+
!scripts/template.py
16+
!scripts/change_pythonpath.py

Documentation/EXAMPLES.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Examples
2+
3+
## Use Cases - Aaron/"Philly"
4+
5+
### Weekly Metrics
6+
I report the number of users, the number of applications onboarded, and number of hosts that are being monitored by Dynatrace.<br/>
7+
Check out the "examples" git branch for aaron_weekly_metrics.py
8+
9+
### List of Host Groups
10+
We keep a document of all the different Host Groups that we are using. So I use a script occasionally to update the document of all the host groups in each environment.<br/>
11+
Check out the "examples" git branch for aaron_host_groups.py
12+
13+
### Host Units by Management Zone
14+
Like many clients, my client uses a single tenant for NonProd and another tenant for Prod. Application teams are split by Management Zones. To track how many host units each team is using, I created a script to get the number of Host Units in use by each team.
15+
16+
### Onboarding New Applications
17+
When onboarding a new application, I run this script. It will create all the user_groups required as well as the management zones needed for the different lifecycles of the application
18+
19+
### Backend for Django Project
20+
Implementing this project as a backend for a Django-based web application. Stay tuned!

Documentation/GETTING_STARTED.md

Whitespace-only changes.

Documentation/HOWTO.md

Whitespace-only changes.

Documentation/INSTALLATION.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Installation
2+
*Installation steps required to run the toolkit<br/>
3+
If you see a TODO for something related, please reach out to Aaron Philipose on Slack, Email, or Zoom*
4+
5+
## Windows
6+
7+
### Script Install
8+
- Open Command Line (cmd) and navigate to the Git Directory
9+
- Navigate to setup folder
10+
- Run "powershell.exe -ExecutionPolicy bypass .\install_python.ps1"
11+
12+
13+
### Install indepentantly
14+
- [Download the latest version of Python 3](https://www.python.org/downloads/)
15+
- Run the installer
16+
- Use default options.
17+
- Select to add PYTHON_HOME to PATH
18+
- Open PowerShell or Command Line
19+
- run "python -m pip install requests"
20+
### Through Company Software Request
21+
- For machines that require Company provided installs, any python version >= 3.4
22+
23+
## Linux
24+
25+
### RHEL, CentOS & Fedora
26+
27+
- Run "sudo yum install python3 python3-pip"
28+
- Run "python3 -m pip install requests"
29+
30+
### Ubuntu & Debian
31+
32+
- Run "sudo apt-get install python3 python3-pip"
33+
- Run "python3 -m pip install requests"

Documentation/LANGUAGE.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Language
2+
3+
4+
## Tenant, Cluster & Set
5+
Tenant - Dynatrace Tenant (aka *Dynatrace Environment*)<br/>
6+
Cluster - Dynatrace Cluster (SaaS can have all tenants under 1 "cluster")<br/>
7+
Set - All defined Dynatrace Clusters in user variables<br/>
8+
9+
### Referencing Tenant, Cluster & Set
10+
Tenant -> function (uv.FULL_SET['CLUSTER_NAME'], "Tenant")<br/>
11+
Cluster -> function (uv.FULL_SET['CLUSTER_NAME])<br/>
12+
Set -> function (uv.FULL_SET)<br/>
13+
14+
15+
## Environment and App
16+
Environment - Customer Environments/Lifecycles (e.g. Dev/Test/Perf/Acpt/Prod/DR)<br/>
17+
App - Customer Applications (used with Tagging and MZ Rules)<br/>
18+
19+
## Python Descriptions
20+
Dict - Python Dictionary (Note: API calls that use JSON payloads should pass in Dicts, and responses will be converted to Dicts)

Documentation/MODULE_GLOSSARY.md

Lines changed: 330 additions & 0 deletions
Large diffs are not rendered by default.

Documentation/PROJECT_OBJECTIVES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Project Objectives
2+
3+
1. Lower the barrier of entry of creating repeatable Dynatrace scripts
4+
2. Easy to Understand (Less time learning another new thing and more time using!)
5+
3. Allow other applications to implement this as a foundation ()

change_variables.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
"""Replace active variables with another set"""
2+
import sys
3+
import os
4+
5+
def replace_env():
6+
"""Replace Variable File"""
7+
print("Enter Set to Import: ", end='')
8+
new_env = input()
9+
10+
if "win" in sys.platform:
11+
os.system("copy variable_sets\\" + str(new_env) + ".py user_variables.py")
12+
else:
13+
os.system("cp variable_sets/" + str(new_env) + ".py user_variables.py")
14+
15+
replace_env()

dynatrace/cluster/config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import dynatrace.requests.request_handler as rh
2+
3+
def get_node_info(cluster):
4+
response = rh.cluster_get(cluster,"cluster")
5+
return response.json()
6+
7+
def get_node_config(cluster):
8+
response = rh.cluster_get(cluster,"cluster/configuration")
9+
return response.json()
10+
11+
def set_node_config(cluster, json):
12+
response = rh.cluster_post(cluster,"cluster/configuration", json=json)
13+
return response.status_code

dynatrace/cluster/ssl.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/python3
2+
"""Cluster SSL Certificate Operations"""
3+
import dynatrace.requests.request_handler as rh
4+
5+
def get_cert_details(cluster, entity_type, entity_id):
6+
"""Get SSL Certificate information for Server or Cluster ActiveGate"""
7+
response = rh.cluster_get(
8+
cluster,
9+
"sslCertificate/" + str(entity_type) + "/" + str(entity_id)
10+
)
11+
return response.json()
12+
13+
def get_cert_install_status(cluster, entity_id):
14+
"""Get SSL Storage Status for Cluster ActiveGate"""
15+
response = rh.cluster_get(
16+
cluster,
17+
"sslCertificate/store/COLLECTOR/" + str(entity_id)
18+
)
19+
return response.text
20+
21+
def set_cert(cluster, entity_type, entity_id, ssl_json):
22+
"""Set SSL Storage Status for Server or Cluster ActiveGate"""
23+
response = rh.cluster_post(
24+
cluster,
25+
"sslCertificate/store/" + str(entity_type) + "/" + str(entity_id),
26+
json=ssl_json
27+
)
28+
return response.json()
29+

dynatrace/cluster/sso.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""SSO Operations for Dynatrace"""
2+
import dynatrace.requests.request_handler as rh
3+
4+
def disable_sso (cluster):
5+
"""Disable SSO Sign-in"""
6+
disable_payload = {
7+
"ssoProvider": "NONE",
8+
"loginPage": "STANDARD",
9+
"ssoEnabled": False,
10+
"ssoGroupsEnabled": False,
11+
"ssoLoginDisabled": True
12+
}
13+
response = rh.cluster_post(cluster, "sso/ssoProvider", json=disable_payload)
14+
return response.status_code
15+
16+
def enable_sso(cluster, disable_local=False, groups_enabled=False, is_openid=False):
17+
"""Turns on SSO that has already been configured"""
18+
enable_payload = {
19+
"ssoProvider":"SAML",
20+
"loginPage":"STANDARD",
21+
"ssoEnabled":True,
22+
"ssoGroupsEnabled":False,
23+
"ssoLoginDisabled":False
24+
}
25+
26+
if disable_local:
27+
enable_payload['loginPage'] = "SSO"
28+
if groups_enabled:
29+
enable_payload['ssoGroupsEnabled'] = True
30+
if is_openid:
31+
enable_payload['ssoProvider'] = "OIDC"
32+
33+
response = rh.cluster_post(cluster, "sso/ssoProvider", json=enable_payload)
34+
return response.status_code
35+
36+
def get_sso_status (cluster):
37+
response = rh.cluster_get(cluster, "sso/ssoProvider")
38+
return response.json()

dynatrace/cluster/user_groups.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#!/bin/python3
2+
"""Cluster Group Operations"""
3+
import user_variables
4+
from dynatrace.requests import request_handler as rh
5+
from dynatrace.tenant import management_zones as mzh
6+
7+
MZ_USER_PERMISSONS = {
8+
"access_env": "VIEWER",
9+
"change_settings": "MANAGE_SETTINGS",
10+
"view_logs": "LOG_VIEWER",
11+
"view_senstive": "VIEW_SENSITIVE_REQUEST_DATA"
12+
}
13+
14+
def generate_group_name(template, user_type, tenant, app_name):
15+
template = template.replace("{USER_TYPE}", user_type)
16+
template = template.replace("{TENANT}", tenant)
17+
template = template.replace("{APP_NAME}", app_name)
18+
template = template.lower()
19+
return template
20+
21+
def create_app_groups(cluster, app_name):
22+
"""Create Dynatrace User Groups for Applications"""
23+
role_types = user_variables.USER_GROUPS['role_types']
24+
role_tenants = user_variables.USER_GROUPS['role_tenants']
25+
26+
all_new_groups = {}
27+
for current_tenant in role_tenants:
28+
all_new_groups[current_tenant] = {}
29+
for current_type_key, current_type_value in role_types.items():
30+
group_id = generate_group_name(user_variables.USER_GROUP_TEMPLATE, current_type_value, current_tenant, app_name)
31+
current_group = {
32+
"isClusterAdminGroup": False,
33+
"name":group_id,
34+
"ldapGroupNames": [
35+
group_id,
36+
],
37+
"accessRight": {}
38+
}
39+
40+
response = rh.cluster_post(
41+
cluster,
42+
"groups",
43+
json=current_group
44+
)
45+
all_new_groups[current_tenant][current_type_key] = ((response.json())['id'])
46+
return all_new_groups
47+
48+
def create_app_groups_setwide(app_name):
49+
"""Create Dynatrace User Groups for Applications"""
50+
for cluster in user_variables.FULL_SET.values():
51+
if cluster['is_managed']:
52+
create_app_groups(cluster, app_name)
53+
54+
def delete_app_groups (cluster, app_name):
55+
role_types = user_variables.USER_GROUPS['role_types']
56+
role_tenants = user_variables.USER_GROUPS['role_tenants']
57+
58+
for current_tenant in role_tenants:
59+
for current_type_value in role_types:
60+
group_id = generate_group_name(user_variables.USER_GROUP_TEMPLATE, current_type_value, current_tenant, app_name)
61+
group_id = ''.join(e for e in group_id if e.isalnum())
62+
rh.cluster_delete(
63+
cluster,
64+
"groups/" + group_id
65+
)
66+
return
67+
68+
def delete_app_groups_setwide(app_name):
69+
"""Create Dynatrace User Groups for Applications"""
70+
for cluster in user_variables.FULL_SET.values():
71+
if cluster['is_managed']:
72+
delete_app_groups(cluster, app_name)
73+
74+
def create_app_clusterwide(cluster, app_name, zones=None):
75+
"""Create App User Groups and Management Zones"""
76+
# Create Standard App MZs
77+
mz_list = {}
78+
for tenant_key in cluster['tenant'].keys():
79+
mzh.add_management_zone(
80+
cluster,
81+
tenant_key,
82+
str.upper(app_name)
83+
)
84+
if tenant_key in zones:
85+
mz_list[tenant_key] = []
86+
for zone in zones[tenant_key]:
87+
mz_id = mzh.add_management_zone(
88+
cluster,
89+
tenant_key,
90+
str.upper(app_name),
91+
zone
92+
)
93+
if mz_id is not None:
94+
mz_list[tenant_key].append(mz_id)
95+
96+
# Create User Groups
97+
user_groups = create_app_groups(cluster, app_name)
98+
print(user_groups)
99+
100+
# for tenant in user_variables.USER_GROUPS['role_tenants']:
101+
# if "access_env" in user_groups [tenant]:
102+
# add_mz_to_user

dynatrace/cluster/users.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""User Operations in Cluster Mangement"""
2+
import dynatrace.requests.request_handler as rh
3+
4+
# TODO add check for is_managed
5+
6+
def check_is_managed(cluster, ignore_saas):
7+
"""Checks if the cluster is Managed"""
8+
if not cluster['is_managed'] and not ignore_saas:
9+
raise Exception ('Cannot run operation on SaaS instances!')
10+
return cluster['is_managed']
11+
12+
def get_users(cluster, ignore_saas=True):
13+
"""Get the list of Users on the Cluster"""
14+
check_is_managed(cluster, ignore_saas)
15+
response = rh.cluster_get(cluster, "users")
16+
return response.json()
17+
18+
def add_user(cluster, user_json, ignore_saas=True):
19+
"""Add User to Cluster"""
20+
check_is_managed(cluster, ignore_saas)
21+
rh.cluster_post(cluster, "/users", json=user_json)
22+
return 'OK'
23+
24+
def update_user(cluster, user_json, ignore_saas=True):
25+
"""Update User to Cluster"""
26+
check_is_managed(cluster, ignore_saas)
27+
rh.cluster_put(cluster, "/users", json=user_json)
28+
return 'OK'
29+
30+
def get_user(cluster, user_id, ignore_saas=True):
31+
"""Get Details for a Single User"""
32+
check_is_managed(cluster, ignore_saas)
33+
response = rh.cluster_get(cluster, "users/" + user_id)
34+
return response.json()
35+
36+
def delete_user(cluster, user_id, ignore_saas=True):
37+
"""Delete a Single User"""
38+
check_is_managed(cluster, ignore_saas)
39+
response = rh.cluster_delete(cluster, "users/" + user_id)
40+
return response.json()
41+
42+
def get_user_count(cluster, ignore_saas=True):
43+
"""Return the number of, users in a cluster"""
44+
check_is_managed(cluster, ignore_saas)
45+
return len(get_users(cluster))
46+
47+
def add_user_bulk(cluster, user_json, ignore_saas=True):
48+
"""Add Multiple Users"""
49+
check_is_managed(cluster, ignore_saas)
50+
rh.cluster_put(cluster, "/users/bulk", json=user_json)
51+
return 'OK'

0 commit comments

Comments
 (0)