Giter Site home page Giter Site logo

ovh / python-ovh Goto Github PK

View Code? Open in Web Editor NEW
269.0 66.0 76.0 795 KB

Thin wrapper around OVH's APIs. Handles all the hard work including credential creation and requests signing.

Home Page: https://pypi.org/project/ovh/

License: Other

Python 94.29% Shell 5.71%
python ovh api-wrapper ovhcloud

python-ovh's Introduction

Python & OVH APIs

Lightweight wrapper around OVHcloud's APIs. Handles all the hard work including credential creation and requests signing.

PyPi Version PyPi repository status PyPi supported Python versions PyPi Wheel status Build Status Coverage Status
import ovh

# Instantiate. Visit https://api.ovh.com/createToken/?GET=/me
# to get your credentials
client = ovh.Client(
    endpoint='ovh-eu',
    application_key='<application key>',
    application_secret='<application secret>',
    consumer_key='<consumer key>',
)

# Print nice welcome message
print("Welcome", client.get('/me')['firstname'])

Installation

The python wrapper works with Python 3.7+.

The easiest way to get the latest stable release is to grab it from pypi using pip.

pip install ovh

Alternatively, you may get latest development version directly from Git.

pip install -e git+https://github.com/ovh/python-ovh.git#egg=ovh

People looking for Python 2 compatibility should use 0.6.x version.

Example Usage

Use the API on behalf of a user

1. Create an application

To interact with the APIs, the SDK needs to identify itself using an application_key and an application_secret. To get them, you need to register your application. Depending the API you plan to use, visit:

Once created, you will obtain an application key (AK) and an application secret (AS).

2. Configure your application

The easiest and safest way to use your application's credentials is to create an ovh.conf configuration file in application's working directory. Here is how it looks like:

[default]
; general configuration: default endpoint
endpoint=ovh-eu

[ovh-eu]
; configuration specific to 'ovh-eu' endpoint
application_key=my_app_key
application_secret=my_application_secret
; uncomment following line when writing a script application
; with a single consumer key.
;consumer_key=my_consumer_key

Depending on the API you want to use, you may set the endpoint to:

  • ovh-eu for OVH Europe API
  • ovh-us for OVH US API
  • ovh-ca for OVH North-America API
  • soyoustart-eu for So you Start Europe API
  • soyoustart-ca for So you Start North America API
  • kimsufi-eu for Kimsufi Europe API
  • kimsufi-ca for Kimsufi North America API

See Configuration for more information on available configuration mechanisms.

Note

When using a versioning system, make sure to add ovh.conf to ignored files. It contains confidential/security-sensitive information!

3. Authorize your application to access a customer account

To allow your application to access a customer account using the API on your behalf, you need a consumer key (CK).

Here is a sample code you can use to allow your application to access a customer's information:

import ovh

# create a client using configuration
client = ovh.Client()

# Request RO, /me API access
ck = client.new_consumer_key_request()
ck.add_rules(ovh.API_READ_ONLY, "/me")

# Request token
validation = ck.request()

print("Please visit %s to authenticate" % validation['validationUrl'])
input("and press Enter to continue...")

# Print nice welcome message
print("Welcome", client.get('/me')['firstname'])
print("Btw, your 'consumerKey' is '%s'" % validation['consumerKey'])

Returned consumerKey should then be kept to avoid re-authenticating your end-user on each use.

Note

To request full and unlimited access to the API, you may use add_recursive_rules:

# Allow all GET, POST, PUT, DELETE on /* (full API)
ck.add_recursive_rules(ovh.API_READ_WRITE, '/')

Install a new mail redirection

e-mail redirections may be freely configured on domains and DNS zones hosted by OVH to an arbitrary destination e-mail using API call POST /email/domain/{domain}/redirection.

For this call, the api specifies that the source address shall be given under the from keyword. Which is a problem as this is also a reserved Python keyword. In this case, simply prefix it with a '_', the wrapper will automatically detect it as being a prefixed reserved keyword and will substitute it. Such aliasing is only supported with reserved keywords.

import ovh

DOMAIN = "example.com"
SOURCE = "[email protected]"
DESTINATION = "[email protected]"

# create a client
client = ovh.Client()

# Create a new alias
client.post('/email/domain/%s/redirection' % DOMAIN,
        _from=SOURCE,
        to=DESTINATION,
        localCopy=False
    )
print("Installed new mail redirection from %s to %s" % (SOURCE, DESTINATION))

Grab bill list

Let's say you want to integrate OVH bills into your own billing system, you could just script around the /me/bills endpoints and even get the details of each bill lines using /me/bill/{billId}/details/{billDetailId}.

This example assumes an existing Configuration with valid application_key, application_secret and consumer_key.

import ovh

# create a client
client = ovh.Client()

# Grab bill list
bills = client.get('/me/bill')
for bill in bills:
    details = client.get('/me/bill/%s' % bill)
    print("%12s (%s): %10s --> %s" % (
        bill,
        details['date'],
        details['priceWithTax']['text'],
        details['pdfUrl'],
    ))

Enable network burst in SBG1

'Network burst' is a free service but is opt-in. What if you have, say, 10 servers in SBG-1 datacenter? You certainly don't want to activate it manually for each servers. You could take advantage of a code like this.

This example assumes an existing Configuration with valid application_key, application_secret and consumer_key.

import ovh

# create a client
client = ovh.Client()

# get list of all server names
servers = client.get('/dedicated/server/')

# find all servers in SBG-1 datacenter
for server in servers:
    details = client.get('/dedicated/server/%s' % server)
    if details['datacenter'] == 'sbg1':
        # enable burst on server
        client.put('/dedicated/server/%s/burst' % server, status='active')
        print("Enabled burst for %s server located in SBG-1" % server)

List application authorized to access your account

Thanks to the application key / consumer key mechanism, it is possible to finely track applications having access to your data and revoke this access. This examples lists validated applications. It could easily be adapted to manage revocation too.

This example assumes an existing Configuration with valid application_key, application_secret and consumer_key.

import ovh
from tabulate import tabulate

# create a client
client = ovh.Client()

credentials = client.get('/me/api/credential', status='validated')

# pretty print credentials status
table = []
for credential_id in credentials:
    credential_method = '/me/api/credential/'+str(credential_id)
    credential = client.get(credential_method)
    application = client.get(credential_method+'/application')

    table.append([
        credential_id,
        '[%s] %s' % (application['status'], application['name']),
        application['description'],
        credential['creation'],
        credential['expiration'],
        credential['lastUse'],
    ])
print(tabulate(table, headers=['ID', 'App Name', 'Description',
                               'Token Creation', 'Token Expiration', 'Token Last Use']))

