Skip to content

Commit

Permalink
Fixups from botched PR
Browse files Browse the repository at this point in the history
  • Loading branch information
codepope committed Aug 10, 2020
1 parent d7c73a0 commit 105d105
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 43 deletions.
11 changes: 1 addition & 10 deletions api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Query struct {
Nodes []Organization
}

Organization *Organization
Organization *Organization
UserOrganizations UserOrganizations
OrganizationDetails OrganizationDetails
Build Build
Expand Down Expand Up @@ -287,15 +287,6 @@ type Database struct {
Engine string
}

type DNSZone struct {
ID string
Domain string
Organization Organization
Records []*DNSRecords
CreatedAt time.Time
UpdatedAt time.Time
}

type DNSRecords struct {
ID string
Name string
Expand Down
223 changes: 191 additions & 32 deletions cmd/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@ import (
"fmt"
"io/ioutil"
"os"
"strconv"
"strings"
"time"

"github.com/AlecAivazis/survey/v2"
"github.com/dustin/go-humanize"
"github.com/olekukonko/tablewriter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/superfly/flyctl/api"
"github.com/superfly/flyctl/cmdctx"
"github.com/superfly/flyctl/docstrings"
)

func newDnsCommand() *Command {
func newDNSCommand() *Command {
dnsStrings := docstrings.Get("dns")
cmd := &Command{
Command: &cobra.Command{
Expand All @@ -24,69 +31,104 @@ func newDnsCommand() *Command {
zonesStrings := docstrings.Get("dns.zones")
zonesCmd := &Command{
Command: &cobra.Command{
Use: zonesStrings.Usage,
Short: zonesStrings.Short,
Long: zonesStrings.Long,
Use: zonesStrings.Usage,
Short: zonesStrings.Short,
Long: zonesStrings.Long,
Aliases: []string{"z"},
},
}
cmd.AddCommand(zonesCmd)

zonesListStrings := docstrings.Get("dns.zones.list")
zonesListCmd := BuildCommand(zonesCmd, runZonesList, zonesListStrings.Usage, zonesListStrings.Short, zonesListStrings.Long, os.Stdout, requireSession)
zonesListCmd.Args = cobra.ExactArgs(1)
zonesListCmd := BuildCommandKS(zonesCmd, runZonesList, zonesListStrings, os.Stdout, requireSession)
zonesListCmd.Args = cobra.MaximumNArgs(1)

zonesCreateStrings := docstrings.Get("dns.zones.create")
zonesCreateCmd := BuildCommand(zonesCmd, runZonesCreate, zonesCreateStrings.Usage, zonesCreateStrings.Short, zonesCreateStrings.Long, os.Stdout, requireSession)
zonesCreateCmd.Args = cobra.ExactArgs(2)
zonesCreateCmd := BuildCommandKS(zonesCmd, runZonesCreate, zonesCreateStrings, os.Stdout, requireSession)
zonesCreateCmd.Args = cobra.MaximumNArgs(2)

zonesDeleteStrings := docstrings.Get("dns.zones.delete")
zonesDeleteCmd := BuildCommand(zonesCmd, runZonesDelete, zonesDeleteStrings.Usage, zonesDeleteStrings.Short, zonesDeleteStrings.Long, os.Stdout, requireSession)
zonesDeleteCmd.Args = cobra.ExactArgs(2)
zonesDeleteCmd := BuildCommandKS(zonesCmd, runZonesDelete, zonesDeleteStrings, os.Stdout, requireSession)
zonesDeleteCmd.Args = cobra.MaximumNArgs(2)

recordsStrings := docstrings.Get("dns.records")
recordsCmd := &Command{
Command: &cobra.Command{
Use: recordsStrings.Usage,
Short: recordsStrings.Short,
Long: recordsStrings.Long,
Use: recordsStrings.Usage,
Short: recordsStrings.Short,
Long: recordsStrings.Long,
Aliases: []string{"r"},
},
}
cmd.AddCommand(recordsCmd)

recordsListStrings := docstrings.Get("dns.records.list")
recordsListCmd := BuildCommand(recordsCmd, runRecordsList, recordsListStrings.Usage, recordsListStrings.Short, recordsListStrings.Long, os.Stdout, requireSession)
recordsListCmd.Args = cobra.ExactArgs(2)
recordsListCmd := BuildCommandKS(recordsCmd, runRecordsList, recordsListStrings, os.Stdout, requireSession)
recordsListCmd.Args = cobra.MaximumNArgs(2)

recordsExportStrings := docstrings.Get("dns.records.export")
recordsExportCmd := BuildCommand(recordsCmd, runRecordsExport, recordsExportStrings.Usage, recordsExportStrings.Short, recordsExportStrings.Long, os.Stdout, requireSession)
recordsExportCmd.Args = cobra.ExactArgs(2)
recordsExportCmd := BuildCommandKS(recordsCmd, runRecordsExport, recordsExportStrings, os.Stdout, requireSession)
recordsExportCmd.Args = cobra.MaximumNArgs(2)

recordsImportStrings := docstrings.Get("dns.records.import")
recordsImportCmd := BuildCommand(recordsCmd, runRecordsImport, recordsImportStrings.Usage, recordsImportStrings.Short, recordsImportStrings.Long, os.Stdout, requireSession)
recordsImportCmd.Args = cobra.ExactArgs(3)
recordsImportCmd := BuildCommandKS(recordsCmd, runRecordsImport, recordsImportStrings, os.Stdout, requireSession)
recordsImportCmd.Args = cobra.MaximumNArgs(3)

return cmd
}

func runZonesList(ctx *cmdctx.CmdContext) error {
orgSlug := ctx.Args[0]
var orgSlug string
if len(ctx.Args) == 0 {
org, err := selectOrganization(ctx.Client.API(), "")
if err != nil {
return err
}
orgSlug = org.Slug
} else {
orgSlug = ctx.Args[0]
}
zones, err := ctx.Client.API().GetDNSZones(orgSlug)
if err != nil {
return err
}

zonetable := tablewriter.NewWriter(ctx.Out)

zonetable.SetHeader([]string{"Domain", "Created"})

for _, zone := range zones {
fmt.Println(zone.ID, zone.Domain, zone.CreatedAt)
zonetable.Append([]string{zone.Domain, fmt.Sprintf("%s (%s)", humanize.Time(zone.CreatedAt), zone.CreatedAt.Format(time.UnixDate))})
}

zonetable.Render()

return nil
}

func runZonesCreate(ctx *cmdctx.CmdContext) error {
org, err := ctx.Client.API().FindOrganizationBySlug(ctx.Args[0])
if err != nil {
return err
var org *api.Organization
var domain string
var err error

if len(ctx.Args) == 0 {
org, err = selectOrganization(ctx.Client.API(), "")
if err != nil {
return err
}

prompt := &survey.Input{Message: "Domain name to create"}
survey.AskOne(prompt, &domain)
// TODO: Add some domain validation here
} else if len(ctx.Args) == 2 {
org, err = ctx.Client.API().FindOrganizationBySlug(ctx.Args[0])
if err != nil {
return err
}
domain = ctx.Args[1]
} else {
return errors.New("specify all arguments (or no arguments to be prompted)")
}
domain := ctx.Args[1]

fmt.Printf("Creating zone %s in organization %s\n", domain, org.Slug)

Expand All @@ -101,7 +143,30 @@ func runZonesCreate(ctx *cmdctx.CmdContext) error {
}

func runZonesDelete(ctx *cmdctx.CmdContext) error {
zone, err := ctx.Client.API().FindDNSZone(ctx.Args[0], ctx.Args[1])
var org *api.Organization
var domain string
var err error

if len(ctx.Args) == 0 {
org, err = selectOrganization(ctx.Client.API(), "")
if err != nil {
return err
}

prompt := &survey.Input{Message: "Domain name to delete"}
survey.AskOne(prompt, &domain)
} else if len(ctx.Args) == 2 {
org, err = ctx.Client.API().FindOrganizationBySlug(ctx.Args[0])
if err != nil {
return err
}
domain = ctx.Args[1]
} else {
return errors.New("specify all arguments (or no arguments to be prompted)")
}

zone, err := ctx.Client.API().FindDNSZone(org.Slug, domain)

if err != nil {
return err
}
Expand All @@ -119,7 +184,30 @@ func runZonesDelete(ctx *cmdctx.CmdContext) error {
}

func runRecordsList(ctx *cmdctx.CmdContext) error {
zone, err := ctx.Client.API().FindDNSZone(ctx.Args[0], ctx.Args[1])
var org *api.Organization
var zoneslug string
var err error

if len(ctx.Args) == 0 {
org, err = selectOrganization(ctx.Client.API(), "")
if err != nil {
return err
}

zoneslug, err = selectZone(ctx.Client.API(), org.Slug, "")

} else if len(ctx.Args) == 2 {
org, err = ctx.Client.API().FindOrganizationBySlug(ctx.Args[0])
if err != nil {
return err
}
zoneslug = ctx.Args[1]
} else {
return errors.New("specify all arguments (or no arguments to be prompted)")
}

zone, err := ctx.Client.API().FindDNSZone(org.Slug, zoneslug)

if err != nil {
return err
}
Expand All @@ -131,15 +219,47 @@ func runRecordsList(ctx *cmdctx.CmdContext) error {
return err
}

if ctx.OutputJSON() {
ctx.WriteJSON(records)
return nil
}

recordtable := tablewriter.NewWriter(ctx.Out)
recordtable.SetHeader([]string{"FQDN", "TTL", "Type", "Values"})

for _, record := range records {
fmt.Println(record.FQDN, record.TTL, record.Type, strings.Join(record.Values, ","))
recordtable.Append([]string{record.FQDN, strconv.Itoa(record.TTL), record.Type, strings.Join(record.Values, ",")})
}

recordtable.Render()

return nil
}

func runRecordsExport(ctx *cmdctx.CmdContext) error {
zone, err := ctx.Client.API().FindDNSZone(ctx.Args[0], ctx.Args[1])
var org *api.Organization
var zoneslug string
var err error

if len(ctx.Args) == 0 {
org, err = selectOrganization(ctx.Client.API(), "")
if err != nil {
return err
}

zoneslug, err = selectZone(ctx.Client.API(), org.Slug, "")

} else if len(ctx.Args) == 2 {
org, err = ctx.Client.API().FindOrganizationBySlug(ctx.Args[0])
if err != nil {
return err
}
zoneslug = ctx.Args[1]
} else {
return errors.New("specify all arguments (or no arguments to be prompted)")
}

zone, err := ctx.Client.API().FindDNSZone(org.Slug, zoneslug)
if err != nil {
return err
}
Expand All @@ -155,12 +275,51 @@ func runRecordsExport(ctx *cmdctx.CmdContext) error {
}

func runRecordsImport(ctx *cmdctx.CmdContext) error {
zone, err := ctx.Client.API().FindDNSZone(ctx.Args[0], ctx.Args[1])
var org *api.Organization
var zoneslug string
var filename string

var err error

if len(ctx.Args) == 0 {
org, err = selectOrganization(ctx.Client.API(), "")
if err != nil {
return err
}

zoneslug, err = selectZone(ctx.Client.API(), org.Slug, "")

validateFile := func(val interface{}) error {
_, err := os.Stat(val.(string))
if os.IsNotExist(err) {
return fmt.Errorf("File %s does not exist", val.(string))
}
return nil
}

err := survey.AskOne(&survey.Input{Message: "Import filename:"}, &filename, survey.WithValidator(validateFile))

if err != nil {
return err
}

} else if len(ctx.Args) == 3 {
org, err = ctx.Client.API().FindOrganizationBySlug(ctx.Args[0])
if err != nil {
return err
}
zoneslug = ctx.Args[1]
filename = ctx.Args[2]
} else {
return errors.New("specify all arguments (or no arguments to be prompted)")
}

zone, err := ctx.Client.API().FindDNSZone(org.Slug, zoneslug)
if err != nil {
return err
}

data, err := ioutil.ReadFile(ctx.Args[2])
data, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
Expand All @@ -170,7 +329,7 @@ func runRecordsImport(ctx *cmdctx.CmdContext) error {
return err
}

fmt.Println("zonefile imported")
fmt.Println("Zonefile import report")

for _, result := range results {
fmt.Printf("%s created: %d, updated: %d, deleted: %d, skipped: %d\n", result.Type, result.Created, result.Updated, result.Deleted, result.Skipped)
Expand Down
27 changes: 27 additions & 0 deletions cmd/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,33 @@ func selectOrganization(client *api.Client, slug string) (*api.Organization, err
return &orgs[selectedOrg], nil
}

func selectZone(client *api.Client, orgslug string, slug string) (string, error) {
zones, err := client.GetDNSZones(orgslug)
if err != nil {
return "", err
}

sort.Slice(zones[:], func(i, j int) bool { return (*zones[i]).Domain < (*zones[j]).Domain })

options := []string{}

for _, zone := range zones {
options = append(options, fmt.Sprintf("%s", zone.Domain))
}

selectedOrg := 0
prompt := &survey.Select{
Message: "Select zone:",
Options: options,
PageSize: 15,
}
if err := survey.AskOne(prompt, &selectedOrg); err != nil {
return "", err
}

return (*zones[selectedOrg]).Domain, nil
}

type suggestedBuilder struct {
Vendor string
Image string
Expand Down
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func init() {
newStatusCommand(),
newSuspendCommand(),
newVersionCommand(),
newDnsCommand(),
newDNSCommand(),
newOrgsCommand(),
)

Expand Down

0 comments on commit 105d105

Please sign in to comment.