Created
February 18, 2016 09:18
-
-
Save InsulaVentus/6eab63e281518e46ab14 to your computer and use it in GitHub Desktop.
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
import argparse | |
import base64 | |
import json | |
import requests | |
from datetime import datetime | |
from lxml import html | |
class ConfluenceBuildVersions(object): | |
""" | |
sudo pip install requests, lxml | |
""" | |
__TEMPLATE_WRAPPER = '<div class="application-versions-table">{paragraph}{table}</div><br></br>' | |
__TEMPLATE_APPLICATION_PARAGRAPH = '<p class="application-name">{application_name}</p>' | |
__TEMPLATE_TABLE = '<table class="confluenceTable">' \ | |
'<tbody>' \ | |
'<tr>' \ | |
'<th class="confluenceTh">Environment</th>' \ | |
'<th class="confluenceTh">Version</th>' \ | |
'<th class="confluenceTh">Build date</th>' \ | |
'</tr>' \ | |
'{table_rows}' \ | |
'</tbody>' \ | |
'</table>' | |
__TEMPLATE_TABLE_ROW = '<tr class="versions-row">' \ | |
'<td class="confluenceTd environment">{environment}</td>' \ | |
'<td class="confluenceTd version">{version}</td>' \ | |
'<td class="confluenceTd timestamp">{timestamp}</td>' \ | |
'</tr>' | |
def __init__(self, base_url, page_id, space_id, application_name, environment, application_version, auth): | |
self.__base_url = base_url | |
self.__page_id = page_id | |
self.__space_id = space_id | |
self.__application_name = application_name | |
self.__environment = environment | |
self.__application_version = application_version | |
self.__auth = ConfluenceBuildVersions.get_auth(auth) | |
self.__timestamp = datetime.now().strftime("%d.%m.%Y %H:%M") | |
self.__current_page_version = '' | |
@staticmethod | |
def get_auth(base64_encoded_auth): | |
""" | |
Get the username and password from a base64 encoded string; base64(username:password) | |
:param base64_encoded_auth: the encoded string | |
:return: the following tuple: (username, password) | |
""" | |
decode = base64.b64decode(base64_encoded_auth).split(':') | |
return decode[0], decode[1] | |
def get_current_page_content(self): | |
""" | |
Get the current page contents. | |
:return: Page contents in html form | |
""" | |
get_url = '{base}/{rest_path}/{page_id}{expansions}'.format( | |
base=self.__base_url, | |
rest_path='rest/api/content', | |
page_id=self.__page_id, | |
expansions='?expand=version,body.storage' | |
) | |
response = requests.get(url=get_url, auth=self.__auth) | |
response.raise_for_status() | |
json_response = response.json() | |
self.__current_page_version = json_response['version']['number'] | |
return json_response['body']['storage']['value'] | |
@staticmethod | |
def parse_html_contents(raw_html): | |
""" | |
Parse the html and build a dict from it's contents. | |
:param raw_html: the unprocessed contents of the page | |
:return: a dict formatted as follows: | |
{ | |
'application_name': { | |
'environment': { | |
'version': { | |
'Date': 'timestamp' | |
} | |
} | |
} | |
} | |
""" | |
contents = {} | |
if raw_html is None or len(raw_html) == 0: | |
return contents | |
tree = html.fromstring(raw_html) | |
applications = tree.find_class('application-versions-table') | |
for application in applications: | |
application_name = application.find_class('application-name')[0].text | |
rows = application.find_class('versions-row') | |
for row in rows: | |
environment = row.find_class('environment')[0].text | |
timestamp = row.find_class('timestamp')[0].text | |
version = row.find_class('version')[0].text | |
ConfluenceBuildVersions.append_content(contents, application_name, environment, version, timestamp) | |
return contents | |
@staticmethod | |
def append_content(current_contents, application_name, environment, version, timestamp): | |
""" | |
Append build information to the current page contents (see parse_html_contents) | |
:param current_contents: append to this | |
:param application_name: application_name | |
:param environment: environment | |
:param version: version | |
:param timestamp: timestamp | |
""" | |
if application_name in current_contents: | |
if environment in current_contents[application_name]: | |
current_contents[application_name][environment][version] = {'Date': timestamp} | |
else: | |
current_contents[application_name][environment] = {version: {'Date': timestamp}} | |
else: | |
current_contents[application_name] = {environment: {version: {'Date': timestamp}}} | |
def create_new_page_contents(self, current_page_contents): | |
""" | |
Create a html representation of the current page contents and the new build information. | |
:param current_page_contents: (see parse_html_contents) | |
:return: the html representation in string form | |
""" | |
ConfluenceBuildVersions.append_content( | |
current_page_contents, | |
self.__application_name, | |
self.__environment, | |
self.__application_version, | |
self.__timestamp | |
) | |
new_page_content = '' | |
for application, environment in current_page_contents.iteritems(): | |
paragraph = self.__TEMPLATE_APPLICATION_PARAGRAPH.format(application_name=application) | |
rows = '' | |
for environment_name, version in environment.iteritems(): | |
for version_name, value in version.iteritems(): | |
rows += self.__TEMPLATE_TABLE_ROW.format( | |
environment=environment_name, | |
version=version_name, | |
timestamp=value['Date'] | |
) | |
table = self.__TEMPLATE_TABLE.format(table_rows=rows) | |
new_page_content += self.__TEMPLATE_WRAPPER.format(paragraph=paragraph, table=table) | |
return new_page_content | |
def update_page(self, new_page_content): | |
""" | |
Update page with new page contents | |
:param new_page_content: (see create_new_page_contents) | |
""" | |
data = { | |
'id': self.__page_id, | |
'type': 'page', | |
'space': { | |
'key': self.__space_id | |
}, | |
'title': 'Build versions', | |
'version': {'number': self.__current_page_version + 1}, | |
'body': { | |
'storage': { | |
'representation': 'storage', | |
'value': new_page_content, | |
} | |
} | |
} | |
put_url = '{base}/{rest_path}/{page_id}'.format( | |
base=self.__base_url, | |
rest_path='rest/api/content', | |
page_id=self.__page_id, | |
) | |
headers = {'Content-Type': 'application/json'} | |
response = requests.put( | |
url=put_url, | |
headers=headers, | |
auth=self.__auth, | |
data=json.dumps(data) | |
) | |
response.raise_for_status() | |
def main(): | |
parser = argparse.ArgumentParser() | |
required_arguments = parser.add_argument_group('required arguments') | |
required_arguments.add_argument( | |
'--confluence-url', | |
required=True, | |
help='a confluence base url' | |
) | |
required_arguments.add_argument( | |
'--version', | |
required=True, | |
help='the new version' | |
) | |
required_arguments.add_argument( | |
'--environment', | |
required=True, | |
help='the environment' | |
) | |
required_arguments.add_argument( | |
'--auth', | |
required=True, | |
help='a base64 encoded user-password pair (user:password)' | |
) | |
required_arguments.add_argument( | |
'--application-name', | |
required=True, | |
help='the application' | |
) | |
required_arguments.add_argument( | |
'--page-id', | |
required=True, | |
help='the page id' | |
) | |
required_arguments.add_argument( | |
'--space-id', | |
required=True, | |
help='the confluence space id' | |
) | |
args = parser.parse_args() | |
cbv = ConfluenceBuildVersions( | |
base_url=args.confluence_url, | |
page_id=args.page_id, | |
space_id=args.space_id, | |
application_name=args.application_name, | |
environment=args.environment, | |
application_version=args.version, | |
auth=args.auth | |
) | |
raw_html_contents = cbv.get_current_page_content() | |
current_page_contents = cbv.parse_html_contents(raw_html_contents) | |
new_page_content = cbv.create_new_page_contents(current_page_contents) | |
cbv.update_page(new_page_content) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment