-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6e98d8b
commit 2b7694f
Showing
7 changed files
with
346 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
__author__ = 'etejeda' | ||
import argparse | ||
from argparse import RawTextHelpFormatter | ||
try: | ||
import configparser | ||
except ImportError as e: | ||
import ConfigParser as configparser | ||
from ecli.lib.dictutils import DictUtils | ||
from bertdotconfig import Config | ||
import json | ||
import os | ||
import getpass | ||
import requests | ||
from requests.auth import HTTPBasicAuth | ||
import sys | ||
import warnings | ||
try: | ||
import urllib.parse as urllib | ||
except ImportError as e: | ||
import urllib | ||
|
||
# compatibility | ||
python_version_major = sys.version_info.major | ||
|
||
# requests stuffs | ||
requests.packages.urllib3.disable_warnings() | ||
|
||
# Internals | ||
current_user = getpass.getuser() | ||
config = '~/.{u}.conflutil'.format(u=current_user) | ||
|
||
# Messages | ||
msg_Invalid_Credentials = """You did not specify valid credentials | ||
and a valid [Auth] section was not found in the specified or default configuration file ({c}). | ||
Proceeding with NO Authentication""" | ||
msg_INVALID_CONFIG = "No valid config file specified and I could not find a default configuration: {c}" | ||
msg_IMPROPER_CONFIG = 'I did find a valid config file but it is improperly formatted: {c}' | ||
msg_NO_CONTENT = 'Although you may have specified a document, there was a problem determining its content' | ||
msg_NO_DOCUMENT = 'You didn''t specify a valid document path (-d option). See usage!' | ||
msg_NO_PAGE_ID = "You didn't specify a PAGE ID" | ||
msg_NO_PAGE_KEY = "You didn't specify a PAGE Key, e.g. VIP" | ||
msg_HTTP_ERROR = 'There was an error updating or creating the specified page: {e}' | ||
msg_RETRV_ERROR = 'Failed in retrieving Confluence object information for "{p}", {msg}' | ||
|
||
# Parse Command-line Parameters | ||
parser = argparse.ArgumentParser( | ||
description='Creates and/or updates a specified confluence page from specified document', | ||
formatter_class=RawTextHelpFormatter, | ||
epilog="""Default configuration file is {c}) formatted as: | ||
[Auth] | ||
username = TomTester | ||
password = 123456ABCD | ||
[API] | ||
server = 'www.confluence.example.local', | ||
rest_endpoint = '/rest/api/content/' | ||
""".format(c=config)) | ||
|
||
parser.add_argument("--config", '-c', | ||
help="Manually specify a configuration file instead of default file path (~/.$USERNAME.confluence)") | ||
parser.add_argument("--username", '-u', help="Specify username used in authentication") | ||
parser.add_argument("--password", '-p', help="Specify password used in authentication") | ||
parser.add_argument("--server", '-s', help="Specify the Confluence server, e.g. www.confluence.example.local") | ||
parser.add_argument("--rest-endpoint", '-r', | ||
help="Specify the Confluence rest api endpoint, e.g. /confluence/rest/api/content/") | ||
parser.add_argument("--document", '-d', help="Specify the document you'll be pushing up") | ||
parser.add_argument("--page-key", '-key', help="Specify the confluence page key, e.g. VIP") | ||
parser.add_argument("--page-id", '-id', help="Specify the confluence page id") | ||
parser.add_argument("--page-title", '-title', help="Specify the confluence page title") | ||
parameters, args = parser.parse_known_args() | ||
|
||
|
||
# Catch bad system calls | ||
if not len(sys.argv[1:]) > 0: | ||
parser.print_help() | ||
sys.exit(0) | ||
|
||
# Content origination | ||
document = parameters.document if parameters.document else None | ||
if not document or not os.path.exists(document): | ||
print(msg_NO_DOCUMENT) | ||
parser.print_help() | ||
print('\n\n' + msg_NO_DOCUMENT) | ||
sys.exit(0) | ||
else: | ||
document_content = open(document).read() | ||
|
||
# Configuration Files | ||
try: | ||
script_dir = os.path.dirname(os.path.abspath(my.invocation.path)) | ||
except NameError: | ||
script_dir = os.path.dirname(os.path.abspath(__file__)) | ||
config_file = os.path.abspath(os.path.join(script_dir, 'config.yaml')) | ||
# Initialize Config | ||
config = Config(config_file_uri=config_file).read() | ||
|
||
# Content origination | ||
document = parameters.document if parameters.document else None | ||
if not document or not os.path.exists(document): | ||
print(msg_NO_DOCUMENT) | ||
parser.print_help() | ||
print('\n\n' + msg_NO_DOCUMENT) | ||
sys.exit(0) | ||
else: | ||
document_content = open(document).read() | ||
|
||
# Catch specified credentials | ||
if all([parameters.username, parameters.password]) or len(args) >= 2: | ||
if args: | ||
username = args[0] | ||
password = args[1] | ||
else: | ||
username = parameters.username | ||
password = parameters.password | ||
elif not config_has_auth: | ||
warnings.warn(msg_Invalid_Credentials.format(c=config)) | ||
|
||
# Catch Config errors | ||
if not any([config_exists, parameters.config]): | ||
quit(msg_INVALID_CONFIG.format(c=config)) | ||
elif not config_is_valid: | ||
quit(msg_IMPROPER_CONFIG.format(c=config)) | ||
|
||
# Variables | ||
username = parameters.username if parameters.username else cfg.get('Auth', 'username') | ||
password = parameters.password if parameters.password else cfg.get('Auth', 'password') | ||
page_title = parameters.page_title if parameters.page_title else os.path.basename(document).split('.')[0] | ||
page_title_safe = urllib.quote(page_title, safe='') | ||
safe_password = urllib.quote(password, safe='') | ||
rest_endpoint = parameters.rest_endpoint if parameters.rest_endpoint else cfg.get('API', 'rest_endpoint') | ||
server = parameters.server if parameters.server else cfg.get('API', 'server') | ||
page_id = parameters.page_id if parameters.page_id else None | ||
page_key = parameters.page_key if parameters.page_key else quit(msg_NO_PAGE_KEY) | ||
|
||
url_http_get = 'https://{u}:{p}@{s}{r}?space={k}&title={t}'.format( | ||
u=username, | ||
p=safe_password, | ||
s=server, | ||
r=rest_endpoint, | ||
k=page_key, | ||
t=page_title_safe | ||
) | ||
|
||
def get_page_data(u=url_http_get): | ||
headers = {'X-Atlassian-Token': 'no-check', 'content-type': 'application/json'} | ||
response = requests.get(u, headers=headers, verify=False) | ||
if not response.status_code == 200: | ||
error = json.loads(response.text)['message'] | ||
quit(msg_HTTP_ERROR.format(e=error)) | ||
return response | ||
|
||
|
||
def update_page(content, title=None, **kwargs): | ||
page = type('obj', (object,), {'type': 'obj_container'}) | ||
try: | ||
if python_version_major > 2: | ||
page_data = get_page_data().json().items() | ||
else: | ||
page_data = get_page_data().json().iteritems() | ||
except Exception as e: | ||
quit(msg_RETRV_ERROR.format(p=page_title, msg="error was %s" % e)) | ||
[setattr(page, str(k), v) for k, v in page_data] | ||
if not len(page.results) > 0: | ||
quit(msg_RETRV_ERROR.format(p=page_title, msg="does this page exist?")) | ||
page_id = page.results[0]['id'] | ||
page_content_url = page.results[0]['_links']['self'] | ||
page_content_auth_url = page_content_url.replace("https://", "https://%s:%s@" % (username, safe_password)) | ||
page_metadata = get_page_data(page_content_auth_url) | ||
old_version = int(page_metadata.json()['version']['number']) | ||
new_version = old_version + 1 | ||
content = content if content else quit(msg_NO_CONTENT) | ||
title = title if title else page.results[0]['title'] | ||
data = {"id": page_id, "type": "page", "title": title, | ||
"space": {"key": page_key}, | ||
"body": {"storage": {"value": content, "representation": "wiki"}}, | ||
"version": {"number": str(new_version)}} | ||
headers = {'X-Atlassian-Token': 'no-check', 'content-type': 'application/json'} | ||
response = requests.put(page_content_url, headers=headers, data=json.dumps(data), | ||
verify=False,auth=HTTPBasicAuth(username, password)) | ||
if not response.status_code == 200: | ||
try: | ||
response_message = "\n" + json.loads(response.text)['message'] | ||
except Exception: | ||
response_message = "" | ||
error_message = "HTTP Return Code: %s Reason: %s %s" % (response.status_code, response.reason, response_message) | ||
quit(msg_HTTP_ERROR.format(e=error_message)) | ||
return response.status_code | ||
|
||
|
||
if __name__ == '__main__': | ||
result = update_page(document_content) | ||
if result == 200: | ||
print("Success: Document Published") | ||
elif result.startswith("5"): | ||
print("Fail: Something went wrong, error: {e}".format(e=result)) | ||
sys.exit(result) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
[CmdletBinding()] | ||
param ([Parameter(Mandatory=$False, ValueFromPipelineByPropertyName=$True,Position=0)][Alias('user')]$UserName, | ||
[Parameter(Mandatory=$False,Position=1)]$Password, | ||
[ValidateNotNull()] | ||
[System.Management.Automation.PSCredential] | ||
[System.Management.Automation.Credential()] | ||
$Credentials = [System.Management.Automation.PSCredential]::Empty, | ||
[Parameter(Mandatory=$True,Position=3)]$URL, | ||
[Parameter(Mandatory=$False,Position=4)]$OutFile | ||
) | ||
|
||
switch ($True) { | ||
($Credentials.username -and $Credentials.password) { | ||
$Username = ($Credentials.GetNetworkCredential()).username | ||
$ClearPassword = ($Credentials.GetNetworkCredential()).password | ||
break; | ||
} | ||
(!$UserName) {$UserName = Read-Host "Enter your Bitbucket Username"} | ||
(!$Password) { | ||
$Password = Read-Host "Enter your Bitbucket Password" -AsSecureString | ||
$ClearPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)) | ||
} | ||
($Password -ne '') {$ClearPassword = $Password;break} | ||
default { break;} | ||
} | ||
$ClearCredentials = "$UserName`:$ClearPassword" | ||
$encodedCredentials = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($ClearCredentials)) | ||
$authorization = "Basic $encodedCredentials" | ||
$Headers = @{ | ||
Authorization = $authorization | ||
"Content-Type" = "application/json" | ||
} | ||
|
||
$RequestURL = "$URL/?raw" | ||
|
||
if ($OutFile){ | ||
Invoke-WebRequest -Headers $Headers $RequestURL -OutFile $OutFile | ||
} else { | ||
return $(Invoke-WebRequest -Headers $Headers $RequestURL).content | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#!/usr/bin/env bash | ||
|
||
script_dir=${0%/*} | ||
script_name=${0##*/} | ||
script_base_name=${script_name%%.*} | ||
script_dir_name=${script_dir##*/} | ||
baseurl=https://service-now.example.local | ||
__docstring__="Query ServiceNow" | ||
|
||
USAGE=""" | ||
Usage: ${script_dir_name}.${script_base_name} | ||
param: [--username|-u <Rancher Username>] | ||
param: [--password|-p <Rancher Password>] | ||
param: [--ticket-numbers|-t <CODE1,CODE2,CODE3,CODENNNN>] | ||
param: [--verbose # Show informational output] | ||
param: [--use-cred-mgr This implicit option | ||
populates the username/password environment | ||
variables from the Operating System's Credential Manager | ||
It expects a entry in the credential manager | ||
for '${script_dir_name}.${script_base_name}' | ||
Note: This must be a Generic Credential for Windows Hosts] | ||
""" | ||
|
||
BINARY=jello | ||
if ! [[ ($(type /usr/{,local/}{,s}bin/${BINARY} 2> /dev/null)) || ($(which $BINARY 2> /dev/null)) ]];then | ||
echo "This function requires $BINARY, install with subcommand pip.install ${BINARY}" | ||
exit 1 | ||
fi | ||
|
||
system_fields="number,state,sys_created_by,sys_created_on,variables.slt_application_name,variables.custom_attribute,variables.custom_attribute_2" | ||
group_name="Some%20Group%20Name" | ||
ticket_category="Some%20Catagory%20Name" | ||
|
||
# CLI | ||
for arg in "${@}";do | ||
shift | ||
if [[ "$arg" =~ '^--username$|^-u$|@The ServiceNow username to authenticate as - required' ]]; then username=$1;continue;fi | ||
if [[ "$arg" =~ '^--password$|^-p$|@The ServiceNow password to use - required' ]]; then password=$1;continue;fi | ||
if [[ "$arg" =~ '^--group-name$|^-g$|@The ServiceNow Group Name for filtering ticket results' ]]; then group_name=$1;continue;fi | ||
if [[ "$arg" =~ '^--ticket-numbers$|^-t$|@Specify ticket numbers explicitly' ]]; then ticket_numbers=$1;continue;fi | ||
if [[ "$arg" =~ '^--system-fields$|^-f$|@Specify ticket numbers explicitly' ]]; then system_fields=$1;continue;fi | ||
if [[ "$arg" =~ '^--short$|@Short output' ]]; then short=true;continue;fi | ||
if [[ "$arg" =~ '^--verbose$|@Verbose logging' ]]; then verbose=true;continue;fi | ||
if [[ "$arg" =~ '^--dry$|@Dry run, only echo commands' ]]; then PREFIX=echo;continue;fi | ||
if [[ "$arg" =~ '^--help$|@Show Help' ]]; then help=true;continue;fi | ||
set -- "$@" "$arg" | ||
done | ||
|
||
if [[ (-z $username) && (-z $password) && (-z $help) ]];then | ||
echo "Warning: Values for Username and password are empty!" | ||
echo -e "${USAGE}" | ||
exit 0 | ||
elif [[ ((-z $username) || (-z $password)) && (-z $help) ]];then | ||
echo "Warning: Values for either of username or password is empty!" | ||
echo -e "${USAGE}" | ||
exit 0 | ||
elif [[ (-n $help) ]];then | ||
echo -e "${USAGE}" | ||
exit 0 | ||
fi | ||
|
||
if [[ -n $verbose ]];then | ||
echo "Querying $baseurl for Tickets matching criteria" | ||
fi | ||
|
||
if [[ -n $ticket_numbers ]];then | ||
tickets_param="number=$(echo $ticket_numbers | sed s/,/^ORnumber=/g)" | ||
query="${baseurl}/api/now/table/sc_req_item?&displayvalue=all&sysparm_query=${tickets_param}&sysparm_display_value=true&sysparm_exclude_reference_li&sysparm_fields=${system_fields}" | ||
else | ||
query="${baseurl}/api/now/table/sc_req_item?&displayvalue=all&sysparm_query=assignment_group.name=${group_name}^state!=-3&cat_item=${ticket_category}&sysparm_fields=${system_fields}" | ||
fi | ||
|
||
result=$(curl -s \ | ||
"${query}" \ | ||
-X GET \ | ||
--header 'Accept:application/json' \ | ||
--user "${username}:${password}") | ||
|
||
if [[ -n $result ]];then | ||
tickets=$(echo "${result}" | jello -r '[r["number"] for r in _["result"]]' | tail -n +2 | head -n -1) | ||
n_tickets=$(echo "${tickets}" | wc -l) | ||
if [[ -n $verbose ]];then | ||
echo "Found $n_tickets tickets:" | ||
fi | ||
if [[ -n $short ]];then | ||
echo "${tickets}" | tr -d \", | ||
else | ||
echo "${result}" | jello -r '_' | ||
fi | ||
else | ||
if [[ -n $verbose ]];then | ||
echo No tickets found | ||
else | ||
echo '{}' | ||
fi | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
|
||
echo 'source <(ecli shell.autocomplete) # setup autocomplete in bash into the current shell.' | ||
echo '"source <(ecli shell.autocomplete)" >> ~/.bashrc # add autocomplete permanently to your bash shell.' |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters