2021-03-06 13:30:43 +01:00
#!/usr/bin/python
# -*- coding: utf-8 -*-
2022-08-05 12:28:29 +02:00
# Copyright (c) 2021, Álvaro Torres Cogollo
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
2021-03-06 13:30:43 +01:00
from __future__ import absolute_import , division , print_function
__metaclass__ = type
DOCUMENTATION = '''
- - -
module : github_repo
short_description : Manage your repositories on Github
version_added : 2.2 .0
description :
2023-02-20 17:26:28 +01:00
- Manages Github repositories using PyGithub library .
- Authentication can be done with I ( access_token ) or with I ( username ) and I ( password ) .
extends_documentation_fragment :
- community . general . attributes
attributes :
check_mode :
support : full
diff_mode :
support : none
2021-03-06 13:30:43 +01:00
options :
username :
description :
- Username used for authentication .
- This is only needed when not using I ( access_token ) .
type : str
required : false
password :
description :
- Password used for authentication .
- This is only needed when not using I ( access_token ) .
type : str
required : false
access_token :
description :
- Token parameter for authentication .
- This is only needed when not using I ( username ) and I ( password ) .
type : str
required : false
name :
description :
- Repository name .
type : str
required : true
description :
description :
- Description for the repository .
2021-11-22 07:11:26 +01:00
- Defaults to empty if I ( force_defaults = true ) , which is the default in this module .
- Defaults to empty if I ( force_defaults = false ) when creating a new repository .
2021-03-06 13:30:43 +01:00
- This is only used when I ( state ) is C ( present ) .
type : str
required : false
private :
description :
2021-11-22 07:11:26 +01:00
- Whether the repository should be private or not .
- Defaults to C ( false ) if I ( force_defaults = true ) , which is the default in this module .
- Defaults to C ( false ) if I ( force_defaults = false ) when creating a new repository .
2021-03-06 13:30:43 +01:00
- This is only used when I ( state ) is C ( present ) .
type : bool
required : false
state :
description :
- Whether the repository should exist or not .
type : str
default : present
choices : [ absent , present ]
required : false
organization :
description :
- Organization for the repository .
- When I ( state ) is C ( present ) , the repository will be created in the current user profile .
type : str
required : false
2021-07-22 16:55:09 +02:00
api_url :
description :
- URL to the GitHub API if not using github . com but you own instance .
type : str
default : ' https://api.github.com '
version_added : " 3.5.0 "
2021-11-22 07:11:26 +01:00
force_defaults :
description :
- Overwrite current I ( description ) and I ( private ) attributes with defaults if set to C ( true ) , which currently is the default .
- The default for this option will be deprecated in a future version of this collection , and eventually change to C ( false ) .
type : bool
default : true
required : false
version_added : 4.1 .0
2021-03-06 13:30:43 +01:00
requirements :
- PyGithub > = 1.54
notes :
- For Python 3 , PyGithub > = 1.54 should be used .
- " For Python 3.5, PyGithub==1.54 should be used. More information: U(https://pygithub.readthedocs.io/en/latest/changes.html#version-1-54-november-30-2020). "
- " For Python 2.7, PyGithub==1.45 should be used. More information: U(https://pygithub.readthedocs.io/en/latest/changes.html#version-1-45-december-29-2019). "
author :
- Álvaro Torres Cogollo ( @atorrescogollo )
'''
EXAMPLES = '''
- name : Create a Github repository
community . general . github_repo :
access_token : mytoken
organization : MyOrganization
name : myrepo
description : " Just for fun "
2022-08-24 19:59:56 +02:00
private : true
2021-03-06 13:30:43 +01:00
state : present
2022-08-24 19:59:56 +02:00
force_defaults : false
2021-03-06 13:30:43 +01:00
register : result
- name : Delete the repository
community . general . github_repo :
username : octocat
password : password
organization : MyOrganization
name : myrepo
state : absent
register : result
'''
RETURN = '''
repo :
description : Repository information as JSON . See U ( https : / / docs . github . com / en / rest / reference / repos #get-a-repository).
returned : success and I ( state ) is C ( present )
type : dict
'''
import traceback
from ansible . module_utils . basic import AnsibleModule , missing_required_lib
GITHUB_IMP_ERR = None
try :
2021-11-22 07:11:26 +01:00
from github import Github , GithubException , GithubObject
2021-03-06 13:30:43 +01:00
from github . GithubException import UnknownObjectException
HAS_GITHUB_PACKAGE = True
except Exception :
GITHUB_IMP_ERR = traceback . format_exc ( )
HAS_GITHUB_PACKAGE = False
2021-07-22 16:55:09 +02:00
def authenticate ( username = None , password = None , access_token = None , api_url = None ) :
if not api_url :
return None
2021-03-06 13:30:43 +01:00
if access_token :
2021-07-22 16:55:09 +02:00
return Github ( base_url = api_url , login_or_token = access_token )
2021-03-06 13:30:43 +01:00
else :
2021-07-22 16:55:09 +02:00
return Github ( base_url = api_url , login_or_token = username , password = password )
2021-03-06 13:30:43 +01:00
2021-11-22 07:11:26 +01:00
def create_repo ( gh , name , organization = None , private = None , description = None , check_mode = False ) :
2021-03-06 13:30:43 +01:00
result = dict (
changed = False ,
repo = dict ( ) )
if organization :
target = gh . get_organization ( organization )
else :
target = gh . get_user ( )
repo = None
try :
repo = target . get_repo ( name = name )
result [ ' repo ' ] = repo . raw_data
except UnknownObjectException :
if not check_mode :
repo = target . create_repo (
2021-11-22 07:11:26 +01:00
name = name ,
private = GithubObject . NotSet if private is None else private ,
description = GithubObject . NotSet if description is None else description ,
)
2021-03-06 13:30:43 +01:00
result [ ' repo ' ] = repo . raw_data
result [ ' changed ' ] = True
changes = { }
2021-11-22 07:11:26 +01:00
if private is not None :
if repo is None or repo . raw_data [ ' private ' ] != private :
changes [ ' private ' ] = private
if description is not None :
if repo is None or repo . raw_data [ ' description ' ] not in ( description , description or None ) :
changes [ ' description ' ] = description
2021-03-06 13:30:43 +01:00
if changes :
if not check_mode :
repo . edit ( * * changes )
result [ ' repo ' ] . update ( {
' private ' : repo . _private . value if not check_mode else private ,
' description ' : repo . _description . value if not check_mode else description ,
} )
result [ ' changed ' ] = True
return result
def delete_repo ( gh , name , organization = None , check_mode = False ) :
result = dict ( changed = False )
if organization :
target = gh . get_organization ( organization )
else :
target = gh . get_user ( )
try :
repo = target . get_repo ( name = name )
if not check_mode :
repo . delete ( )
result [ ' changed ' ] = True
except UnknownObjectException :
pass
return result
def run_module ( params , check_mode = False ) :
2021-11-22 07:11:26 +01:00
if params [ ' force_defaults ' ] :
params [ ' description ' ] = params [ ' description ' ] or ' '
params [ ' private ' ] = params [ ' private ' ] or False
2021-03-06 13:30:43 +01:00
gh = authenticate (
2021-07-22 16:55:09 +02:00
username = params [ ' username ' ] , password = params [ ' password ' ] , access_token = params [ ' access_token ' ] ,
api_url = params [ ' api_url ' ] )
2021-03-06 13:30:43 +01:00
if params [ ' state ' ] == " absent " :
return delete_repo (
gh = gh ,
name = params [ ' name ' ] ,
organization = params [ ' organization ' ] ,
check_mode = check_mode
)
else :
return create_repo (
gh = gh ,
name = params [ ' name ' ] ,
organization = params [ ' organization ' ] ,
private = params [ ' private ' ] ,
description = params [ ' description ' ] ,
check_mode = check_mode
)
def main ( ) :
module_args = dict (
2021-11-22 07:11:26 +01:00
username = dict ( type = ' str ' ) ,
password = dict ( type = ' str ' , no_log = True ) ,
access_token = dict ( type = ' str ' , no_log = True ) ,
2021-03-06 13:30:43 +01:00
name = dict ( type = ' str ' , required = True ) ,
state = dict ( type = ' str ' , required = False , default = " present " ,
choices = [ " present " , " absent " ] ) ,
organization = dict ( type = ' str ' , required = False , default = None ) ,
2021-11-22 07:11:26 +01:00
private = dict ( type = ' bool ' ) ,
description = dict ( type = ' str ' ) ,
2021-07-22 16:55:09 +02:00
api_url = dict ( type = ' str ' , required = False , default = ' https://api.github.com ' ) ,
2021-11-22 07:11:26 +01:00
force_defaults = dict ( type = ' bool ' , default = True ) ,
2021-03-06 13:30:43 +01:00
)
module = AnsibleModule (
argument_spec = module_args ,
supports_check_mode = True ,
required_together = [ ( ' username ' , ' password ' ) ] ,
required_one_of = [ ( ' username ' , ' access_token ' ) ] ,
mutually_exclusive = [ ( ' username ' , ' access_token ' ) ]
)
if not HAS_GITHUB_PACKAGE :
module . fail_json ( msg = missing_required_lib (
" PyGithub " ) , exception = GITHUB_IMP_ERR )
try :
result = run_module ( module . params , module . check_mode )
module . exit_json ( * * result )
except GithubException as e :
module . fail_json ( msg = " Github error. {0} " . format ( repr ( e ) ) )
except Exception as e :
module . fail_json ( msg = " Unexpected error. {0} " . format ( repr ( e ) ) )
if __name__ == ' __main__ ' :
main ( )