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

[A2-815] list rules with staged and current rules #646

Merged
merged 9 commits into from
Jun 24, 2019

Conversation

srenatus
Copy link
Contributor

@srenatus srenatus commented Jun 20, 2019

🔩 Description

ListRules: Refactor or write separate APIs to return both a current rules list and staged rules list

This adds a ListStagedAndAppliedRules to the storage layer, and another grpc method to authz-service exposing it.

TODO:

  • expose in the gateway, using an ENUM for applied/staged

👍 Definition of Done

ListRules: Refactor or write separate APIs to return both a current rules list and staged rules list

😉

👟 Demo Script / Repro Steps

  • rebuild components/authz-service
  • create a project

TODO

⛓️ Related Resources

✅ Checklist

  • Necessary tests added/updated?
  • Necessary docs added/updated?
  • Code actually executed?
  • Vetting performed (unit tests, lint, etc.)?

@srenatus srenatus added automate-auth iamv2 This issue or pull request applies to iamv2 work for Automate labels Jun 20, 2019
@srenatus srenatus self-assigned this Jun 20, 2019
@srenatus srenatus force-pushed the sr/a2-815/list-rules-with-staged-and-current-rules branch 3 times, most recently from eda06f7 to b617f66 Compare June 20, 2019 13:52
Copy link
Contributor Author

@srenatus srenatus left a comment

Choose a reason for hiding this comment

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

Some reviewer notes inline

