Skip to content

Commit

Permalink
Move service logic to separate command (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
patricksanders authored Dec 30, 2020
1 parent e48eed8 commit fbffb04
Show file tree
Hide file tree
Showing 23 changed files with 327 additions and 270 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@ This README contains developer documentation. Weep user documentation can be fou
Weep can be compiled with an embedded configuration (See the Building section below), or it can get its configuration
from a YAML-formatted file. We've included an example config file in [example-config.yaml](example-config.yaml).

Weep searches for a configuration file in the following locations:
Weep searches for a configuration in the following locations:

- `./.weep.yaml`
- embedded configuration (see below)
- `/etc/weep/weep.yaml`
- `~/.config/weep/weep.yaml`
- `~/.weep.yaml`
- `~/.config/weep/.weep.yaml`
- `./weep.yaml`

You can also specify a config file as a CLI arg:
Multiple configurations in these locations **will be merged**.

```
You can also specify a config file as a CLI arg. This configuration will be used exclusively and will not be merged with other configurations:

```bash
weep --config somethingdifferent.yaml list
```

Expand Down
5 changes: 1 addition & 4 deletions challenge/challenge.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,7 @@ func RefreshChallenge() error {
}
}
if user == "" {
log.Fatalf(
"Invalid configuration. You must define challenge_settings.user as the user you wish to authenticate" +
" as.",
)
return fmt.Errorf("invalid configuration: challenge_settings.user must be set")
}
var consoleMeChallengeGeneratorEndpoint = fmt.Sprintf(
"%s/noauth/v1/challenge_generator/%s",
Expand Down
2 changes: 1 addition & 1 deletion cmd/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
package cmd

import (
"log"
"os"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

Expand Down
2 changes: 1 addition & 1 deletion cmd/credential_process.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"time"

"github.com/netflix/weep/util"
ini "gopkg.in/ini.v1"
"gopkg.in/ini.v1"

"github.com/netflix/weep/creds"
log "github.com/sirupsen/logrus"
Expand Down
3 changes: 1 addition & 2 deletions cmd/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
package cmd

import (
"log"

log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/cobra/doc"
)
Expand Down
7 changes: 2 additions & 5 deletions cmd/ecs_credential_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"fmt"
"net"
"net/http"
"os"

"github.com/spf13/viper"

Expand All @@ -46,8 +45,7 @@ func runEcsMetadata(cmd *cobra.Command, args []string) error {
ipaddress := net.ParseIP(ecsProviderListenAddr)

if ipaddress == nil {
fmt.Println("Invalid IP: ", ecsProviderListenAddr)
os.Exit(1)
return fmt.Errorf("invalid IP: %s", ecsProviderListenAddr)
}

listenAddr := fmt.Sprintf("%s:%d", ipaddress, ecsProviderListenPort)
Expand All @@ -64,7 +62,6 @@ func runEcsMetadata(cmd *cobra.Command, args []string) error {

// Check for interrupt signal and exit cleanly
<-shutdown
log.Print("Shutdown signal received, exiting weep...")

log.Print("Shutdown signal received, stopping server...")
return nil
}
10 changes: 4 additions & 6 deletions cmd/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ package cmd

import (
"fmt"
"os"
"path"

ini "gopkg.in/ini.v1"
"gopkg.in/ini.v1"

"github.com/mitchellh/go-homedir"
"github.com/netflix/weep/creds"
"github.com/netflix/weep/util"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -60,17 +60,15 @@ func runFile(cmd *cobra.Command, args []string) error {
func getDefaultCredentialsFile() string {
home, err := homedir.Dir()
if err != nil {
fmt.Printf("couldn't get default directory!")
os.Exit(1)
log.Fatal("couldn't get default directory")
}
return path.Join(home, ".aws", "credentials")
}

func getDefaultAwsConfigFile() string {
home, err := homedir.Dir()
if err != nil {
fmt.Printf("couldn't get default directory!")
os.Exit(1)
log.Fatal("couldn't get default directory")
}
return path.Join(home, ".aws", "config")
}
Expand Down
4 changes: 1 addition & 3 deletions cmd/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"fmt"
"net"
"net/http"
"os"

"github.com/netflix/weep/cache"

Expand Down Expand Up @@ -60,8 +59,7 @@ func runMetadata(cmd *cobra.Command, args []string) error {
ipaddress := net.ParseIP(metadataListenAddr)

if ipaddress == nil {
fmt.Println("Invalid IP: ", metadataListenAddr)
os.Exit(1)
return fmt.Errorf("Invalid IP: %s", metadataListenAddr)
}

listenAddr := fmt.Sprintf("%s:%d", ipaddress, metadataListenPort)
Expand Down
149 changes: 92 additions & 57 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@
package cmd

import (
"fmt"
"io"
"os"
"os/signal"
"path"
"runtime"
"strings"
"path/filepath"
"syscall"

"github.com/netflix/weep/util"

"github.com/mattn/go-isatty"
"github.com/kardianos/service"

"github.com/mitchellh/go-homedir"
"github.com/netflix/weep/config"
Expand All @@ -52,83 +48,90 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is $HOME/.weep.yaml)")
rootCmd.PersistentFlags().StringSliceVarP(&assumeRole, "assume-role", "A", make([]string, 0), "one or more roles to assume after retrieving credentials")
rootCmd.PersistentFlags().StringVar(&logFormat, "log-format", "", "log format (json or tty)")
rootCmd.PersistentFlags().StringVar(&logFile, "log-file", viper.GetString("log_file"), "log file path")
rootCmd.PersistentFlags().StringVar(&logLevel, "log-level", "", "log level (debug, info, warn)")
rootCmd.PersistentFlags().BoolVarP(&runAsService, "svc", "s", false, "run weep as a service")
}

func Execute() {
shutdown = make(chan os.Signal, 1)
done = make(chan int, 1)
signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM)
if runAsService {
RunService()
} else {
if err := rootCmd.Execute(); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
signal.Notify(shutdown, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)

if err := rootCmd.Execute(); err != nil {
rootCmd.PrintErr(err)
}
}

// initConfig reads in configs by precedence, with later configs overriding earlier:
// - embedded
// - /etc/weep/weep.yaml
// - ~/.config/weep/weep.yaml
// - ~/.weep.yaml
// - ./weep.yaml
// If a config file is specified via CLI arg, it will be read exclusively and not merged with other
// configuration.
func initConfig() {
home, err := homedir.Dir()
if err != nil {
log.Fatal(err)
}
viper.SetConfigType("yaml")

// Read in explicitly defined config file
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
home, err := homedir.Dir()
err = viper.ReadInConfig()
if err != nil {
fmt.Println(err)
os.Exit(1)
log.Fatalf("could not open config file %s: %v", cfgFile, err)
}
viper.SetConfigType("yaml")
viper.SetConfigName(".weep")
viper.AddConfigPath(".")
viper.AddConfigPath(home)
viper.AddConfigPath(home + "/.config/weep/")
return
}

// Read embedded config if available
if err := config.ReadEmbeddedConfig(); err != nil {
log.Debugf("unable to read embedded config: %v; falling back to config file", err)
}

if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok && config.EmbeddedConfigFile != "" {
log.Debugf("no config file found, trying to use embedded config")
} else if isatty.IsTerminal(os.Stdout.Fd()) {
err = util.FirstRunPrompt()
if err != nil {
log.Fatalf("config bootstrap failed: %v", err)
}
} else {
log.Debugf("unable to read config file: %v", err)
}
}
// Read in config from etc
viper.SetConfigName("weep")
viper.AddConfigPath("/etc/weep/")
_ = viper.MergeInConfig()

// Read in config from config dir
viper.SetConfigName("weep")
viper.AddConfigPath(home + "/.config/weep/")
_ = viper.MergeInConfig()

// Read in config from home dir
viper.SetConfigName(".weep")
viper.AddConfigPath(home)
_ = viper.MergeInConfig()

// Read in config from current directory
viper.SetConfigName("weep")
viper.AddConfigPath(".")
_ = viper.MergeInConfig()

// TODO: revisit first-run setup
//if err := viper.MergeInConfig(); err != nil {
// if _, ok := err.(viper.ConfigFileNotFoundError); ok && config.EmbeddedConfigFile != "" {
// log.Debugf("no config file found, trying to use embedded config")
// } else if isatty.IsTerminal(os.Stdout.Fd()) {
// err = util.FirstRunPrompt()
// if err != nil {
// log.Fatalf("config bootstrap failed: %v", err)
// }
// } else {
// log.Debugf("unable to read config file: %v", err)
// }
//}

log.Debugf("found config at %s", viper.ConfigFileUsed())
if err := viper.Unmarshal(&config.Config); err != nil {
log.Fatalf("unable to decode config into struct: %v", err)
}
}

func initLogging() {
// Set the log format. Default to Text
if logFormat == "json" {
log.SetFormatter(&log.JSONFormatter{
CallerPrettyfier: func(f *runtime.Frame) (string, string) {
s := strings.Split(f.Function, ".")
funcName := s[len(s)-1]
return funcName, fmt.Sprintf("%s:%d", path.Base(f.File), f.Line)
},
})
} else {
log.SetFormatter(&log.TextFormatter{
CallerPrettyfier: func(f *runtime.Frame) (string, string) {
s := strings.Split(f.Function, ".")
funcName := s[len(s)-1]
return funcName, fmt.Sprintf("%s:%d", path.Base(f.File), f.Line)
},
})
}

// Set the log level and default to INFO
switch logLevel {
case "error":
Expand All @@ -140,4 +143,36 @@ func initLogging() {
default:
log.SetLevel(log.InfoLevel)
}

log.Debug("configuring logging")

// Set the log format. Default to Text
if logFormat == "json" {
log.SetFormatter(&log.JSONFormatter{})
} else {
log.SetFormatter(&log.TextFormatter{})
}

logDir := filepath.Dir(logFile)
if _, err := os.Stat(logDir); os.IsNotExist(err) {
log.Debugf("attempting to create log directory %s", logDir)
err := os.MkdirAll(logDir, os.ModePerm)
if err != nil {
log.Errorf("could not create log directory")
}
}

var w io.Writer
file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Errorf("could not open %s for logging, defaulting to stderr: %v", logFile, err)
log.SetOutput(os.Stderr)
w = os.Stderr
} else if service.Interactive() {
w = io.MultiWriter(os.Stderr, file)
} else {
w = file
}
log.SetOutput(w)
log.Debug("logging configured")
}
Loading

0 comments on commit fbffb04

Please sign in to comment.