Skip to content

Commit

Permalink
Use a lockfile to serialize blessclient invocations (#84)
Browse files Browse the repository at this point in the history
Use a lockfile to serialize blessclient invocationsWhen integrated with tools like terraform or ansible, multiple concurrent runs of blessclient resulted in unnecessary work. Instead, serialize blessclient commands.
  • Loading branch information
Eduardo Lopez authored and czimergebot committed Nov 20, 2018
1 parent 0b4e23b commit 9a6eedc
Show file tree
Hide file tree
Showing 93 changed files with 5,577 additions and 625 deletions.
46 changes: 36 additions & 10 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions Gopkg.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
[[constraint]]
name = "github.com/aws/aws-sdk-go"
version = "1.15.76"
version = "1.15.79"

[[constraint]]
name = "github.com/blang/semver"
version = "3.5.1"

[[constraint]]
name = "github.com/cenkalti/backoff"
version = "2.0.0"

[[constraint]]
branch = "master"
name = "github.com/chanzuckerberg/go-misc"
Expand All @@ -16,7 +20,7 @@

[[constraint]]
name = "github.com/google/uuid"
version = "1.0.0"
version = "1.1.0"

[[constraint]]
branch = "master"
Expand All @@ -34,6 +38,10 @@
name = "github.com/mitchellh/go-homedir"
version = "1.0.0"

[[constraint]]
branch = "master"
name = "github.com/nightlyone/lockfile"

[[constraint]]
name = "github.com/pkg/errors"
version = "0.8.0"
Expand Down
2 changes: 0 additions & 2 deletions cmd/import-config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,9 @@ import (

const (
flagKeyFile = "key-file"
flagConfig = "config"
)

func init() {
importConfigCmd.Flags().StringP(flagConfig, "c", config.DefaultConfigFile, "Use this to override the bless config file.")
importConfigCmd.Flags().StringP(flagKeyFile, "k", config.DefaultSSHPrivateKey, "Location of SSH private key")
rootCmd.AddCommand(importConfigCmd)
}
Expand Down
34 changes: 27 additions & 7 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,33 +1,53 @@
package cmd

import (
"github.com/chanzuckerberg/blessclient/pkg/config"
"github.com/chanzuckerberg/blessclient/pkg/util"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

const (
flagConfig = "config"
flagVerbose = "verbose"
)

func init() {
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "Use this to enable verbose mode")
rootCmd.PersistentFlags().StringP(flagConfig, "c", config.DefaultConfigFile, "Use this to override the bless config file.")
rootCmd.PersistentFlags().BoolP(flagVerbose, "v", false, "Use this to enable verbose mode")
}

var pidLock *util.Lock
var rootCmd = &cobra.Command{
Use: "blessclient",
Short: "",
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
return errors.Wrap(pidLock.Unlock(), "Error releasing lock")
},
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
verbose, err := cmd.Flags().GetBool("verbose")
verbose, err := cmd.Flags().GetBool(flagVerbose)
if err != nil {
return errors.Wrap(err, "Missing verbose flag")
}
if verbose {
log.SetLevel(log.DebugLevel)
}
return nil

// pid lock
configPath, err := util.GetConfigPath(cmd)
if err != nil {
return err
}
pidLock, err = util.NewLock(configPath)
if err != nil {
return err
}
return errors.Wrap(pidLock.Lock(), "Error acquiring lock")
},
}

// Execute executes the command
func Execute() {
if err := rootCmd.Execute(); err != nil {
log.Fatal(err)
}
func Execute() error {
return rootCmd.Execute()
}
60 changes: 60 additions & 0 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cmd

import (
"io/ioutil"
"os"
"testing"

"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
)

func TestRootNoError(t *testing.T) {
a := assert.New(t)
err := rootCmd.Execute()
a.Nil(err)
}

func TestRootMissingVerbose(t *testing.T) {
a := assert.New(t)
cmd := &cobra.Command{}
err := rootCmd.PersistentPreRunE(cmd, nil)
a.NotNil(err)
a.Contains(err.Error(), "flag accessed but not defined: verbose")
}

func TestRootMissingConfig(t *testing.T) {
a := assert.New(t)
cmd := &cobra.Command{}
cmd.PersistentFlags().BoolP("verbose", "v", false, "Use this to enable verbose mode")

flags := []string{"--verbose"}
err := cmd.ParseFlags(flags)
a.Nil(err)

err = rootCmd.PersistentPreRunE(cmd, nil)
a.NotNil(err)
a.Contains(err.Error(), "Missing config")
}

func TestRootLock(t *testing.T) {
a := assert.New(t)
cmd := &cobra.Command{}

name, err := ioutil.TempDir("", "blessclient-tests")
a.Nil(err)
defer os.RemoveAll(name)

cmd.PersistentFlags().BoolP("verbose", "v", false, "Use this to enable verbose mode")
cmd.PersistentFlags().StringP(flagConfig, "c", name, "Use this to override the bless config file.")

flags := []string{"--verbose", "--config", name}
err = cmd.ParseFlags(flags)
a.Nil(err)

err = rootCmd.PersistentPreRunE(cmd, nil)
a.Nil(err)

err = rootCmd.PersistentPostRunE(cmd, nil)
a.Nil(err)
}
12 changes: 2 additions & 10 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,13 @@ import (
"github.com/google/uuid"
multierror "github.com/hashicorp/go-multierror"
"github.com/honeycombio/opencensus-exporter/honeycomb"
homedir "github.com/mitchellh/go-homedir"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"go.opencensus.io/trace"
)

func init() {
runCmd.Flags().StringP("config", "c", config.DefaultConfigFile, "Use this to override the bless config file.")
rootCmd.AddCommand(runCmd)
}

Expand All @@ -38,18 +36,12 @@ var runCmd = &cobra.Command{
// Just for telemetry so ignore errors
log.Debugf("Failed to generate UUID with error %s", err.Error())
}

log.Debugf("Running blessclient v%s", util.VersionCacheKey())
log.Debugf("RunID: %s", id.String())

ctx := context.Background()
configFile, err := cmd.Flags().GetString("config")
expandedConfigFile, err := util.GetConfigPath(cmd)
if err != nil {
return errors.New("Missing config")
}
expandedConfigFile, err := homedir.Expand(configFile)
if err != nil {
return errors.Wrapf(err, "Could not expand %s", configFile)
return err
}
log.Debugf("Reading config from %s", expandedConfigFile)

Expand Down
5 changes: 4 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package main

import (
"github.com/chanzuckerberg/blessclient/cmd"
"github.com/sirupsen/logrus"
)

func main() {
cmd.Execute()
if err := cmd.Execute(); err != nil {
logrus.Fatal(err)
}
}
20 changes: 20 additions & 0 deletions pkg/util/cobra.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package util

import (
homedir "github.com/mitchellh/go-homedir"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

// GetConfigPath gets the config path from a cobra cmd
func GetConfigPath(cmd *cobra.Command) (string, error) {
configFile, err := cmd.Flags().GetString("config")
if err != nil {
return "", errors.New("Missing config")
}
expandedConfigFile, err := homedir.Expand(configFile)
if err != nil {
return "", errors.Wrapf(err, "Could not expand %s", configFile)
}
return expandedConfigFile, nil
}
Loading

0 comments on commit 9a6eedc

Please sign in to comment.