Turned out we don't really want to break users configurations, so deprecated values stay with us at least before 2.0 is released.
122 lines
3.2 KiB
Go
122 lines
3.2 KiB
Go
// Package cmd has all top-level commands dispatched by main's flag.Parse
|
|
// The entry point of each command is Execute function
|
|
package cmd
|
|
|
|
import (
|
|
"bytes"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"text/template"
|
|
"time"
|
|
|
|
log "github.com/go-pkgz/lgr"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// CommonOptionsCommander extends flags.Commander with SetCommon
|
|
// All commands should implement this interfaces
|
|
type CommonOptionsCommander interface {
|
|
SetCommon(commonOpts CommonOpts)
|
|
Execute(args []string) error
|
|
HandleDeprecatedFlags() []DeprecatedFlag
|
|
}
|
|
|
|
// CommonOpts sets externally from main, shared across all commands
|
|
type CommonOpts struct {
|
|
RemarkURL string
|
|
SharedSecret string
|
|
Revision string
|
|
}
|
|
|
|
// DeprecatedFlag contains information about deprecated option
|
|
type DeprecatedFlag struct {
|
|
Old string
|
|
New string
|
|
Version string
|
|
}
|
|
|
|
// SetCommon satisfies CommonOptionsCommander interface and sets common option fields
|
|
// The method called by main for each command
|
|
func (c *CommonOpts) SetCommon(commonOpts CommonOpts) {
|
|
c.RemarkURL = strings.TrimSuffix(commonOpts.RemarkURL, "/") // allow RemarkURL with trailing /
|
|
c.SharedSecret = commonOpts.SharedSecret
|
|
c.Revision = commonOpts.Revision
|
|
}
|
|
|
|
// HandleDeprecatedFlags sets new flags from deprecated and returns their list
|
|
func (c *CommonOpts) HandleDeprecatedFlags() []DeprecatedFlag { return nil }
|
|
|
|
// fileParser used to convert template strings like blah-{{.SITE}}-{{.YYYYMMDD}} the final format
|
|
type fileParser struct {
|
|
site string
|
|
file string
|
|
path string
|
|
}
|
|
|
|
// parse apply template and also concat path and file. In case if file contains path separator path will be ignored
|
|
func (p *fileParser) parse(now time.Time) (string, error) {
|
|
|
|
// file/location parameters my have template masks
|
|
fileTemplate := struct {
|
|
YYYYMMDD string
|
|
YYYY string
|
|
YYYYMM string
|
|
MM string
|
|
DD string
|
|
TS string
|
|
UNIX int64
|
|
SITE string
|
|
}{
|
|
YYYYMMDD: now.Format("20060102"),
|
|
YYYY: now.Format("2006"),
|
|
YYYYMM: now.Format("200601"),
|
|
MM: now.Format("01"),
|
|
DD: now.Format("02"),
|
|
UNIX: now.Unix(),
|
|
SITE: p.site,
|
|
TS: now.Format("20060102T150405"),
|
|
}
|
|
|
|
bb := bytes.Buffer{}
|
|
fname := p.file
|
|
if !strings.Contains(p.file, string(filepath.Separator)) {
|
|
fname = filepath.Join(p.path, p.file)
|
|
}
|
|
|
|
if err := template.Must(template.New("bb").Parse(fname)).Execute(&bb, fileTemplate); err != nil {
|
|
return "", errors.Wrapf(err, "failed to parse %q", fname)
|
|
}
|
|
return bb.String(), nil
|
|
}
|
|
|
|
// resetEnv clears sensitive env vars
|
|
func resetEnv(envs ...string) {
|
|
for _, env := range envs {
|
|
if err := os.Unsetenv(env); err != nil {
|
|
log.Printf("[WARN] can't unset env %s, %s", env, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// responseError returns error with status and response body
|
|
func responseError(resp *http.Response) error {
|
|
body, e := ioutil.ReadAll(resp.Body)
|
|
if e != nil {
|
|
body = []byte("")
|
|
}
|
|
return errors.Errorf("error response %q, %s", resp.Status, body)
|
|
}
|
|
|
|
// mkdir -p for all dirs
|
|
func makeDirs(dirs ...string) error {
|
|
for _, dir := range dirs {
|
|
if err := os.MkdirAll(dir, 0700); err != nil { // If path is already a directory, MkdirAll does nothing
|
|
return errors.Wrapf(err, "can't make directory %s", dir)
|
|
}
|
|
}
|
|
return nil
|
|
}
|