aws-mgmt-go/internal/cmd/update-a.go
2024-12-12 20:22:11 -05:00

140 lines
3.5 KiB
Go

package cmd
import (
"fmt"
"strings"
cli "github.com/urfave/cli/v2"
"aws-mgmt/pkg/client"
)
const updateADesc = `Update a DNS A record for an instance.
The only required argument is the FQDN: other information required to update
the appropriate Route53 record is determined by querying Route53 and IMDS (or
EC2) APIs.
If run on an EC2 instance with an appropriate IAM EC2 role, an A record will be
created for that instance. Required IAM permissions include:
- route53:ListHostedZonesByName
- route53:ChangeResourceRecordSets
Alternatively, an instance ID must be specified: an A record will be created
for that instance. Required IAM permissions include:
- route53:ListHostedZonesByName
- route53:ChangeResourceRecordSets
- ec2:DescribeInstances`
var UpdateAApp = &cli.App{
Name: "update-a",
Usage: "Create / update an A record for an instance with a public IP",
UsageText: "update-a [options] <FQDN>",
HideHelpCommand: true,
Args: true,
ArgsUsage: "<FQDN>",
Action: updateAFunc,
Description: updateADesc,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "instance-id",
Value: "",
Usage: "set the instance id, defaults to the instance running this command",
},
&cli.StringFlag{
Name: "loglevel",
Value: "error",
Usage: "set the loglevel: debug, info, error",
},
},
}
var UpdateACommand = &cli.Command{
Name: "update-a",
Usage: "Create / update an A record for an instance with a public IP",
UsageText: "update-a [options] <FQDN>",
HideHelpCommand: true,
Args: true,
ArgsUsage: "<FQDN>",
Action: updateAFunc,
Description: updateADesc,
Flags: []cli.Flag{
&cli.StringFlag{
Name: "instance-id",
Value: "",
Usage: "set the instance id, defaults to the instance running this command",
},
&cli.StringFlag{
Name: "loglevel",
Value: "error",
Usage: "set the loglevel: debug, info, error",
},
},
}
func updateAFunc(ctx *cli.Context) error {
// create logger
log, err := createLogger(ctx.String("loglevel"))
if err != nil {
return fmt.Errorf("unable to create a logger, %w", err)
}
// create aws config
cfg, err := client.CreateAWSConfig()
if err != nil {
return err
}
awsClient := client.NewAWSClient(
client.SetConfig(cfg),
)
// determine instance id
instance_id := ctx.String("instance-id")
// get hostname & domain
hostname := ctx.Args().Get(0)
domain, err := parseHostname(hostname)
if err != nil {
return err
}
log.Debug("input received", "instance-id", instance_id, "hostname", hostname, "domain", domain)
zoneID, err := awsClient.GetZoneID(domain)
if err != nil {
return err
}
log.Debug("zone id set", "zone-id", zoneID)
var publicIP string
if instance_id != "" {
log.Debug("attempting to retrieve public ip from the EC2 API")
publicIP, err = awsClient.GetEC2PublicIP(instance_id)
} else {
log.Debug("attempting to retrieve public ip from IMDS")
publicIP, err = awsClient.GetMetadata("public-ipv4")
}
if err != nil {
return err
}
log.Debug("public ip retrieved", "public_ip", publicIP)
err = awsClient.UpdateA(hostname, publicIP, zoneID)
if err != nil {
return err
}
log.Info("dns record updated", "hostname", hostname, "zone-id", zoneID, "public-ipv4", publicIP)
return nil
}
func parseHostname(h string) (string, error) {
var domain string
if idx := strings.IndexByte(h, '.'); idx >= 0 {
domain = h[idx+1:]
} else {
return "", fmt.Errorf("hostname (%s) must be a FQDN", h)
}
return domain, nil
}