digitalocean / terraform-provider-digitalocean

Terraform DigitalOcean provider
https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs
Mozilla Public License 2.0
496 stars 265 forks source link

resource/datasource_digitalocean_droplet should return also information about gateway (and netmask) #529

Open fiksn opened 3 years ago

fiksn commented 3 years ago

I am playing around with Terraform and NixOS. Idea is to use something like https://github.com/tweag/terraform-nixos/tree/master/deploy_nixos w/ DigitalOcean Droplets. Therefore beside IP of the instance I'd also need other networking information (like standard gateway) so I can locally prepare a configuration.nix. This is very specific but I am quite sure that there are other use-cases for obtaining that data after a VM was provisioned. Or is there any reason why that would be a bad idea?

fiksn commented 3 years ago

Now I solved this through (sharing in case anybody else needs it):

data "external" "do_network" {
  program = ["${path.module}/do_network.sh"]

  query = {
    id       = ...
    token = ...
  }
}

and

#!/bin/bash
set -euo pipefail

# requires jq, curl and ipcalc

eval "$(jq -r '@sh "ID=\(.id) TOKEN=\(.token)"')"

function finish {
  rm -rf temp.$$
}
trap finish EXIT

curl -X GET -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" "https://api.digitalocean.com/v2/droplets/$ID" 2>/dev/null > temp.$$
IP4_ADDRESS=$(cat temp.$$ | jq '.droplet.networks.v4[] | select(.type=="public") | .ip_address')
IP4_NETMASK=$(cat temp.$$ | jq '.droplet.networks.v4[] | select(.type=="public") | .netmask')
IP4_GATEWAY=$(cat temp.$$ | jq '.droplet.networks.v4[] | select(.type=="public") | .gateway')
IP4_CIDR=$(ipcalc 1.3.3.7 $IP4_NETMASK -b | grep Netmask | cut -d"=" -f 2 | tr -d " \n")

IP6_ADDRESS=$(cat temp.$$ | jq '.droplet.networks.v6[] | select(.type=="public") | .ip_address')
IP6_CIDR=$(cat temp.$$ | jq '.droplet.networks.v6[] | select(.type=="public") | .netmask')
IP6_GATEWAY=$(cat temp.$$ | jq '.droplet.networks.v6[] | select(.type=="public") | .gateway')

rm -rf temp.$$

jq -n --arg ip4_address "$IP4_ADDRESS" --arg ip4_netmask "$IP4_NETMASK" --arg ip4_gateway "$IP4_GATEWAY" --arg ip4_cidr "$IP4_CIDR" --arg ip6_address "$IP6_ADDRESS" --arg ip6_cidr "$IP6_CIDR" --arg ip6_gateway "$IP6_GATEWAY" \
  '{"ip4_address":$ip4_address, "ip4_netmask":$ip4_netmask, "ip4_gateway":$ip4_gateway, "ip4_cidr":$ip4_cidr, "ip6_adress":$ip6_address, "ip6_cidr":$ip6_cidr, "ip6_gateway":$ip6_gateway}'

which allows me to use something like data.external.do_network.result["ip4_gateway"], but this still feels hackish. As a Terraform noob I am not really sure, is this the desired way to go or should provider return more data?

tdyas commented 3 years ago

As a Terraform noob I am not really sure, is this the desired way to go or should provider return more data?

The better way would be to update the digitialocean_droplet data source and resource to return the networks information that the API appears to already return (going by your shell script). It would just involve some boilerplate Go code to define the schema and then code to take the attributes from the godo client library struct and set it in the Terraform schema.

Do you want to make the changes? I can guide you to the applicable parts of the code.