-
Notifications
You must be signed in to change notification settings - Fork 361
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
Move setting endpoints to be under /settings/
#6649
Conversation
♻️ PR Preview 91c95f3 has been successfully destroyed since this PR has been closed. 🤖 By surge-preview |
/settings/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice and clean 😄
Added some comments, didn't go over tests and controller yet
@@ -4077,8 +4201,8 @@ paths: | |||
|
|||
post: | |||
tags: | |||
- retention |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not leave retention
and add internal
? same goes for other removed tags
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tags are reflected in the method names in the SDK, we want them to appear as "internal" to emphasize the fact that they are deprecated. These endpoints will be removed in the future.
err = json.NewDecoder(reader).Decode(&body) | ||
if err != nil { | ||
DieErr(err) | ||
} | ||
client := getClient() | ||
resp, err := client.SetGarbageCollectionRulesWithResponse(cmd.Context(), u.Repository, body) | ||
resp, err := client.SetGCRules(cmd.Context(), u.Repository, body) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With response
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed here, I think?
if errors.Is(err, graveler.ErrNotFound) { | ||
return &graveler.BranchProtectionRules{}, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was removed, and seems good, just checking it was intentional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intentional: decided to propagate the error to the controller, and handle it there.
} | ||
if err != nil { | ||
return nil, err | ||
func (m *ProtectionManager) SetRules(ctx context.Context, repository *graveler.RepositoryRecord, rules *graveler.BranchProtectionRules, ifMatchETag *string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
func (m *ProtectionManager) SetRules(ctx context.Context, repository *graveler.RepositoryRecord, rules *graveler.BranchProtectionRules, ifMatchETag *string) error { | |
func (m *ProtectionManager) SetRules(ctx context.Context, repository *graveler.RepositoryRecord, rules *graveler.BranchProtectionRules, etagPredicate *string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed to lastKnownChecksum
. Didn't want to reuse the "predicate" word, it's not really a predicate
pkg/graveler/graveler.go
Outdated
// If ifMatchETag is not nil, the update will only succeed if the current ETag matches the given one. | ||
// Otherwise, ErrPreconditionFailed is returned. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And if ifMatchETag
? no validation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added clarification and changed the behavior in some of the levels.
pkg/graveler/settings/manager.go
Outdated
@@ -67,6 +68,21 @@ func (m *Manager) Save(ctx context.Context, repository *graveler.RepositoryRecor | |||
return kv.SetMsg(ctx, m.store, graveler.RepoPartition(repository), []byte(graveler.SettingsPath(key)), setting) | |||
} | |||
|
|||
// SaveIf persists the given setting under the given repository and key. Overrides settings key in KV Store. | |||
// The setting is persisted only if the given ETag matches the ETag of the current setting. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, I think we should document what happens ifMatchETag
is nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -4059,8 +4183,8 @@ paths: | |||
type: string | |||
get: | |||
tags: | |||
- retention | |||
operationId: getGarbageCollectionRules | |||
- internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with the new settings path, are the old ones internal or deprecated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are deprecated: marking them as internal was a way to make sure users know they are deprecated. I will also add the deprecated notation like you did in your recent PR.
webui/src/lib/api/index.js
Outdated
const response = await apiRequest(`/repositories/${encodeURIComponent(repoID)}/settings/branch_protection`, { | ||
method: 'PUT', | ||
body: JSON.stringify(rules), | ||
}, {'ETag': lastKnownChecksum}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure we want the name to be ETag, it's basically an implementation detail, for the user it's just a lock/token/predicate or something like that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not care much either way: ETag is by now a term of HTTP, not only of S3. It's an actual standard header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ETag is part of the HTTP spec and is intended to be used together with the If-Match header.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UPDATE: this was a mistake, the header used here should be If-Match
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Nothing major except my confusion around ETags and the if-match stuff, sorry.
cmd/lakectl/cmd/branch_protect.go
Outdated
resp, err := client.GetBranchProtectionRulesWithResponse(cmd.Context(), u.Repository) | ||
DieOnErrorOrUnexpectedStatusCode(resp, err, http.StatusOK) | ||
rules := *resp.JSON200 | ||
for i, rule := range *resp.JSON200 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use https://pkg.go.dev/golang.org/x/exp/slices#DeleteFunc here instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks!
pkg/api/controller.go
Outdated
if eTag == "" { | ||
// workaround since swagger doesn't allow empty headers | ||
// https://github.com/deepmap/oapi-codegen/issues/954 | ||
eTag = base64.StdEncoding.EncodeToString([]byte("EMPTY")) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is quite worrying. Can we omit the etag if this happens? What if we used openapi-codegen version 6.6.0, or 7.0.0? @Jonathan-Rosenberg & I need to bump at least to 6.6.0 and probably to 7.0.0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed this.
pkg/api/controller.go
Outdated
eTag := params.IfMatch | ||
if swag.StringValue(eTag) == "" { | ||
// workaround since swagger doesn't allow empty headers | ||
// https://github.com/deepmap/oapi-codegen/issues/954 | ||
eTag = swag.String(base64.StdEncoding.EncodeToString([]byte("EMPTY"))) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this. If there is no If-Match
header, I think this makes it behave as though we did ask for a particular ETag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, this is not needed.
@@ -2113,7 +2241,9 @@ func (c *Controller) handleAPIErrorCallback(ctx context.Context, w http.Response | |||
case errors.Is(err, graveler.ErrTooManyTries): | |||
log.Debug("Retried too many times") | |||
cb(w, r, http.StatusLocked, "Too many attempts, try again later") | |||
|
|||
case errors.Is(err, graveler.ErrPreconditionFailed): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What changed that we need this now? Or is it a quick fix for a bug that you discovered along the way?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error is now returned from Graveler when the conditional update of branch protection rules fails.
webui/src/lib/api/index.js
Outdated
const response = await apiRequest(`/repositories/${encodeURIComponent(repoID)}/settings/branch_protection`, { | ||
method: 'PUT', | ||
body: JSON.stringify(rules), | ||
}, {'ETag': lastKnownChecksum}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not care much either way: ETag is by now a term of HTTP, not only of S3. It's an actual standard header.
@@ -2113,7 +2241,9 @@ func (c *Controller) handleAPIErrorCallback(ctx context.Context, w http.Response | |||
case errors.Is(err, graveler.ErrTooManyTries): | |||
log.Debug("Retried too many times") | |||
cb(w, r, http.StatusLocked, "Too many attempts, try again later") | |||
|
|||
case errors.Is(err, graveler.ErrPreconditionFailed): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏽
pkg/graveler/settings/manager.go
Outdated
@@ -67,6 +68,21 @@ func (m *Manager) Save(ctx context.Context, repository *graveler.RepositoryRecor | |||
return kv.SetMsg(ctx, m.store, graveler.RepoPartition(repository), []byte(graveler.SettingsPath(key)), setting) | |||
} | |||
|
|||
// SaveIf persists the given setting under the given repository and key. Overrides settings key in KV Store. | |||
// The setting is persisted only if the given ETag matches the ETag of the current setting. | |||
// Otherwise, ErrPreconditionFailed is returned. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually in our code when predicate (ifMatchETag) is nil - this is an indication for saveIf not exists. This might cause a bit of confusion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, will this make the Save method redundant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed (kind of): changed this to no longer be a pointer. The update is always conditional - empty string means update-if-not-exists. Now branch.ProtectionManager
exposes both SetRules
and SetRulesIf
. SetRules uses the unconditional Save
.
However, the catalog and graveler still use a pointer, where nil means unconditional update, and empty string means update-if-not-exists.
esti/ugc_test.go
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did we remove this?
We are removing test coverage without providing an alternative
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that these are not Spark tests - they test the lakeFS API
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is no longer used (it tests code that doesn't exist). It is replaced by "unified GC tests".
return | ||
} | ||
writeResponse(w, r, http.StatusNoContent, nil) | ||
func (c *Controller) InternalSetGarbageCollectionRules(w http.ResponseWriter, r *http.Request, body apigen.InternalSetGarbageCollectionRulesJSONRequestBody, repository string) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain why we need the Internal
functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are keeping them for backward compatibility, and they will be removed in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I see what you did there - the api endpoint didn't change
@@ -610,15 +610,12 @@ type VersionController interface { | |||
GCNewRunID() string | |||
|
|||
// GetBranchProtectionRules return all branch protection rules for the repository | |||
GetBranchProtectionRules(ctx context.Context, repository *RepositoryRecord) (*BranchProtectionRules, error) | |||
GetBranchProtectionRules(ctx context.Context, repository *RepositoryRecord) (*BranchProtectionRules, string, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you update documentation on the returned values.
Also why is the etag necessary on the branch protection rules but not in GC rules?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Resolves #6535.
/settings
:/settings/gc_rules
: GET/PUT/DELETE all garbage collection rules./settings/branch_protect
: GET/PUT all branch protection rules.Notes
If-Match
header when setting the rules.