Skip to content
This repository has been archived by the owner on Oct 3, 2019. It is now read-only.

Commit

Permalink
Merge branch 'master' into cs/deadlines
Browse files Browse the repository at this point in the history
  • Loading branch information
csstaub committed Mar 23, 2016
2 parents b506861 + fccd7a0 commit d133d53
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 43 deletions.
30 changes: 25 additions & 5 deletions fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/hanwen/go-fuse/fuse"
"github.com/hanwen/go-fuse/fuse/nodefs"
"github.com/hanwen/go-fuse/fuse/pathfs"
"github.com/square/go-sq-metrics"
"github.com/square/keywhiz-fs/log"
"golang.org/x/sys/unix"
)
Expand Down Expand Up @@ -59,11 +60,12 @@ type KeywhizFs struct {
*log.Logger
Client *Client
Cache *Cache
Metrics *sqmetrics.SquareMetrics
StartTime time.Time
Ownership Ownership
}

func (kwfs KeywhizFs) StatusJSON() []byte {
func (kwfs KeywhizFs) statusJSON() []byte {
// Convert buildTime (seconds since epoch) into an actual time.Time object,
// makes for nicer JSON marshalling (and matches mount time format).
seconds, err := strconv.ParseInt(buildTime, 10, 64)
Expand All @@ -83,15 +85,27 @@ func (kwfs KeywhizFs) StatusJSON() []byte {
return status
}

func (kwfs KeywhizFs) metricsJSON() []byte {
if kwfs.Metrics != nil {
metrics := kwfs.Metrics.SerializeMetrics()
data, err := json.Marshal(metrics)
if err == nil {
return data
}
kwfs.Warnf("Error serializing metrics: %v", err)
}
return []byte{}
}

// NewKeywhizFs readies a KeywhizFs struct and its parent filesystem objects.
func NewKeywhizFs(client *Client, ownership Ownership, timeouts Timeouts, logConfig log.Config) (kwfs *KeywhizFs, root nodefs.Node, err error) {
func NewKeywhizFs(client *Client, ownership Ownership, timeouts Timeouts, metrics *sqmetrics.SquareMetrics, logConfig log.Config) (kwfs *KeywhizFs, root nodefs.Node, err error) {
logger := log.New("kwfs", logConfig)
cache := NewCache(client, timeouts, logConfig)

defaultfs := pathfs.NewDefaultFileSystem() // Returns ENOSYS by default
readonlyfs := pathfs.NewReadonlyFileSystem(defaultfs) // R/W calls return EPERM

kwfs = &KeywhizFs{readonlyfs, logger, client, cache, time.Now(), ownership}
kwfs = &KeywhizFs{readonlyfs, logger, client, cache, metrics, time.Now(), ownership}
nfs := pathfs.NewPathNodeFs(kwfs, nil)
nfs.SetDebug(logConfig.Debug)
return kwfs, nfs.Root(), nil
Expand All @@ -118,7 +132,10 @@ func (kwfs KeywhizFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, f
case name == ".json":
attr = kwfs.directoryAttr(1, 0700)
case name == ".json/status":
size := uint64(len(kwfs.StatusJSON()))
size := uint64(len(kwfs.statusJSON()))
attr = kwfs.fileAttr(size, 0444)
case name == ".json/metrics":
size := uint64(len(kwfs.metricsJSON()))
attr = kwfs.fileAttr(size, 0444)
case name == ".json/secret":
attr = kwfs.directoryAttr(0, 0700)
Expand Down Expand Up @@ -159,7 +176,9 @@ func (kwfs KeywhizFs) Open(name string, flags uint32, context *fuse.Context) (no
case name == ".version":
file = nodefs.NewDataFile([]byte(fsVersion))
case name == ".json/status":
file = nodefs.NewDataFile(kwfs.StatusJSON())
file = nodefs.NewDataFile(kwfs.statusJSON())
case name == ".json/metrics":
file = nodefs.NewDataFile(kwfs.metricsJSON())
case name == ".clear_cache":
file = nodefs.NewDevNullFile()
case name == ".running":
Expand Down Expand Up @@ -205,6 +224,7 @@ func (kwfs KeywhizFs) OpenDir(name string, context *fuse.Context) (stream []fuse
fuse.DirEntry{Name: ".version", Mode: fuse.S_IFREG})
case ".json":
entries = []fuse.DirEntry{
fuse.DirEntry{Name: "metrics", Mode: fuse.S_IFREG},
fuse.DirEntry{Name: "secret", Mode: fuse.S_IFDIR},
fuse.DirEntry{Name: "secrets", Mode: fuse.S_IFREG},
fuse.DirEntry{Name: "status", Mode: fuse.S_IFREG},
Expand Down
7 changes: 4 additions & 3 deletions fs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (suite *FsTestSuite) SetupTest() {
timeouts := Timeouts{0, 10 * time.Millisecond, 20 * time.Millisecond}
client := NewClient(clientFile, clientFile, testCaFile, suite.url, timeouts.MaxWait, logConfig)
ownership := Ownership{Uid: _SomeUID, Gid: _SomeUID}
kwfs, _, _ := NewKeywhizFs(&client, ownership, timeouts, logConfig)
kwfs, _, _ := NewKeywhizFs(&client, ownership, timeouts, nil, logConfig)
suite.fs = kwfs
}

Expand All @@ -60,7 +60,7 @@ func (suite *FsTestSuite) TestSpecialFileAttrs() {
}{
{"", 4096, 0755 | fuse.S_IFDIR},
{".version", len(fsVersion), 0444 | fuse.S_IFREG},
{".json/status", len(suite.fs.StatusJSON()), 0444 | fuse.S_IFREG},
{".json/status", len(suite.fs.statusJSON()), 0444 | fuse.S_IFREG},
{".running", -1, 0444 | fuse.S_IFREG},
{".clear_cache", 0, 0440 | fuse.S_IFREG},
{".json", 4096, 0700 | fuse.S_IFDIR},
Expand Down Expand Up @@ -156,7 +156,7 @@ func (suite *FsTestSuite) TestSpecialFileOpen() {

file, status = suite.fs.Open(".json/status", 0, fuseContext)
assert.Equal(fuse.OK, status)
assert.EqualValues(suite.fs.StatusJSON(), read(file))
assert.EqualValues(suite.fs.statusJSON(), read(file))

file, status = suite.fs.Open(".clear_cache", 0, fuseContext)
assert.Equal(fuse.OK, status)
Expand Down Expand Up @@ -241,6 +241,7 @@ func (suite *FsTestSuite) TestOpenDir() {
{
".json",
map[string]bool{
"metrics": true,
"status": true,
"secret": false,
"secrets": true,
Expand Down
17 changes: 3 additions & 14 deletions glide.lock

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

44 changes: 23 additions & 21 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ func main() {
certFile = keyFile
}

if *metricsURL != "" && !strings.HasPrefix(*metricsURL, "http://") && !strings.HasPrefix(*metricsURL, "https://") {
log.Fatalf("--metrics-url should start with http:// or https://")
os.Exit(1)
}
metricsHandle := setupMetrics(metricsURL, metricsPrefix, mountpoint)

lockMemory()

Expand All @@ -91,7 +88,7 @@ func main() {
client := NewClient(*certFile, *keyFile, *caFile, serverURL, clientTimeout, logConfig)

ownership := NewOwnership(*asuser, *asgroup)
kwfs, root, err := NewKeywhizFs(&client, ownership, timeouts, logConfig)
kwfs, root, err := NewKeywhizFs(&client, ownership, timeouts, metricsHandle, logConfig)
if err != nil {
log.Fatalf("KeywhizFs init fail: %v\n", err)
}
Expand Down Expand Up @@ -123,22 +120,6 @@ func main() {
}
}()

// Setup metrics
// Replace slashes with _ for easier aggregation
if *metricsURL != "" {
log.Printf("metrics enabled; reporting metrics via POST to %s", *metricsURL)

var prefix string
if *metricsPrefix != "" {
prefix = *metricsPrefix
} else {
// By default, prefix metrics with escaped mount path
prefix = fmt.Sprintf("keywhizfs.%s", strings.Replace(strings.Replace(mountpoint, "-", "--", -1), "/", "-", -1))
}

sqmetrics.NewMetrics(*metricsURL, prefix, metrics.DefaultRegistry)
}

// Prime cache: we retrieve the initial secrets list right away, so that
// we can make sure we're ready to show contents as soon as we get mounted.
if *ping {
Expand All @@ -153,6 +134,27 @@ func main() {
logger.Infof("Exiting")
}

// Setup metrics
func setupMetrics(metricsURL *string, metricsPrefix *string, mountpoint string) *sqmetrics.SquareMetrics {
if *metricsURL != "" {
if !strings.HasPrefix(*metricsURL, "http://") && !strings.HasPrefix(*metricsURL, "https://") {
log.Fatalf("--metrics-url should start with http:// or https://")
os.Exit(1)
}
log.Printf("metrics enabled; reporting metrics via POST to %s", *metricsURL)
}

var prefix string
if *metricsPrefix != "" {
prefix = *metricsPrefix
} else {
// By default, prefix metrics with escaped mount path. Replace slashes with - for easier aggregation
prefix = fmt.Sprintf("keywhizfs.%s", strings.Replace(strings.Replace(mountpoint, "-", "--", -1), "/", "-", -1))
}

return sqmetrics.NewMetrics(*metricsURL, prefix, metrics.DefaultRegistry)
}

// Locks memory, preventing memory from being written to disk as swap
func lockMemory() {
err := unix.Mlockall(unix.MCL_FUTURE | unix.MCL_CURRENT)
Expand Down

0 comments on commit d133d53

Please sign in to comment.