-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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
migrate e2e & integration role_test to common #14020
Conversation
func TestCtlV3RoleAddTimeout(t *testing.T) { testCtl(t, roleAddTest, withDialTimeout(0)) } | ||
|
||
func TestCtlV3RoleGrant(t *testing.T) { testCtl(t, roleGrantTest) } | ||
|
||
func roleAddTest(cx ctlCtx) { |
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.
Called from TestCtlV3RoleAddTimeout
. So it was left un-deleted.
cmdArgs = append(cmdArgs, args...) | ||
|
||
return e2e.SpawnWithExpects(cmdArgs, cx.envMap, expStr...) | ||
} | ||
func ctlV3Role(cx ctlCtx, args []string, expStr 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.
Line 52 and below are retained only in this PR. After auth_test are migrated to common, they should be cleaned up.
err = json.Unmarshal([]byte(line), &resp) | ||
return &resp, err | ||
} | ||
|
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.
Almost all methods have similar implementation. I think it makes more sense to wrap them into 1 ~ 2 common methods so as to simplify the overall implementation.
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.
It's a good idea, however let's try not to mix in to many changes into PR.
tests/common/role_test.go
Outdated
if err == nil || !strings.Contains(err.Error(), rpctypes.ErrRoleAlreadyExist.Error()) { | ||
t.Fatalf("want (%v) error, but got (%v)", rpctypes.ErrRoleAlreadyExist, err) | ||
} | ||
_, err = cc.RoleAdd("") |
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 looks like a separate test, like TestRoleError
was merged with other test.
Codecov Report
@@ Coverage Diff @@
## main #14020 +/- ##
==========================================
- Coverage 75.12% 74.65% -0.47%
==========================================
Files 448 448
Lines 37193 37193
==========================================
- Hits 27941 27768 -173
- Misses 7482 7626 +144
- Partials 1770 1799 +29
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
All comments are addressed. PTAL, thx! @ahrtr @serathius |
client/v3/maintenance.go
Outdated
header := ar.Header | ||
for _, am := range ar.Alarms { | ||
dresp, derr := m.AlarmDisarm(ctx, (*AlarmMember)(am)) | ||
if derr != nil { | ||
return nil, toErr(ctx, derr) | ||
} | ||
ret.Alarms = append(ret.Alarms, dresp.Alarms...) | ||
header = dresp.Header | ||
} | ||
ret.Header = 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.
header := ar.Header | |
for _, am := range ar.Alarms { | |
dresp, derr := m.AlarmDisarm(ctx, (*AlarmMember)(am)) | |
if derr != nil { | |
return nil, toErr(ctx, derr) | |
} | |
ret.Alarms = append(ret.Alarms, dresp.Alarms...) | |
header = dresp.Header | |
} | |
ret.Header = header | |
ret.Header = ar.Header | |
for _, am := range ar.Alarms { | |
dresp, derr := m.AlarmDisarm(ctx, (*AlarmMember)(am)) | |
if derr != nil { | |
return nil, toErr(ctx, derr) | |
} | |
ret.Alarms = append(ret.Alarms, dresp.Alarms...) | |
ret.Header = dresp.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.
This looks like a reasonable fix for a bug, however I would want to make sure that it's properly reviewed. Can you send it in separate PR?
tests/common/user_test.go
Outdated
@@ -301,7 +302,8 @@ func TestUserDelete(t *testing.T) { | |||
if err == nil { | |||
t.Fatalf("deleting a non-existent user should fail") | |||
} | |||
assert.Contains(t, err.Error(), "user name not found") | |||
expectErrMsg := "user name not found" |
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.
Looks like unrelated change.
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 related.
tests/framework/e2e/etcd_spawn.go
Outdated
"go.etcd.io/etcd/pkg/v3/expect" | ||
"go.uber.org/zap" | ||
) | ||
|
||
func SpawnCmd(args []string, envVars map[string]string) (*expect.ExpectProcess, error) { | ||
return SpawnCmdWithLogger(zap.NewNop(), args, envVars) | ||
} | ||
|
||
// SpawnCmdWithJsonPrinter spawns an etcdctl process with provided command line arguments and environment variables |
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 function has strong assumptions about working only for etcdctl
, this makes both name and location (etcd_spawn.go
) not match expectations. Please consider making this a helper method for EtcdctlV3
struct below.
tests/framework/e2e/etcd_spawn.go
Outdated
return cmd.ExpectFunc(func(txt string) bool { | ||
// lease response does not have header substring | ||
// member add response does not have revision substring | ||
return strings.Contains(txt, "header") || strings.Contains(txt, "revision") |
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 consider using or here a workaround for tests, however I think more important here is to find out why we have such inconsistency and consider fixing it. Could you give exact examples of Response
protos in https://github.com/etcd-io/etcd/blob/main/api/etcdserverpb/rpc.proto that are missing some fields?
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.
Yeah, let me raise a issue instead of fixing it in the tests migration PR.
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.
It's not grpc client implementation missed some fields but client v3.
Examples:
header
substring is missing because of embedding.
Lines 71 to 75 in b7be91f
// LeaseLeasesResponse wraps the protobuf message LeaseLeasesResponse. type LeaseLeasesResponse struct { *pb.ResponseHeader Leases []LeaseStatus `json:"leases"` } revision
is not populated in
etcd/server/etcdserver/api/v3rpc/member.go
Lines 108 to 110 in b7be91f
func (cs *ClusterServer) header() *pb.ResponseHeader { return &pb.ResponseHeader{ClusterId: uint64(cs.cluster.ID()), MemberId: uint64(cs.server.ID()), RaftTerm: cs.server.Term()} }
I guess #2 is intended as etcd member reconfiguration does not going though MVCC but just stored in memory.
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 for raising this.
For lease, we need some big change on this. There is an issue discussing this. The problem mentioned here is lease response indeed has the header info, but it isn't included under the "header" section. For example,
$ etcdctl lease list -w json | jq
{
"cluster_id": 14841639068965180000,
"member_id": 10276657743932975000,
"revision": 1,
"raft_term": 2,
"leases": []
}
$ etcdctl get k1 -w json | jq
{
"header": {
"cluster_id": 14841639068965180000,
"member_id": 10276657743932975000,
"revision": 1,
"raft_term": 2
}
}
With regard to the missing "revision" in the memer related commands, I think we might need to fix it. Feel free to raise a PR to send out for review.
$ etcdctl member list -w json | jq
{
"header": {
"cluster_id": 14841639068965180000,
"member_id": 10276657743932975000,
"raft_term": 2
},
"members": [
{
"ID": 10276657743932975000,
"name": "default",
"peerURLs": [
"http://localhost:2380"
],
"clientURLs": [
"http://localhost:2379"
]
}
]
}
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 problem mentioned here is lease response indeed has the header info, but it isn't included under the "header" section
Exactly. I think may be a json tag added to the LeaseLeasesResponse struct should help. It's a relatively small change.
I just realized we cannot update client v3 directly as it would break the library users. So I will leave them as they are for now.
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.
Technically speaking, it's a small change. But it has impact on user experience. So we should be cautious about this. Let's track this in the issue I mentioned above.
Feel free to fix the missing revision in member related commands for now, although it might also change the user experience, but I think the impact should be minimal.
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.
Yeah, 100% agree. I just realized it like kube-apiserver will be impacted by this small change so I dropped the drafted PR.
tests/framework/e2e/etcdctl.go
Outdated
@@ -120,8 +121,7 @@ func (ctl *EtcdctlV3) Put(key, value string, opts config.PutOptions) error { | |||
} | |||
|
|||
func (ctl *EtcdctlV3) Delete(key string, o config.DeleteOptions) (*clientv3.DeleteResponse, error) { | |||
args := ctl.cmdArgs() | |||
args = append(args, "del", key, "-w", "json") | |||
args := ctl.cmdArgs("del", key) |
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 for refactor, however I'm worried that this might make a breaking change for othere when they migrate. Could we move it to separate PR so it can be quickly reviewed and merged?
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.
Make sense.
tests/framework/integration.go
Outdated
integrationCfg.QuotaBackendBytes = cfg.QuotaBackendBytes | ||
integrationCfg.ClientTLS, err = tlsInfo(t, cfg.ClientTLS) |
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 sure this is related.
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 related. Just refactor.
tests/framework/interface.go
Outdated
@@ -39,6 +39,7 @@ type Member interface { | |||
Stop() | |||
} | |||
|
|||
// Client is a wrapper on top of "go.etcd.io/etcd/client/v3".Client interface |
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 sure what what wrapper on top of ... interface
means. I would set that this interface is meant as a subset of clientv3.Client
interface implemented by common framework, however this is also not true as options are passed differently to be more expressive.
Overall this is still work in progress, so I would propose that you skip adding documentation in this PR.
Thanks for the review. I will keep the current PR for the minimal changes of I agree the issues/bugs exposed by refactoring with etcdctl json printer should be addressed in a separate PR. |
tests/framework/e2e/etcdctl.go
Outdated
return "", err | ||
} | ||
return cmd.ExpectFunc(func(txt string) bool { | ||
// header substring is missing because of embedding in LeaseLeasesResponse. |
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 PR doesn't touch LeaseLeasesResponse
, let's skip this for now.
tests/framework/e2e/etcdctl.go
Outdated
func (ctl *EtcdctlV3) RoleDelete(role string) (*clientv3.AuthRoleDeleteResponse, error) { | ||
line, err := SpawnCmdWithJsonPrinter(ctl.cmdArgs("role", "delete", role), nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var resp clientv3.AuthRoleDeleteResponse | ||
err = json.Unmarshal([]byte(line), &resp) | ||
return &resp, err | ||
} | ||
|
||
// SpawnCmdWithJsonPrinter spawns an etcdctl process with provided command line arguments and environment variables | ||
// with json printer output and capture header line as output. | ||
func SpawnCmdWithJsonPrinter(args []string, envVars map[string]string) (string, error) { | ||
args = append(args, "-w", "json") | ||
cmd, err := SpawnCmd(args, envVars) | ||
if err != nil { | ||
return "", err | ||
} | ||
return cmd.ExpectFunc(func(txt string) bool { | ||
// header substring is missing because of embedding in LeaseLeasesResponse. | ||
// revision substring is missing because ClusterServer.header() does not fill revision in the header | ||
return strings.Contains(txt, "header") || strings.Contains(txt, "revision") | ||
}) | ||
} |
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 (ctl *EtcdctlV3) RoleDelete(role string) (*clientv3.AuthRoleDeleteResponse, error) { | |
line, err := SpawnCmdWithJsonPrinter(ctl.cmdArgs("role", "delete", role), nil) | |
if err != nil { | |
return nil, err | |
} | |
var resp clientv3.AuthRoleDeleteResponse | |
err = json.Unmarshal([]byte(line), &resp) | |
return &resp, err | |
} | |
// SpawnCmdWithJsonPrinter spawns an etcdctl process with provided command line arguments and environment variables | |
// with json printer output and capture header line as output. | |
func SpawnCmdWithJsonPrinter(args []string, envVars map[string]string) (string, error) { | |
args = append(args, "-w", "json") | |
cmd, err := SpawnCmd(args, envVars) | |
if err != nil { | |
return "", err | |
} | |
return cmd.ExpectFunc(func(txt string) bool { | |
// header substring is missing because of embedding in LeaseLeasesResponse. | |
// revision substring is missing because ClusterServer.header() does not fill revision in the header | |
return strings.Contains(txt, "header") || strings.Contains(txt, "revision") | |
}) | |
} | |
func (ctl *EtcdctlV3) RoleDelete(role string) (*clientv3.AuthRoleDeleteResponse, error) { | |
var resp clientv3.AuthRoleDeleteResponse | |
err := ctl.spawnJsonCmd(&resp, "role", "delete", role) | |
return &resp, err | |
} | |
func (ctl *EtcdctlV3) spawnJsonCmd(output interface{}, args ...string) error { | |
args = append(args, "-w", "json") | |
cmd, err := SpawnCmd(append(ctl.cmdArgs(), args...), nil) | |
if err != nil { | |
return err | |
} | |
line, err := cmd.Expect("header") | |
if err != nil { | |
return err | |
} | |
err = json.Unmarshal([]byte(line), output) | |
if err != nil { | |
return err | |
} | |
return nil | |
} |
SpawnCmdWithJsonPrinter
you proposed doesn't work for any cmd, it depends directly on -w json
parameters available only for some of the etcdctl commands. As so it should not be a function, but a method on EtcdctlV3 struct.
I also proposed to make one additional step to include json parsing. It make sense that if we provide commands used to force json output, then we should always be able to parse json.
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 for the suggestions!! Much appreciate it.
Partially fix #13637