@@ -111,6 +111,8 @@ message ProjectRule {
string name = 3;
ProjectRuleTypes type = 4;
repeated Condition conditions = 5;
bool deleted = 6;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ℹ️Surfacing the deleted and staged/applied status of a rule in the interservice API. Nothing done for automate-gateway yet.

@@ -173,7 +175,9 @@ message GetRuleResp {
ProjectRule rule = 1;
}

message ListRulesReq {}
message ListRulesReq {
bool include_staged = 1;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ℹ️ Pass ListRulesReq{IncludeStaged: true} to also see staged rules.

@@ -111,6 +111,8 @@ message ProjectRule {
string name = 3;
ProjectRuleTypes type = 4;
repeated Condition conditions = 5;
bool deleted = 6;
string status = 7;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

OMG why no enum?!!!

I hear you -- but it's just so annoying to convert three different kinds of enums (storage layer, authz-service GRPC, automate-gateway GRPC), and I'm not convinced it's worth it. Happy to listen to arguments, but maybe we can just make our lives a little brighter and our PRs a little smaller. 😉

Also, in the external API (automate-gateway), we can (and should) still use an enum.

Copy link
Contributor

Choose a reason for hiding this comment

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

I really like the compromise of having an enum at the gateway and not in the domain layer. The enum unwrapping code is super super annoying.

@@ -143,6 +143,7 @@ func TestCreateRule(t *testing.T) {
Operator: api.ProjectRuleConditionOperators_MEMBER_OF,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ℹ️I haven't added any tests on that layer yet.

@@ -0,0 +1,154 @@
BEGIN;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ℹ️ Updated SQL functions to return the "status" = "applied"/"staged".

Converted to use json_build_object in the process.

@@ -137,7 +137,7 @@ SELECT array_agg(policy_id) FROM pol_ids`,
func (p *pg) ListPolicies(ctx context.Context) ([]*v2.Policy, error) {
projectsFilter, err := projectsListFromContext(ctx)
if err != nil {
return nil, p.processError(err)
return nil, err
Copy link
Contributor Author

Choose a reason for hiding this comment

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

one of two drive-by cleanups, please see the commit

}

ctx, cancel := context.WithCancel(ctx)
defer cancel()

tx, err := p.db.BeginTx(ctx, nil)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

one of two drive-by cleanups, please see the commit

return p.listRulesUsingFunction(ctx, "SELECT query_rules($1)")
}

func (p *pg) ListStagedAndAppliedRules(ctx context.Context) ([]*v2.Rule, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ℹ️ new method for retrieving rules of each state -- as mentioned in A2-815.

db.Flush(t)
}
}
func TestListStagedAndAppliedRules(t *testing.T) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The amount of copy-paste involved in creating these tests is deeply unsatisfying :grumpycat:

}

func insertStagedRule(t *testing.T, db *testhelpers.TestDB, rule storage.Rule) {
func insertStagedRule(t *testing.T, db *testhelpers.TestDB, rule *storage.Rule) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ℹ️ We have to change the function type to pass a pointer to mutate the rule argument, to add the status below

@srenatus srenatus added the WIP label Jun 20, 2019
BEGIN;

CREATE OR REPLACE FUNCTION
query_staged_and_applied_rules(_project_filter TEXT[])
Copy link
Contributor

Choose a reason for hiding this comment

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

does this query concatenate the rows from the two tables?

for GetStagedOrAppliedRule(id) we return the staged rule if it exists, otherwise return the applied rule (due to an acceptance requirement that users should always see the latest staged change). we may want to make this query work the same way - returning only one version of each rule.

although since i don't know of a specific case where we're using this query yet, this is probably ok for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

A couple points.

  1. Looking at GetStagedOrAppliedRule I do not believe it does what you think, @bcmdarroch . Looks like the SQL underlying that call, query_staged_rule, works exactly the same as this new function, returning both staged and applied rules.
  2. I do take issue with the name of this new function query_staged_and_applied_rules compared to the aforementioned function query_staged_rule. Please rename one or the other so they differ only in plurality. 😁

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we've resolved that in standup:

returning both staged and applied rules.

but we use QueryRowContext, so we're basically returning the staged one first (if it exists), so we're OK here, even if by accident. There might be a cleaner solution, but this one will do. 😉

Copy link
Contributor

Choose a reason for hiding this comment

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

query_staged_rules checks both applied and staged but only returns the applied rule if no staged version exists.

@@ -243,6 +243,7 @@ func (s *State) GetPolicyChangeNotifier(ctx context.Context) (v2.PolicyChangeNot
}

func (s *State) CreateRule(_ context.Context, rule *storage.Rule) (*storage.Rule, error) {
rule.Status = "applied"
Copy link
Contributor

Choose a reason for hiding this comment

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

if we want to match postgres behavior, the status here would be staged. only on ApplyRule does everything staged get set to applied.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Leaving this as-is to not break all the memstore-based tests. Let's nuke them. 😉

Copy link
Contributor

@tylercloke tylercloke left a comment

Choose a reason for hiding this comment

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

Generally looks good to me. I find it a bit strange that we don't just have separate APIs for some of the staged vs applied stuff but that's the general shape we've taken so far so might as well see it through and refactor as needed in the future.

@@ -111,6 +111,8 @@ message ProjectRule {
string name = 3;
ProjectRuleTypes type = 4;
repeated Condition conditions = 5;
bool deleted = 6;
string status = 7;
Copy link
Contributor

Choose a reason for hiding this comment

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

I really like the compromise of having an enum at the gateway and not in the domain layer. The enum unwrapping code is super super annoying.

@@ -470,6 +471,7 @@ func TestGetRule(t *testing.T) {
Type: api.ProjectRuleTypes_NODE,
ProjectId: projectID,
Conditions: apiConditions,
Status: "applied",
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this could be a constant? We have some at the DB level after the DeleteRule refactor PR merged.

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 a constant in a different package 😉 this is only tests I'll add another package-level one.

@@ -243,6 +243,7 @@ func (s *State) GetPolicyChangeNotifier(ctx context.Context) (v2.PolicyChangeNot
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Heh probably not as much WIP as we should. Left a comment in Slack.

BEGIN;

CREATE OR REPLACE FUNCTION
query_staged_and_applied_rules(_project_filter TEXT[])
Copy link
Contributor

Choose a reason for hiding this comment

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

A couple points.

  1. Looking at GetStagedOrAppliedRule I do not believe it does what you think, @bcmdarroch . Looks like the SQL underlying that call, query_staged_rule, works exactly the same as this new function, returning both staged and applied rules.
  2. I do take issue with the name of this new function query_staged_and_applied_rules compared to the aforementioned function query_staged_rule. Please rename one or the other so they differ only in plurality. 😁

'name', r.name,
'type', r.type,
'deleted', r.deleted,
'status', 'staged',
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider SQL constants for 'staged' and 'applied'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Really? As far as I understand it, constants in SQL are scoped per-function. So, this functions could have a constant, but there's not much to gain, really, since both strings only occurr once.... Also it doesn't look common in our code base to have SQL constants. 😃

@srenatus srenatus force-pushed the sr/a2-815/list-rules-with-staged-and-current-rules branch from b617f66 to 500d2a3 Compare June 21, 2019 12:51
@srenatus
Copy link
Contributor Author

rebased. will adress review comments later.

@srenatus srenatus force-pushed the sr/a2-815/list-rules-with-staged-and-current-rules branch from 500d2a3 to 72969e2 Compare June 21, 2019 17:18
@srenatus srenatus marked this pull request as ready for review June 21, 2019 17:34
srenatus added 2 commits June 21, 2019 14:50
If these methods _had_ multiple SQL calls, using a transaction, properly
threaded in, would be reasonable.  However right now, they both only
execute one query, so I've cleaned these up.

> Read Committed is the default isolation level in PostgreSQL. When a
> transaction uses this isolation level, a SELECT query (without a FOR
> UPDATE/SHARE clause) sees only data committed before the query began; it
> never sees either uncommitted data or changes committed during query
> execution by concurrent transactions. In effect, a SELECT query sees a
> snapshot of the database as of the instant the query begins to run.

See https://www.postgresql.org/docs/9.1/transaction-iso.html

Signed-off-by: Stephan Renatus <[email protected]>
@blakestier blakestier force-pushed the sr/a2-815/list-rules-with-staged-and-current-rules branch from cfe939d to b97fd6e Compare June 21, 2019 22:27
@blakestier blakestier removed the WIP label Jun 21, 2019
@srenatus srenatus merged commit ec30f22 into master Jun 24, 2019
@chef-ci chef-ci deleted the sr/a2-815/list-rules-with-staged-and-current-rules branch June 24, 2019 06:28
@susanev susanev added the auth-team anything that needs to be on the auth team board label Jul 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth-team anything that needs to be on the auth team board automate-auth iamv2 This issue or pull request applies to iamv2 work for Automate
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants