diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 159aad2..7af963d 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '1.20' + go-version: '1.22' - name: Build run: go build -v ./... diff --git a/Makefile b/Makefile index 2d35866..be99c0a 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,10 @@ lint-fix: test: go test ./... +.PHONY: test-fast +test-fast: + REUSE_YT_CONTAINER=yes go test ./... + .PHONY: format format: go fmt diff --git a/app_test.go b/app_test.go index 704a714..8da5e4a 100644 --- a/app_test.go +++ b/app_test.go @@ -2,10 +2,17 @@ package main import ( "context" + "fmt" + "log" "os" + "slices" "testing" "time" + "github.com/stretchr/testify/suite" + "go.ytsaurus.tech/yt/go/ypath" + "k8s.io/utils/clock" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/require" @@ -15,7 +22,8 @@ import ( ) const ( - ytDevToken = "password" + ytDevToken = "password" + reuseYtContainerEnvVar = "REUSE_YT_CONTAINER" ) type testCase struct { @@ -512,7 +520,223 @@ var ( } ) -// TestAppSync uses local YTsaurus container and fake Azure to test all the cases: +type AppTestSuite struct { + suite.Suite + ytsaurusLocal *YtsaurusLocal + ytsaurusClient yt.Client + initialYtsaurusUsers []YtsaurusUser + initialYtsaurusGroups []YtsaurusGroupWithMembers + initialYtsaurusUsernames []string + initialYtsaurusGroupnames []string + ctx context.Context +} + +func (suite *AppTestSuite) SetupSuite() { + suite.ctx = context.Background() + suite.ytsaurusLocal = NewYtsaurusLocal() + + if err := suite.ytsaurusLocal.Start(); err != nil { + log.Fatalf("error starting ytsaurus local container: %s", err) + } + + err := os.Setenv(defaultYtsaurusSecretEnvVar, ytDevToken) + if err != nil { + log.Fatalf("failed to set YT_TOKEN: %s", err) + } + + ytsaurusClient, err := suite.ytsaurusLocal.GetClient() + if err != nil { + log.Fatalf("error creating ytsaurus local client: %s", err) + } + + suite.ytsaurusClient = ytsaurusClient + + suite.initialYtsaurusUsers, suite.initialYtsaurusGroups, err = suite.getAllYtsaurusObjects() + if err != nil { + log.Fatalf("error getting initial ytsaurus objects: %s", err) + } + + for _, user := range suite.initialYtsaurusUsers { + suite.initialYtsaurusUsernames = append(suite.initialYtsaurusUsernames, user.Username) + } + + for _, group := range suite.initialYtsaurusGroups { + suite.initialYtsaurusGroupnames = append(suite.initialYtsaurusGroupnames, group.Name) + } +} + +func (suite *AppTestSuite) TearDownSuite() { + if err := suite.ytsaurusLocal.Stop(); err != nil { + log.Fatalf("error terminating ytsaurus local container: %s", err) + } +} + +func (suite *AppTestSuite) restartYtsaurusIfNeeded() { + if os.Getenv(reuseYtContainerEnvVar) != "1" && os.Getenv(reuseYtContainerEnvVar) != "yes" { + suite.TearDownSuite() + suite.SetupSuite() + } +} + +func (suite *AppTestSuite) getAllYtsaurusObjects() (users []YtsaurusUser, groups []YtsaurusGroupWithMembers, err error) { + allUsers, err := doGetAllYtsaurusUsers(context.Background(), suite.ytsaurusClient, "azure") + if err != nil { + return nil, nil, err + } + allGroups, err := doGetAllYtsaurusGroupsWithMembers(context.Background(), suite.ytsaurusClient, "azure") + return allUsers, allGroups, err +} + +func (suite *AppTestSuite) diffYtsaurusObjects(expectedUsers []YtsaurusUser, expectedGroups []YtsaurusGroupWithMembers) (string, string) { + actualUsers, actualGroups, err := suite.getAllYtsaurusObjects() + if err != nil { + log.Fatalf("failed to get all ytsaurus objects: %s", err) + } + allExpectedUsers := append(suite.initialYtsaurusUsers, expectedUsers...) + + // It seems that `users` group @members attr contains not the all users in the system: + // for example it doesn't include: + // alien_cell_synchronizer, file_cache, guest, operations_cleaner, operations_client, etc... + // we don't want to test that. + // Though we expect it to include users created in test, so we update group members in out expected group list. + var expectedNewUsernamesInUsersGroup []string + for _, u := range expectedUsers { + expectedNewUsernamesInUsersGroup = append(expectedNewUsernamesInUsersGroup, u.Username) + } + + var allExpectedGroups []YtsaurusGroupWithMembers + for _, initialGroup := range suite.initialYtsaurusGroups { + group := YtsaurusGroupWithMembers{YtsaurusGroup: initialGroup.YtsaurusGroup, Members: NewStringSet()} + if initialGroup.Name != "users" { + group.Members = initialGroup.Members + } else { + for member := range initialGroup.Members.Iter() { + group.Members.Add(member) + } + for _, uname := range expectedNewUsernamesInUsersGroup { + group.Members.Add(uname) + } + } + allExpectedGroups = append(allExpectedGroups, group) + } + allExpectedGroups = append(allExpectedGroups, expectedGroups...) + + uDiff := cmp.Diff( + actualUsers, + allExpectedUsers, + cmpopts.SortSlices(func(left, right YtsaurusUser) bool { + return left.Username < right.Username + }), + ) + gDiff := cmp.Diff( + actualGroups, + allExpectedGroups, + cmpopts.SortSlices(func(left, right YtsaurusGroupWithMembers) bool { + return left.Name < right.Name + }), + ) + + return uDiff, gDiff +} + +func (suite *AppTestSuite) clear() { + users, groups, err := suite.getAllYtsaurusObjects() + if err != nil { + log.Fatalf("failed to get ytsaurus objects: %s", err) + } + + for _, user := range users { + if !slices.Contains(suite.initialYtsaurusUsernames, user.Username) { + path := ypath.Path(fmt.Sprintf("//sys/users/%s", user.Username)) + err := suite.ytsaurusClient.RemoveNode(suite.ctx, path, nil) + if err != nil { + log.Fatalf("failed to remove user: %s", user.Username) + } + + exists := true + for exists { + exists, err = suite.ytsaurusClient.NodeExists(suite.ctx, path, nil) + if err != nil { + log.Fatalf("failed to check is group removed") + } + } + } + } + + for _, group := range groups { + if !slices.Contains(suite.initialYtsaurusGroupnames, group.Name) { + path := ypath.Path(fmt.Sprintf("//sys/groups/%s", group.Name)) + err := suite.ytsaurusClient.RemoveNode(suite.ctx, path, nil) + if err != nil { + log.Fatalf("failed to remove group: %s", err) + } + exists := true + for exists { + exists, err = suite.ytsaurusClient.NodeExists(suite.ctx, path, nil) + if err != nil { + log.Fatalf("failed to check is group removed") + } + } + } + } + + suite.restartYtsaurusIfNeeded() +} + +func (suite *AppTestSuite) syncOnce(t *testing.T, source Source, clock clock.PassiveClock, appConfig *AppConfig) { + if appConfig == nil { + appConfig = defaultAppConfig + } + + app, err := NewAppCustomized( + &Config{ + App: *appConfig, + Azure: &AzureConfig{}, + Ytsaurus: YtsaurusConfig{ + Proxy: suite.ytsaurusLocal.GetProxy(), + ApplyUserChanges: true, + ApplyGroupChanges: true, + ApplyMemberChanges: true, + LogLevel: "DEBUG", + SourceAttributeName: "azure", + }, + }, getDevelopmentLogger(), + source, + clock, + ) + require.NoError(t, err) + + app.syncOnce() +} + +func (suite *AppTestSuite) check(t *testing.T, expectedUsers []YtsaurusUser, expectedGroups []YtsaurusGroupWithMembers) { + // We have eventually here, because user removal takes some time. + require.Eventually( + t, + func() bool { + udiff, gdiff := suite.diffYtsaurusObjects(expectedUsers, expectedGroups) + actualUsers, actualGroups, err := suite.getAllYtsaurusObjects() + if err != nil { + log.Fatalf("failed to get all ytsaurus objects: %s", err) + } + if udiff != "" { + t.Log("Users diff is not empty yet:", udiff) + t.Log("expected users", expectedUsers) + t.Log("actual users", actualUsers) + } + if gdiff != "" { + t.Log("Groups diff is not empty yet:", gdiff) + t.Log("expected groups", expectedGroups) + t.Log("actual groups", actualGroups) + } + return udiff == "" && gdiff == "" + }, + 3*time.Second, + 300*time.Millisecond, + ) +} + +// TestAzureSyncOnce uses local YTsaurus container and fake Azure to test all the cases: // [x] If Azure user not in YTsaurus -> created; // [x] If Azure user already in YTsaurus no changes -> skipped; // [x] If Azure user already in YTsaurus with changes -> updated; @@ -530,93 +754,49 @@ var ( // [x] If Azure group displayName changed AND Azure members changed -> recreate YTsaurus group with actual members set; // [x] YTsaurus group name is built according to config; // [x] Remove limits config option works. -func TestAppSync(t *testing.T) { - require.NoError(t, os.Setenv(defaultYtsaurusSecretEnvVar, ytDevToken)) +func (suite *AppTestSuite) TestAzureSyncOnce() { + t := suite.T() + for _, tc := range testCases { t.Run( tc.name, func(tc testCase) func(t *testing.T) { return func(t *testing.T) { + defer suite.clear() + if tc.testTime.IsZero() { tc.testTime = initialTestTime } - clock := testclock.NewFakePassiveClock(initialTestTime) - - ytLocal := NewYtsaurusLocal() - defer func() { require.NoError(t, ytLocal.Stop()) }() - require.NoError(t, ytLocal.Start()) + passiveClock := testclock.NewFakePassiveClock(tc.testTime) azure := NewAzureFake() azure.setUsers(tc.azureUsersSetUp) azure.setGroups(tc.azureGroupsSetUp) - ytClient, err := ytLocal.GetClient() - require.NoError(t, err) - - initialYtUsers, initialYtGroups := getAllYtsaurusObjects(t, ytClient) - setupYtsaurusObjects(t, ytClient, tc.ytUsersSetUp, tc.ytGroupsSetUp) - - if tc.appConfig == nil { - tc.appConfig = defaultAppConfig - } - app, err := NewAppCustomized( - &Config{ - App: *tc.appConfig, - Azure: &AzureConfig{}, - Ytsaurus: YtsaurusConfig{ - Proxy: ytLocal.GetProxy(), - ApplyUserChanges: true, - ApplyGroupChanges: true, - ApplyMemberChanges: true, - LogLevel: "DEBUG", - SourceAttributeName: "azure", - }, - }, getDevelopmentLogger(), - azure, - clock, + setupYtsaurusObjects( + t, + suite.ytsaurusClient, + tc.ytUsersSetUp, + tc.ytGroupsSetUp, ) - require.NoError(t, err) - app.syncOnce() + suite.syncOnce(t, azure, passiveClock, tc.appConfig) - // we have eventually here, because user removal takes some time. - require.Eventually( - t, - func() bool { - udiff, gdiff := diffYtsaurusObjects(t, ytClient, tc.ytUsersExpected, initialYtUsers, tc.ytGroupsExpected, initialYtGroups) - actualUsers, actualGroups := getAllYtsaurusObjects(t, ytClient) - if udiff != "" { - t.Log("Users diff is not empty yet:", udiff) - t.Log("expected users", tc.ytUsersExpected) - t.Log("actual users", actualUsers) - } - if gdiff != "" { - t.Log("Groups diff is not empty yet:", gdiff) - t.Log("expected groups", tc.ytGroupsExpected) - t.Log("actual groups", actualGroups) - } - return udiff == "" && gdiff == "" - }, - 3*time.Second, - 300*time.Millisecond, - ) + suite.check(t, tc.ytUsersExpected, tc.ytGroupsExpected) } }(tc), ) } } -func TestManageUnmanagedUsersIsForbidden(t *testing.T) { - ytLocal := NewYtsaurusLocal() - defer func() { require.NoError(t, ytLocal.Stop()) }() - require.NoError(t, ytLocal.Start()) +func (suite *AppTestSuite) TestManageUnmanagedUsersIsForbidden() { + t := suite.T() - ytClient, err := ytLocal.GetClient() - require.NoError(t, err) + defer suite.clear() ytsaurus, err := NewYtsaurus( &YtsaurusConfig{ - Proxy: ytLocal.GetProxy(), + Proxy: suite.ytsaurusLocal.GetProxy(), LogLevel: "DEBUG", }, getDevelopmentLogger(), @@ -628,7 +808,7 @@ func TestManageUnmanagedUsersIsForbidden(t *testing.T) { err = doCreateYtsaurusUser( context.Background(), - ytClient, + suite.ytsaurusClient, unmanagedOleg, nil, ) @@ -653,36 +833,37 @@ func TestManageUnmanagedUsersIsForbidden(t *testing.T) { } } -func getAllYtsaurusObjects(t *testing.T, client yt.Client) (users []YtsaurusUser, groups []YtsaurusGroupWithMembers) { - allUsers, err := doGetAllYtsaurusUsers(context.Background(), client, "azure") - require.NoError(t, err) - allGroups, err := doGetAllYtsaurusGroupsWithMembers(context.Background(), client, "azure") - require.NoError(t, err) - return allUsers, allGroups +func TestAppTestSuite(t *testing.T) { + suite.Run(t, new(AppTestSuite)) } func setupYtsaurusObjects(t *testing.T, client yt.Client, users []YtsaurusUser, groups []YtsaurusGroupWithMembers) { - t.Log("Setting up yt for test") + t.Log("Setting up ytsaurus for test") + for _, user := range users { t.Logf("creating user: %v", user) + + userAttributes := buildUserAttributes(user, "azure") err := doCreateYtsaurusUser( context.Background(), client, user.Username, - buildUserAttributes(user, "azure"), + userAttributes, ) require.NoError(t, err) } for _, group := range groups { t.Log("creating group:", group) + + groupAttributes := buildGroupAttributes(group.YtsaurusGroup, "azure") err := doCreateYtsaurusGroup( context.Background(), client, group.Name, - buildGroupAttributes(group.YtsaurusGroup, "azure"), + groupAttributes, ) - require.NoError(t, err) + for member := range group.Members.Iter() { err = doAddMemberYtsaurusGroup( context.Background(), @@ -695,46 +876,6 @@ func setupYtsaurusObjects(t *testing.T, client yt.Client, users []YtsaurusUser, } } -func diffYtsaurusObjects(t *testing.T, client yt.Client, expectedUsers, initialUsers []YtsaurusUser, expectedGroups, initalGroups []YtsaurusGroupWithMembers) (string, string) { - actualUsers, actualGroups := getAllYtsaurusObjects(t, client) - allExpectedUsers := append(initialUsers, expectedUsers...) - allExpectedGroups := append(initalGroups, expectedGroups...) - - // It seems that `users` group @members attr contains not the all users in the system: - // for example it doesn't include: - // alien_cell_synchronizer, file_cache, guest, operations_cleaner, operations_client, etc... - // we don't want to test that. - // Though we expect it to include users created in test, so we update group members in out expected group list. - var expectedNewUsernamesInUsersGroup []string - for _, u := range expectedUsers { - expectedNewUsernamesInUsersGroup = append(expectedNewUsernamesInUsersGroup, u.Username) - } - for idx, group := range allExpectedGroups { - if group.Name == "users" { - for _, uname := range expectedNewUsernamesInUsersGroup { - allExpectedGroups[idx].Members.Add(uname) - } - } - } - - uDiff := cmp.Diff( - actualUsers, - allExpectedUsers, - cmpopts.SortSlices(func(left, right YtsaurusUser) bool { - return left.Username < right.Username - }), - ) - gDiff := cmp.Diff( - actualGroups, - allExpectedGroups, - cmpopts.SortSlices(func(left, right YtsaurusGroupWithMembers) bool { - return left.Name < right.Name - }), - ) - - return uDiff, gDiff -} - func parseAppTime(timStr string) time.Time { parsed, err := time.Parse(appTimeFormat, timStr) if err != nil { diff --git a/go.mod b/go.mod index baf7029..ee2c2cb 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/nebius/ytsaurus-active-directory-integration -go 1.20 +go 1.22 require ( github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 @@ -14,7 +14,6 @@ require ( github.com/stretchr/testify v1.8.4 github.com/testcontainers/testcontainers-go v0.28.0 go.uber.org/zap v1.26.0 - go.ytsaurus.tech/library/go/ptr v0.0.1 go.ytsaurus.tech/yt/go v0.0.13 gopkg.in/yaml.v3 v3.0.1 k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 @@ -90,6 +89,7 @@ require ( go.ytsaurus.tech/library/go/blockcodecs v0.0.2 // indirect go.ytsaurus.tech/library/go/core/log v0.0.3 // indirect go.ytsaurus.tech/library/go/core/xerrors v0.0.3 // indirect + go.ytsaurus.tech/library/go/ptr v0.0.1 // indirect go.ytsaurus.tech/library/go/x/xreflect v0.0.2 // indirect go.ytsaurus.tech/library/go/x/xruntime v0.0.3 // indirect golang.org/x/crypto v0.17.0 // indirect diff --git a/go.sum b/go.sum index 795c6e1..54d148b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,7 @@ dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= +github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0 h1:9kDVnTz3vbfweTqAUmk/a/pH5pWFCHtvRpHYC0G/dcA= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.8.0/go.mod h1:3Ug6Qzto9anB6mGlEdgYMDF5zHQ+wwhEaYR4s17PHMw= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.4.0 h1:BMAjVKJM0U/CYF27gA0ZMmXGkOcvfFtD0oHVZ1TIPRI= @@ -28,6 +29,7 @@ github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3 github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -36,6 +38,7 @@ github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpO github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY= github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= @@ -45,6 +48,7 @@ github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -73,6 +77,7 @@ github.com/google/tink/go v1.7.0/go.mod h1:GAUOd+QE3pgj9q8VKIGTCP33c/B7eb4NhxLcg github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= @@ -80,7 +85,9 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= @@ -136,6 +143,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -170,16 +178,21 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1: go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= @@ -193,6 +206,7 @@ go.ytsaurus.tech/library/go/core/xerrors v0.0.3/go.mod h1:8u4Vm+WwEJceSGO3+D1m70 go.ytsaurus.tech/library/go/ptr v0.0.1 h1:TXR35NUQREmcifYt4qic7eYGIFgdc0cn+KNqkwpnsBU= go.ytsaurus.tech/library/go/ptr v0.0.1/go.mod h1:3HhS2x1phVP+4agBp7QZ7ywdOL7Jo1aYRYEyrxFbKSA= go.ytsaurus.tech/library/go/test/testhelpers v0.0.1 h1:X2y+zhLgd2y0DxF4V6HJyZwIp7rpewFKXlb+XZWGjio= +go.ytsaurus.tech/library/go/test/testhelpers v0.0.1/go.mod h1:kDwN91Sg68g0gYeYhLTA1sVlLJHdAtxZq6xWYj32TLI= go.ytsaurus.tech/library/go/x/xreflect v0.0.2 h1:S+lfg3G+WrfiBfTYz8droZeyiYYvT4mxLxEbQcNXQFs= go.ytsaurus.tech/library/go/x/xreflect v0.0.2/go.mod h1:FJB6bzAVFQxi99CZjUqDSAMu5puEjswFW9Qwj41Yyy8= go.ytsaurus.tech/library/go/x/xruntime v0.0.3 h1:/km3v+CPSuID5FsPKvE2LcwmYJPS8TcxeBMGH1MjtVs= @@ -220,6 +234,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -239,6 +254,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -253,6 +269,7 @@ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3j golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g= google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= @@ -263,10 +280,13 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk= k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=