Git Product home page Git Product logo

hetzner's Introduction

Python API for the Hetzner Robot

API usage

This is a small example session to illustrate how to use the API:

>>> from hetzner.robot import Robot
>>> robot = Robot("username", "password")
>>> list(robot.servers)
[<Server1>, <Server2>, <Server3>, <Server4>]
>>> server = robot.servers.get("1.2.3.4")
>>> server.status
u'ready'
>>> server.name
u'shiny server'
>>> server.reboot(mode='hard')
<httplib.HTTPResponse instance at 0x90d5a8>
>>> list(server.ips)
[<IpAddress 1.2.3.4>]
>>> server.set_name("foobar")
>>> server.name
u'foobar'
>>>
>>> server.rescue.shell()
Linux rescue 3.10.25 #128 SMP Tue Jan 7 10:58:27 CET 2014 x86_64

-------------------------------------------------------------------

  Welcome to the Hetzner Rescue System.

  This Rescue System is based on Debian 7.0 (wheezy) with a newer
  kernel. You can install software as in a normal system.

  To install a new operating system from one of our prebuilt
  images, run 'installimage' and follow the instructions.

  More information at http://wiki.hetzner.de

-------------------------------------------------------------------

Hardware data:
   ...

Network data:
   ...

root@rescue ~ # logout
>>> server.rescue.active
False
>>>

Commandline helper tool

There is also a small commandline helper tool called hetznerctl, which exposes most of the API functionality in a CLI similar to popular SCMs like Git or SVN.

In order to show the available commands type hetznerctl --help. Every subcommand has its own help, like for example hetznerctl rescue --help.

hetzner's People

Contributors

acjohnson avatar aszlig avatar basvandijk avatar dangra avatar haron avatar nh2 avatar pk-lms-dev avatar rbvermaa avatar tomsiewert 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

hetzner's Issues

robot access seems broken

user> hetznerctl admin -C 1.2.3.4 --debug
usage: hetznerctl [-h] [-c CONFIGFILE] command ...
hetznerctl: error: unrecognized arguments: --debug
svm-nixops> hetznerctl admin -C 1.2.3.4
Traceback (most recent call last):
  File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/bin/..hetznerctl-wrapped-wrapped", line 378, in <module>
    main()
  File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/bin/..hetznerctl-wrapped-wrapped", line 375, in main
    subcommand.execute(robot, parser, args)
  File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/bin/..hetznerctl-wrapped-wrapped", line 255, in execute
    login, passwd = server.admin.create(passwd=args.admpasswd)
  File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/lib/python3.6/site-packages/hetzner/server.py", line 425, in admin
    self._admin_account = AdminAccount(self)
  File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/lib/python3.6/site-packages/hetzner/server.py", line 167, in __init__
    self.update_info()
  File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/lib/python3.6/site-packages/hetzner/server.py", line 173, in update_info
    self._scraper.login()
  File "/nix/store/vwxdqcw9s9nnfam1m8ml80hpvqrwzagf-python3.6-python3.6-hetzner-0.7.1/lib/python3.6/site-packages/hetzner/robot.py", line 95, in login
    " page".format(response.status))
hetzner.WebRobotError: Invalid status code 302 while visiting login page

Documentation on how to use it?

Hi,

Could you put a README.md file with simple examples how to extract infos from Hetzner interface?

I have a hard time understanding what is the syntax of the config file, etc...

Handle DELL servers that don't have reboot option

Hi!

We're using now new DELL servers and got some problems with the library.

One of the problems is the encoding, I see @dangra commited a pull request, and I commited another.

The other is that DELL servers don't have a reboot command available cause they have a second interface with its own IP, where the user can reboot the server, even cool boots.

When we try to enable rescue mode, it fails with the error:

hetzner.RobotError: 400 - invalid input, fields: type (400)

on line 500:

    return self.conn.post('/reset/{0}'.format(self.ip), {'type': modekey})

The rescue mode is enabled, but we never get the password unless we do a 'info'.

I'm now testing some code to allow a reboot via ssh when DELL server is detected, but maybe the best is just to inform the user to reboot the server manually. What do you think?

I can provide my code as a pull request and then you decide what to do.

Regards,
Luar

hetznerctl list hangs

 File "/usr/local/bin/hetznerctl", line 414, in <module>
    main()
  File "/usr/local/bin/hetznerctl", line 410, in main
    subcommand.execute(robot, parser, args)
  File "/usr/local/bin/hetznerctl", line 127, in execute
    for server in robot.servers:
  File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 391, in __iter__
    return iter([Server(self.conn, s) for s in self.conn.get('/server')])
  File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 368, in get
    return self.request('GET', path)
  File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 329, in request
    response = self._request(method, path, data, headers)
  File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 301, in _request
    self.conn.request(method.upper(), path, data, headers)
  File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1279, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1325, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1274, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1034, in _send_output
    self.send(msg)
  File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 974, in send
    self.connect()
  File "/usr/local/lib/python3.9/site-packages/hetzner/util/http.py", line 55, in connect
    sock = socket.create_connection((self.host, self.port),
  File "/usr/local/Cellar/[email protected]/3.9.7/Frameworks/Python.framework/Versions/3.9/lib/python3.9/socket.py", line 832, in create_connection
    sock.connect(sa)

Compatibility issues on Windows

On Windows, any attempt to use the library will ultimately end up with a permission error. I tracked it down to the way you handle the certificate checks in case no bundles can be found (which you will not find on Windows, period). If you can't find a bundle, you ultimately end up writing out the root cert yourself using NamedTemporaryFile. However, NamedTemporaryFile does not work on Windows:

https://bugs.python.org/issue14243

My advice would be to simply bundle the cert as part of the Python package and read it from the class folder or alternatively disable automatic delete when using NamedTemporaryFile, make sure the file gets closed before being passed into wrap_socket, so that wrap_socket can actually open it, and then delete it yourself later when it is no longer needed. But IMHO the cleanest way is to simply get rid of any of that code and simply go with a bundled file.

getting UNAUTHORIZED error

I'm getting the response bellow with right credentials, whats wrong ?

{"error":{"status":401,"code":"UNAUTHORIZED","message":"Unauthorized"}}

Support IPv6-only server and Colocation

Hetzner offers IPv6-Only for Bare-Metal systems for since Nov. 2021. The current server_ip field is empty and the server_ipv6_net is filled instead. The query for the server can't be made via the Legacy-IP address anymore, but via the server id.

E.g. Colocation does not support server reset.

Server:
$ hetznerctl show 123
Number:        123
Main IP:       None
Name:          footlong-meatless-teriyaki
Product:       RX170
Data center:   FSN1-DC17
Traffic:       unlimited
Status:        ready
Cancelled:     False
Paid until:    1970-01-01 00:00:00
Traceback (most recent call last): [TRUNCATED]
hetzner.RobotError: 404 - server not found (404)

Colocation:
$ hetznerctl show 122 
Number:        122
Main IP:       None
Name:          filet-o-fish
Product:       Colocation Rack Basic
Data center:   FSN1-DC2-LOC9999-9999
Traffic:       10 TB
Status:        ready
Cancelled:     False
Paid until:    1970-01-01 00:00:00
hetzner.RobotError: 404 - server not found (404)

Reset method "soft" does not work on AX servers

Hello,

Attempting to reset an AX root server does not work:

$ hetznerctl rescue -a $SSH_FINGERPRINT $IP
Server #1234567: Trying to reboot using the 'soft' method.
hetzner.RobotError: 400 - invalid input, fields: type (400)

According to the Robot documentation, the sw reboot method (used by soft) is no longer available:

"type":[
  "power",
  "power_long",
  "hw",
  "man"
]

Attempts to call the reset API with the sw reset method (used by soft which is the default) fail with the above 400 error. Changing the default reset method to hw (hard) resolves the issue:

diff --git a/hetzner/reset.py b/hetzner/reset.py
index 4afc310..873ad9f 100644
--- a/hetzner/reset.py
+++ b/hetzner/reset.py
@@ -77,7 +77,7 @@ class Reset(object):
         is_down = False
 
         if tries is None:
-            tries = ['soft', 'hard']
+            tries = ['hard']
 
         for mode in tries:
             self.server.logger.info("Trying to reboot using the %r method.",
@@ -110,7 +110,7 @@ class Reset(object):
         else:
             raise ConnectError("Server keeps playing dead after reboot :-(")
 
-    def reboot(self, mode='soft'):
+    def reboot(self, mode='hard'):
         """
         Reboot the server, modes are "soft" for reboot by triggering Ctrl-Alt-
         Del, "hard" for triggering a hardware reset and "manual" for requesting
@@ -124,6 +124,6 @@ class Reset(object):
             'power': 'power',
         }
 
-        modekey = modes.get(mode, modes['soft'])
+        modekey = modes.get(mode, modes['hard'])
         return self.conn.post('/reset/{0}'.format(self.server.number),
                               {'type': modekey})

Fix Python 3 compatibility.

Especially since most distros now ship with Python 3 being the default, it really makes sense to support py3k and with that refactor all that py2.x crap (probably refactoring has to wait until 1.0).

Remove SSH code from the API

This really shouldn't belong to the API, so let's move it to the hetznerctl tool entirely.

Scheduled for 1.0.0, because this is a backwards-incompatible change.

Check that Hetzner returns 2FA info message

I've put in a support ticket with Hetzner that instead of 401 - Unauthorized they should return a more descriptive error code when using the API fails because 2-factor auth is enabled.

Their reply:

thank you for your suggestion. We will add a info about 2fa in the error message.

We should check soon if that is really returned.

hetznerctl reboot throws error

Not sure what I'm doing wrong here. Have the module installed and configured properly. hetznerctl list shows the servers.
But running
hetznerctl reboot IP x.x.x.x or herznerctl reboot x.x.x.x gives this error

File "/usr/local/bin/hetznerctl", line 414, in <module>
    main()
  File "/usr/local/bin/hetznerctl", line 410, in main
    subcommand.execute(robot, parser, args)
  File "/usr/local/bin/hetznerctl", line 60, in execute
    server = robot.servers.get(ip)
  File "/usr/local/lib/python3.10/dist-packages/hetzner/robot.py", line 388, in get
    return Server(self.conn, self.conn.get('/server/{0}'.format(ip)))
  File "/usr/local/lib/python3.10/dist-packages/hetzner/robot.py", line 368, in get
    return self.request('GET', path)
  File "/usr/local/lib/python3.10/dist-packages/hetzner/robot.py", line 333, in request
    raise RobotError(msg.format(response.status), response.status)
hetzner.RobotError: Empty response, status 404. (404)`

Login error from unexpected redirection

Did something change again on Hetzner's side?

$ nixops deploy
runner1..> creating an exclusive robot admin sub-account for ‘runner1’... Traceback (most recent call last):
  File "/nix/store/n82y5s41cqv05iq9ik4ryc1z28vvnwzn-python3.10-nixops-2.0.0-pre-fc9b55c/bin/.nixops-wrapped", line 9, in <module>
    sys.exit(main())
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/__main__.py", line 56, in main
    args.op(args)
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/script_defs.py", line 715, in op_deploy
    depl.deploy(
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1365, in deploy
    self.run_with_notify("deploy", lambda: self._deploy(**kwargs))
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1354, in run_with_notify
    f()
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1365, in <lambda>
    self.run_with_notify("deploy", lambda: self._deploy(**kwargs))
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1268, in _deploy
    nixops.parallel.run_tasks(
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/parallel.py", line 106, in run_tasks
    raise list(exceptions.values())[0]
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/parallel.py", line 70, in thread_fun
    work_result = (worker_fun(t), None, t.name)
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops/deployment.py", line 1220, in worker
    r.create(
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/nixops_hetzner/backends/server.py", line 713, in create
    ) = server.admin.create()
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/hetzner/server.py", line 425, in admin
    self._admin_account = AdminAccount(self)
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/hetzner/server.py", line 167, in __init__
    self.update_info()
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/hetzner/server.py", line 173, in update_info
    self._scraper.login()
  File "/nix/store/fdar1svp8cwzbxyngr6lkmibp6z4l4pw-python3-3.10.12-env/lib/python3.10/site-packages/hetzner/robot.py", line 124, in login
    raise WebRobotError(msg.format(ROBOT_WEBHOST, ROBOT_LOGINHOST,
hetzner.WebRobotError: https://robot.your-server.de/ does not redirect to https://accounts.hetzner.com/ but instead redirects to: https://robot.hetzner.com/

Validate the Robot's SSL certificate.

Python's httplib doesn't do certificate validation, so we need to do it ourselves to prevent man-in-the-middle attacks of the users of this library.

Probably the best is to validate the certificate chain using Thawte's root certificate, to compensate for certificate expiration (it's valid until 2020, which should be long enough).

SSL Certificates Issue - 'CERTIFICATE_VERIFY_FAILED'

I'm using Python 3.9 on OSX 10.15.7 and I've been running into the following error:

  File "watch_server_and_reset.py", line 16, in hetzner_list
    list(robot.servers)
  File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 391, in __iter__
    return iter([Server(self.conn, s) for s in self.conn.get('/server')])
  File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 368, in get
    return self.request('GET', path)
  File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 329, in request
    response = self._request(method, path, data, headers)
  File "/usr/local/lib/python3.9/site-packages/hetzner/robot.py", line 301, in _request
    self.conn.request(method.upper(), path, data, headers)
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1279, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1325, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1274, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 1034, in _send_output
    self.send(msg)
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/http/client.py", line 974, in send
    self.connect()
  File "/usr/local/lib/python3.9/site-packages/hetzner/util/http.py", line 68, in connect
    self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 1405, in wrap_socket
    return context.wrap_socket(
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/local/Cellar/[email protected]/3.9.7_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)

I've found Stackoverflow threads where other people fixed this by running the python update .command files, or by modifying the ssl library's certificate validating mechanism (code below), but neither solution has fixed the issue for me.

import ssl
ssl._create_default_https_context = ssl._create_unverified_context

Add a password_command config option

I am not happy with saving my Hetzner password to disk in plain text. So I was looking for a way to allow hetznerctl to query my password manager but did not see one (I could hack together a shell script that generates a temporary config file and calls hetznerctl, but that is ugly).

Would you be interested to support some kind of integration with password managers? I am interested in coding it.

Ideas

  1. Add a password_cmd config option that can be set instead of password and use it as a shell command that will output the password that will be used. I would implement this option as it is little work and fixes the issue for me. Down side: not very integrated UI, every user who wants to use it has to write a shell command into the config.
  2. Depend on a library like https://github.com/jaraco/keyring, I am not sure which one is the best library for this but this looks like a more integrated solution for end uses (I am not sure if that library supports pass so that might not be a solution for me)

hetzner API broken?

nixops broke for me today when I was trying to provision a new hetzner server. Tracking down the bug I found that it brakes here https://github.com/aszlig/hetzner/blob/master/hetzner/robot.py#L173 , It seems the expected cookie is not set. I tried to change the cookie name to "robot" (which you get if you login with a web-browser) but with no success. Can anyone confirm this? Has hetzner broke there API or am I doing something wrong?

Cheers

hetznerctl not executable

I installed hetzner for python.

root@om:~# pip install hetzner

Collecting hetzner
  Downloading hetzner-0.7.5.tar.gz
Building wheels for collected packages: hetzner
  Running setup.py bdist_wheel for hetzner ... done
  Stored in directory: /root/.cache/pip/wheels/ff/4e/42/3aac160c19e683ce1db4f7f47882187843907cc61939a3df4c
Successfully built hetzner
Installing collected packages: hetzner
Successfully installed hetzner-0.7.5

But the script is not executable:

root@om:~# hetznerctl
-bash: /usr/local/bin/hetznerctl: Keine Berechtigung

root@om:~# ls -l /usr/local/bin/hetznerctl
-rw-r--r-- 1 root root 8327 Feb 26 22:12 /usr/local/bin/hetznerctl

How to change DNS records

Is there a way to change DNS records?

My domain is thomas-guettler.de. I want to add a new DNS entry (foo.thomas-guettler.de) which points to FritzBox at home.

I want to update the DNS record with the hetzner-python library.

Can you please provide a hint how to do this?

root@om:~# host -a thomas-guettler.de
Trying "thomas-guettler.de"
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 20548
;; flags: qr rd ra; QUERY: 1, ANSWER: 7, AUTHORITY: 0, ADDITIONAL: 1

;; QUESTION SECTION:
;thomas-guettler.de.		IN	ANY

;; ANSWER SECTION:
thomas-guettler.de.	7200	IN	SOA	ns1.your-server.de. postmaster.your-server.de. 2015052000 86400 1800 3600000 86400
thomas-guettler.de.	7200	IN	NS	ns1.your-server.de.
thomas-guettler.de.	7200	IN	NS	ns.second-ns.com.
thomas-guettler.de.	7200	IN	NS	ns3.second-ns.de.
thomas-guettler.de.	7200	IN	A	178.63.61.147
thomas-guettler.de.	7200	IN	MX	10 mail.thomas-guettler.de.
thomas-guettler.de.	7200	IN	TXT	"v=spf1 a a:thomas-guettler.de a:hz1.yz.to mx -all"

;; ADDITIONAL SECTION:
mail.thomas-guettler.de. 7200	IN	A	178.63.61.147

Received 286 bytes from 127.0.1.1#53 in 90 ms

Creating admin accounts seems broken in 0.7.4

Not able to confirm this yet but I'm going to test it tomorrow, but it seems that right now creation of per-server admin accounts are not possible.

Originally reported in NixOS/nixops#563 by @grahamc:

nix-dev...............> creating an exclusive robot admin account for ‘nix-dev’... Traceback (most recent call last):
  File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/bin/..nixops-wrapped-wrapped", line 939, in <module>
    args.op()
  File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/bin/..nixops-wrapped-wrapped", line 374, in op_deploy
    repair=args.repair, dry_activate=args.dry_activate)
  File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/deployment.py", line 971, in deploy
    self._deploy(**kwargs)
  File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/deployment.py", line 928, in _deploy
    nixops.parallel.run_tasks(nr_workers=-1, tasks=self.active_resources.itervalues(), worker_fun=worker)
  File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/parallel.py", line 41, in thread_fun
    result_queue.put((worker_fun(t), None))
  File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/deployment.py", line 901, in worker
    r.create(self.definitions[r.name], check=check, allow_reboot=allow_reboot, allow_recreate=allow_recreate)
  File "/nix/store/b8dgrq5wv624xwbd3404sn026i9jxy00-nixops-1.4/lib/python2.7/site-packages/nixops/backends/hetzner.py", line 589, in create
    self.robot_admin_pass) = server.admin.create()
  File "/nix/store/lwqybpcw6vyd8s9gm4jbh1q069pnkbp2-python2.7-hetzner-0.7.4/lib/python2.7/site-packages/hetzner/server.py", line 222, in create
    assert "msgbox_success" in response.read()
AssertionError

once I created a user with an arbitrary password, it seemed to do okay (though I have not yet successfully deployed to it.)

Initial debugging by @FPtje:

Also hitting this issue. Printing response.read() gives the following:

<form id="admin_update" onsubmit="new Ajax.Updater('admin_422502', '/server/adminUpdate', {asynchronous:true, evalScripts:true, onLoading:function(request, json){addAjaxLoader('admin_422502')}, parameters:Form.serialize(this)}); return false;" action="/server/adminUpdate" method="post"><table class="form">
  <tr>
    <td class="label_req">Login</td>
    <td class="element"></td>
  </tr>
    <tr class="submit_row">
    <td class="label">
      <input class='button calltoaction' type='submit' value='Save'  />      <input type="hidden" name="id" value="422502" />
    </td>
  </tr>
</table>
</form>
<input class='button' type='button' value='Delete account' onclick="javascript:  new Ajax.Updater('admin_422502', '/server/adminDelete/id/422502', {asynchronous:true, evalScripts:true}); addAjaxLoader('admin_422502'); return false; ">

Cc: @grahamc, @FPtje, @domenkozar

Unspecified dependency on ConfigParser

When I run ./hetznerctl from within the cloned source directory, it works as expected.

However, when I install it with pip install hetzner or by running python setup.py install in the cloned source directory, and then just run hetznerctl from the command line I get:

Traceback (most recent call last):
  File "/usr/local/bin/hetznerctl", line 7, in <module>
    from ConfigParser import RawConfigParser, Error
ImportError: No module named 'ConfigParser'

This only happens with python 2.x.

With the following commands I get a happy installation:

$> python3 setup.py install
$> /Library/Frameworks/Python.framework/Versions/3.5/bin/hetznerctl list

I'm cautious just to put that bin directory on my PATH before the corresponding python2 directory because I think OS X maybe expecting certain python tools to be written in python2.

The specific versions of python I am using are:

$> python --version
Python 2.7.12

$> python3 --version
Python 3.5.2

Please advise.

Default certificate doesn't work on windows

A problem with the temporary file created from this was causing a failure.
http://tinyurl.com/ycfs48vu
"Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later)."

Solution:
line 61 in hetzner\util\http.py:

        if bundle is None:
            ca_certs = NamedTemporaryFile(delete=False)
            ca_certs.write('\n'.join(
                map(str.strip, self.CA_ROOT_CERT_FALLBACK.splitlines())
            ).encode('ascii'))
            ca_certs.flush()
            cafile = ca_certs.name
            ca_certs.close()
        try:
          self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
                                      cert_reqs=ssl.CERT_REQUIRED,
                                      ca_certs=cafile)
        finally:
          if bundle is None:
            try:
              os.remove(bundle)
            except:
              pass

Implement a small test suite with mocked up robot API replies.

It's about time that we have proper test cases, especially when it comes to encoding and py2/3 compatibility.

So essentially, we're replicating the API part of the robot and testing against it, so the test suite might be used for testing other Hetzner API implementations as well.

Exit gracefully if reset isn't available for a server.

This is what's returned when trying to reset a server which doesn't have the option:

{
  "error": {
    "status": 404,
    "code": "RESET_NOT_AVAILABLE",
    "message": "resetting this server is not possible"
  }
}

So let's try to raise a better exception than RobotError

Pull SubCommands into libraries

I'd like to make a command-line tool very similar in structure to the hetznerctl tool you have. But, it would have different SubCommand instances specific to the needs of my organization. It would be great to extract the definitions of the commands and the generic parts of the main function into libraries which would make it easy for my tool to use some of the same SubCommand instances, plus some new ones of my own design.

If you think this is a good idea, I'd be happy to provide you a pull-request refactoring the code for better reuse. (For now, I've just copied and pasted the parts I actually want from the hetznerctl tool.

Let me know.

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.