Giter VIP home page Giter VIP logo

hcloud-go's People

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

hcloud-go's Issues

Get returns nil when name of server is a number

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)
}

Bare Metal support?

  • Does this library support scripting of bare metal servers?
  • If not, are there any short-term plans to have this supported?

Hitting the Hetzner API limits

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:

ticker := time.NewTicker(500 * time.Millisecond)

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

Allow booting ipxe images

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.

Provide api mock for testing

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

Volume status field?

Where is "Status" field in "Volume" struct?

Current status of the volume
Choices: creating, available

Add support for resource protection

Resource protection has been added to the API on 2018-03-28. What we need to implement:

  • ImageClient.ChangeProtection() (docs)
  • ServerClient.ChangeProtection() (docs)
  • FloatingIPClient.ChangeProtection() (docs)

What I am doing wrong with this issue? could_not_verify_domain_delegated_to_zone

ErrorCodeCloudNotVerifyDomainDelegatedToZone ErrorCode = "could_not_verify_domain_delegated_to_zone" // Could not verify domain delegated to zone

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

Bildschirmfoto 2021-10-26 um 03 45 14

Bildschirmfoto 2021-10-26 um 03 45 33

Bildschirmfoto 2021-10-26 um 03 53 41

screenshot-dash cloudflare com-2021 10 26-03_52_07

I hope I gave enough information.
What I am doing wrong? Are there settings in Cloudflare I have to respect?

Thank you very much

Call close on response body method to prevent a resource leak

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.

Spawning a new instance inside a private network does not return private IP.

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
image

,"Rules":null,"AppliedTo":null},"Status":"applied"}]},"PrivateNet":null,"ServerType":{"ID":23,"Name":"cpx21"

Availability zone endpoint does not work

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.

Allow SSHKey fingerprint instead of SSHKey ID

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.

[proposal] add interface for client type

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?

Type []*SSHKey

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.

Metrics

It would be nice if I could get some metrics like in the API.

Remove WatchProgressInterval and provide a generic poll interval option

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.

Specifying a network twice prevents server from starting up

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

Querying non-existent objects does not return an error

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")
}

I deleted the wrong server because empty server arg selects the first server (?)

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.

Missing ErrorCodes

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
}

Fix enum types

For example, Floating IP types are defined like this:

const (
	FloatingIPTypeIPv4 FloatingIPType = "ipv4"
	FloatingIPTypeIPv6                = "ipv6"
)

But FloatingIPTypeIPv6 is of type string. 😢

PublicNet IPv4/IPv6 is nil after creating a loadbalancer

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 <--
      }
    },

refresh time of traffic values

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?

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.