Attempt to implement and test setting static ips from instance metadata
This commit is contained in:
parent
dd1cfa79e7
commit
47dbb7cdd3
16 changed files with 258 additions and 59 deletions
13
rust/program/hetzner-static-ip/Cargo.toml
Normal file
13
rust/program/hetzner-static-ip/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "hetzner-static-ip"
|
||||
edition = "2024"
|
||||
version = "1.0.0"
|
||||
metadata.crane.name = "hetzner-static-ip"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true }
|
||||
common = { path = "../../lib/common" }
|
||||
log = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
hakari = { version = "0.1", path = "../../lib/hakari" }
|
71
rust/program/hetzner-static-ip/src/main.rs
Normal file
71
rust/program/hetzner-static-ip/src/main.rs
Normal file
|
@ -0,0 +1,71 @@
|
|||
use anyhow::Context as _;
|
||||
use clap::{Parser, Subcommand};
|
||||
|
||||
use crate::metadata::Instance;
|
||||
|
||||
mod metadata;
|
||||
|
||||
fn main() {
|
||||
common::entrypoint(program);
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct Args {
|
||||
#[command(subcommand)]
|
||||
pub command: Commands,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum Commands {
|
||||
/// Configures the ipv6 address using instance metadata and iproute2
|
||||
Configure,
|
||||
}
|
||||
|
||||
fn program() -> anyhow::Result<()> {
|
||||
let args = Args::parse();
|
||||
match args.command {
|
||||
Commands::Configure => configure(),
|
||||
}
|
||||
}
|
||||
|
||||
fn configure() -> anyhow::Result<()> {
|
||||
let metadata_api = common::env::read_env("INSTANCE_API_URI")
|
||||
.unwrap_or(String::from("http://169.254.169.254/hetzner/v1/metadata"));
|
||||
let metadata = common::curl::read_text_as_string(&metadata_api)?;
|
||||
let metadata: Instance = common::yaml::from_str(&metadata)
|
||||
.context("Could not parse instance metadata into expected format")?;
|
||||
for m in metadata.network_config.config {
|
||||
for subnet in m.subnets {
|
||||
match subnet {
|
||||
metadata::InstanceNetworkConfigConfigSubnet::Static {
|
||||
ipv6,
|
||||
ipv4,
|
||||
address,
|
||||
gateway,
|
||||
} => {
|
||||
let mut cmd = common::proc::Command::new("ip");
|
||||
if ipv6.is_some_and(|v| v) {
|
||||
cmd.arg("-6");
|
||||
}
|
||||
if ipv4.is_some_and(|v| v) {
|
||||
cmd.arg("-4");
|
||||
}
|
||||
cmd.args(["addr", "add", &address, "dev", &m.name]);
|
||||
cmd.try_spawn_to_string()?;
|
||||
let mut cmd = common::proc::Command::new("ip");
|
||||
if ipv6.is_some_and(|v| v) {
|
||||
cmd.arg("-6");
|
||||
}
|
||||
if ipv4.is_some_and(|v| v) {
|
||||
cmd.arg("-4");
|
||||
}
|
||||
cmd.args(["route", "add", "default", "via", &gateway, "dev", &m.name]);
|
||||
cmd.try_spawn_to_string()?;
|
||||
}
|
||||
metadata::InstanceNetworkConfigConfigSubnet::Dhcp {} => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
32
rust/program/hetzner-static-ip/src/metadata.rs
Normal file
32
rust/program/hetzner-static-ip/src/metadata.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct Instance {
|
||||
#[serde(rename = "network-config")]
|
||||
pub network_config: InstanceNetworkConfig,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct InstanceNetworkConfig {
|
||||
pub config: Vec<InstanceNetworkConfigConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct InstanceNetworkConfigConfig {
|
||||
pub name: String,
|
||||
pub subnets: Vec<InstanceNetworkConfigConfigSubnet>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum InstanceNetworkConfigConfigSubnet {
|
||||
#[serde(rename = "static")]
|
||||
Static {
|
||||
ipv6: Option<bool>,
|
||||
ipv4: Option<bool>,
|
||||
address: String,
|
||||
gateway: String,
|
||||
},
|
||||
#[serde(rename = "dhcp")]
|
||||
Dhcp {},
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue