Skip to content

Commit

Permalink
storage: Write/Read runbooks to a local file
Browse files Browse the repository at this point in the history
  • Loading branch information
joshi4 committed Nov 7, 2024
1 parent a2f403d commit 3121233
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 0 deletions.
59 changes: 59 additions & 0 deletions cmd/sync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"github.com/getsavvyinc/savvy-cli/client"
"github.com/getsavvyinc/savvy-cli/storage"
"github.com/spf13/cobra"
)

// syncCmd represents the sync command
var syncCmd = &cobra.Command{
Use: "sync",
Short: "Create a local copy of all your Savvy Artifacts",
Long: `
Create a local copy of all your Savvy Artifacts.
This command will download all your artifacts from the Savvy API and store them in a local directory.
You can access the artifacts in the local directory even when you are offline using savvy run --local.
`,
Run: syncRunbooks,
}

func syncRunbooks(cmd *cobra.Command, args []string) {
store := map[string]*client.Runbook{}
ctx := cmd.Context()
logger := loggerFromCtx(ctx).With("command", "sync")

var cl client.RunbookClient
var err error
cl, err = client.GetLoggedInClient()
if err != nil {
logger.Error(err.Error())
return
}

runbookInfo, err := cl.Runbooks(ctx)
if err != nil {
logger.Error("failed to fetch runbooks", "error", err)
return
}

for _, rb := range runbookInfo {
rb, err := cl.RunbookByID(ctx, rb.RunbookID)
if err != nil {
logger.Error("failed to fetch runbook", "runbook_id", rb.RunbookID, "error", err)
return
}

store[rb.RunbookID] = rb
}

if err := storage.Write(store); err != nil {
logger.Error("failed to write runbooks to local storage", "error", err)
return
}
}

func init() {
rootCmd.AddCommand(syncCmd)
}
77 changes: 77 additions & 0 deletions storage/storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package storage

import (
"encoding/binary"
"encoding/json"
"os"
"os/user"
"path/filepath"

"github.com/getsavvyinc/savvy-cli/client"
)

const defaultLocalDBDir = "savvy"
const defaultDBFilename = "savvy.local"

var defaultLocalDBPath = filepath.Join(defaultLocalDBDir, defaultDBFilename)

func Write(store map[string]*client.Runbook) error {
// Write the store to disk
data, err := json.Marshal(store)
if err != nil {
return err
}

f, err := openStore()
if err != nil {
return err
}
defer f.Close()

if err := f.Truncate(0); err != nil {
return err
}

if err := binary.Write(f, binary.LittleEndian, data); err != nil {
return err
}
return nil
}

func Read() (map[string]*client.Runbook, error) {
// Read the store from disk
f, err := openStore()
if err != nil {
return nil, err
}
defer f.Close()

stat, err := f.Stat()
if err != nil {
return nil, err
}

data := make([]byte, stat.Size())

if err := binary.Read(f, binary.LittleEndian, data); err != nil {
return nil, err
}

store := make(map[string]*client.Runbook)
if err := json.Unmarshal(data, &store); err != nil {
return nil, err
}
return store, nil
}

func openStore() (*os.File, error) {
u, err := user.Current()
if err != nil {
return nil, err
}
homeDir := u.HomeDir

storageFile := filepath.Join(homeDir, defaultLocalDBDir, defaultDBFilename)

return os.OpenFile(storageFile, os.O_RDWR|os.O_CREATE, 0666)
}

0 comments on commit 3121233

Please sign in to comment.