Skip to content
Yuwei Zhou edited this page Apr 29, 2019 · 2 revisions

TOC

Functional contribution

We are welcome for any contribution. But every new implemented should:

  • Be useful enough for lot of people (should not cover only your professional case).
  • Should not break existing use cases and should avoid breaking the backward compatibility.
  • Should be easily maintained.
  • Have document for what the new feature is together with an example.

Setup development environment

Refer Ansible Module Development Walkthrough to know how to set up an environment for developing, testing and debugging.

Coding style

All the coding style should obey Ansible's CODING_GUIDELINES.

Create Pull Request

Before you create a pull request

  • Search the issues board to find the same problem you have. If you don't find a one, note a new issue. If the request doesn't make sense or has some concern, maintainers can quickly notify you. It can save your time to avoid useless work.
  • Search the PR board to find whether some one is already working on this issue. It can avoid redundant work.

When you create a PR

  • You need follow the pull request template to fill some field.
  • Beside this, you need note Fixes #<issue-number> to say which issue you try to fix. This will tell bot close the issue after your PR is merged. Also tell users and other contributors you are working on it.

New added resource module

Where to position the new module file

A new added resource module should be added under /lib/ansible/modules/cloud/azure folder, with prefix azure_rm_.

Code implementation

The new module should contains:

  • A class AzureRMInstance extends from AzureRMModuleBase.

    • __init__(self)

      • define the parameter in self.module_arg_spec
      • initialize all field
    • exec_module(self, **kwargs) Should have the following logic:

      instance = self.get()                          # get current instance from cloud
      if instance and self.state == 'absent':        # if the command is delete and the instance exist
          change = true
          if not self.check_mode:                    # create/delete api should be called iff self.check_mode is true
             self.delete()
      elif self.state == 'present':
          newInstance = CONSTRUCT_INSTANCE           # command is create/update, construct instance according to parameters
          if not instance:
             change = true
          else:
             if isDiff(newInstance, instance):       # compare new construct instance and the one retrieved from cloud. 
                                                     # (self.update_tags(instance.tags) can check whether tags are updated)       
                 change = true
          if change and not self.check_mode:
             newInstance = self.create_or_update()
      result = instance_to_dict(newInstance) if newInstance else dict()
      result['changed'] = changed
      return result                                  # return results should be the same structure as parameters
    • create_or_update(self) - Call SDK create_or_update method. Most SDK create_or_update method returns poller, in this method, you should wait the poller finish and return the instance by self.get_poller_result(poller). It need catch exception and throw it with a user friendly message.

    • get(self) - Call SDK get method. SDK will throw 404 when the instance not found, you should catch the error here and return None.

    • delete(self) - Call SDK delete method.

  • A method instance_to_dict(instance): This method defined out of the class, which is convient for facts module to import it. This method accept a model and transform it to a dict. The return dict should have the same structure as parameters defined in module_arg_spec. Except the dict contains a resource id additionally.

Package dependency

If your module requires new packages, you need to add the pip information in the /packaging/requirements/requirements-azure.txt

Documentation

Every module has a documentation part at the beginning of the file, starts with DOCUMENTATION = ''' and ends with '''. This part should be a valid yaml part, which contains:

  • module: name of the module, which should be the filename without extension.

  • version_added: The smallest version this module been added. It should be current released version's next major release (+ 0.1).

  • short_description: Manage Azure XXX resource.

  • description: Description of this module.

  • options: this should be the detail of parameters this module accepted. E.G.

    resource_group:
        description:
            - name of resource group.
        required: true
  • extends_documentation_fragment: a list must contain azure and azure_tags

  • author: "Your name (Your github id)"

Sample

Below the documentation part, you also need add EXAMPLES and RETURN. Both of them should also in yaml format.

  • example should show how to use this module in some plays
  • return should have a sample of the return value when calling present.

New added facts module

The facts module never make change(create/delete/update) to resource in the cloud. It is a search module to show the resource with name, resource group. Or list resources under a resource group/subscription.

Facts module's return value should be

{
    "instance_facts": [
        // details of the instance
        {
            "id" : "/subscription/XXXXXXX/XXXX/XXX/XXXX",
            "name": "XXXX",
            ...
        }
    ]
}

Facts module should also contain documentation, example and return part at the head of the file. Refer Documentation part to see the detail.

Feature Pull request

If you want to implement some new feature for existing module, you should not break any current behavior. The most common things are:

  • Add a new option with default value, this default value should be None or the default value from API.
  • Collapse some flatten options in a list to support mutilple configuration. Here you need add a transformer to construct flatten options to the new list. To compatite current behavior.
  • Return value should not remove or change any existing field to prevent any breaking in the user case.

With above rules, if you add a new option, besides the code, you should also add the documentation, sample and Return. Refer Documentation part to see the detail. For new added option, the option should contain version_added part to indicate the smallest version this module been added.

Here is a sample documentation of the new added option:

availability_set:
   description:
       - Name or ID of an existing availability set to add the VM to.
   version_added: "2.5"

Your new added feature should not break current integration test cases. That means you cannot modify all the existing test to skip the compatible test. Refer Integration test for more test details.

Bugfix pull request

Don't forget to modify the documentation, sample and Return if necessary. Refer Documentation part to see the detail.

After your Bugfix PR merged, you can send another PR to backport this one to the release branch, then your bugfix can be availiable in next minor release. Otherwise, you could see your change in next regular release. If you don't know how to backport a PR, go to section Backport PR.

Integration test

Add package dependency for test

To run your integration test, if you have add some depencies in Package dependency part, you should add the dependency for your test, too. The pip file is at /test/runner/requirements/integration.cloud.azure.txt.

Where to add integration test

You need to create a folder at /test/integration/targets with the resource module name. The folder should in the following structure:

---- azure_rm_xxx
 |-- alias
 |-- meta
  |- main.yml
 |-- tasks
  |- main.yml

You can refer all the files in /test/integration/targets/azure_rm_subnet, except tasks/main.yml. This file should include the test cases of your integration test.

Test cases

In the tasks/main.yml file, you can write your integration test cases. For your resource module, your test should contain:

  • Create resource in check mode: It should return changed == True but the resource is not created.
  • Create resource after the check mode: It should also return changed == True, and there is an id in the return result.
  • Create resoruce again to test idempontent: Sending the play again without change, it should return changed == False
  • Update resource and exactly updated
  • Delete resource in check mode: It should return changed == True
  • Delete resource after check mode: It should return changed == True
  • Delete resource again to test idempontent: Sending the delete play again without change, it should return chagned == False

Backport PR

If your pull request is a bugfix one, you can send a backport PR to the stable branch. Then you can see your changes in the next minor release. You should follow the steps to send a backport PR.

  • Make sure your change is merged into devel branch, and the PR is for bugfix. (Feature should wait next regular release).
  • Switch to stable-<version> branch, the version should be the largest one currently.
  • Run git cherry-pick -x <commit-sha> to cherry pick the commit you want to backport to the stable branch.
  • [IMPORTANT] Add a changelog yaml under /changelogs/fragments to say what you have backported.

For more contribution guide from Ansible, please click Ansible Community Guide

Clone this wiki locally