Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds pg implementations for admin GetTree(id) and CreateTree #1305

Merged
merged 10 commits into from
Oct 4, 2018

Conversation

vishalkuo
Copy link
Contributor

@vishalkuo vishalkuo commented Sep 25, 2018

This PR introduces a partial implementation for admin storage in postgres. Particularly, it implements the CreateTree and GetTree(id) methods.

Much of the logic is borrowed heavily from the MySQL methods (including validation and setup) so I tried to pull out common helpers wherever I could. That being said, I think there were even further commonalities I could pull out but I worried that that'd be too big a change for this PR (let me know if you feel otherwise).

As far as testing, I copied most of the logic in mysql's storage tests but have yet to build our a test driver. I figured I'd leave that to another PR as this one was getting fairly large.

Issue: #1298

@codecov
Copy link

codecov bot commented Sep 25, 2018

Codecov Report

Merging #1305 into master will decrease coverage by 0.77%.
The diff coverage is 7.07%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1305      +/-   ##
==========================================
- Coverage   61.09%   60.32%   -0.78%     
==========================================
  Files         125      127       +2     
  Lines       10070    10091      +21     
==========================================
- Hits         6152     6087      -65     
- Misses       3224     3324     +100     
+ Partials      694      680      -14
Impacted Files Coverage Δ
storage/sql.go 0% <0%> (ø)
storage/mysql/admin_storage.go 75.78% <100%> (+0.7%) ⬆️
server/postgres_storage_provider.go 4.34% <4.34%> (ø)
testonly/hammer/hammer.go 63.05% <0%> (-0.81%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f58fff5...cbc4d6a. Read the comment docs.

Copy link
Member

@AlCutter AlCutter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Vishal, thanks for pushing on the PG implementation!
A few quick comments inline

"github.com/google/trillian/storage"
"github.com/google/trillian/storage/postgres"

// Load MySQL driver
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Load PG driver :)

)

var (
pgConnStr = flag.String("pg_uri", "user=postgres dbname=test port=5432 sslmode=disable", "Connection string for Postgres database")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change the flag name to match too?
It's not really a URI any more by the looks of things.


var (
// ErrNotImplemented is an error indicating a function's implementation has not been completed
ErrNotImplemented = errors.New("not implemented")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can probably be unexported?


"github.com/google/trillian/testonly"

_ "github.com/lib/pq" // mysql driver
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

postgres driver

}
}

func cleanTestDB(db *sql.DB) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could pass T in here, and call t.Helper() as the first line, and t.Fatal rather than panic.

func OpenDB(dbURL string) (*sql.DB, error) {
db, err := sql.Open("postgres", dbURL)
if err != nil {
// Don't log uri as it could contain credentials
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't log xxx

import (
"database/sql"
"fmt"
time "time"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to rename time to time :)


// FromMillisSinceEpoch converts an UNIX typestamp to a time struct
func FromMillisSinceEpoch(ts int64) time.Time {
secs := int64(ts / 1000)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can just be return time.Unix(0, ts*1000000)

@@ -0,0 +1,162 @@
// Copyright 2018 Google Inc. All Rights Reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should go under storage/sql or something - explicitly helpers for golang SQL compatible implementations?

@@ -161,7 +158,7 @@ func (t *adminTX) GetTree(ctx context.Context, treeID int64) (*trillian.Tree, er
defer stmt.Close()

// GetTree is an entry point for most RPCs, let's provide somewhat nicer error messages.
tree, err := readTree(stmt.QueryRowContext(ctx, treeID))
tree, err := storage.ReadTree(stmt.QueryRowContext(ctx, treeID))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if this is a good idea or not...
OTOH it does promote reuse and reduce boilerplate, but on the other it forces some restrictions on implementations, maybe that's a good trade off to make until we discover a scenario where it doesn't work, let's see what others think.

@pphaneuf @Martin2112 @RJPercival @daviddrysdale

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, definitely wasn't sure how much to pull out/leave in. My general understanding was that db/sql abstracted most differences away to only being at the query level but I could be wrong about that (especially with types, etc.)

return nil
}

// Row defines a common interface between sql.Row and sql.Rows(!), so we have to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this comment got a bit mangled. It was originally "There's no common interface between sql.Row and sql.Rows(!), so we have to define one."

}

// ValidateStorageSettings checks for storage settings and returns an error if they exist
func ValidateStorageSettings(tree *trillian.Tree) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem like this should be a general helper, since storage_settings is supposed to be specific to individual storage implementations.

}

// skipIfNoPG is a test helper that skips tests that require a local PG.
func skipIfNoPG(t *testing.T) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skipIfNoPG is unused

storage/sql.go Outdated
}

// Let's make sure we didn't mismatch any of the casts above
ok := tree.TreeState.String() == treeState
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just make this:

ok := tree.TreeState.String() == treestate &&
      tree.TreeType.String() == treeType &&
      tree.HashStrategy.String() == hashStrategy &&
      ...

?

@AlCutter
Copy link
Member

AlCutter commented Oct 4, 2018

Thanks, Vishal!

@AlCutter AlCutter merged commit bff2f3b into google:master Oct 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants