hetznercloud / hcloud-go Goto Github PK
View Code? Open in Web Editor NEWA Go library for the Hetzner Cloud API
Home Page: https://pkg.go.dev/github.com/hetznercloud/hcloud-go/v2/hcloud
License: MIT License
A Go library for the Hetzner Cloud API
Home Page: https://pkg.go.dev/github.com/hetznercloud/hcloud-go/v2/hcloud
License: MIT License
Hello,
it would be nice if I could pass parameters like type
to the images
endpoint.
I guess to accomplish this, the ImageListOpts must be extended.
Steps to reproduce
c := hcloud.NewClient(hcloud.WithToken(token))
_, err := c.Server.GetByID(context.Background(), nonExistentID)
fmt.Println(err)
Actual result
nil
Expected result
Server with ID #1234 not found
In my case, querying a non-existent resource clearly is an error condition. Right now to handle both cases, ugly hacks have to be implemented:
srv, err := c.Server.GetByID(context.Background(), nonExistentID)
if err != nil {
// errors.Wrap() returns nil if err is nil
return errors.Wrap(err, "error querying server")
}
if srv == nil {
return errors.New("server not found")
}
While creating an instance it could be nice to use the SSHKey fingerprint instead of the primary key of an SSHKey. Looks like that API already supports that as an undocumented feature.
I would like to use that for a Hetzner Cloud integration to avoid another roundtrip to get the ID for a key instead of simply providing the fingerprint.
Should be rate_limit_exceeded
, not limit_reached
.
Line 70 in 1cde0d7
I wanna secure my page with the Hetzners Letsencrypt Certificate mechanism.
I have a simple k8s cluster running (also tried single server) with a loadbalancer in between.
I followed exactly the Hetzner Community tutorial for Cloudflare (provided here: https://community.hetzner.com/tutorials/configure-lb-cert-with-external-domain)
But I always end up with this error: could_not_verify_domain_delegated_to_zone
When I do a nslookup
:
❯ nslookup staging.mydomain.at
Server: XXX.XXX.XXX.XXX <<<< Resolves CORRECTLY to the IP of my Loadbalancer
Address: 195.58.161.123#53
Non-authoritative answer:
Name: staging.XXXXXX.at
Address: 49.12.16.238
I hope I gave enough information.
What I am doing wrong? Are there settings in Cloudflare I have to respect?
Thank you very much
Hi, I try to add a key via &hcloud.SSHKey{}
, but I encounter this error:
Cannot use '&hcloud.SSHKey{}' (type *SSHKey) as type []*SSHKey
How can I wrap it to make it work? Thank you.
Hi,
we have recently encountered unexpected behavior where a server would not start up if the same network was specified twice in ServerCreateOpts
. While this was ultimately an end-user error, I would still like to get some clarification on the underlying cause.
The whole process of creating the server works as expected and provisioning works -- given the machine is started from the cloud panel. So this begs the question: Is specifying a network twice really an error (as it does not seem to cause side-effects other than the auto-startup not working as expected)? If so, should the Server.Create
not indicate this by returning an error, rather than going through with it?
Just to be clear, I do not want to shift blame or anything, I just wondered if filtering out multiple network occurrences or having code to handle the side effects of it is something that downstream applications have to deal with themselves.
Original issue for reference: docker-machine-driver-hetzner#81
Thanks in advance
I understand that this project is for hetzner cloud, but could we have something with this quality for hetzner dns ?
there are issues with the existing implementations as you can see here: kubernetes-sigs/external-dns#2569
This is more of a feature request to the platform itself:
I'd be super convenient if it'd be possible to boot hcloud servers via IPXE, by selecting "ipxe" as a "os type", and pointing to a custom URL.
It could be made possible by a custom ipxe image that fetches a special field from the metadata servers http endpoint.
That'd simplify booting new images like Fedora Core OS, Flatcar or custom images dramatically.
The user-data
field should probably not be used for this, because these OSes use it to read their cloud-init configuration from.
I can't find any documentation about it, so I try my luck here.
How often are the following values refreshed for the server API:
"included_traffic": 21990232555520,
"ingoing_traffic": 4161740000,
....
"outgoing_traffic": 20802648000,
These values seem pretty static to me (I did several things that should have an effect on the server traffic, e.g. downloading big files etc). Is there a command line option for hcloud to increase the refresh time or is there at least something like a SLA that defines 'freshness' of the API data?
We use it in WatchAction
. Update the value of ErrorCodeLimitReached
to the new error code for rate limiting.
Not closing the body of HTTP responses can lead to a huge resource leak when doing HTTP requests intensively. The connection probably can remain open, in which case the file descriptor won't be freed. After some time this can cause you to get a 'too many files open' error. Therefore inserting a close statement right before wrapping the response body would be a good change.
If I have misunderstood something or the response is already closed, please let me know.
Tested it a several different machines in the Hetzner cloud, but http://169.254.169.254/hetzner/v1/metadata/availability-zone (dispatched here always returns a HTTP 404
):
curl -i http://169.254.169.254/hetzner/v1/metadata/availability-zone
HTTP/1.1 404 Not Found
Server: fasthttp
Date: Fri, 18 Feb 2022 18:45:54 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 27
availability-zone not found
This is a problem, since this call is used in the csi-driver where it always gets back the response availability-zone not found
and from that parses, that the availability zone itself is called availability
instead of for example nbg1
.
Note: Other endpoints like http://169.254.169.254/hetzner/v1/metadata or http://169.254.169.254/hetzner/v1/metadata/public-ipv4 work just fine.
I noticed that hcloud.Pricing
does not expose a field Volume
, even though the API documention is mentioning such a field.
It would be nice to have a mock suite in order to be easily able to perform e2e test.
In my opinion it would be enough to extract the mocks already present in the tests.
For example: considering the GetByID action test, it defines the mock as shown belown
env.Mux.HandleFunc("/actions/1", func(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(schema.ActionGetResponse{
Action: schema.Action{
ID: 1,
Status: "running",
Command: "create_server",
Progress: 50,
Started: time.Date(2017, 12, 4, 14, 31, 1, 0, time.UTC),
},
})
})
that could be done in a separate package
Where is "Status" field in "Volume" struct?
Current status of the volume
Choices: creating, available
As introduced in the API on 2018-02-26 and 2018-04-05.
We should have all available error codes as constant (https://github.com/hetznercloud/hcloud-go/blob/master/hcloud/error.go#L9).
Currently missing:
locked
forbidden
json_error
resource_limit_exceeded
uniqueness_error
protected
maintenance
This allows use (as sample in the terraform provider) to specify error codes, where a retry can be made (like: locked
) or when not (like: uniqueness_error
or protected
). At the moment i need to make this with a simple string:
if hcloud.IsError(err, "locked"){
// retry
}
instead of
if hcloud.IsError(err, hcloud.ErrorCodeLocked){
// retry
}
Hello, when i am creating a loadbalancer the responses PublicNet ipv4 and ipv6 value is null.
I put a debug statement into client.go to see where the error comes from.
It seems that the api does not return the right public net of the loadbalancer.
"load_balancer": {
"id": 12345,
"name": "xxx",
"public_net": {
"enabled": true,
"ipv4": {
"ip": null <--
},
"ipv6": {
"ip": null <--
}
},
The clients try to parse the argument for Get
as an integer. When the parsing succeeds it will interpret it as the id. When the server name for example is a number, it will not be found.
// Get retrieves a server by its ID if the input can be parsed as an integer, otherwise it
// retrieves a server by its name. If the server does not exist, nil is returned.
func (c *ServerClient) Get(ctx context.Context, idOrName string) (*Server, *Response, error) {
if id, err := strconv.Atoi(idOrName); err == nil {
return c.GetByID(ctx, int(id))
}
return c.GetByName(ctx, idOrName)
}
Using interfaces instead of structs for the client would make writing tests with mocks considerably easier.
Right now, in order to write "grey-box" tests mocking API calls, I can't see any other way than wrapping the client in an interface myself, but this means some non-testable boiler-plate code that could introduce or hide subtle bugs.
The current nested-struct
API would of course have to remain for backward-compatibility, but I believe adding an interface layer above it should be relatively straightforward. Something like:
type Clienter interface {
Volume() Volume
...
}
With the accompanying implementations for each "getter" methods.
Or maybe even going full-on interface (though the gains in this case seem less significant):
type Clienter interface {
Volume() VolumeClienter
...
}
type VolumeClienter interface {
All(ctx context.Context) ([]*Volume, error)
...
}
This feels like a rather minor change. Am I maybe overlooking something?
Otherwise: thoughts?
Hi,
I'm currently using the terraform provider to deploy my infrastructure. Due to the nature of my project, sometimes I need to start a cluster (26 nodes), delete it, then start it again within the same hour.
During this I always hit the 3600 requests / hour API limit enforced by Hetzner in the middle of starting the new cluster after shutting down the old one.
This would mean the terraform provider somehow issues (3600 Calls / 3x (Start, Stop, Start) / 26 Nodes) => more than 46 calls per node to hit this limit assuming an even distribution.
While investigating this client library the terraform provider is based upon, the following section grabbed my attention:
Line 151 in e37d001
It seems that every 500ms a call is being made to check if an action has been completed. It furthermore seems, that those calls count against the API limit, too. This would explain the rate limit issue.
If this is the case, would it be possible to expose the "magic number" 500ms as a configuration option?
Kind regards,
Matthias Gliwka
For example, Floating IP types are defined like this:
const (
FloatingIPTypeIPv4 FloatingIPType = "ipv4"
FloatingIPTypeIPv6 = "ipv6"
)
But FloatingIPTypeIPv6
is of type string
. 😢
Using dep.
I am spawning a server inside a private network as shown below. Yet, as can be seen in the logs, the response does not return the IP of that newly created server. It just says null
.
Any help would be greatly appreciated :D
,"Rules":null,"AppliedTo":null},"Status":"applied"}]},"PrivateNet":null,"ServerType":{"ID":23,"Name":"cpx21"
It would be nice if I could get some metrics like in the API.
It will be renamed to price_per_tb
shortly.
Line 187 in 63d492d
Should return the error from GetByID().
Feel free to send me to the hcloud cli github, but I feel the problem lies in the API.
command:
hcloud server delete "$( hcloud server list | awk '$2 == "already-manually-deleted-server.domain.net" {print $1}' )"
In effect: hcloud delete ""
Deletes the first server (order determined by hcloud server list).
Why would I do that? I wanted to use the server I payed for for the month before deleting it, so I put this delete command into the crontab for June 22 0:00. In the meantime, someone (me?) deleted it manually, so the list command returned an empty string "" so that hcloud delete "" happened.
Whatever convenience you had in mind, this convenience stops when you can delete the wrong server by this or a typo.
In the mean time, I learned that you can use the server name, too, so the awk command was unnecessary. As an aside, can you make that clear in the help output?
hcloud server describe --help
Describe a server
Usage:
hcloud server describe [FLAGS] SERVER
Flags:
-h, --help help for describe
-o, --output stringArray output options: json|format
Global Flags:
--poll-interval duration Interval at which to poll information, for example action progress (default 500ms)
ADD: SERVER can refer to id or name
As my nick name suggests, I would accept if you just decline this request.
E: I got the server back via support (apparantly that is possible within up to 24h).
E2: The code is straightforward and starts here: https://github.com/hetznercloud/cli/blob/50a7de3c37155fd71ff1e6cb0f9206eeb6c37eb8/cli/server_delete.go#L23
The code behind the API request (/servers?name=[empty string]) is not open source, I suppose.
Documentation says "Can be used to filter Servers by their name. The response will only contain the Server matching the specified name." well unless it is empty, then it shows all.
After discussion with @thetechnick we decided that having a generic poll interval option in the client and having WatchProgress()
use that option is the better solution.
So remove WatchProgressInterval()
again, add a PollInterval
option to Client
, and use that interval in WatchProgress()
.
client := hcloud.NewClient(
hcloud.WithToken("token"),
hcloud.WithPollInterval(1*time.Second),
)
Default should be 500ms.
Reasoning behind this is that in the long term we don’t want polling and WatchProgressInterval()
would be deprecated. It’s better to have an potentially unused option than a deprecated method. It’s also nicer to have only one variant of the WatchProgress
method.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.