327 lines
9.1 KiB
Python
327 lines
9.1 KiB
Python
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright: (c) 2021, Rainer Leber <rainerleber@gmail.com> <rainer.leber@sva.de>
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
from __future__ import (absolute_import, division, print_function)
|
|
__metaclass__ = type
|
|
|
|
DOCUMENTATION = r'''
|
|
---
|
|
module: sap_company
|
|
|
|
short_description: This module will manage a company entities in a SAP S4HANA environment
|
|
|
|
version_added: "1.0.0"
|
|
|
|
description:
|
|
- The M(community.sap.sap_user) module depends on C(pyrfc) Python library (version 2.4.0 and upwards).
|
|
Depending on distribution you are using, you may need to install additional packages to
|
|
have these available.
|
|
- This module will use the company BAPIs C(BAPI_COMPANY_CLONE) and C(BAPI_COMPANY_DELETE) to manage company entities.
|
|
|
|
options:
|
|
state:
|
|
description:
|
|
- The decision what to do with the company.
|
|
default: 'present'
|
|
choices:
|
|
- 'present'
|
|
- 'absent'
|
|
required: false
|
|
type: str
|
|
conn_username:
|
|
description: The required username for the SAP system.
|
|
required: true
|
|
type: str
|
|
conn_password:
|
|
description: The required password for the SAP system.
|
|
required: true
|
|
type: str
|
|
host:
|
|
description: The required host for the SAP system. Can be either an FQDN or IP Address.
|
|
required: true
|
|
type: str
|
|
sysnr:
|
|
description:
|
|
- The system number of the SAP system.
|
|
- You must quote the value to ensure retaining the leading zeros.
|
|
required: false
|
|
default: '01'
|
|
type: str
|
|
client:
|
|
description:
|
|
- The client number to connect to.
|
|
- You must quote the value to ensure retaining the leading zeros.
|
|
required: false
|
|
default: '000'
|
|
type: str
|
|
company_id:
|
|
description: The company id.
|
|
required: true
|
|
type: str
|
|
name:
|
|
description: The company name.
|
|
required: false
|
|
type: str
|
|
name_2:
|
|
description: Additional company name.
|
|
required: false
|
|
type: str
|
|
country:
|
|
description: The country code for the company. For example, C('DE').
|
|
required: false
|
|
type: str
|
|
time_zone:
|
|
description: The timezone.
|
|
required: false
|
|
type: str
|
|
city:
|
|
description: The city where the company is located.
|
|
required: false
|
|
type: str
|
|
post_code:
|
|
description: The post code from the city.
|
|
required: false
|
|
type: str
|
|
street:
|
|
description: Street where the company is located.
|
|
required: false
|
|
type: str
|
|
street_no:
|
|
description: Street number.
|
|
required: false
|
|
type: str
|
|
e_mail:
|
|
description: General E-Mail address.
|
|
required: false
|
|
type: str
|
|
|
|
requirements:
|
|
- pyrfc >= 2.4.0
|
|
|
|
author:
|
|
- Rainer Leber (@rainerleber)
|
|
|
|
notes:
|
|
- Does not support C(check_mode).
|
|
'''
|
|
|
|
EXAMPLES = r'''
|
|
- name: Create SAP Company
|
|
community.sap.sap_company:
|
|
conn_username: 'DDIC'
|
|
conn_password: 'HECtna2021#'
|
|
host: 100.0.201.20
|
|
sysnr: '01'
|
|
client: '000'
|
|
state: present
|
|
company_id: "Comp_ID"
|
|
name: "Test_comp"
|
|
name_2: "LTD"
|
|
country: "DE"
|
|
time_zone: "UTC"
|
|
city: "City"
|
|
post_code: "12345"
|
|
street: "test_street"
|
|
street_no: "1"
|
|
e_mail: "test@test.de"
|
|
|
|
# pass in a message and have changed true
|
|
- name: Delete SAP Company
|
|
community.sap.sap_company:
|
|
conn_username: 'DDIC'
|
|
conn_password: 'HECtna2021#'
|
|
host: 100.0.201.20
|
|
sysnr: '01'
|
|
client: '000'
|
|
state: absent
|
|
company_id: "Comp_ID"
|
|
name: "Test_comp"
|
|
name_2: "LTD"
|
|
country: "DE"
|
|
time_zone: "UTC"
|
|
city: "City"
|
|
post_code: "12345"
|
|
street: "test_street"
|
|
street_no: "1"
|
|
e_mail: "test@test.de"
|
|
'''
|
|
|
|
RETURN = r'''
|
|
# These are examples of possible return values, and in general should use other names for return values.
|
|
msg:
|
|
description: A small execution description.
|
|
type: str
|
|
returned: always
|
|
sample: 'Company address COMP_ID created'
|
|
out:
|
|
description: A complete description of the executed tasks. If this is available.
|
|
type: list
|
|
elements: dict
|
|
returned: always
|
|
sample: '{
|
|
"RETURN": [
|
|
{
|
|
"FIELD": "",
|
|
"ID": "01",
|
|
"LOG_MSG_NO": "000000",
|
|
"LOG_NO": "",
|
|
"MESSAGE": "Company address COMP_ID created",
|
|
"MESSAGE_V1": "COMP_ID",
|
|
"MESSAGE_V2": "",
|
|
"MESSAGE_V3": "",
|
|
"MESSAGE_V4": "",
|
|
"NUMBER": "078",
|
|
"PARAMETER": "",
|
|
"ROW": 0,
|
|
"SYSTEM": "",
|
|
"TYPE": "S"
|
|
}
|
|
]
|
|
}
|
|
}'
|
|
'''
|
|
|
|
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
|
|
import traceback
|
|
try:
|
|
from pyrfc import Connection
|
|
except ImportError:
|
|
HAS_PYRFC_LIBRARY = False
|
|
ANOTHER_LIBRARY_IMPORT_ERROR = traceback.format_exc()
|
|
else:
|
|
HAS_PYRFC_LIBRARY = True
|
|
|
|
|
|
def call_rfc_method(connection, method_name, kwargs):
|
|
# PyRFC call function
|
|
return connection.call(method_name, **kwargs)
|
|
|
|
|
|
def build_company_params(name, name_2, country, time_zone, city, post_code, street, street_no, e_mail):
|
|
# Creates RFC parameters for creating organizations
|
|
# define dicts in batch
|
|
params = dict()
|
|
# define company name
|
|
params['NAME'] = name
|
|
params['NAME_2'] = name_2
|
|
# define location
|
|
params['COUNTRY'] = country
|
|
params['TIME_ZONE'] = time_zone
|
|
params['CITY'] = city
|
|
params['POSTL_COD1'] = post_code
|
|
params['STREET'] = street
|
|
params['STREET_NO'] = street_no
|
|
# define communication
|
|
params['E_MAIL'] = e_mail
|
|
# return dict
|
|
return params
|
|
|
|
|
|
def return_analysis(raw):
|
|
change = False
|
|
failed = False
|
|
msg = raw['RETURN'][0]['MESSAGE']
|
|
for state in raw['RETURN']:
|
|
if state['TYPE'] == "E":
|
|
if state['NUMBER'] == '081':
|
|
change = False
|
|
else:
|
|
failed = True
|
|
if state['TYPE'] == "S":
|
|
if state['NUMBER'] != '079':
|
|
change = True
|
|
else:
|
|
msg = "No changes where made."
|
|
return [{"change": change}, {"failed": failed}, {"msg": msg}]
|
|
|
|
|
|
def run_module():
|
|
module = AnsibleModule(
|
|
argument_spec=dict(
|
|
state=dict(default='present', choices=['absent', 'present']),
|
|
conn_username=dict(type='str', required=True),
|
|
conn_password=dict(type='str', required=True, no_log=True),
|
|
host=dict(type='str', required=True),
|
|
sysnr=dict(type='str', default="01"),
|
|
client=dict(type='str', default="000"),
|
|
company_id=dict(type='str', required=True),
|
|
name=dict(type='str', required=False),
|
|
name_2=dict(type='str', required=False),
|
|
country=dict(type='str', required=False),
|
|
time_zone=dict(type='str', required=False),
|
|
city=dict(type='str', required=False),
|
|
post_code=dict(type='str', required=False),
|
|
street=dict(type='str', required=False),
|
|
street_no=dict(type='str', required=False),
|
|
e_mail=dict(type='str', required=False),
|
|
),
|
|
supports_check_mode=False,
|
|
)
|
|
result = dict(changed=False, msg='', out={})
|
|
raw = ""
|
|
|
|
params = module.params
|
|
|
|
state = params['state']
|
|
conn_username = (params['conn_username']).upper()
|
|
conn_password = params['conn_password']
|
|
host = params['host']
|
|
sysnr = params['sysnr']
|
|
client = params['client']
|
|
|
|
company_id = (params['company_id']).upper()
|
|
name = params['name']
|
|
name_2 = params['name_2']
|
|
country = params['country']
|
|
time_zone = params['time_zone']
|
|
city = params['city']
|
|
post_code = params['post_code']
|
|
street = params['street']
|
|
street_no = params['street_no']
|
|
e_mail = params['e_mail']
|
|
|
|
if not HAS_PYRFC_LIBRARY:
|
|
module.fail_json(
|
|
msg=missing_required_lib('pyrfc'),
|
|
exception=ANOTHER_LIBRARY_IMPORT_ERROR)
|
|
|
|
# basic RFC connection with pyrfc
|
|
try:
|
|
conn = Connection(user=conn_username, passwd=conn_password, ashost=host, sysnr=sysnr, client=client)
|
|
except Exception as err:
|
|
result['error'] = str(err)
|
|
result['msg'] = 'Something went wrong connecting to the SAP system.'
|
|
module.fail_json(**result)
|
|
|
|
# build parameter dict of dict
|
|
company_params = build_company_params(name, name_2, country, time_zone, city, post_code, street, street_no, e_mail)
|
|
|
|
if state == "absent":
|
|
raw = call_rfc_method(conn, 'BAPI_COMPANY_DELETE', {'COMPANY': company_id})
|
|
|
|
if state == "present":
|
|
raw = call_rfc_method(conn, 'BAPI_COMPANY_CLONE',
|
|
{'METHOD': {'USMETHOD': 'COMPANY_CLONE'}, 'COMPANY': company_id, 'COMP_DATA': company_params})
|
|
|
|
analysed = return_analysis(raw)
|
|
|
|
result['out'] = raw
|
|
|
|
result['changed'] = analysed[0]['change']
|
|
result['msg'] = analysed[2]['msg']
|
|
|
|
if analysed[1]['failed']:
|
|
module.fail_json(**result)
|
|
|
|
module.exit_json(**result)
|
|
|
|
|
|
def main():
|
|
run_module()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|