Skip to content

Commit 20402d5

Browse files
Merge pull request #69 from splunk/dev-class-based
Refactor: Switch from singular utils.py with all fuctions to class based approach
2 parents db42ba8 + 401e7d7 commit 20402d5

File tree

11 files changed

+672
-577
lines changed

11 files changed

+672
-577
lines changed

.github/workflows/deploy.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ jobs:
3232
run: |
3333
python -m pip install --upgrade pip
3434
pip install --upgrade pyyaml
35-
pip install boto3
36-
pip install requests
35+
pip install boto3 requests schema
3736
- name: Deploy to ${{ matrix.environment.name }}
3837
continue-on-error: true
3938
env:
@@ -42,9 +41,10 @@ jobs:
4241
SPLUNK_USERNAME: ${{ secrets.SPLUNK_USERNAME }}
4342
SPLUNK_PASSWORD: ${{ secrets.SPLUNK_PASSWORD }}
4443
SPLUNK_TOKEN: ${{ secrets[matrix.environment.token_key] }}
44+
DEPLOYMENT_CONFIG_PATH: "environments/${{ matrix.environment.name }}"
4545
run: |
4646
echo "Deploying to ${{ matrix.environment.name }} environment"
47-
python -u deploy.py ${{ matrix.environment.name }}
47+
python -u deploy.py
4848
- name: Upload deployment report as artifact
4949
uses: actions/upload-artifact@v3
5050
with:

README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Splunk Apps Deployment Architecture
2-
This is just an idea developed for Philips Electronics Nederland within the context of [JIRA ticket](https://splunk.atlassian.net/browse/FDSE-2571). To be extended and used at own risk.
2+
This is just an idea developed within the context of [JIRA ticket](https://splunk.atlassian.net/browse/FDSE-2571). To be extended and used at own risk.
33

44
Assumptions:
55
* All apps are stored into a single GitHub repository
@@ -17,6 +17,10 @@ Assumptions:
1717
│ ├── collections.conf
1818
│ └── logging.conf
1919
├── deploy.py
20+
├── modules
21+
│ ├── apps_processing.py
22+
│ ├── report_generator.py
23+
│ └── splunkcloud.py
2024
└── environments
2125
├── prod
2226
│ ├── es
@@ -38,16 +42,19 @@ Assumptions:
3842
* deployment instructions per each environment (`deployment.yml`)
3943
* specific apps configurations (e.g. `uat/es/app1`)
4044
* `deploy.py` Used by the automation to perform the deployment
45+
* `modules/` Contains methods used in deployment automation
4146

4247
This repository follows the same structure. Please navigate it to verify its content.
4348

4449
### `deployment.yml`
4550
As mentioned, these deployment files specify the apps and configurations needed on each specific environment. Example:
4651
```yml
4752
target:
48-
url: <deployment server URL>
53+
url: https://admin.splunk.com/{stack}
54+
experience: <victoria|classic>
4955
apps:
5056
# Private apps
57+
# - Leave empty if target does not need private apps
5158
app1:
5259
s3-bucket: bucket-1
5360
source: apps/app1.tgz
@@ -57,7 +64,8 @@ apps:
5764
- ./app1/*.conf
5865
splunkbase-apps:
5966
# Splunkbase apps
60-
cb-protection-app-for-splunk:
67+
# - Leave empty if target does not need private apps
68+
Cb Protection App for Splunk:
6169
version: 1.0.0
6270
```
6371

deploy.py

Lines changed: 71 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,92 @@
1-
import sys
2-
import json
31
import os
2+
import boto3
43

5-
import yaml
4+
from modules.splunkcloud import SplunkCloudConnector
5+
from modules.apps_processing import AppFilesProcessor, DeploymentParser
6+
from modules.report_generator import DeploymentReportGenerator
67

7-
from utils import *
8+
DEPLOYMENT_CONFIG_PATH = os.getenv("DEPLOYMENT_CONFIG_PATH")
89

9-
# FOR LOCAL TESTING
10-
# from dotenv import load_dotenv
11-
# load_dotenv(dotenv_path="local.env")
1210

1311
def main():
14-
if len(sys.argv) != 2:
15-
print("Usage: python script.py <path_to_yaml_file>")
16-
sys.exit(1)
12+
# Initiate deployment report
13+
deployment_report = DeploymentReportGenerator()
14+
# Initiate AwsS3Connector object
15+
s3_connector = boto3.client("s3")
16+
# Initiate DeploymentParser object
17+
config = DeploymentParser()
18+
# Initiate AppFilesProcessor object
19+
app_processor = AppFilesProcessor(config)
20+
# Initiate SplunkCloudConnector object
21+
cloud_connector = SplunkCloudConnector(config.url, config.cloud_experience)
1722

18-
yaml_file_path = "environments/" + sys.argv[1] + "/deployment.yml"
19-
20-
deployment_report = {}
21-
22-
try:
23-
data = read_yaml(yaml_file_path)
24-
except FileNotFoundError:
25-
print(f"Error: The file '{yaml_file_path}' was not found.")
26-
except yaml.YAMLError as e:
27-
print(f"Error parsing YAML file: {e}")
28-
sys.exit(1)
29-
### 1. Validate data and retrieve all apps listed in deployment.yml from S3 ###
30-
private_apps, splunkbase_apps = validate_data(data)
31-
# List all apps in yaml file and then their S3 bucket
32-
if private_apps:
33-
apps = data.get("apps", {}).keys()
34-
s3_buckets = [data["apps"][app]["s3-bucket"] for app in apps]
35-
app_directories = [data["apps"][app]["source"] for app in apps]
36-
target_url = data["target"]["url"]
37-
# Download all apps from S3
38-
if private_apps:
39-
print("Found private apps in deployment.yml, starting deployment...")
40-
for app, bucket, directory in zip(apps, s3_buckets, app_directories):
41-
object_name = directory
23+
# Check for private apps
24+
if config.has_private_apps():
25+
print("Found private apps, starting deployment...")
26+
# Loop through all apps
27+
for app in config.private_apps.keys():
28+
bucket = config.get_bucket(app)
29+
app_path = config.get_app_path(app)
4230
file_name = f"{app}.tgz"
4331
# Donwload app from S3
44-
download_file_from_s3(bucket, object_name, file_name)
32+
try:
33+
s3_connector.download_file(bucket, app_path, file_name)
34+
except Exception as e:
35+
raise Exception(f"Error downloading {app_path} from {bucket}: {e}")
4536

46-
### 2. Upload_local_configuration ###
47-
# Check if the configuration exists for the app
48-
path = os.path.join("environments", sys.argv[1], app)
49-
print(path)
50-
if path:
51-
unpack_merge_conf_and_meta_repack(app, path)
37+
### Upload_local_configuration ###
38+
# Check whether the app needs specific configs for this env
39+
path = os.path.join(DEPLOYMENT_CONFIG_PATH, app)
40+
if len(config.get_app_configs(app)) > 0:
41+
app_processor.unpack_merge_conf_and_meta_repack(app, path)
5242
else:
53-
print(f"No configuration found for app {app}. Skipping.")
43+
print(f"No configurations needed for app {app}. Skipping.")
5444

55-
### 3. Validate app for Splunk Cloud ###
56-
report, token = cloud_validate_app(app)
57-
if report is None:
58-
print(f"App {app} failed validation.")
59-
deployment_report[app] = {"validation": "failed"}
45+
### Validate app for Splunk Cloud ###
46+
appinspect_handler = cloud_connector.get_appinspect_handler()
47+
is_valid = appinspect_handler.validate(app)
48+
if not is_valid:
49+
print(f"App {app} failed validation. Skipping distribution.\n")
50+
deployment_report.add_data(app, ("report", appinspect_handler.report))
51+
deployment_report.add_data(app, ("validation", "failed"))
52+
deployment_report.add_data(
53+
app, ("distribution", "failed due to app validation error")
54+
)
6055
continue
61-
result = report["summary"]
62-
deployment_report[app] = report
63-
### 4. If app is valid, distribute it ###
64-
if (
65-
result["error"] == 0
66-
and result["failure"] == 0
67-
and result["manual_check"] == 0
68-
):
69-
distribution_status = distribute_app(app, target_url, token)
70-
if distribution_status == 200:
71-
print(f"App {app} successfully distributed.\n")
72-
deployment_report[app]["distribution"] = "success"
73-
else:
74-
print(f"App {app} failed distribution.")
75-
deployment_report[app][
76-
"distribution"
77-
] = f"failed with status code: {distribution_status}"
56+
### App is valid: distribute it ###
57+
deployment_report.add_data(app, ("report", appinspect_handler.report))
58+
dist_succeeded, dist_status = cloud_connector.distribute(app)
59+
if dist_succeeded:
60+
print(f"App {app} successfully distributed.\n")
61+
deployment_report.add_data(app, ("distribution", "success"))
7862
else:
79-
print(f"App {app} failed validation. Skipping distribution.\n")
80-
deployment_report[app][
81-
"distribution"
82-
] = "failed due to app validation error"
63+
print(f"App {app} failed distribution.")
64+
deployment_report.add_data(
65+
app,
66+
(
67+
"distribution",
68+
f"failed with status code: {dist_status}",
69+
),
70+
)
8371
else:
84-
print("No private apps found in deployment.yml, skipping...")
72+
print("No private apps found, skipping...")
8573

86-
### 5. Handle Splunkbase apps ###
87-
if splunkbase_apps:
88-
print("Found Splunkbase apps in deployment.yml, starting deployment...")
89-
splunkbase_apps_dict = data.get("splunkbase-apps", {})
90-
for splunkbase_app in splunkbase_apps_dict:
91-
app = splunkbase_apps_dict[splunkbase_app]
92-
app_name = splunkbase_app
93-
version = app['version']
94-
app_id = get_app_id(app_name)
95-
token = os.getenv("SPLUNK_TOKEN")
96-
license = get_license_url(app_name)
97-
install_status = install_splunkbase_app(app_name, app_id, version, target_url, token, license)
98-
print(f"App {app_name} installation status: {install_status}")
99-
deployment_report[app_name] = {
100-
"splunkbase_installation": install_status,
101-
"version": version,
102-
"app_id": app_id,
103-
}
74+
### Handle Splunkbase apps ###
75+
if config.has_splunkbase_apps():
76+
print("Found Splunkbase apps, starting deployment...")
77+
for splunkbase_app in config.splunkbase_apps.keys():
78+
version = config.get_version(splunkbase_app)
79+
install_status = cloud_connector.install(splunkbase_app, version)
80+
print(f"App {splunkbase_app} installation status: {install_status}")
81+
deployment_report.add_data(
82+
splunkbase_app,
83+
{"splunkbase_installation": install_status, "version": version},
84+
)
10485
else:
105-
print("No Splunkbase apps found in deployment.yml, skipping...")
86+
print("No Splunkbase apps found, skipping...")
10687

107-
### 6. Save deployment report to json file ###
108-
report_prefix = f"{sys.argv[1].split('/')[-2]}_{sys.argv[1].split('/')[-1]}"
109-
output_dir = "artifacts"
110-
os.makedirs(output_dir, exist_ok=True)
111-
with open(f"{output_dir}/{report_prefix}_deployment_report.json", "w") as file:
112-
json.dump(deployment_report, file)
88+
### Save deployment report to json file ###
89+
deployment_report.generate_report()
11390

11491

11592
if __name__ == "__main__":

environments/prod/es/deployment.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
target:
22
url: https://splunk-es-prod.example.com
3+
experience: classic
34
apps:
45
app1:
56
s3-bucket: splunk-apps-deployment
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
target:
22
url: <Staging ES URL>
3+
experience: <classic|victoria>
34
apps:
45
app1:
56
s3-bucket: splunk-apps-deployment
6-
source: apps/Splunk_TA_app1.tgz
7+
source: apps/Splunk_TA_app1.tgz
8+
splunkbase-apps:

environments/uat/es/deployment.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
target:
2-
url: https://staging.admin.splunk.com/scv-shw-217bd09bcbf264/adminconfig/v2/apps/victoria
2+
url: https://staging.admin.splunk.com/scv-shw-a7f6020a334e01
3+
experience: victoria
34
apps:
45
Splunk_TA_app1:
56
s3-bucket: splunk-apps-deployment
@@ -12,7 +13,6 @@ apps:
1213
config:
1314
- ./buttercup_app_for_splunk/*.conf
1415
splunkbase-apps:
15-
# Splunkbase apps
1616
Splunk Add-on for Amazon Web Services:
1717
version: 7.9.0
1818
Cisco Networks Add-on for Splunk Enterprise:
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
target:
2-
url: https://staging.admin.splunk.com/scv-shw-d037e758abafa2/adminconfig/v2/apps/victoria
2+
url: https://staging.admin.splunk.com/scv-shw-d037e758abafa2
3+
experience: victoria
34
apps:
45
Splunk_TA_app1:
56
s3-bucket: splunk-apps-deployment
67
source: apps/Splunk_TA_app1.tgz
78
config:
89
- ./Splunk_TA_app1/*.conf
910
splunkbase-apps:
10-
TA for Tebable:
11+
Tenable Add-On for Splunk:
1112
version: 7.0.0
12-
TA for MS Azure:
13+
Splunk Add on for Microsoft Azure:
1314
version: 4.2.0

0 commit comments

Comments
 (0)