Skip to content

Instantly share code, notes, and snippets.

@Kiwi

Kiwi/git.diff Secret

Last active July 26, 2020 09:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kiwi/c9777b6ab1e98665f41d758a0efdcbca to your computer and use it in GitHub Desktop.
Save Kiwi/c9777b6ab1e98665f41d758a0efdcbca to your computer and use it in GitHub Desktop.
private networking and monitoring for nixops-digitalocean
diff --git a/nixops_digitalocean/backends/droplet.py b/nixops_digitalocean/backends/droplet.py
index 5bb5dbf..c92db5d 100644
--- a/nixops_digitalocean/backends/droplet.py
+++ b/nixops_digitalocean/backends/droplet.py
@@ -44,6 +44,10 @@ class DropletOptions(ResourceOptions):
region: Optional[str]
size: Optional[str]
enableIpv6: Optional[bool]
+ enablePrivateNetworking: Optional[bool]
+ enableMonitoring: Optional[bool]
+ enableFloatingIP: Optional[bool]
+ floatingIP: Optional[str]
class DropletDeploymentOptions(MachineOptions):
@@ -61,6 +65,10 @@ class DropletDefinition(MachineDefinition):
region: Optional[str]
size: Optional[str]
enable_ipv6: Optional[bool]
+ enable_private_networking: Optional[bool]
+ enable_monitoring: Optional[bool]
+ enable_floating_ip: Optional[bool]
+ floating_ip: Optional[str]
def __init__(self, name: str, config: ResourceEval):
super().__init__(name, config)
@@ -73,6 +81,12 @@ class DropletDefinition(MachineDefinition):
self.region = self.config.droplet.region
self.size = self.config.droplet.size
self.enable_ipv6 = self.config.droplet.enableIpv6
+ self.enable_private_networking = self.config.droplet.enablePrivateNetworking
+ self.enable_monitoring = self.config.droplet.enableMonitoring
+ self.enable_floating_ip = self.config.droplet.enableFloatingIP
+ self.floating_ip = self.config.droplet.floatingIP
+ print(self.enable_monitoring)
+ print(self.enable_floating_ip)
def show_type(self) -> str:
return "{0} [{1}]".format(self.get_type(), self.region)
@@ -84,7 +98,7 @@ class DropletState(MachineState[DropletDefinition]):
return "droplet"
# generic options
- # state: int= attr_property("state", MachineState.MISSING, int) # override
+ state: int = attr_property("state", MachineState.MISSING, int) # override
public_ipv4: Optional[str] = attr_property("publicIpv4", None)
public_ipv6: dict = attr_property("publicIpv6", {}, "json")
default_gateway: Optional[str] = attr_property("defaultGateway", None)
@@ -97,6 +111,16 @@ class DropletState(MachineState[DropletDefinition]):
auth_token: Optional[str] = attr_property("droplet.authToken", None)
droplet_id: Optional[str] = attr_property("droplet.dropletId", None)
key_pair: Optional[str] = attr_property("droplet.keyPair", None)
+ enable_monitoring: Optional[bool] = attr_property(
+ "droplet.enableMonitoring", False, bool
+ )
+ enable_floating_ip: Optional[bool] = attr_property(
+ "droplet.enableFloatingIP", False, bool
+ )
+ enable_private_networking: Optional[bool] = attr_property(
+ "droplet.enablePrivateNetworking", False, bool
+ )
+ private_ipv4_address: Optional[str] = attr_property("droplet.privateIpv4", None)
def __init__(self, depl: Deployment, name: str, id: RecordId) -> None:
MachineState.__init__(self, depl, name, id)
@@ -124,11 +148,30 @@ class DropletState(MachineState[DropletDefinition]):
networking = {
"defaultGateway": self.default_gateway,
- "nameservers": ["8.8.8.8"], # default provided by DO
+ "nameservers": ["67.207.67.2", "67.207.67.3"], # default provided by DO
+ ("dhcpcd", "enable"): False,
("interfaces", "ens3", "ipv4", "addresses"): [
{"address": self.public_ipv4, "prefixLength": prefix_len(self.netmask)}
],
}
+
+ if self.private_ipv4_address and self.enable_private_networking:
+ networking[("interfaces", "ens4", "ipv4", "addresses")] = [
+ {"address": self.private_ipv4_address, "prefixLength": 16}
+ ]
+
+ if self.enable_floating_ip:
+ networking[("interfaces", "ens3", "ipv4", "addresses")] += [
+ {
+ "address": self.run_command(
+ "curl -s http://169.254.169.254/metadata/v1/interfaces/public/0/anchor_ipv4/address",
+ capture_stdout=True,
+ ),
+ "prefixLength": 16,
+ },
+ ]
+
+ print(networking)
if self.public_ipv6:
networking[("interfaces", "ens3", "ipv6", "addresses")] = [
{
@@ -156,6 +199,7 @@ class DropletState(MachineState[DropletDefinition]):
("users", "extraUsers", "root", "openssh", "authorizedKeys", "keys"): [
self.get_ssh_key_resource().public_key
],
+ ("services", "do-agent", "enable"): self.enable_monitoring,
},
)
@@ -172,6 +216,33 @@ class DropletState(MachineState[DropletDefinition]):
def set_common_state(self, defn: DropletDefinition) -> None:
super().set_common_state(defn)
self.auth_token = defn.auth_token
+ self.enable_monitoring = defn.enable_monitoring
+ self.enable_floating_ip = defn.enable_floating_ip
+
+ # Once it is on it can't be disabled with this api;
+ # all we can do is disable the interface in NixOS
+ # Only need to enable it if it's not enabled at creation time and
+ # is changed in the definition later
+ # these checks make the DO api be called less often
+ if defn.enable_private_networking and not self.enable_private_networking:
+ droplet = digitalocean.Droplet(
+ id=self.droplet_id, token=self.get_auth_token()
+ )
+ droplet.shutdown()
+ self.wait_for_down()
+ droplet.enable_private_networking()
+ droplet.power_on()
+ droplet.load()
+ self.private_ipv4_address = droplet.private_ip_address
+
+ self.enable_private_networking = defn.enable_private_networking
+
+ if defn.floating_ip:
+ droplet = digitalocean.Droplet(
+ id=self.droplet_id, token=self.get_auth_token()
+ )
+ floatingIp = digitalocean.FloatingIP(ip=defn.floating_ip, token=self.get_auth_token())
+ floatingIp.assign(droplet_id=self.droplet_id)
def get_auth_token(self) -> Optional[str]:
return os.environ.get("DIGITAL_OCEAN_AUTH_TOKEN", self.auth_token)
@@ -209,6 +280,8 @@ class DropletState(MachineState[DropletDefinition]):
name=self.name,
region=defn.region,
ipv6=defn.enable_ipv6,
+ monitoring=defn.enable_monitoring,
+ private_networking=defn.enable_private_networking,
ssh_keys=[ssh_key.public_key],
image="ubuntu-16-04-x64", # only for lustration
size_slug=defn.size,
@@ -233,11 +306,19 @@ class DropletState(MachineState[DropletDefinition]):
droplet.load()
self.droplet_id = droplet.id
self.public_ipv4 = droplet.ip_address
+ self.private_ipv4_address = droplet.private_ip_address
+ self.enable_private_networking = defn.enable_private_networking
+ self.enable_monitoring = defn.enable_monitoring
+ self.enable_floating_ip = defn.enable_floating_ip
self.log_end("{}".format(droplet.ip_address))
- # Not sure when I'd have more than one interface from the DO
- # API but networks is an array nevertheless.
- self.default_gateway = droplet.networks["v4"][0]["gateway"]
+ for n in droplet.networks["v4"]:
+ if n["ip_address"] == self.public_ipv4:
+ self.default_gateway = n["gateway"]
+
+ print(droplet.networks)
+ print("DEFAULT_GATEWAY")
+ print(self.default_gateway)
self.netmask = droplet.networks["v4"][0]["netmask"]
first_ipv6 = {}
diff --git a/nixops_digitalocean/data/nixos-infect b/nixops_digitalocean/data/nixos-infect
index f7bcce6..80bca11 100644
--- a/nixops_digitalocean/data/nixos-infect
+++ b/nixops_digitalocean/data/nixos-infect
@@ -98,6 +98,7 @@ EOF
];
defaultGateway = "${gateway}";
defaultGateway6 = "${gateway6}";
+ dhcpcd.enable = false;
interfaces = {
ens3 = {
ipv4.addresses = [$(for a in ${ens3_ip4s[@]}; do echo -n "
@@ -158,7 +159,8 @@ curl -L https://nixos.org/nix/install | sh
source ~/.nix-profile/etc/profile.d/nix.sh
-[ -z "$NIX_CHANNEL" ] && NIX_CHANNEL="nixos-19.03"
+[ -z "$NIX_CHANNEL" ] && NIX_CHANNEL="nixos-unstable"
+#[ -z "$NIX_CHANNEL" ] && NIX_CHANNEL="nixos-20.03"
nix-channel --remove nixpkgs
nix-channel --add "https://nixos.org/channels/$NIX_CHANNEL" nixos
nix-channel --update
diff --git a/nixops_digitalocean/nix/droplet.nix b/nixops_digitalocean/nix/droplet.nix
index 9f56b77..fdfc3ad 100644
--- a/nixops_digitalocean/nix/droplet.nix
+++ b/nixops_digitalocean/nix/droplet.nix
@@ -6,6 +6,37 @@ let
in
{
options = {
+ deployment.droplet.enableFloatingIP = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Whether to enable the Floating IP anchor IP on the droplet.
+ '';
+ };
+
+ deployment.droplet.floatingIP = mkOption {
+ default = "";
+ type = types.str;
+ description = ''
+ An existing floatingIP to use.
+ '';
+ };
+
+ deployment.droplet.enablePrivateNetworking = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Whether to enable private networking support on the droplet.
+ '';
+ };
+
+ deployment.droplet.enableMonitoring = mkOption {
+ default = false;
+ type = types.bool;
+ description = ''
+ Whether to enable do-agent on the droplet.
+ '';
+ };
deployment.droplet.authToken = mkOption {
default = "";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment