140 lines
3.5 KiB
Go
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
|
|
}
|