Skip to content

Commit

Permalink
refactor: use cobra to handle CLI arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
danroc committed Apr 26, 2022
1 parent 5289ca9 commit 53f97d6
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 61 deletions.
125 changes: 65 additions & 60 deletions cmd/htp/main.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package main

import (
"flag"
"fmt"
"log"
"os"
"os/exec"
"runtime"
"strings"
"time"

"github.com/danroc/htp/pkg/htp"
"github.com/spf13/cobra"
)

const (
Expand All @@ -20,53 +19,78 @@ const (
second = int64(time.Second)
)

type options struct {
host string
count uint
verbose bool
date bool
sync bool
format string
}
func buildRootCommand() *cobra.Command {
var (
host string
silent bool
format string
sync bool
date bool
count int
timeout int
)

func main() {
opts := parseArgs()
if !strings.Contains(opts.host, "://") {
opts.host = "https://" + opts.host
}
cmd := &cobra.Command{
Use: "htp",
Short: "HTP - Date and time from HTTP headers",
RunE: func(cmd *cobra.Command, args []string) error {
if !strings.Contains(host, "://") {
host = "https://" + host
}

logger := log.New(os.Stderr, "", 0)
model := htp.NewSyncModel()
client, err := htp.NewSyncClient(opts.host, 10*time.Second)
if err != nil {
logger.Fatal("Cannot create client: ", err)
}
client, err := htp.NewSyncClient(host, time.Duration(timeout)*time.Second)
if err != nil {
return nil
}

model := htp.NewSyncModel()

options := &htp.SyncOptions{
Count: int(count),
Trace: func(round *htp.SyncRound) {
if !silent {
fmt.Fprintf(os.Stderr, "offset: %+.3f (±%.3f) seconds\n",
toSec(model.Offset()), toSec(model.Margin()))
}
},
}

if err := htp.Sync(client, model, options); err != nil {
return err
}

if date {
now := time.Now().Add(time.Duration(-model.Offset()))
fmt.Printf("%s\n", now.Format(format))
} else {
fmt.Printf("%+.3f\n", toSec(-model.Offset()))
}

options := &htp.SyncOptions{
Count: int(opts.count),
Trace: func(round *htp.SyncRound) {
if opts.verbose {
offset := model.Offset()
margin := model.Margin()
logger.Printf("offset: %+.3f (±%.3f) seconds\n", toSec(offset), toSec(margin))
if sync {
if err := syncSystem(model.Offset()); err != nil {
return fmt.Errorf("cannot set system clock: %w", err)
}
}

return nil
},
}
if err = htp.Sync(client, model, options); err != nil {
logger.Fatal("Cannot sync clock: ", err)
}

if opts.date {
now := time.Now().Add(time.Duration(-model.Offset()))
fmt.Printf("%s\n", now.Format(opts.format))
} else {
fmt.Printf("%+.3f\n", toSec(-model.Offset()))
}
cmd.Flags().IntVarP(&count, "num-requests", "n", 10, "Number of requests")
cmd.Flags().IntVarP(&timeout, "timeout", "t", 10, "Timeout in seconds")
cmd.Flags().BoolVarP(&silent, "silent", "s", false, "Do not show offsets")
cmd.Flags().BoolVarP(&date, "date", "d", false, "Show date and time instead of offset")
cmd.Flags().BoolVarP(&sync, "set", "e", false, "Set system time")
cmd.Flags().StringVarP(&format, "format", "f", time.UnixDate, "Date and time format")
cmd.Flags().StringVarP(&host, "url", "u", "https://www.google.com", "Host URL")

return cmd
}

if opts.sync {
if err := syncSystem(model.Offset()); err != nil {
logger.Fatal("Cannot set system clock: ", err)
}
func main() {
cmd := buildRootCommand()
if err := cmd.Execute(); err != nil {
os.Exit(1)
}
}

Expand All @@ -89,25 +113,6 @@ func syncSystem(offset int64) error {
}
}

func parseArgs() *options {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(),
"HTP - Date and time from HTTP headers\n\nUsage:\n")
flag.PrintDefaults()
}

opts := options{}
flag.StringVar(&opts.host, "u", "https://www.google.com", "Host URL")
flag.UintVar(&opts.count, "n", 8, "Number of requests")
flag.BoolVar(&opts.verbose, "v", false, "Show offsets during synchronization")
flag.BoolVar(&opts.date, "d", false, "Display date and time instead of offset")
flag.StringVar(&opts.format, "f", time.UnixDate, "Date and time format")
flag.BoolVar(&opts.sync, "s", false, "Synchronize system time")
flag.Parse()

return &opts
}

func toSec(t int64) float64 {
return float64(t) / float64(second)
}
10 changes: 9 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,12 @@ module github.com/danroc/htp

go 1.18

require golang.org/x/exp v0.0.0-20220414153411-bcd21879b8fd
require (
github.com/spf13/cobra v1.4.0
golang.org/x/exp v0.0.0-20220414153411-bcd21879b8fd
)

require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q=
github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/exp v0.0.0-20220414153411-bcd21879b8fd h1:zVFyTKZN/Q7mNRWSs1GOYnHM9NiFSJ54YVRsD0rNWT4=
golang.org/x/exp v0.0.0-20220414153411-bcd21879b8fd/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

0 comments on commit 53f97d6

Please # to comment.