TUN-4425: --overwrite-dns flag for in adhoc and route dns cmds

This commit is contained in:
Adam Chalmers 2021-05-19 12:38:09 -05:00
parent a3153c6add
commit 4c5ebccacc
4 changed files with 41 additions and 17 deletions

View File

@ -1,5 +1,12 @@
**Experimental**: This is a new format for release notes. The format and availability is subject to change. **Experimental**: This is a new format for release notes. The format and availability is subject to change.
## 2021.5.8
### New Features
- When creating a DNS record to point a hostname at a tunnel, you can now use --overwrite-dns to overwrite any existing
DNS records with that hostname. This works when using the CLI to provision DNS, and when starting an adhoc tunnel, e.g.
- `cloudflared route --overwrite-dns dns foo foo.example.com`
- `cloudflared tunnel --overwrite-dns --name foo --hostname foo.example.com`
## 2021.5.7 ## 2021.5.7
### New Features ### New Features
- Named Tunnels will automatically select the protocol to connect to Cloudflare's edge network. - Named Tunnels will automatically select the protocol to connect to Cloudflare's edge network.

View File

@ -87,6 +87,10 @@ const (
var ( var (
graceShutdownC chan struct{} graceShutdownC chan struct{}
version string version string
routeFailMsg = fmt.Sprintf("failed to provision routing, please create it manually via Cloudflare dashboard or UI; "+
"most likely you already have a conflicting record there. You can also rerun this command with --%s to overwrite "+
"any existing DNS records for this hostname.", overwriteDNSFlag)
) )
func Flags() []cli.Flag { func Flags() []cli.Flag {
@ -181,7 +185,7 @@ func runAdhocNamedTunnel(sc *subcommandContext, name, credentialsOutputPath stri
if r, ok := routeFromFlag(sc.c); ok { if r, ok := routeFromFlag(sc.c); ok {
if res, err := sc.route(tunnel.ID, r); err != nil { if res, err := sc.route(tunnel.ID, r); err != nil {
sc.log.Err(err).Str("route", r.String()).Msg("failed to provision routing, please create it manually via Cloudflare dashboard or UI; most likely you already have a conflicting record there") sc.log.Err(err).Str("route", r.String()).Msg(routeFailMsg)
} else { } else {
sc.log.Info().Msg(res.SuccessSummary()) sc.log.Info().Msg(res.SuccessSummary())
} }
@ -199,12 +203,12 @@ func runClassicTunnel(sc *subcommandContext) error {
return StartServer(sc.c, version, nil, sc.log, sc.isUIEnabled) return StartServer(sc.c, version, nil, sc.log, sc.isUIEnabled)
} }
func routeFromFlag(c *cli.Context) (tunnelstore.Route, bool) { func routeFromFlag(c *cli.Context) (route tunnelstore.Route, ok bool) {
if hostname := c.String("hostname"); hostname != "" { if hostname := c.String("hostname"); hostname != "" {
if lbPool := c.String("lb-pool"); lbPool != "" { if lbPool := c.String("lb-pool"); lbPool != "" {
return tunnelstore.NewLBRoute(hostname, lbPool), true return tunnelstore.NewLBRoute(hostname, lbPool), true
} }
return tunnelstore.NewDNSRoute(hostname), true return tunnelstore.NewDNSRoute(hostname, c.Bool(overwriteDNSFlagName)), true
} }
return nil, false return nil, false
} }
@ -613,6 +617,7 @@ func tunnelFlags(shouldHide bool) []cli.Flag {
Hidden: shouldHide, Hidden: shouldHide,
}), }),
selectProtocolFlag, selectProtocolFlag,
overwriteDNSFlag,
}...) }...)
return flags return flags

View File

