Skip to content

Commit

Permalink
allow not passing stage (#31)
Browse files Browse the repository at this point in the history
* add gpg store

* refactor config to not use aws specific session

* add local store

* add ability to write to file

* read and write config

* implement delete many

* make stage optional

* remove examples

* implement get command

* set default db dir

* refactor printing summary

* refactor to set filepath in config

* wip gpg store

* update install script
  • Loading branch information
adikari committed Aug 15, 2023
1 parent 53abdb5 commit ff922f6
Show file tree
Hide file tree
Showing 24 changed files with 1,147 additions and 219 deletions.
4 changes: 3 additions & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ before:
- ./scripts/completions.sh
builds:
- binary: safebox
ldflags:
- -s -w
env:
- CGO_ENABLED=0
goos:
Expand All @@ -16,7 +18,7 @@ checksum:
name_template: 'checksums.txt'

archives:
- format: 'binary'
- format: 'tar.gz'
name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
files:
- completions/*
Expand Down
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ generate:
config:
defaults:
DB_NAME: "database name updated"
API_ENDPOINT: "http://some-endpoint-{{ .stage }}.com"
API_ENDPOINT: "http://some-endpoint-{{ .stage }}.com" # stage is only available when passed through the cli flag

prod:
DB_NAME: "production db name"
Expand All @@ -61,14 +61,18 @@ secret:
2. Use `safebox` CLI tool to deploy your configuration.

```bash
$ safebox deploy --config path/to/safebox.yml --prompt="missing"

# staged deployment when you want to have separate config per environment.
# eg. prod, dev
$ safebox deploy --stage <stage> --config path/to/safebox.yml --prompt="missing"
```

You can then run list command to view the pushed configurations.

The variables under
1. `defaults` is deployed with path prefix of `/<stage>/<service>`
1. `shared` is deployed with path prefix of `/<stage>/shared/`
1. `defaults` is deployed with path prefix of `/<stage>/<service>` or `/<service>`
1. `shared` is deployed with path prefix of `/<stage>/shared/` or `/shared>`

### CLI Reference

Expand All @@ -92,7 +96,7 @@ Available Commands:
Flags:
-c, --config string path to safebox configuration file (default "safebox.yml")
-h, --help help for safebox
-s, --stage string stage to deploy to (default "dev")
-s, --stage string stage to deploy to
-v, --version version for safebox

Use "safebox [command] --help" for more information about a command.
Expand Down Expand Up @@ -153,7 +157,7 @@ Following is the configuration file will all possible options:

```yaml
service: my-service
provider: secrets-manager # ssm OR secrets-manager
provider: secrets-manager # ssm OR secrets-manager
prefix: "/custom/prefix/{{.stage}}/" # Optional. Defaults to /<stage>/<service>/. Prefix all parameters. Does not apply for shared

stacks: # Outputs from cloudformation stacks that needs to be interpolated.
Expand Down
24 changes: 15 additions & 9 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ var (
prompt string

deployCmd = &cobra.Command{
Use: "deploy",
Short: "Deploys all configurations specified in config file",
RunE: deploy,
Example: `TODO: deploy command example`,
Use: "deploy",
Short: "Deploys all configurations specified in config file",
RunE: deploy,
}
)

Expand All @@ -38,7 +37,11 @@ func deploy(_ *cobra.Command, _ []string) error {
return errors.Wrap(err, "failed to load config")
}

st, err := store.GetStore(store.StoreConfig{Session: config.Session, Provider: config.Provider})
st, err := store.GetStore(store.StoreConfig{
Provider: config.Provider,
Region: config.Region,
FilePath: config.Filepath,
})

if err != nil {
return errors.Wrap(err, "failed to instantiate store")
Expand Down Expand Up @@ -117,11 +120,9 @@ func deploy(_ *cobra.Command, _ []string) error {
fmt.Printf("%s\n", errors.Wrap(err, "Error: failed to remove orphan"))
}

fmt.Printf("%d orphans removed.\n", len(orphans))
fmt.Printf("orphans removed = %d.\n", len(orphans))
}

fmt.Printf("%d new configs deployed. service = %s, stage = %s, region = %s\n", len(configsToDeploy), config.Service, stage, *config.Session.Config.Region)

if len(config.Generate) > 0 {
for _, t := range config.Generate {
err := exportToFile(ExportParams{
Expand All @@ -136,10 +137,15 @@ func deploy(_ *cobra.Command, _ []string) error {
continue
}

fmt.Printf("file written: %s\n", t.Path)
fmt.Printf("wrote file -> %s\n", t.Path)
}
}

PrintSummary(Summary{
Message: fmt.Sprintf("%s = %d", "new configs", len(configsToDeploy)),
Config: *config,
})

return nil
}

Expand Down
13 changes: 8 additions & 5 deletions cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ var (
keysToExport []string

exportCmd = &cobra.Command{
Use: "export",
Short: "Exports all configuration to a file",
RunE: export,
Example: `TODO: export command example`,
Use: "export",
Short: "Exports all configuration to a file",
RunE: export,
}
)

Expand Down Expand Up @@ -64,7 +63,11 @@ type ExportParams struct {
}

func exportToFile(p ExportParams) error {
store, err := store.GetStore(store.StoreConfig{Session: p.config.Session, Provider: p.config.Provider})
store, err := store.GetStore(store.StoreConfig{
Provider: p.config.Provider,
Region: p.config.Region,
FilePath: p.config.Filepath,
})

if err != nil {
return errors.Wrap(err, "failed to instantiate store")
Expand Down
55 changes: 55 additions & 0 deletions cmd/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cmd

import (
"fmt"

"github.com/adikari/safebox/v2/store"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

var (
getParam string

getCmd = &cobra.Command{
Use: "get",
Short: "Gets parameter",
RunE: getE,
}
)

func init() {
getCmd.Flags().StringVarP(&getParam, "param", "p", "", "parameter to get")
getCmd.MarkFlagRequired("param")

rootCmd.AddCommand(getCmd)
}

func getE(_ *cobra.Command, _ []string) error {
config, err := loadConfig()

if err != nil {
return errors.Wrap(err, "failed to load config")
}

st, err := store.GetStore(store.StoreConfig{
Provider: config.Provider,
Region: config.Region,
FilePath: config.Filepath,
})

if err != nil {
return errors.Wrap(err, "failed to instantiate store")
}

found, err := st.Get(store.ConfigInput{Name: fmt.Sprintf("%s%s", config.Prefix, getParam)})

if err != nil {
return errors.Wrap(err, "failed to get param")
}

if found != nil {
fmt.Printf("%s\n", *found.Value)
}
return nil
}
7 changes: 3 additions & 4 deletions cmd/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ var (
inputFile string

importCmd = &cobra.Command{
Use: "import",
Short: "Imports all configuration from a file",
RunE: importE,
Example: `TODO: import command example`,
Use: "import",
Short: "Imports all configuration from a file",
RunE: importE,
}
)

Expand Down
27 changes: 19 additions & 8 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ import (

// runCmd represents the exec command
var listCmd = &cobra.Command{
Use: "list",
Short: "Lists all the configs available",
RunE: list,
Example: `TODO: list command example`,
Use: "list",
Short: "Lists all the configs available",
RunE: list,
}

var (
Expand All @@ -39,7 +38,11 @@ func list(_ *cobra.Command, _ []string) error {
return errors.Wrap(err, "failed to load config")
}

store, err := store.GetStore(store.StoreConfig{Session: config.Session, Provider: config.Provider})
store, err := store.GetStore(store.StoreConfig{
Provider: config.Provider,
Region: config.Region,
FilePath: config.Filepath,
})

if err != nil {
return errors.Wrap(err, "failed to instantiate store")
Expand All @@ -66,7 +69,12 @@ func list(_ *cobra.Command, _ []string) error {

func printList(configs []store.Config, cfg *config.Config) {
if len(configs) <= 0 {
fmt.Printf("no configurations to list. stage = %s, service = %s, region = %s\n", cfg.Stage, cfg.Service, *cfg.Session.Config.Region)

PrintSummary(Summary{
Message: "Total parameters = 0",
Config: *cfg,
})

return
}

Expand All @@ -86,9 +94,12 @@ func printList(configs []store.Config, cfg *config.Config) {

fmt.Fprintln(w, "")
}

fmt.Fprintln(w, "---")
fmt.Fprintf(w, "Total parameters = %d, stage = %s, service = %s, region = %s\n", len(configs), cfg.Stage, cfg.Service, *cfg.Session.Config.Region)

PrintSummary(Summary{
Message: fmt.Sprintf("Total parameters = %d", len(configs)),
Config: *cfg,
})

w.Flush()
}
Expand Down
38 changes: 38 additions & 0 deletions cmd/print.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package cmd

import (
"fmt"

c "github.com/adikari/safebox/v2/config"
)

type Summary struct {
Message string
Config c.Config
}

func PrintSummary(s Summary) {
msg := ""

if s.Message != "" {
msg += fmt.Sprintf("%s", s.Message)
}

if s.Config.Service != "" && s.Config.Provider != "gpg" {
msg += fmt.Sprintf(", service = %s", s.Config.Service)
}

if s.Config.Stage != "" {
msg += fmt.Sprintf(", stage = %s", s.Config.Stage)
}

if s.Config.Region != "" && s.Config.Provider != "gpg" {
msg += fmt.Sprintf(", region = %s", s.Config.Region)
}

if s.Config.Provider == "gpg" {
msg += fmt.Sprintf(", file = %s", s.Config.Filepath)
}

fmt.Printf("%s\n", msg)
}
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var rootCmd = &cobra.Command{
}

func init() {
rootCmd.PersistentFlags().StringVarP(&stage, "stage", "s", "dev", "stage to deploy to")
rootCmd.PersistentFlags().StringVarP(&stage, "stage", "s", "", "stage to deploy to")

rootCmd.PersistentFlags().StringVarP(&pathToConfig, "config", "c", "", "path to safebox configuration file")
rootCmd.MarkFlagFilename("config")
Expand Down
Loading

0 comments on commit ff922f6

Please sign in to comment.