Skip to content
GitLab
Explore
Sign in
Commits on Source (1)
Version 3.9.0
· d1bec1ad
JonasS
authored
Oct 21, 2022
- added support for user-specified primary IPs (#88, thanks @ItsReddi)
d1bec1ad
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
d1bec1ad
...
...
@@ -15,8 +15,8 @@ You can find sources and pre-compiled binaries [here](https://github.com/JonasPr
```
bash
# Download the binary (this example downloads the binary for linux amd64)
$
wget https://github.com/JonasProgrammer/docker-machine-driver-hetzner/releases/download/3.
8.1
/docker-machine-driver-hetzner_3.
8.1
_linux_amd64.tar.gz
$
tar
-xvf
docker-machine-driver-hetzner_3.
8.1
_linux_amd64.tar.gz
$
wget https://github.com/JonasProgrammer/docker-machine-driver-hetzner/releases/download/3.
9.0
/docker-machine-driver-hetzner_3.
9.0
_linux_amd64.tar.gz
$
tar
-xvf
docker-machine-driver-hetzner_3.
9.0
_linux_amd64.tar.gz
# Make it executable and copy the binary in a directory accessible with your $PATH
$
chmod
+x docker-machine-driver-hetzner
...
...
@@ -110,6 +110,7 @@ $ docker-machine create \
-
`--hetzner-auto-spread`
: Add to a
`docker-machine`
provided
`spread`
group (mutually exclusive with
`--hetzner-placement-group`
)
-
`--hetzner-ssh-user`
: Change the default SSH-User
-
`--hetzner-ssh-port`
: Change the default SSH-Port
-
`--hetzner-primary-ipv4/6`
: Sets an existing primary IP (v4 or v6 respectively) for the server, as documented in
[
Networking
](
#networking
)
#### Existing SSH keys
...
...
@@ -152,8 +153,24 @@ was used during creation.
|
`--hetzner-auto-spread`
|
`HETZNER_AUTO_SPREAD`
| false |
|
`--hetzner-ssh-user`
|
`HETZNER_SSH_USER`
| root |
|
`--hetzner-ssh-port`
|
`HETZNER_SSH_PORT`
| 22 |
|
`--hetzner-primary-ipv4`
|
`HETZNER_PRIMARY_IPV4`
| |
|
`--hetzner-primary-ipv6`
|
`HETZNER_PRIMARY_IPV6`
| |
**Networking hint:**
When disabling all public IPs,
`--hetzner-use-private-network`
must be given.
#### Networking
Given
`--hetzner-primary-ipv4`
or
`--hetzner-primary-ipv6`
, the driver
attempts to set up machine creation with an existing
[
primary IP
](
https://docs.hetzner.com/cloud/servers/primary-ips/overview/
)
as follows: If the passed argument parses to a valid IP address, the primary IP is resolved via address.
Otherwise, it is resolved in the default Hetzner Cloud API way (i.e. via ID and name as a fallback).
No address family validation is performed, so when specifying an IP address it is the user's responsibility to pass the
appropriate type. This also applies to any given preconditions regarding the state of the address being attached.
If no existing primary IPs are specified and public address creation is not disabled for a given address family, a new
primary IP will be auto-generated by default. Primary IPs created in that fashion will exhibit whatever default behavior
Hetzner assigns them at the given time, so users should take care what retention flags etc. are being set.
When disabling all public IPs,
`--hetzner-use-private-network`
must be given.
`--hetzner-disable-public`
will take care of that, and behaves as if
`--hetzner-disable-public-4 --hetzner-disable-public-6 --hetzner-use-private-network`
were given.
...
...
driver.go
View file @
d1bec1ad
...
...
@@ -44,6 +44,10 @@ type Driver struct {
UsePrivateNetwork
bool
DisablePublic4
bool
DisablePublic6
bool
PrimaryIPv4
string
cachedPrimaryIPv4
*
hcloud
.
PrimaryIP
PrimaryIPv6
string
cachedPrimaryIPv6
*
hcloud
.
PrimaryIP
Firewalls
[]
string
ServerLabels
map
[
string
]
string
keyLabels
map
[
string
]
string
...
...
@@ -72,6 +76,8 @@ const (
flagUsePrivateNetwork
=
"hetzner-use-private-network"
flagDisablePublic4
=
"hetzner-disable-public-4"
flagDisablePublic6
=
"hetzner-disable-public-6"
flagPrimary4
=
"hetzner-primary-ipv4"
flagPrimary6
=
"hetzner-primary-ipv6"
flagDisablePublic
=
"hetzner-disable-public"
flagFirewalls
=
"hetzner-firewalls"
flagAdditionalKeys
=
"hetzner-additional-key"
...
...
@@ -189,6 +195,18 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
Name
:
flagDisablePublic
,
Usage
:
"Disable public ip (v4 & v6)"
,
},
mcnflag
.
StringFlag
{
EnvVar
:
"HETZNER_PRIMARY_IPV4"
,
Name
:
flagPrimary4
,
Usage
:
"Existing primary IPv4 address"
,
Value
:
""
,
},
mcnflag
.
StringFlag
{
EnvVar
:
"HETZNER_PRIMARY_IPV6"
,
Name
:
flagPrimary6
,
Usage
:
"Existing primary IPv6 address"
,
Value
:
""
,
},
mcnflag
.
StringSliceFlag
{
EnvVar
:
"HETZNER_FIREWALLS"
,
Name
:
flagFirewalls
,
...
...
@@ -261,6 +279,8 @@ func (d *Driver) setConfigFromFlagsImpl(opts drivers.DriverOptions) error {
d
.
UsePrivateNetwork
=
opts
.
Bool
(
flagUsePrivateNetwork
)
||
disablePublic
d
.
DisablePublic4
=
opts
.
Bool
(
flagDisablePublic4
)
||
disablePublic
d
.
DisablePublic6
=
opts
.
Bool
(
flagDisablePublic6
)
||
disablePublic
d
.
PrimaryIPv4
=
opts
.
String
(
flagPrimary4
)
d
.
PrimaryIPv6
=
opts
.
String
(
flagPrimary6
)
d
.
Firewalls
=
opts
.
StringSlice
(
flagFirewalls
)
d
.
AdditionalKeys
=
opts
.
StringSlice
(
flagAdditionalKeys
)
...
...
@@ -297,6 +317,14 @@ func (d *Driver) setConfigFromFlagsImpl(opts drivers.DriverOptions) error {
flagUsePrivateNetwork
,
flagDisablePublic
)
}
if
d
.
DisablePublic4
&&
d
.
PrimaryIPv4
!=
""
{
return
d
.
flagFailure
(
"--%v and --%v are mutually exclusive"
,
flagPrimary4
,
flagDisablePublic4
)
}
if
d
.
DisablePublic6
&&
d
.
PrimaryIPv6
!=
""
{
return
d
.
flagFailure
(
"--%v and --%v are mutually exclusive"
,
flagPrimary6
,
flagDisablePublic6
)
}
return
nil
}
...
...
@@ -375,6 +403,14 @@ func (d *Driver) PreCreateCheck() error {
return
fmt
.
Errorf
(
"could not create placement group: %w"
,
err
)
}
if
_
,
err
:=
d
.
getPrimaryIPv4
();
err
!=
nil
{
return
fmt
.
Errorf
(
"could not resolve primary IPv4: %w"
,
err
)
}
if
_
,
err
:=
d
.
getPrimaryIPv6
();
err
!=
nil
{
return
fmt
.
Errorf
(
"could not resolve primary IPv6: %w"
,
err
)
}
if
d
.
UsePrivateNetwork
&&
len
(
d
.
Networks
)
==
0
{
return
errors
.
Errorf
(
"No private network attached."
)
}
...
...
@@ -495,11 +531,9 @@ func (d *Driver) makeCreateServerOptions() (*hcloud.ServerCreateOpts, error) {
PlacementGroup
:
pgrp
,
}
if
d
.
DisablePublic4
||
d
.
DisablePublic6
{
srvopts
.
PublicNet
=
&
hcloud
.
ServerCreatePublicNet
{
EnableIPv4
:
!
d
.
DisablePublic4
,
EnableIPv6
:
!
d
.
DisablePublic6
,
}
err
=
d
.
setPublicNetIfRequired
(
srvopts
)
if
err
!=
nil
{
return
nil
,
err
}
networks
,
err
:=
d
.
createNetworks
()
...
...
@@ -537,6 +571,27 @@ func (d *Driver) makeCreateServerOptions() (*hcloud.ServerCreateOpts, error) {
return
&
srvopts
,
nil
}
func
(
d
*
Driver
)
setPublicNetIfRequired
(
srvopts
hcloud
.
ServerCreateOpts
)
error
{
pip4
,
err
:=
d
.
getPrimaryIPv4
()
if
err
!=
nil
{
return
err
}
pip6
,
err
:=
d
.
getPrimaryIPv6
()
if
err
!=
nil
{
return
err
}
if
d
.
DisablePublic4
||
d
.
DisablePublic6
||
pip4
!=
nil
||
pip6
!=
nil
{
srvopts
.
PublicNet
=
&
hcloud
.
ServerCreatePublicNet
{
EnableIPv4
:
!
d
.
DisablePublic4
,
EnableIPv6
:
!
d
.
DisablePublic6
,
IPv4
:
pip4
,
IPv6
:
pip6
,
}
}
return
nil
}
func
(
d
*
Driver
)
createNetworks
()
([]
*
hcloud
.
Network
,
error
)
{
networks
:=
[]
*
hcloud
.
Network
{}
for
_
,
networkIDorName
:=
range
d
.
Networks
{
...
...
@@ -1094,3 +1149,52 @@ func (d *Driver) removeEmptyServerPlacementGroup(srv *hcloud.Server) error {
return
nil
}
}
func
(
d
*
Driver
)
getPrimaryIPv4
()
(
*
hcloud
.
PrimaryIP
,
error
)
{
raw
:=
d
.
PrimaryIPv4
if
raw
==
""
{
return
nil
,
nil
}
else
if
d
.
cachedPrimaryIPv4
!=
nil
{
return
d
.
cachedPrimaryIPv4
,
nil
}
ip
,
err
:=
d
.
resolvePrimaryIP
(
raw
)
d
.
cachedPrimaryIPv4
=
ip
return
ip
,
err
}
func
(
d
*
Driver
)
getPrimaryIPv6
()
(
*
hcloud
.
PrimaryIP
,
error
)
{
raw
:=
d
.
PrimaryIPv6
if
raw
==
""
{
return
nil
,
nil
}
else
if
d
.
cachedPrimaryIPv6
!=
nil
{
return
d
.
cachedPrimaryIPv6
,
nil
}
ip
,
err
:=
d
.
resolvePrimaryIP
(
raw
)
d
.
cachedPrimaryIPv6
=
ip
return
ip
,
err
}
func
(
d
*
Driver
)
resolvePrimaryIP
(
raw
string
)
(
*
hcloud
.
PrimaryIP
,
error
)
{
client
:=
d
.
getClient
()
.
PrimaryIP
var
getter
func
(
context
.
Context
,
string
)
(
*
hcloud
.
PrimaryIP
,
*
hcloud
.
Response
,
error
)
if
net
.
ParseIP
(
raw
)
!=
nil
{
getter
=
client
.
GetByIP
}
else
{
getter
=
client
.
Get
}
ip
,
_
,
err
:=
getter
(
context
.
Background
(),
raw
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"could not get primary IP: %w"
,
err
)
}
if
ip
!=
nil
{
return
ip
,
nil
}
return
nil
,
fmt
.
Errorf
(
"primary IP not found: %v"
,
raw
)
}