@ -29,10 +29,11 @@ import (
) )
const ( const (
allSortByOptions = "name, id, createdAt, deletedAt, numConnections" allSortByOptions = "name, id, createdAt, deletedAt, numConnections"
connsSortByOptions = "id, startedAt, numConnections, version" connsSortByOptions = "id, startedAt, numConnections, version"
CredFileFlagAlias = "cred-file" CredFileFlagAlias = "cred-file"
CredFileFlag = "credentials-file" CredFileFlag = "credentials-file"
overwriteDNSFlagName = "overwrite-dns"
LogFieldTunnelID = "tunnelID" LogFieldTunnelID = "tunnelID"
) )
@ -133,6 +134,12 @@ var (
Usage: `Constraints the cleanup to stop the connections of a single Connector (by its ID). You can find the various Connectors (and their IDs) currently connected to your tunnel via 'cloudflared tunnel info <name>'.`, Usage: `Constraints the cleanup to stop the connections of a single Connector (by its ID). You can find the various Connectors (and their IDs) currently connected to your tunnel via 'cloudflared tunnel info <name>'.`,
EnvVars: []string{"TUNNEL_CLEANUP_CONNECTOR"}, EnvVars: []string{"TUNNEL_CLEANUP_CONNECTOR"},
} }
overwriteDNSFlag = &cli.BoolFlag{
Name: overwriteDNSFlagName,
Aliases: []string{"f"},
Usage: `Overwrites existing DNS records with this hostname`,
EnvVars: []string{"TUNNEL_FORCE_PROVISIONING_DNS"},
}
) )
func buildCreateCommand() *cli.Command { func buildCreateCommand() *cli.Command {
@ -670,10 +677,11 @@ Further information about managing Cloudflare WARP traffic to your tunnel is ava
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
buildRouteIPSubcommand(), buildRouteIPSubcommand(),
}, },
Flags: []cli.Flag{overwriteDNSFlag},
} }
} }
func dnsRouteFromArg(c *cli.Context) (tunnelstore.Route, error) { func dnsRouteFromArg(c *cli.Context, overwriteExisting bool) (tunnelstore.Route, error) {
const ( const (
userHostnameIndex = 2 userHostnameIndex = 2
expectedNArgs = 3 expectedNArgs = 3
@ -687,7 +695,7 @@ func dnsRouteFromArg(c *cli.Context) (tunnelstore.Route, error) {
} else if !validateHostname(userHostname, true) { } else if !validateHostname(userHostname, true) {
return nil, errors.Errorf("%s is not a valid hostname", userHostname) return nil, errors.Errorf("%s is not a valid hostname", userHostname)
} }
return tunnelstore.NewDNSRoute(userHostname), nil return tunnelstore.NewDNSRoute(userHostname, overwriteExisting), nil
} }
func lbRouteFromArg(c *cli.Context) (tunnelstore.Route, error) { func lbRouteFromArg(c *cli.Context) (tunnelstore.Route, error) {
@ -756,7 +764,7 @@ func routeCommand(c *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
route, err = dnsRouteFromArg(c) route, err = dnsRouteFromArg(c, c.Bool(overwriteDNSFlagName))
if err != nil { if err != nil {
return err return err
} }

View File

@ -81,7 +81,8 @@ type RouteResult interface {
} }
type DNSRoute struct { type DNSRoute struct {
userHostname string userHostname string
overwriteExisting bool
} }
type DNSRouteResult struct { type DNSRouteResult struct {
@ -89,19 +90,22 @@ type DNSRouteResult struct {
CName Change `json:"cname"` CName Change `json:"cname"`
} }
func NewDNSRoute(userHostname string) Route { func NewDNSRoute(userHostname string, overwriteExisting bool) Route {
return &DNSRoute{ return &DNSRoute{
userHostname: userHostname, userHostname: userHostname,
overwriteExisting: overwriteExisting,
} }
} }
func (dr *DNSRoute) MarshalJSON() ([]byte, error) { func (dr *DNSRoute) MarshalJSON() ([]byte, error) {
s := struct { s := struct {
Type string `json:"type"` Type string `json:"type"`
UserHostname string `json:"user_hostname"` UserHostname string `json:"user_hostname"`
OverwriteExisting bool `json:"overwrite_existing"`
}{ }{
Type: dr.RecordType(), Type: dr.RecordType(),
UserHostname: dr.userHostname, UserHostname: dr.userHostname,
OverwriteExisting: dr.overwriteExisting,
} }
return json.Marshal(&s) return json.Marshal(&s)
} }