Before running this example, make sure you have the tabulate library installed. It's a pretty cool library to pretty print tabular data in a clean and easy way.

>>> pip install tabulate

Open a KVM (remote screen) on a dedicated server

Recent dedicated servers come with an IPMI interface. A lightweight control board embedded on the server. Using IPMI, it is possible to get a remote screen on a server. This is particularly useful to tweak the BIOS or troubleshoot boot issues.

Hopefully, this can easily be automated using a simple script. It assumes Java Web Start is fully installed on the machine and a consumer key allowed on the server exists.

import ovh
import sys
import time
import tempfile
import subprocess

# check arguments
if len(sys.argv) != 3:
    print("Usage: %s SERVER_NAME ALLOWED_IP_V4" % sys.argv[0])
    sys.exit(1)

server_name = sys.argv[1]
allowed_ip = sys.argv[2]

# create a client
client = ovh.Client()

# create a KVM
client.post('/dedicated/server/'+server_name+'/features/ipmi/access', ipToAllow=allowed_ip, ttl=15, type="kvmipJnlp")

# open the KVM, when ready
while True:
    try:
        # use a named temfile and feed it to java web start
        with tempfile.NamedTemporaryFile() as f:
            f.write(client.get('/dedicated/server/'+server_name+'/features/ipmi/access?type=kvmipJnlp')['value'])
            f.flush()
            subprocess.call(["javaws", f.name])
        break
    except:
        time.sleep(1)

Running is only a simple command line:

# Basic
python open_kvm.py ns1234567.ip-42-42-42.eu $(curl ifconfig.ovh)

# Use a specific consumer key
OVH_CONSUMER_KEY=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA python open_kvm.py ns1234567.ip-42-42-42.eu $(curl -s ifconfig.ovh)

Configuration

You have 3 ways to provide configuration to the client:
  • write it directly in the application code
  • read environment variables or predefined configuration files
  • read it from a custom configuration file

Embed the configuration in the code

The straightforward way to use OVH's API keys is to embed them directly in the application code. While this is very convenient, it lacks of elegance and flexibility.

Example usage:

client = ovh.Client(
    endpoint='ovh-eu',
    application_key='<application key>',
    application_secret='<application secret>',
    consumer_key='<consumer key>',
)

Environment vars and predefined configuration files

Alternatively it is suggested to use configuration files or environment variables so that the same code may run seamlessly in multiple environments. Production and development for instance.

This wrapper will first look for direct instantiation parameters then OVH_ENDPOINT, OVH_APPLICATION_KEY, OVH_APPLICATION_SECRET and OVH_CONSUMER_KEY environment variables. If either of these parameter is not provided, it will look for a configuration file of the form:

[default]
; general configuration: default endpoint
endpoint=ovh-eu

[ovh-eu]
; configuration specific to 'ovh-eu' endpoint
application_key=my_app_key
application_secret=my_application_secret
consumer_key=my_consumer_key

The client will successively attempt to locate this configuration file in

  1. Current working directory: ./ovh.conf
  2. Current user's home directory ~/.ovh.conf
  3. System wide configuration /etc/ovh.conf

This lookup mechanism makes it easy to overload credentials for a specific project or user.

Example usage:

client = ovh.Client()

Use v1 and v2 API versions

When using OVHcloud APIs (not So you Start or Kimsufi ones), you are given the opportunity to aim for two API versions. For the European API, for example:

Calling client.get, you can target the API version you want:
client = ovh.Client(endpoint="ovh-eu")

# Call to https://eu.api.ovh.com/v1/xdsl/xdsl-yourservice
client.get("/v1/xdsl/xdsl-yourservice")

# Call to https://eu.api.ovh.com/v2/xdsl/xdsl-yourservice
client.get("/v2/xdsl/xdsl-yourservice")

# Legacy call to https://eu.api.ovh.com/1.0/xdsl/xdsl-yourservice
client.get("/xdsl/xdsl-yourservice")

Custom configuration file

You can also specify a custom configuration file. With this method, you won't be able to inherit values from environment.

Example usage:

client = ovh.Client(config_file='/my/config.conf')

Passing parameters

You can call all the methods of the API with the necessary arguments.

If an API needs an argument colliding with a Python reserved keyword, it can be prefixed with an underscore. For example, from argument of POST /email/domain/{domain}/redirection may be replaced by _from.

With characters invalid in python argument name like a dot, you can:

import ovh

params = {}
params['date.from'] = '2014-01-01'
params['date.to'] = '2015-01-01'

# create a client
client = ovh.Client()

# pass parameters using **
client.post('/me/bills', **params)

Advanced usage

Un-authenticated calls

If the user has not authenticated yet (ie, there is no valid Consumer Key), you may force python-ovh to issue the call by passing _need_auth=True to the high level get(), post(), put() and delete() helpers or need_auth=True to the low level method Client.call() and Client.raw_call().

This is needed when calling POST /auth/credential and GET /auth/time which are used internally for authentication and can optionally be done for most of the /order calls.

Access the raw requests response objects

The high level get(), post(), put() and delete() helpers as well as the lower level call() will returned a parsed json response or raise in case of error.

In some rare scenario, advanced setups, you may need to perform customer processing on the raw request response. It may be accessed via raw_call(). This is the lowest level call in python-ovh. See the source for more information.

Hacking

This wrapper uses standard Python tools, so you should feel at home with it. Here is a quick outline of what it may look like. A good practice is to run this from a virtualenv.

Get the sources

git clone https://github.com/ovh/python-ovh.git
cd python-ovh
python setup.py develop

You've developed a new cool feature? Fixed an annoying bug? We'd be happy to hear from you!

Run the tests

Simply run pytest. It will automatically load its configuration from setup.cfg and output full coverage status. Since we all love quality, please note that we do not accept contributions with test coverage under 100%.

pip install -e .[dev]
pytest

Build the documentation

Documentation is managed using the excellent Sphinx system. For example, to build HTML documentation:

cd python-ovh/docs
make html

Supported APIs

OVH Europe

OVH US

OVH North America

So you Start Europe

So you Start North America

Kimsufi Europe

Kimsufi North America

Related links

License

3-Clause BSD

python-ovh's People

Contributors

4383 avatar achaussier avatar amartinunowhy avatar arnaudmorin avatar bewiwi avatar brouberol avatar chtitux avatar deathiop avatar djangoliv avatar geoffreybauduin avatar gierschv avatar hugovk avatar jon-d avatar kwadrat avatar lalmeras avatar piotron avatar rbeuque74 avatar tomeros avatar umbsublime avatar vincentcasse avatar yadutaf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-ovh's Issues

