Skip to content

Commit 0630bfc

Browse files
Merge pull request #806 from splunk/develop
Changes for UDS and 9.0.9 release
2 parents 64895a6 + d72e633 commit 0630bfc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+722
-383
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ test*.xml
2323
**/*.xml
2424
.pytest_cache
2525
version.txt
26+
env

default.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
hide_password: false
2+
retry_delay: 3
3+
retry_num: 60
4+
wait_for_splunk_retry_num: 60
5+
shc_sync_retry_num: 60
6+
splunk_home_ownership_enforcement: true
7+
8+
config:
9+
baked: default.yml
10+
defaults_dir: /tmp/defaults
11+
env:
12+
headers: null
13+
var: SPLUNK_DEFAULTS_URL
14+
verify: true
15+
host:
16+
headers: null
17+
url: null
18+
verify: true
19+
max_delay: 60
20+
max_retries: 3
21+
max_timeout: 1200
22+
23+
splunk:
24+
role: splunk_standalone
25+
enable_tcp_mode: false
26+
upgrade: false
27+
build_location: /tmp/splunk.tgz
28+
apps_location: null
29+
license_uri: null
30+
admin_user: admin
31+
app_paths:
32+
default: /opt/splunk/etc/apps
33+
deployment: /opt/splunk/etc/deployment-apps
34+
httpinput: /opt/splunk/etc/apps/splunk_httpinput
35+
idxc: /opt/splunk/etc/master-apps
36+
shc: /opt/splunk/etc/shcluster/apps
37+
enable_service: false
38+
exec: /opt/splunk/bin/splunk
39+
group: splunk
40+
hec:
41+
enable: True
42+
ssl: True
43+
port: 8088
44+
token: 4a8a737d-5452-426c-a6f7-106dca4e813f
45+
home: /opt/splunk
46+
http_enableSSL: 0
47+
http_enableSSL_cert: null
48+
http_enableSSL_privKey: null
49+
http_enableSSL_privKey_password: null
50+
http_port: 8000
51+
idxc:
52+
enable: false
53+
label: idxc_label
54+
replication_factor: 3
55+
replication_port: 9887
56+
search_factor: 3
57+
secret: dmwHG97SpM+GzeGPUELwr7xXowSAVmLW
58+
ignore_license: false
59+
license_download_dest: /tmp/splunk.lic
60+
opt: /opt
61+
password: helloworld
62+
pid: /opt/splunk/var/run/splunk/splunkd.pid
63+
s2s_enable: true
64+
s2s_port: 9997
65+
search_head_captain_url: null
66+
secret: null
67+
splunk_http_enabled: True
68+
shc:
69+
enable: false
70+
label: shc_label
71+
replication_factor: 3
72+
replication_port: 9887
73+
secret: EpcUlTUHMSOhdjRZb3QqPYf9Lf7L991c
74+
smartstore: null
75+
svc_port: 8089
76+
tar_dir: splunk
77+
user: splunk
78+
wildcard_license: false

docs/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* [9.1.1](#911)
99
* [9.1.0.2](#9102)
1010
* [9.1.0.1](#9101)
11+
* [9.0.9](#909)
1112
* [9.0.8](#908)
1213
* [9.0.7](#907)
1314
* [9.0.6](#906)
@@ -140,6 +141,14 @@
140141

141142
---
142143

144+
## 9.0.9
145+
146+
#### Changes
147+
* Support for latest major Splunk release
148+
* Documentation updates
149+
150+
---
151+
143152
## 9.0.8
144153

145154
#### Changes

inventory/environ.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ def getDefaultVars():
108108
environment variables to return a consolidated inventory object
109109
"""
110110
defaultVars = loadDefaults()
111+
defaultVars["splunk"]["role"] = os.environ.get('SPLUNK_ROLE', defaultVars["splunk"].get("role") or "splunk_standalone")
111112
overrideEnvironmentVars(defaultVars)
112113
getAnsibleContext(defaultVars)
113114
getASan(defaultVars)
@@ -124,7 +125,6 @@ def getDefaultVars():
124125
getSplunkdSSL(defaultVars)
125126
getDistributedTopology(defaultVars)
126127
getLicenses(defaultVars)
127-
defaultVars["splunk"]["role"] = os.environ.get('SPLUNK_ROLE', defaultVars["splunk"].get("role") or "splunk_standalone")
128128
# Determine DMC settings
129129
defaultVars["dmc_forwarder_monitoring"] = os.environ.get('DMC_FORWARDER_MONITORING', False)
130130
defaultVars["dmc_asset_interval"] = os.environ.get('DMC_ASSET_INTERVAL', '3,18,33,48 * * * *')
@@ -133,7 +133,6 @@ def getDefaultVars():
133133
if os.environ.get("SPLUNK_HOME_OWNERSHIP_ENFORCEMENT", "").lower() == "false":
134134
defaultVars["splunk_home_ownership_enforcement"] = False
135135
# Determine password visibility
136-
defaultVars["hide_password"] = False
137136
if os.environ.get("HIDE_PASSWORD", "").lower() == "true":
138137
defaultVars["hide_password"] = True
139138
# Determine SHC preferred captaincy
@@ -145,6 +144,7 @@ def getDefaultVars():
145144
getJava(defaultVars)
146145
getSplunkBuild(defaultVars)
147146
getSplunkbaseToken(defaultVars)
147+
getSplunkBuildAuth(defaultVars)
148148
getSplunkApps(defaultVars)
149149
getSplunkAppsLocal(defaultVars)
150150
getLaunchConf(defaultVars)
@@ -357,6 +357,13 @@ def getSplunkbaseToken(vars_scope):
357357
splunkbase_token = re.search("<id>(.*)</id>", output, re.IGNORECASE)
358358
vars_scope["splunkbase_token"] = splunkbase_token.group(1) if splunkbase_token else None
359359

360+
def getSplunkBuildAuth(vars_scope):
361+
"""
362+
Load username and password to be used in basic auth when fetching splunk build or apps
363+
"""
364+
vars_scope["splunk"]["artifact_auth_user"] = os.environ.get("ARTIFACTORY_USER", vars_scope["splunk"].get("artifact_auth_user"))
365+
vars_scope["splunk"]["artifact_auth_pass"] = os.environ.get("ARTIFACTORY_TOKEN", vars_scope["splunk"].get("artifact_auth_pass"))
366+
360367
def getSplunkApps(vars_scope):
361368
"""
362369
Determine the set of Splunk apps to install as union of defaults.yml and environment variables
@@ -566,6 +573,7 @@ def overrideEnvironmentVars(vars_scope):
566573
vars_scope["cert_prefix"] = os.environ.get("SPLUNK_CERT_PREFIX", vars_scope.get("cert_prefix", "https"))
567574
vars_scope["splunk"]["root_endpoint"] = os.environ.get('SPLUNK_ROOT_ENDPOINT', vars_scope["splunk"]["root_endpoint"])
568575
vars_scope["splunk"]["svc_port"] = os.environ.get('SPLUNK_SVC_PORT', vars_scope["splunk"]["svc_port"])
576+
vars_scope["splunk"]["splunk_http_enabled"] = os.environ.get('ENABLE_TCP_MODE', vars_scope["splunk"]["enable_tcp_mode"])
569577
vars_scope["splunk"]["s2s"]["port"] = int(os.environ.get('SPLUNK_S2S_PORT', vars_scope["splunk"]["s2s"]["port"]))
570578
vars_scope["splunk"]["enable_service"] = os.environ.get('SPLUNK_ENABLE_SERVICE', vars_scope["splunk"]["enable_service"])
571579
vars_scope["splunk"]["service_name"] = os.environ.get('SPLUNK_SERVICE_NAME', vars_scope["splunk"]["service_name"])
@@ -574,6 +582,8 @@ def overrideEnvironmentVars(vars_scope):
574582
vars_scope["splunk"]["kvstore"]["port"] = os.environ.get('SPLUNK_KVSTORE_PORT', vars_scope["splunk"]["kvstore"]["port"])
575583
vars_scope["splunk"]["connection_timeout"] = int(os.environ.get('SPLUNK_CONNECTION_TIMEOUT', vars_scope["splunk"]["connection_timeout"]))
576584

585+
if vars_scope["splunk"]["splunk_http_enabled"] == "false" and "forwarder" not in vars_scope["splunk"]["role"].lower():
586+
vars_scope["splunk"]["splunk_http_enabled"] = "true"
577587
# Set set_search_peers to False to disable peering to indexers when creating multisite topology
578588
if os.environ.get("SPLUNK_SET_SEARCH_PEERS", "").lower() == "false":
579589
vars_scope["splunk"]["set_search_peers"] = False

inventory/splunk_defaults_linux.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ansible_post_tasks:
44
ansible_environment: {}
55
retry_delay: 6
66
retry_num: 60
7+
hide_password: false
78
wait_for_splunk_retry_num: 60
89
shc_sync_retry_num: 60
910

@@ -23,6 +24,7 @@ config:
2324
verify: True
2425

2526
splunk:
27+
enable_tcp_mode: False
2628
build_location:
2729
allow_upgrade: True
2830
tar_dir: "splunk"
@@ -31,6 +33,7 @@ splunk:
3133
user: "splunk"
3234
group: "splunk"
3335
exec: !!python/object/apply:os.path.join [*home, "bin", "splunk"]
36+
uds_socket_path_url: "%2Fopt%2Fsplunkforwarder%2Fvar%2Frun%2Fsplunk%2Fcli.socket"
3437
pid: !!python/object/apply:os.path.join [*home, "var", "run", "splunk", "splunkd.pid"]
3538
admin_user: "admin"
3639
root_endpoint:

inventory/splunk_defaults_windows.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ansible_post_tasks:
44
ansible_environment: {}
55
retry_delay: 10
66
retry_num: 60
7+
hide_password: false
78
wait_for_splunk_retry_num: 150
89
shc_sync_retry_num: 300
910

@@ -23,6 +24,7 @@ config:
2324
verify: True
2425

2526
splunk:
27+
enable_tcp_mode: False
2628
build_location:
2729
allow_upgrade: True
2830
tar_dir: "splunk"

inventory/splunkforwarder_defaults_linux.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ansible_post_tasks:
44
ansible_environment: {}
55
retry_delay: 6
66
retry_num: 60
7+
hide_password: false
78
wait_for_splunk_retry_num: 60
89
shc_sync_retry_num: 60
910

@@ -24,6 +25,7 @@ config:
2425

2526
splunk:
2627
build_location:
28+
enable_tcp_mode: False
2729
allow_upgrade: True
2830
tar_dir: "splunkforwarder"
2931
opt: &opt "/opt"

inventory/splunkforwarder_defaults_windows.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ ansible_post_tasks:
44
ansible_environment: {}
55
retry_delay: 10
66
retry_num: 60
7+
hide_password: false
78
wait_for_splunk_retry_num: 150
89
shc_sync_retry_num: 300
910

@@ -24,6 +25,7 @@ config:
2425

2526
splunk:
2627
build_location:
28+
enable_tcp_mode: False
2729
allow_upgrade: True
2830
tar_dir: "splunkforwarder"
2931
opt: &opt "/opt"

library/splunk_api.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#!/usr/bin/python
2+
3+
from ansible.module_utils.basic import AnsibleModule
4+
import os
5+
import requests
6+
import requests_unixsocket
7+
import json
8+
9+
UDS_SOCKET_PATH = "/opt/splunkforwarder/var/run/splunk/cli.socket"
10+
UDS_SOCKET_PATH_URL = "%2Fopt%2Fsplunkforwarder%2Fvar%2Frun%2Fsplunk%2Fcli.socket"
11+
12+
def supports_uds():
13+
return os.path.exists(UDS_SOCKET_PATH)
14+
15+
def api_call_tcp(cert_prefix, method, endpoint, username, password, svc_port, payload=None, headers=None, verify=False, status_code=None, timeout=None, body_format=None):
16+
if not cert_prefix or cert_prefix not in ['http', 'https']:
17+
cert_prefix = 'https'
18+
if not svc_port:
19+
svc_port = 8089
20+
url = "{}://127.0.0.1:{}{}".format(cert_prefix, svc_port, endpoint)
21+
if headers is None:
22+
headers = {}
23+
headers['Content-Type'] = 'application/json'
24+
auth = (username, password)
25+
26+
data = None
27+
if payload and body_format and body_format == "form-urlencoded":
28+
data = payload
29+
elif payload:
30+
data = json.dumps(payload)
31+
32+
session = requests.Session()
33+
# Disable SSL verification for the session
34+
session.verify = False
35+
36+
response = None
37+
excep_str = "No Exception"
38+
try:
39+
if data is None:
40+
response = session.request(method, url, headers=headers, auth=auth, verify=verify, timeout=timeout)
41+
else:
42+
response = session.request(method, url, headers=headers, auth=auth, data=data, verify=verify, timeout=timeout)
43+
if status_code is not None and response.status_code not in status_code:
44+
raise ValueError("API call for {} and data as {} failed with status code {}: {}".format(url, payload, response.status_code, response.text))
45+
except Exception as e:
46+
excep_str = "URL: {}; data: {}, exception: {}".format(url, data, e)
47+
cwd = os.getcwd()
48+
return response, excep_str
49+
50+
def api_call_uds(method, endpoint, username, password, svc_port, payload=None, headers=None, verify=False, status_code=None, timeout=None, body_format=None):
51+
url = "http+unix://{}{}".format(UDS_SOCKET_PATH_URL,endpoint)
52+
if headers is None:
53+
headers = {}
54+
headers['Content-Type'] = 'application/json'
55+
auth = (username, password)
56+
57+
session = requests_unixsocket.Session()
58+
# Disable SSL verification for the session
59+
session.verify = False
60+
61+
data = None
62+
if payload and body_format and body_format == "form-urlencoded":
63+
data = payload
64+
elif payload:
65+
data = json.dumps(payload)
66+
67+
excep_str = "No Exception"
68+
response = None
69+
try:
70+
if data is None:
71+
response = session.request(method, url, headers=headers, auth=auth, verify=verify, timeout=timeout)
72+
else:
73+
response = session.request(method, url, headers=headers, auth=auth, data=data, verify=verify, timeout=timeout)
74+
if status_code is not None and response.status_code not in status_code:
75+
raise ValueError("API call for {} and data as {} failed with status code {}: {}".format(url, payload, response.status_code, response.text))
76+
except Exception as e:
77+
excep_str = "{}".format(e)
78+
return response, excep_str
79+
80+
def main():
81+
module_args = dict(
82+
method=dict(type='str', required=True),
83+
url=dict(type='str', required=True),
84+
username=dict(type='str', required=True),
85+
password=dict(type='str', required=True, no_log=True),
86+
cert_prefix=dict(type='str', required=False),
87+
body=dict(type='dict', required=False),
88+
body_format=dict(type='str', required=False),
89+
headers=dict(type='dict', required=False),
90+
verify=dict(type='bool', required=False),
91+
return_content=dict(type='bool', required=False),
92+
use_proxy=dict(type='str', required=False),
93+
status_code=dict(type='list', required=False),
94+
timeout=dict(type='int', required=False),
95+
svc_port=dict(type='int', required=False)
96+
)
97+
98+
module = AnsibleModule(
99+
argument_spec=module_args,
100+
supports_check_mode=True
101+
)
102+
103+
if module.check_mode:
104+
module.exit_json(changed=False)
105+
106+
method = module.params['method']
107+
endpoint = module.params['url']
108+
username = module.params['username']
109+
password = module.params['password']
110+
cert_prefix = module.params.get('cert_prefix', 'http')
111+
body_format = module.params.get('body_format', None)
112+
payload = module.params.get('body', None)
113+
headers = module.params.get('headers', None)
114+
verify = module.params.get('verify', False)
115+
status_code = module.params.get('status_code', None)
116+
timeout = module.params.get('timeout', None)
117+
svc_port = module.params.get('svc_port', 8089)
118+
return_content = module.params.get('return_content', False)
119+
use_proxy = module.params.get('use_proxy', "no")
120+
121+
if status_code:
122+
status_code = [int(x) for x in status_code]
123+
if not use_proxy:
124+
use_proxy = 'no'
125+
if not return_content:
126+
return_content = False
127+
128+
s = "{}{}{}{}{}{}{}{}{}".format(method, endpoint, username, password, svc_port, payload, headers, verify, status_code, timeout)
129+
if supports_uds():
130+
response, excep_str = api_call_uds(method, endpoint, username, password, svc_port, payload, headers, verify, status_code, timeout, body_format)
131+
else:
132+
response, excep_str = api_call_tcp(cert_prefix, method, endpoint, username, password, svc_port, payload, headers, verify, status_code, timeout, body_format)
133+
134+
if response is not None and ((status_code and response.status_code in status_code) or (status_code is None and response.status_code >= 200 and response.status_code < 300)):
135+
try:
136+
content = response.json()
137+
except:
138+
content = response.text
139+
module.exit_json(changed=True, status = response.status_code, json=content,excep_str=excep_str)
140+
else:
141+
if response is None:
142+
module.fail_json(msg="{};;; failed with NO RESPONSE and EXCEP_STR as {}".format(s, excep_str))
143+
else:
144+
module.fail_json(msg="{};;; AND excep_str: {}, failed with status code {}: {}".format(s, excep_str, response.status_code, response.text))
145+
146+
if __name__ == '__main__':
147+
main()

0 commit comments

Comments
 (0)