Ensure that a data source is present.

    name
        Name of the data source.

    type
        Type of the datasource ('graphite', 'influxdb' etc.).

    access
        Use proxy or direct. Default: proxy

    url
        The URL to the data source API.

    user
        Optional - user to authenticate with the data source.

    password
        Optional - password to authenticate with the data source.

    database
        Optional - database to use with the data source.

    basic_auth
        Optional - set to True to use HTTP basic auth to authenticate with the
        data source.

    basic_auth_user
        Optional - HTTP basic auth username.

    basic_auth_password
        Optional - HTTP basic auth password.

    json_data
        Optional - additional json data to post (eg. "timeInterval").

    is_default
        Optional - set data source as default.

    with_credentials
        Optional - Whether credentials such as cookies or auth headers should
        be sent with cross-site requests.

    type_logo_url
        Optional - Logo to use for this datasource.

    orgname
        Name of the organization in which the data source should be present.

    profile
        Configuration profile used to connect to the Grafana instance.
        Default is 'grafana'.

def present(name,
            type,
            url,
            access=None,
            user=None,
            password=None,
            database=None,
            basic_auth=None,
            basic_auth_user=None,
            basic_auth_password=None,
            tls_auth=None,
            json_data=None,
            is_default=None,
            with_credentials=None,
            type_logo_url=None,
            orgname=None,
            profile='grafana'):
    '''
    Ensure that a data source is present.

    name
        Name of the data source.

    type
        Type of the datasource ('graphite', 'influxdb' etc.).

    access
        Use proxy or direct. Default: proxy

    url
        The URL to the data source API.

    user
        Optional - user to authenticate with the data source.

    password
        Optional - password to authenticate with the data source.

    database
        Optional - database to use with the data source.

    basic_auth
        Optional - set to True to use HTTP basic auth to authenticate with the
        data source.

    basic_auth_user
        Optional - HTTP basic auth username.

    basic_auth_password
        Optional - HTTP basic auth password.

    json_data
        Optional - additional json data to post (eg. "timeInterval").

    is_default
        Optional - set data source as default.

    with_credentials
        Optional - Whether credentials such as cookies or auth headers should
        be sent with cross-site requests.

    type_logo_url
        Optional - Logo to use for this datasource.

    orgname
        Name of the organization in which the data source should be present.

    profile
        Configuration profile used to connect to the Grafana instance.
        Default is 'grafana'.
    '''
    if isinstance(profile, string_types):
        profile = __salt__['config.option'](profile)

    ret = {'name': name, 'result': None, 'comment': None, 'changes': {}}
    datasource = __salt__['grafana4.get_datasource'](name, orgname, profile)
    data = _get_json_data(
        name=name,
        type=type,
        url=url,
        access=access,
        user=user,
        password=password,
        database=database,
        basicAuth=basic_auth,
        basicAuthUser=basic_auth_user,
        basicAuthPassword=basic_auth_password,
        tlsAuth=tls_auth,
        jsonData=json_data,
        isDefault=is_default,
        withCredentials=with_credentials,
        typeLogoUrl=type_logo_url,
        defaults=datasource)

    if not datasource:
        if __opts__['test']:
            ret['comment'] = 'Datasource {0} will be created'.format(name)
            return ret
        __salt__['grafana4.create_datasource'](profile=profile, **data)
        datasource = __salt__['grafana4.get_datasource'](name, profile=profile)
        ret['result'] = True
        ret['comment'] = 'New data source {0} added'.format(name)
        ret['changes'] = data
        return ret

    # At this stage, the datasource exists; however, the object provided by
    # Grafana may lack some null keys compared to our "data" dict:
    for key in data:
        if key not in datasource:
            datasource[key] = None

    if data == datasource:
        ret['comment'] = 'Data source {0} already up-to-date'.format(name)
        return ret

    if __opts__['test']:
        ret['comment'] = 'Datasource {0} will be updated'.format(name)
        return ret
    __salt__['grafana4.update_datasource'](
        datasource['id'], profile=profile, **data)
    ret['result'] = True
    ret['changes'] = deep_diff(datasource, data, ignore=['id', 'orgId', 'readOnly'])
    ret['comment'] = 'Data source {0} updated'.format(name)
    return ret