Get cloud/project/{serviceName}/bill impossible in python3 ?

I'm using Python3 and i try to get the bill for the projects with this reqest :

client = ovh.Client(
endpoint='ovh-eu',
application_key='****************',
application_secret='',
consumer_key='
******',
)

result = client.get('/cloud/project/'+ projectId+'/bill',from=d1,to=d2)

and i have a synthax error

ps: ProjectId is existing (i have checking with the api console) and
d1='2019-01-01'
d2='2019-06-06'

what's wrong ? I do a lot of auther request and they don't failled...

Drop python 2.6 support

Hello,
Following this last failing build on Python 2.6 (https://travis-ci.org/ovh/python-ovh/jobs/452406500) regarding SNI requirements on ca.api.soyoustart.com and ca.api.kimsufi.com, I recommand that we drop Python 2.6 support on python-ovh.

Python 2.6 is no longer supported by the Python core team, and pip will also drop support for Python 2.6 too, I think we should consider to move on.

Any objection ?

"Invalid signature" on write operations

This might be an internal change on OVH's side, but a script that modified entries on a domain suddenly stopped working, giving that exception

ovh.exceptions.BadParametersError: Invalid signature

It authenticates, reads all the info well, but when it gets to the point where it tries to PUT on /domain/zone/{zoneName}/record/{id} it gets this error even though it worked just yesterday and everything is correct. Even more, the exact same command works on the OVH API web console. Thought it was the credentials (that again were working just fine yesterday), so made new ones with full write access, same result.

If this is something on OVH side the module will be able to do nothing about it, but might be worth checking.

204 response is not handled

The requests:

result = client.put(
'/cloud/project//kube//nodepool/',
desiredNodes=2,
maxNodes=4,
minNodes=1,
nodesToRemove=[],
)

return 204 but the the parse of the result faied.

In client.py

       try:
           json_result = result.json()
       except ValueError as error:
           raise InvalidResponse("Failed to decode API response", error)

=> simplejson.errors.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

which is normal since 204 is a No Content response .

Regards

Pb avec API /télephony et l'ajout d'un agent dans une queue

Hello,

I'm using OVH /telephony API to manage agents and queues but I've an issue with

POST /telephony/{billingAccount}/easyHunting/{serviceName}/hunting/queue/{queueId}/agent

This request should create a new skill for an agent (it adds the agent in a queue) as stated in the docs (https://eu.api.ovh.com/console/#/telephony)

But no agent ID is posted in the request (nor is accepted), and I've got this error (using the api on eu.api.ovh.com/console/#/telephony or with my own code) (obviously I've got agents and agents ID to be put in the queue)

Traceback (most recent call last): File "GetLineProperties.py", line 72, in <module> queue_add_agent(1668903,2) File "GetLineProperties.py", line 57, in queue_add_agent result = client.post('/telephony/'+billingAccount+'/easyHunting/'+serviceName+'/hunting/queue/'+queue+"/agent/", File "/home/superman/.local/lib/python3.8/site-packages/ovh/client.py", line 377, in post return self.call('POST', _target, kwargs, _need_auth) File "/home/superman/.local/lib/python3.8/site-packages/ovh/client.py", line 445, in call raise BadParametersError(json_result.get('message'), ovh.exceptions.BadParametersError: Agent doest not exist, create it first OVH-Query-ID: EU.ext-2.5f22a3d7.28601.b25639bb-7876-4a01-997d-7d0b41cb63f9

NB: the response class in the API docs mentions an "Agent ID"

{ -telephony.OvhPabxHuntingAgentQueue: { description: "Agent assigned to a queue" -properties: { -agentId: { type: "long" fullType: "long" canBeNull: false readOnly: true required: false } -position: { type: "long" fullType: "long" canBeNull: false readOnly: false description: "The position in the queue" required: false } -queueId: { type: "long" fullType: "long" canBeNull: false readOnly: true required: false } } } }

Is there any issue with this request in the API (someone forgot an "AgentID" variable ?) ?

module 'ovh' has no attribute 'Client'

Hi everybody,
I have installed ovh module via pip and I have latest version:

xxx$ pip3 list | grep ovh
ovh 0.5.0

when I run the script I have the following error:
Traceback (most recent call last):
File "/Users/xxx/Script/./ovh.py", line 5, in
import ovh
File "/Users/xxx/Script/ovh.py", line 7, in
client = ovh.Client(
AttributeError: partially initialized module 'ovh' has no attribute 'Client' (most likely due to a circular import)

pip install fails

Hello,

pip install ovh fails on:

from six.moves import UserString
ImportError: cannot import name 'UserString'

However six is available:

Python 3.5.1 (default, Mar  3 2016, 09:29:07)
[GCC 5.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from six.moves import UserString
>>>

$ uname -a Linux xxxx 4.5.3-1-ARCH #1 SMP PREEMPT Sat May 7 20:43:57 CEST 2016 x86_64 GNU/Linux

Full error message:

# pip install ovh
Collecting ovh
  Using cached ovh-0.4.2.tar.gz
Requirement already satisfied (use --upgrade to upgrade): setuptools in /usr/lib/python3.5/site-packages (from ovh)
Collecting d2to1==0.2.11 (from ovh)
  Using cached d2to1-0.2.11.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-hhg6m9le/d2to1/setup.py", line 13, in <module>
        setup(**cfg_to_args())
      File "/tmp/pip-build-hhg6m9le/d2to1/d2to1/util.py", line 204, in cfg_to_args
        wrap_commands(kwargs)
      File "/tmp/pip-build-hhg6m9le/d2to1/d2to1/util.py", line 439, in wrap_commands
        for cmd, _ in dist.get_command_list():
      File "/usr/lib/python3.5/site-packages/setuptools/dist.py", line 447, in get_command_list
        cmdclass = ep.resolve()
      File "/usr/lib/python3.5/site-packages/pkg_resources/__init__.py", line 2235, in resolve
        module = __import__(self.module_name, fromlist=['__name__'], level=0)
      File "/usr/lib/python3.5/site-packages/sphinx/setup_command.py", line 23, in <module>
        from sphinx.application import Sphinx
      File "/usr/lib/python3.5/site-packages/sphinx/application.py", line 30, in <module>
        from sphinx import package_dir, locale
      File "/usr/lib/python3.5/site-packages/sphinx/locale/__init__.py", line 15, in <module>
        from six.moves import UserString
    ImportError: cannot import name 'UserString'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-hhg6m9le/d2to1/
You are using pip version 8.1.1, however version 8.1.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

Error while importing Module ovh

Hi!

I'm getting the following error when trying to import ovh in my current project.
I'm using Python 3.10.0 on Windows 11 with ovh Verison 0.5.0.
pip3 install ovh says that all dependencies are satisfied, and all installed modules are up to date.

The error doesn't occur on Debian 11 with Python 3.9.2.

Exception has occurred: AttributeError
module 'collections' has no attribute 'MutableMapping'
  File "D:\Git\dyndns-script\dyndns_update.py", line 8, in <module>
    import ovh
Traceback (most recent call last):
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "c:\Users\lauralani\.vscode\extensions\ms-python.python-2021.11.1422169775\pythonFiles\lib\python\debugpy\__main__.py", line 45, in <module>
    cli.main()
  File "c:\Users\lauralani\.vscode\extensions\ms-python.python-2021.11.1422169775\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 444, in main
    run()
  File "c:\Users\lauralani\.vscode\extensions\ms-python.python-2021.11.1422169775\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 285, in run_file
    runpy.run_path(target_as_str, run_name=compat.force_str("__main__"))
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 269, in run_path
    return _run_module_code(code, init_globals, run_name,
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 96, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "d:\Git\dyndns-script\dyndns_update.py", line 8, in <module>
    import ovh
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\site-packages\ovh\__init__.py", line 29, in <module>
    from .client import Client
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\site-packages\ovh\client.py", line 49, in <module>
    from .vendor.requests import request, Session
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\site-packages\ovh\vendor\requests\__init__.py", line 58, in <module>
    from . import utils
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\site-packages\ovh\vendor\requests\utils.py", line 30, in <module>
    from .cookies import RequestsCookieJar, cookiejar_from_dict
  File "C:\Users\lauralani\AppData\Local\Programs\Python\Python310\lib\site-packages\ovh\vendor\requests\cookies.py", line 164, in <module>
    class RequestsCookieJar(cookielib.CookieJar, collections.MutableMapping):
AttributeError: module 'collections' has no attribute 'MutableMapping'

how to call /me/bill with date range ?

Hi,

https://api.ovh.com/console/#/me/bill#GET says options are date.from date.to and orderId.

The example states:

result = client.get('/me/bill',
date.from='2019-01-01', // Filter the value of date property (>=) (type: datetime)
date.to=None, // Filter the value of date property (<=) (type: datetime)
orderId=None, // Filter the value of orderId property (=) (type: long)
)

how is this supposed to work in python since the keyword arguments cannot be named with a dot in the middle ?

I tried date, datefrom, _from, etc. but did not get it to work. Reading the source and the canonicalize method did not help me either.

I look forward to the correct syntax. Thank you.

Error ovh

Hi.
plz help fixed.

Traceback (most recent call last):
File "C:\Users\1\Desktop\2.py", line 18, in
result = client.post("/auth/credential",
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python311\Lib\site-packages\ovh\client.py", line 385, in post
return self.call("POST", _target, kwargs, _need_auth)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Python311\Lib\site-packages\ovh\client.py", line 465, in call
raise BadParametersError(json_result.get("message"), response=result)
ovh.exceptions.BadParametersError: Body parameter accessRules isn't formated correctly
OVH-Query-ID: EU.ext-2.64415cf2.40437.b4d78937-363f-44a4-aa8c-ba3793266eec

Low HTTP request failed error

Trying:
any api call!
The first call will work, second call will always fail.

Getting:
Failed to call OVH API: ('Low HTTP request failed error', ConnectionError(MaxRetryError("HTTPSConnectionPool(host='ca.api.ovh.com', port=443): Max retries exceeded with url: /1.0/dedicated/server/ns553576.ip-142-44-212.net/task (Caused by NewConnectionError('<ovh.vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7f07f1e81790>: Failed to establish a new connection: [Errno 4] Interrupted system call',))",),))

Unit tests fail on debian 9 preventing simple debian 9 packaging.

When you run the following code block on debian 8 everything works, but on debian 9 it fails.

python setup.py --command-packages=stdeb.command sdist_dsc
cd deb_dist/
cd `find -type d | find -type d | head -n 2 | tail -n 1`
pwd
debuild -uc -us

Notably:

test_endpoints (tests.test_client.testClient)
...
ERROR
test_init_from_custom_config (tests.test_client.testClient)
...
ERROR
test_config_get_conf (tests.test_config.testConfig)
...
FAIL
test_config_get_conf_env_rules_them_all (tests.test_config.testConfig)
...
ok
test_config_get_custom_conf (tests.test_config.testConfig)
...
FAIL
test_real_lookup_path (tests.test_config.testConfig)
...

And drilling down:

======================================================================
ERROR: test_endpoints (tests.test_client.testClient)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/test_client.py", line 403, in test_endpoints
auth_time = Client(endpoint).get('/auth/time', _need_auth=False)
File "ovh/client.py", line 346, in get
return self.call('GET', _target, None, _need_auth)
File "ovh/client.py", line 414, in call
raise HTTPError("Low HTTP request failed error", error)
HTTPError: ('Low HTTP request failed error', ConnectionError(MaxRetryError("HTTPSConnectionPool(host='ca.api.kimsufi.com', port=443): Max retries exceeded with url: /1.0/auth/time (Caused by ProxyError('Cannot connect to proxy.', NewConnectionError('<ovh.vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x7f176ae9a550>: Failed to establish a new connection: [Errno 111] Connection refused',)))",),))
======================================================================
ERROR: test_init_from_custom_config (tests.test_client.testClient)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/test_client.py", line 111, in test_init_from_custom_config
api = Client(config_file=M_CUSTOM_CONFIG_PATH)
File "ovh/client.py", line 164, in __init__
endpoint, ENDPOINTS.keys())
InvalidRegion: ('Unknow endpoint %s. Valid endpoints: %s', None, ['kimsufi-ca', 'kimsufi-eu', 'soyoustart-eu', 'ovh-ca', 'ovh-eu', 'soyoustart-ca'])
======================================================================
FAIL: test_config_get_conf (tests.test_config.testConfig)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/test_config.py", line 73, in test_config_get_conf
self.assertEqual('soyoustart-ca', conf.get('default', 'endpoint'))
AssertionError: 'soyoustart-ca' != None
======================================================================
FAIL: test_config_get_custom_conf (tests.test_config.testConfig)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/test_config.py", line 100, in test_config_get_custom_conf
self.assertEqual('ovh-ca', conf.get('default', 'endpoint'))
AssertionError: 'ovh-ca' != None
======================================================================
FAIL: test_real_lookup_path (tests.test_config.testConfig)
----------------------------------------------------------------------
Traceback (most recent call last):
File "tests/test_config.py", line 68, in test_real_lookup_path
], self._orig_CONFIG_PATH)
AssertionError: Lists differ: ['/etc/ovh.conf', '/home/jenki... != ['/etc/ovh.conf', '/home/jenki...
First differing element 2:

ovh.exceptions.APIError: Service is temporarily unavailable

i have this code to add vps server item in my cart:

client.post('/order/cart/{cartid}/vps',
                  duration='PT18.179651S',
                  planCode='vps_ceph-nvme_model3',
                  pricingMode='default',
                  quantity=1)

But the answer gives me the following error:
ovh.exceptions.APIError: Service is temporarily unavailable
OVH-Query-ID: CA.ws-2.592b81b1.10921.5307

Python Code from Console not working

Trying to create a kube cluster from API in Python. So I ran the command from the API Console and picked the Python code being generated.
But at the time of testing it, once authenticated, the code to call the post command seems to be incorrect:

result = client.post('/cloud/project/<serviceID>/kube', 
    ='{"name":"test1","nodepool":{"antiAffinity":false,"autoscale":false,"desiredNodes":1,"flavorName":"d2-4","monthlyBilled":false,"name":"nodepool1"},"privateNetworkId":"A-private-network-id","region":"DE1","updatePolicy":"NEVER_UPDATE","version":"1.26"}', // Request Body (type: cloud.ProjectKubeCreation)
)

In fact, the code seems syntactically incorrect. I made this fix:

result = client.post('/cloud/project/<serviceID>/kube', 
    '{"name":"test1","nodepool":{"antiAffinity":false,"autoscale":false,"desiredNodes":1,"flavorName":"d2-4","monthlyBilled":false,"name":"nodepool1"},"privateNetworkId":"A-private-network-id","region":"DE1","updatePolicy":"NEVER_UPDATE","version":"1.26"}' )

And now at least is tried to run, but fires an exception "The input that you provided isn't valid JSON or not well formatted".
I've also tried to build a dict with all the parameters, then dump it into json format, but same error appeared.

It seems the code generated by the console is not ok.

Empty response

Sometimes calling your API sends back an empty response, maybe an error could be shown?
This happens after a lot of calls to cart/order/domain

EPIPE when underlying SSL connexion has timed-out

When waiting more than a few seconds between consecutive calls, I get an SysCallError: (32, 'EPIPE').

This is something we should handle automatically and replay the request on a fresh connection.

tried to use multiple endpoint in ovh.conf but failed

as discussed on twitter with @oyadutaf

i've tried to use several endpoint but it seems to have failed.
here is an ovh.conf example (not a real one of course :) ):

;[default]
; general configuration: default endpoint
endpoint=ovh-eu

[ovh-eu]
; configuration specific to 'ovh-eu' endpoint
application_key=SDi4hq7ZD6IxcAxI
application_secret=5xaqN4BeD30WKt0qk9Z12wZVcx9MhxAZ
; uncomment following line when writing a script application
; with a single consumer key.
consumer_key=oKKIeDF5JZnGA4wrIa0LZVAZ9xKK8M

[soyoustart-eu]
; configuration specific to 'soyoustart-eu' endpoint
application_key=adrDGpstz3nt2ed8
application_secret=iWgcINEYRqChWH29MEnUhwWkqsuoxs0T
; uncomment following line when writing a script application
; with a single consumer key.
consumer_key=W5ZvsdXnAGpamjEfO9IDSjSHJbL7jkIf

here is a python PoC:

import ovh
import sugarcrm
import datetime
from tabulate import tabulate

mydata= []

def ovh_request():
# create a client for dedicated hosting
    clientd = ovh.Client(endpoint='ovh-eu')
# create a client for SYS hosting
    clients = ovh.Client(endpoint='soyoustart-eu')
    clientall = [clientd , clients]
# get list of all server names
    for cli_connect in clientall:
        lbills = cli_connect.get('/me/bill?date.from=20150201&date.to=20150331')

        for idbills in lbills:

            idbillsd = cli_connect.get('/me/bill/%s/details' % idbills)
            for bills in idbillsd:
                billdetail = cli_connect.get('/me/bill/%s/details/%s' % (idbills, bills) )
                source=billdetail['domain']
                price=billdetail['totalPrice']['value']
                startmonth=billdetail['periodStart']
                endmonth=billdetail['periodEnd']
                mydata.append([str(source),int(price),str(startmonth),str(endmonth)])

ovh_request()
print tabulate(mydata, headers=['Type', 'Prix', 'SPeriode','EPeriode'])

the ovh-eu endpoint works, but the soyoustart-eu endpoint doesn't.

both only works if i specify the connection strings like:
clientd = ovh.Client(endpoint='ovh-eu',application_key='XXXXX', application_secret='XXXX', consumer_key='XXXX')

clientd = ovh.Client(endpoint='soyoustart-eu', application_key='XXXXX', application_secret='XXXX', consumer_key='XXXX')

any clues on why ? have i made a mistake somewhere ?

API raises BadParameterError for boolean arguments

Hello,

When an API call requires a boolean argument, we send it as True or False (valid Python booleans) but the API raises BadParametersError because it waits for a string ('true' or 'false') :

In [1]: import ovh

In [2]: client = ovh.Client()

In [3]: client.get('/hosting/web/ncrocfer.ovh/ovhConfig', historical=False)
---------------------------------------------------------------------------
BadParametersError                        Traceback (most recent call last)
<ipython-input-3-b9140291291d> in <module>()
----> 1 client.get('/hosting/web/ncrocfer.ovh/ovhConfig', historical=False)

/home/ncrocfer/.virtualenvs/ovh/lib/python3.4/site-packages/ovh/client.py in get(self, _target, _need_auth, **kwargs)
    317                 _target = '%s?%s' % (_target, query_string)
    318 
--> 319         return self.call('GET', _target, None, _need_auth)
    320 
    321     def put(self, _target, _need_auth=True, **kwargs):

/home/ncrocfer/.virtualenvs/ovh/lib/python3.4/site-packages/ovh/client.py in call(self, method, path, data, need_auth)
    446             raise ResourceNotFoundError(json_result.get('message'))
    447         elif status == 400:
--> 448             raise BadParametersError(json_result.get('message'))
    449         elif status == 409:
    450             raise ResourceConflictError(json_result.get('message'))

BadParametersError: [historical] Given data (False) is not valid for type boolean

In [4]: client.get('/hosting/web/ncrocfer.ovh/ovhConfig', historical='false')
Out[4]: [1779827]

Is it possible to translate automatically the boolean argument to be API compatible ?
Thanks.

Low HTTP request failed error

Hi, trying to execute one of the examples but am getting an error.
I've gotten my key, secret key, and consumer key. Have endpoint=ovh-ca in my ovh.conf file along with the keys

Here's my code, config and the error I'm getting:

# to get your credentials
client = ovh.Client()
# Print nice welcome message
print "Welcome", client.get('/me')['firstname']

Error

INFO:ovh.vendor.requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): ca.api.ovh.com
Welcome
Traceback (most recent call last):
  File "hw.py", line 29, in <module>
    print "Welcome", client.get('/me')['firstname']
  File "/usr/local/lib/python2.7/dist-packages/ovh/client.py", line 319, in get
    return self.call('GET', _target, None, _need_auth)
  File "/usr/local/lib/python2.7/dist-packages/ovh/client.py", line 404, in call
    now = str(int(time.time()) + self.time_delta)
  File "/usr/local/lib/python2.7/dist-packages/ovh/client.py", line 197, in time_delta
    server_time = self.get('/auth/time', _need_auth=False)
  File "/usr/local/lib/python2.7/dist-packages/ovh/client.py", line 319, in get
    return self.call('GET', _target, None, _need_auth)
  File "/usr/local/lib/python2.7/dist-packages/ovh/client.py", line 422, in call
    raise HTTPError("Low HTTP request failed error", error)
ovh.exceptions.HTTPError: ('Low HTTP request failed error', SSLError(SSLError(IOError(2, 'No such file or directory'),),))

PUT/POST without Body on /cloud/project/{service_name}/ai/job/{job_id}/kill

Issue is very similar to #95 with the /cloud/project/{service_name}/ai/job/{job_id}/kill entrypoint.

Unfortunately the trip to call directly client.call('PUT', '/cloud/project/{serviceName}/user/{userID}/s3Credentials') is not enough, because the OVH API returns 204 (good), and no content (good), but this OVH package attempts to convert this 'no content' to json, which is thus failing:

ovh/client.py", line 423, in call
    raise InvalidResponse("Failed to decode API response", error)
ovh.exceptions.InvalidResponse: ('Failed to decode API response', JSONDecodeError('Expecting value: line 1 column 1 (char 0)'))

Documentation and API bug for dedicated servers

Hi!
Sorry, this is not strictly speaking a python-ovh related issue, but I found it using the client and don't know how to contact the server-side developpers... feel free to transfer the issue to whomever is better qualified to handle it.

First bug is a documentation bug on the web interface of the API (https://eu.api.ovh.com/console/#/dedicated/server/%7BserviceName%7D/serviceInfos#PUT), the python tab show the following code (using "my-server" as service name placeholder):

result = client.put('/dedicated/server/my-server/serviceInfos', 
    renew='{"manualPayment":true,"forced":false,"automatic":false,"deleteAtExpiration":false}', // Way of handling the renew (type: service.RenewType)
)

but this doesn't work!
Actual working code is:

client.put('/dedicated/server/my-server/serviceInfos',
    renew={"manualPayment":True,"forced":False,"automatic":False,"deleteAtExpiration":False}
)

(using correct python structure that will be turned into json by the client, instead of json string that I guess will be turned into "json-ified" json \{\"manualPayment\":true,\"forced\":false,\"automatic\":false,\"deleteAtExpiration\":false\})

Second bug is in the API itself and is made of several smaller problems:

  • first: the manualPayment and deleteAtExpiration do not work as expected. When trying to switch a server that is on automatic payment (call to GET /dedicated/server/my-server/serviceInfos returns "automatic":true,"manualPayment":false,"deleteAtExpiration":false,"period":1} ), I would expect to pass renew={"manualPayment":True,"forced":False,"automatic":False,"deleteAtExpiration":True} to PUT /dedicated/server/my-server/serviceInfos but then I get ovh.exceptions.BadParametersError: Arguments conflicting. Indeed I have to pass renew={"manualPayment":True,"forced":False,"automatic":False,"deleteAtExpiration":False} which does toggle the state of the server to manual payment AND delete at expiration (call to GET /dedicated/server/my-server/serviceInfos returns "automatic":false,"manualPayment":true,"deleteAtExpiration":true,"period":1} ). But calling the exact same code again (manual: true, deleteAtExpiration: false) will toggle the server back to automatic payment!
  • second: automatic and manualPayment parameters (for the same endpoint) are mutually exclusive (if it is automatic, it can't be manual, and vice-versa) so this is redundant at best, error-prone at worst.
  • third (as bonus): forced is useless, as it can't be changed but is mandatory all the same. ovh.exceptions.BadParametersError: Can not change forced field of the service if you try to change it, ovh.exceptions.BadParametersError: [renew] Missing properties: (forced) for type RenewType if missing

ContentDecodingError POST /cloud/project/{service_name}/kube

Hi
I have an error when I want to create a new instance of K8s managed by OVH :

ovh.exceptions.HTTPError: ('Low HTTP request failed error', ContentDecodingError(DecodeError('Received response with content-encoding: gzip, but failed to decode it.', error('Error -3 while decompressing data: incorrect header check'))))

I am using Python 3.9 and python-ovh 0.5.0 :

lib/python3.9/site-packages/ovh/client.py", line 415, in call
    raise HTTPError("Low HTTP request failed error", error)

The endpoint API : POST /cloud/project/{service_name}/kube
Body :
{'name': 'Test', 'region': 'SBG5', 'version': '1.18', 'nodepool': {'antiAffinity': True, 'desiredNodes': 3, 'flavorName': 'b2-15', 'maxNodes': 10, 'minNodes': 3, 'monthlyBilled': False, 'name': 'node-pool-test-1'}}

Proxy support available ?

Hi all
Thanks for this lib.
I may be wrong but I didn't find a way to setup a proxy for the Ovh Client.
Since vendor library 'requests' handles this, would it be possible to add proxy support ?
Thank you in advance

FirewallOptionTCP Data is not a hash for a complex type

I tried to create a rule authorising TCP protocol on all the IPs with an established option, as following:

rule = {'action': 'permit', 'protocol': 'tcp', 'sequence': 0, 'tcpOption': 'established'}
ip = 'xxx.xxx.xxx.xxx'
ovh_client.post(f'/ip/{ip}/firewall/{ip}/rule', **rule)

That raised the following exception:

 File "/miniconda/lib/python3.7/site-packages/ovh/client.py", line 377, in post
    return self.call('POST', _target, kwargs, _need_auth)
  File "/miniconda/lib/python3.7/site-packages/ovh/client.py", line 446, in call
    response=result)
ovh.exceptions.BadParametersError: [tcpOption] FirewallOptionTCP Data is not a hash for a complex type

What is the appropriate value to pass to tcpOption parameter?

Queries on /domain/{Zone}/serviceInfos

Hello,

In my attempt to manage my domains with the Ovh API, I have found some problems.

When I use the Python Wrapper, the information that I receive for the expiration date are wrong.
Can you explain me why the expiration date is one day before the creation date ?

Python Wrapper

{
    "renewalType": "oneShot",
    "contactAdmin": "xxxxx",
    "expiration": "2014-04-08",
    "status": "ok",
    "contactBilling": "xxxxx",
    "engagedUpTo": null,
    "possibleRenewPeriod": [],
    "canDeleteAtExpiration": false,
    "contactTech": "xxxxx",
    "creation": "2014-04-09",
    "serviceId": 61023049,
    "renew": {
        "forced": true,
        "automatic": false,
        "manualPayment": false,
        "period": null,
        "deleteAtExpiration": false
    },
    "domain": "votre-mariage-ideal.com"
}

And I don't have this problem with the same code in PHP.

PHP Wrapper

(
    [renewalType] => automaticV2012
    [status] => ok
    [engagedUpTo] =>
    [possibleRenewPeriod] => Array
        (
            [0] => 12
            [1] => 24
            [2] => 36
            [3] => 48
            [4] => 60
            [5] => 72
            [6] => 84
        )

    [serviceId] => 61023050
    [contactBilling] => xxxxx
    [renew] => Array
        (
            [manualPayment] =>
            [period] => 12
            [forced] =>
            [automatic] => 1
            [deleteAtExpiration] =>
        )

    [domain] => votre-mariage-ideal.com
    [contactTech] => xxxxx
    [expiration] => 2018-04-08
    [contactAdmin] => xxxxx
    [creation] => 2014-04-09
    [canDeleteAtExpiration] =>
)

Thanks for your help
Best Regards

Use maintainable dependencies for testing

I'm Fedora maintainer and I'm in the process of packaging python-ovh for Fedora. Unfortunately, python-ovh relies on yanc (not in the repos, newest version released: Dec 16, 2014) and old nose (Fedora has newer, incompatible version), which makes it hard to test the library. Please consider updating testing dependencies (tox/pytest would be perfect).

"target" variable

Hi
How to use the "target" argument of the api (POST /domain/zone/$/record) with this wrapper ?

client.post('/domain/zone/%s/record' % ndd,
        fieldType="TXT",
        subDomain=sub,
        _target=token
    )

return: TypeError: post() got multiple values for keyword argument '_target'

And without the "_" = error

Thanks

Methode POST sans body

Bonjour,

Avec les nouvelles API que vous proposez (par exemple /cloud/project/{serviceName}/user/{userId}/s3Credentials), il n'y a pas de body à envoyer.

Cependant, la méthode post envoie tout le temps un body dans la requête. Cela provoque l'erreur suivante :

  File ".local/lib/python3.8/site-packages/ovh/client.py", line 377, in post
    return self.call('POST', _target, kwargs, _need_auth)
  File ".local/lib/python3.8/site-packages/ovh/client.py", line 448, in call
    raise BadParametersError(json_result.get('message'),
ovh.exceptions.BadParametersError: You provided an input body while none was expected

Si je crée une méthode (pour le test) postnobody(), cela fonctionne :

def postnobody(self, _target, _need_auth=True):
        return self.call('POST', _target, None, _need_auth)

Peut être est il possible de ne pas envoyer de body via la méthode post actuelle, mais dans ce cas, je n'ai pas trouvé comment faire.

Je vous remercie par avance pour la prise en compte de ce retour.

Cordialement,

Wrapper doesn't respect https://api.ovh.com/ documentation with None value

For example:

result = client.get('/domain/zone/hashicorp4noobs.fr/record', 
    fieldType=None, // Filter the value of fieldType property (like) (type: zone.NamedResolutionFieldTypeEnum)
    subDomain=None, // Filter the value of subDomain property (like) (type: string)
)

Return a:

ovh.exceptions.BadParametersError: [fieldType] Given data (None) does not belong to the NamedResolutionFieldTypeEnum enumeration
OVH-Query-ID: EU.ext-2.612b4d7e.29385.a922ffb9-cbe4-4e2c-bca3-5888c1cbc55e

ovh.exceptions.APIError: Internal server error on vps/use api

I am getting server error on the following route for trying to find the memory usage for the vps:

client = ovh.Client()
params = {'type': 'mem:used'}
result = client.get("/vps/{server-name}/use", True, **params)

response:

ovh.exceptions.APIError: Internal server error 
OVH-Query-ID: CA.ext-5.6468811b.18216.a9ba91f3-57a2-499f-91e7-9c57547fbd49

Also,
/vps/{serviceName}/statistics does not work either to get memory usage.

/vps route works fine and return the vps information so my connection is working fine and it's the issue with the route.
Same error displays when using from the console preview for these routes: https://ca.api.ovh.com/console-preview

Error when try to add SSL certificate in IPLB

Hi everybody,

I have an error when I try to add let's encrypt certificate in IPLB.
So let's encrypt (through dehydrated project ) give to me 4 files

  • privkey.pem
  • cert.pem
  • fullchain.pem
  • chain.pem

In the following code, it fail when I try to pass the fullchain or the chain.
But it's working when I doesn't pass the chain, and it's also working when I pass fullchain or chain in the ovh API console

ovh_client = ovh.Client()

with open('cert.pem', 'r') as content_file:
    certif = content_file.read()

with open('privkey.pem', 'r') as content_file:
    privatekey = content_file.read()

with open('chain.pem', 'r') as content_file:
    chain = content_file.read()

with open('fullchain.pem', 'r') as content_file:
    fullchain = content_file.read()
    
try:
    result = ovh_client.post('/ipLoadbalancing/{}/ssl'.format(ip_lb_name),
                                  certificate=certif,
                                  key=privatekey,
                                  chain=chain # or fullchain generate the same error
                                  )
except (ovh.exceptions.BadParametersError, ovh.exceptions.ResourceConflictError) as err:
    print('Impossible to add certificate. err: {}'.format(err)) # error like 'chain not valid'

So I made a stupid things or there is a little bug here ?

Have fun ;)

Pb with new api call PUT for nodepool

Hi,

The method PUT on the api /cloud/project//kube//nodepool/* has a 204 response instead of 200.
I know it's weird ... but I guess it's still in progress.

I guess a check for result emptyness is missing here

        # attempt to decode and return the response
        try:
            json_result = result.json()
        except ValueError as error:
            raise InvalidResponse("Failed to decode API response", error)

I can use the raw_call but it will be nice tu use put method.

log :

[DEBUG] "PUT /1.0/cloud/project/XXXXXXX/kube/XXXXXX/nodepool/XXXXXHTTP/1.1" 204 0
[ERROR] ('Failed to decode API response', JSONDecodeError('Expecting value: line 1 column 1 (char 0)'))

This call has not been granted

i create application_key, application_secret and consumer_key followin this blog https://docs.ovh.com/gb/en/customer/first-steps-with-ovh-api/ . but when i run my code i got error : ovh.exceptions.NotGrantedCall: This call has not been granted

Note: when i chose Validity for 5 min it work but when i chose {} i got error

application_key = getenv("application_key")
application_secret = getenv("application_secret")
consumer_key = getenv("consumer_key")
client = ovh.Client(
    endpoint='ovh-eu',
    application_key=application_key,
    application_secret=application_secret,
    consumer_key=consumer_key,
)
result = client.get("/me")
print(json.dumps(result, indent=4))

Sending data structure as parameter

first of all "chapeau" for this module, it's really great 👍 🎩

The post/get/put/delete methods do not seem to translate data structures passed as parameters properly.

For example, the POST /cloud/project/{serviceName}/instance API endpoint accepts a networks parameter of type cloud.instance.NetworkParams[], which as Raw data translates to something like:

{
  "flavorId": "eeb4ccc9-faa0-4afb-955e-6a0224f93055",
  "imageId": "40b6d3ca-ab2a-48e3-b07d-c707f13a0115",
  "monthlyBilling": false,
  "name": "foo",
  "networks": [
    {
      "networkId": "ab_cdef_0"
    }
  ],
  "region": "GRA3"
}

However passing a list of dict as a parameter to the aforementioned method doesn't seem to do the trick, neither does a string:

networks = [ { 'networkId': 'ab_cdef_0' } ]
# or
networks = str([ { 'networkId': 'ab_cdef_0' } ])

c.post('/cloud/project/{}/instance'.format(service_name),
         name='foo',
         flavorId='eeb4ccc9-faa0-4afb-955e-6a0224f93055',
         imageId='40b6d3ca-ab2a-48e3-b07d-c707f13a0115',
         networks=networks,
         region='GRA3'
      )
400
Invalid JSON received 

edited 23/03 11:20

I played a little bit in the console and here are my findings:

from ovh.client import Client
c = Client()

data = { 'key1': 'value1', 'key2': [ { 'key': 'value' } ] }
c._canonicalize_kwargs(data)

>>> {'key1': 'value1', 'key2': [{'key': 'value'}]}

It's a effectively a dict which structure looks valid to me.

Retrieve rescue password from API

I apologize for having to submit this directly here but I have tried OVH support and have not received any response two weeks later.

This is more of an feature / information request.

I am automating the deployment of dedicated servers via ansible and need to put a server into rescue mode to start an installation process.

The problem area is retrieving the rescue OTP.
Currently rescue mode will send an OTP via email once the system is in a ready state.

Is there a way to obtain the OTP from the API directly rather than have to fish it out of an email?
Could this be populated into the dedicated_servers output? For example, retrieving a server returns:

{u'linkSpeed': 10000, u'datacenter': u'gra2', u'monitoring': True, u'reverse': u'foo.domain.com', u'supportLevel': u'pro', u'ip': u'xx.xx.xx.xx', u'commercialRange': u'host', u'rootDevice': None, u'professionalUse': False, u'bootId': 1122, u'state': u'ok', u'rescueMail': u'[email protected]', u'serverId': xxxxxx, u'os': u'none_64', u'rack': u'G210A01', u'name': u'nsXXXXXXX.ip-x.x.x.eu'}

Currently having to retrieve the OTP "out of band" through email makes it difficult to keep the process fully automated.

Thank you,

David

Endpoints limits

Are there any limits on certain endpoints? Like X per day X per minute?

help with add of a DomainNS

hello
as API subscriber I am trying to automate a change of secondary DNS

my application_key=vBdLGPsBNVvzWiWP

and my code

client = ovh.Client()
#for example
dns = client.get('/domain/mydomain.com/nameServer')
for ns in dns:
    dnssec = client.get('/domain/mydomain.com/nameServer/' + str(ns))
    # i am able to delete a record
#NS = {'host' : 'ns2.myns.it', 'ip' : '123.123.123.123'}
#NS = ['ns2.myns.it']
#NS = {u'host': u'ns2.myns.it', u'ip': None, u'toDelete': False, u'isUsed': True}
#NS = {'host': 'ns2.myns.it'}
NS = {
    'namespace': "domain",
    'id': "DomainNs",
    'description': "Name server", 'properties':
        {
            'host': 'ns2.myns.it'
        }
    }

client.post('/domain/italiancasinoonline.com/nameServer', nameServer=NS)

PROBLEM IS HERE
as you can see, I have tried list, dict, tuple ... no luck for me

Traceback (most recent call last):
File "C:\Users\user\Documents\NetBeansProjects\ovhape\src\ovhape.py", line 63, in
client.post('/domain/italiancasinoonline.com/nameServer', nameServer=NS)
File "c:\Python27\lib\site-packages\ovh\client.py", line 305, in post
return self.call('POST', _target, kwargs, _need_auth)
File "c:\Python27\lib\site-packages\ovh\client.py", line 394, in call
raise BadParametersError(json_result.get('message'))
ovh.exceptions.BadParametersError: [nameServer] DomainNs Data is not an array for an array type

How can I add a name server to a domain?
How can I create correctly a DomainNs Data??

Thanks
Francesco

Deprecation in collections call

Hi, using python3.9 with poetry, I found out running pytest that the collections call used in ovh are deprecated and will stop working with 3.10

[...] lib/python3.9/site-packages/ovh/vendor/requests/packages/urllib3/_collections.py:2: DeprecationWarning: 
Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, 
and in 3.10 it will stop working
    from collections import Mapping, MutableMapping

-- Docs: https://docs.pytest.org/en/stable/warnings.html

PyPI currently says ovh package is compatible with at most python3.6 which according to https://www.python.org/dev/peps/pep-0494/ will stop being updated on 2021-12.

Is there any work on making this package compatible with newer python version. It would be good to be able to continue using it under Python 3.10 !

integrating with flask doesn't find ovh.conf

Hello,

When i try to integrate this with flask what exactly do i need to do to include the ovh.conf ?
It never seems to find it, even if it resides in the current directory as my .py flask file.
*** I am working on windows using pycharm ***

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.