1

I am trying to implement hostname like module and my target machine in an amazon-ec2. But When I am running the script its giving me below error:

[ansible-user@ansible-master ~]$ ansible node1 -m edit_hostname.py -a node2
ERROR! this task 'edit_hostname.py' has extra params, which is only allowed in the following modules: meta, group_by, add_host, include_tasks, import_role, raw, set_fact, command, win_shell, import_tasks, script, shell, include_vars, include_role, include, win_command

My module is like this:

#!/usr/bin/python


from ansible.module_utils.basic import *

try:
    import json
except ImportError:
    import simplejson as json


def write_to_file(module, hostname, hostname_file):

    try:
        with open(hostname_file, 'w+') as f:
            try:
                f.write("%s\n" %hostname)
            finally:
                f.close()
    except Exception:
        err = get_exception()
        module.fail_json(msg="failed to write to the /etc/hostname file")

def main():

    hostname_file = '/etc/hostname'
    module = AnsibleModule(argument_spec=dict(name=dict(required=True, type=str)))
    name = module.params['name']
    write_to _file(module, name, hostname_file)
    module.exit_json(changed=True, meta=name)

if __name__ == "__main__":

    main()

I don't know where I am making the mistake. Any help will be greatly appreciated. Thank you.

Sandipan
  • 683
  • 8
  • 25

2 Answers2

2

When developing a new module, I would recommend to use the boilerplate described in the documentation. This also shows that you'll need to use AnsibleModule to define your arguments.

In your main, you should add something like the following:

def main():
    # define available arguments/parameters a user can pass to the module
    module_args = dict(
        name=dict(type='str', required=True)
    )

    # seed the result dict in the object
    # we primarily care about changed and state
    # change is if this module effectively modified the target
    # state will include any data that you want your module to pass back
    # for consumption, for example, in a subsequent task
    result = dict(
        changed=False,
        original_hostname='',
        hostname=''
    )

    module = AnsibleModule(
        argument_spec=module_args
        supports_check_mode=False
    )

    # manipulate or modify the state as needed (this is going to be the
    # part where your module will do what it needs to do)
    result['original_hostname'] = module.params['name']
    result['hostname'] = 'goodbye'

    # use whatever logic you need to determine whether or not this module
    # made any modifications to your target
    result['changed'] = True

    # in the event of a successful module execution, you will want to
    # simple AnsibleModule.exit_json(), passing the key/value results
    module.exit_json(**result)

Then, you can call the module like so:

ansible node1 -m mymodule.py -a "name=myname"
Simon
  • 4,251
  • 2
  • 24
  • 34
0

ERROR! this task 'edit_hostname.py' has extra params, which is only allowed in the following modules: meta, group_by, add_host, include_tasks, import_role, raw, set_fact, command, win_shell, import_tasks, script, shell, include_vars, include_role, include, win_command

As explained by your error message, an anonymous default parameter is only supported by a limited number of modules. In your custom module, the paramter you created is called name. Moreover, you should not include the .py extension in the module name. You have to call your module like so as an ad-hoc command:

$ ansible node1 -m edit_hostname -a name=node2

I did not test your module code so you may have further errors to fix.

Meanwhile, I still strongly suggest you use the default boilerplate from the ansible documentation as proposed in @Simon's answer.

Zeitounator
  • 38,476
  • 7
  • 53
  • 66