From b3b69581c460fa574b96218c10b901c16c0ccddf Mon Sep 17 00:00:00 2001 From: Roman Perekhod Date: Mon, 8 Jan 2024 16:55:51 +0100 Subject: [PATCH 01/73] rework disabling the password policy --- .../disabled-password-policy-rework.md | 7 +++ services/frontend/README.md | 2 + services/frontend/pkg/revaconfig/config.go | 50 +++++++++++------- services/sharing/pkg/revaconfig/config.go | 52 ++++++++++++------- 4 files changed, 74 insertions(+), 37 deletions(-) create mode 100644 changelog/unreleased/disabled-password-policy-rework.md diff --git a/changelog/unreleased/disabled-password-policy-rework.md b/changelog/unreleased/disabled-password-policy-rework.md new file mode 100644 index 0000000000..b5e85b38a8 --- /dev/null +++ b/changelog/unreleased/disabled-password-policy-rework.md @@ -0,0 +1,7 @@ +Enhancement: Disable the password policy + +We reworked and moved disabling the password policy logic from the reva to the ocis. + +https://github.com/owncloud/ocis/pull/8152 +https://github.com/cs3org/reva/pull/4453 +https://github.com/owncloud/ocis/issues/7916 diff --git a/services/frontend/README.md b/services/frontend/README.md index 11db15e717..83b395348b 100644 --- a/services/frontend/README.md +++ b/services/frontend/README.md @@ -75,6 +75,8 @@ When setting the `FRONTEND_AUTO_ACCEPT_SHARES` to `true`, all incoming shares wi Note that the password policy currently impacts only **public link password validation**. +In Infinite Scale, the password policy is always enabled because the max-length restriction is always applying and should be taken into account by the clients. + With the password policy, mandatory criteria for the password can be defined via the environment variables listed below. Generally, a password can contain any UTF-8 characters, however some characters are regarded as special since they are not used in ordinary texts. Which characters should be treated as special is defined by "The OWASP® Foundation" [password-special-characters](https://owasp.org/www-community/password-special-characters) (between double quotes): " !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~" diff --git a/services/frontend/pkg/revaconfig/config.go b/services/frontend/pkg/revaconfig/config.go index 0dfdcbc370..51c4138560 100644 --- a/services/frontend/pkg/revaconfig/config.go +++ b/services/frontend/pkg/revaconfig/config.go @@ -25,14 +25,10 @@ func FrontendConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string webURL.Path = path.Join(webURL.Path, "external") webOpenInAppURL := webURL.String() - var bannedPasswordsList map[string]struct{} - if cfg.PasswordPolicy.BannedPasswordsList != "" { - bannedPasswordsList, err = readMultilineFile(cfg.PasswordPolicy.BannedPasswordsList) - if err != nil { - err = fmt.Errorf("failed to load the banned passwords from a file %s: %w", cfg.PasswordPolicy.BannedPasswordsList, err) - logger.Err(err).Send() - return nil, err - } + passwordPolicyCfg, err := passwordPolicyConfig(cfg) + if err != nil { + logger.Err(err).Send() + return nil, err } archivers := []map[string]interface{}{ @@ -327,16 +323,7 @@ func FrontendConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string }, }, }, - "password_policy": map[string]interface{}{ - "max_characters": 72, - "disabled": cfg.PasswordPolicy.Disabled, - "min_characters": cfg.PasswordPolicy.MinCharacters, - "min_lowercase_characters": cfg.PasswordPolicy.MinLowerCaseCharacters, - "min_uppercase_characters": cfg.PasswordPolicy.MinUpperCaseCharacters, - "min_digits": cfg.PasswordPolicy.MinDigits, - "min_special_characters": cfg.PasswordPolicy.MinSpecialCharacters, - "banned_passwords_list": bannedPasswordsList, - }, + "password_policy": passwordPolicyCfg, "notifications": map[string]interface{}{ "endpoints": []string{"list", "get", "delete"}, }, @@ -385,3 +372,30 @@ func fileExists(path string) bool { } return !info.IsDir() } + +func passwordPolicyConfig(cfg *config.Config) (map[string]interface{}, error) { + _maxCharacters := 72 + if cfg.PasswordPolicy.Disabled { + return map[string]interface{}{ + "max_characters": _maxCharacters, + "banned_passwords_list": nil, + }, nil + } + var bannedPasswordsList map[string]struct{} + var err error + if cfg.PasswordPolicy.BannedPasswordsList != "" { + bannedPasswordsList, err = readMultilineFile(cfg.PasswordPolicy.BannedPasswordsList) + if err != nil { + return nil, fmt.Errorf("failed to load the banned passwords from a file %s: %w", cfg.PasswordPolicy.BannedPasswordsList, err) + } + } + return map[string]interface{}{ + "max_characters": _maxCharacters, + "min_digits": cfg.PasswordPolicy.MinDigits, + "min_characters": cfg.PasswordPolicy.MinCharacters, + "min_lowercase_characters": cfg.PasswordPolicy.MinLowerCaseCharacters, + "min_uppercase_characters": cfg.PasswordPolicy.MinUpperCaseCharacters, + "min_special_characters": cfg.PasswordPolicy.MinSpecialCharacters, + "banned_passwords_list": bannedPasswordsList, + }, nil +} diff --git a/services/sharing/pkg/revaconfig/config.go b/services/sharing/pkg/revaconfig/config.go index 3854d9b5bc..b1f7e0d46a 100644 --- a/services/sharing/pkg/revaconfig/config.go +++ b/services/sharing/pkg/revaconfig/config.go @@ -14,15 +14,10 @@ import ( // SharingConfigFromStruct will adapt an oCIS config struct into a reva mapstructure to start a reva service. func SharingConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string]interface{}, error) { - var bannedPasswordsList map[string]struct{} - var err error - if cfg.PasswordPolicy.BannedPasswordsList != "" { - bannedPasswordsList, err = readMultilineFile(cfg.PasswordPolicy.BannedPasswordsList) - if err != nil { - err = fmt.Errorf("failed to load the banned passwords from a file %s: %w", cfg.PasswordPolicy.BannedPasswordsList, err) - logger.Err(err).Send() - return nil, err - } + passwordPolicyCfg, err := passwordPolicyConfig(cfg) + if err != nil { + logger.Err(err).Send() + return nil, err } rcfg := map[string]interface{}{ "shared": map[string]interface{}{ @@ -94,16 +89,8 @@ func SharingConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string] "gateway_addr": cfg.Reva.Address, "writeable_share_must_have_password": cfg.WriteableShareMustHavePassword, "public_share_must_have_password": cfg.PublicShareMustHavePassword, - "password_policy": map[string]interface{}{ - "disabled": cfg.PasswordPolicy.Disabled, - "min_digits": cfg.PasswordPolicy.MinDigits, - "min_characters": cfg.PasswordPolicy.MinCharacters, - "min_lowercase_characters": cfg.PasswordPolicy.MinLowerCaseCharacters, - "min_uppercase_characters": cfg.PasswordPolicy.MinUpperCaseCharacters, - "min_special_characters": cfg.PasswordPolicy.MinSpecialCharacters, - "banned_passwords_list": bannedPasswordsList, - }, - "driver": cfg.PublicSharingDriver, + "password_policy": passwordPolicyCfg, + "driver": cfg.PublicSharingDriver, "drivers": map[string]interface{}{ "json": map[string]interface{}{ "file": cfg.PublicSharingDrivers.JSON.File, @@ -185,3 +172,30 @@ func fileExists(path string) bool { } return !info.IsDir() } + +func passwordPolicyConfig(cfg *config.Config) (map[string]interface{}, error) { + _maxCharacters := 72 + if cfg.PasswordPolicy.Disabled { + return map[string]interface{}{ + "max_characters": _maxCharacters, + "banned_passwords_list": nil, + }, nil + } + var bannedPasswordsList map[string]struct{} + var err error + if cfg.PasswordPolicy.BannedPasswordsList != "" { + bannedPasswordsList, err = readMultilineFile(cfg.PasswordPolicy.BannedPasswordsList) + if err != nil { + return nil, fmt.Errorf("failed to load the banned passwords from a file %s: %w", cfg.PasswordPolicy.BannedPasswordsList, err) + } + } + return map[string]interface{}{ + "max_characters": _maxCharacters, + "min_digits": cfg.PasswordPolicy.MinDigits, + "min_characters": cfg.PasswordPolicy.MinCharacters, + "min_lowercase_characters": cfg.PasswordPolicy.MinLowerCaseCharacters, + "min_uppercase_characters": cfg.PasswordPolicy.MinUpperCaseCharacters, + "min_special_characters": cfg.PasswordPolicy.MinSpecialCharacters, + "banned_passwords_list": bannedPasswordsList, + }, nil +} From b2db0c790241f3ca8fe7fde97472192fa938343a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Duffeck?= Date: Tue, 16 Jan 2024 08:06:23 +0100 Subject: [PATCH 02/73] Bump reva to pull in the latest changes --- go.mod | 2 +- go.sum | 4 +- .../sharesstorageprovider.go | 78 ++++++++++------ .../storageprovider/storageprovider.go | 16 +++- .../http/services/owncloud/ocdav/put.go | 90 +++++++++---------- .../http/services/owncloud/ocdav/tus.go | 85 +++++++++--------- .../manager/jsoncs3/sharecache/sharecache.go | 60 +++++++------ .../fs/nextcloud/nextcloud_server_mock.go | 3 +- .../utils/decomposedfs/decomposedfs.go | 11 ++- .../storage/utils/decomposedfs/revisions.go | 13 ++- .../storage/utils/decomposedfs/tree/tree.go | 5 ++ .../pkg/storage/utils/decomposedfs/upload.go | 8 ++ .../utils/decomposedfs/upload/store.go | 26 +++--- .../utils/decomposedfs/upload/upload.go | 10 +-- .../reva/v2/pkg/storage/utils/metadata/cs3.go | 2 + vendor/modules.txt | 2 +- 16 files changed, 238 insertions(+), 177 deletions(-) diff --git a/go.mod b/go.mod index 2d458e658a..381e82365d 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/coreos/go-oidc v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.9.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.18.1-0.20240104084554-e85441869c2b + github.com/cs3org/reva/v2 v2.18.1-0.20240115094008-bde86a38bd77 github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e diff --git a/go.sum b/go.sum index a2d73cb7d0..377e5412ab 100644 --- a/go.sum +++ b/go.sum @@ -1018,8 +1018,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c= github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.18.1-0.20240104084554-e85441869c2b h1:Nh0SZn2MyCWC/gmV6le7e9eVzux9WWGPQ/nECgh/gyg= -github.com/cs3org/reva/v2 v2.18.1-0.20240104084554-e85441869c2b/go.mod h1:QW31Q1IQ9ZCJMFv3u8/SdHSyLfCcSVNcRbqIJj+Y+7o= +github.com/cs3org/reva/v2 v2.18.1-0.20240115094008-bde86a38bd77 h1:wDi6MOBGdd9zyqDSwhm2FBYqkiEVgDUevpMBKQ6zSf4= +github.com/cs3org/reva/v2 v2.18.1-0.20240115094008-bde86a38bd77/go.mod h1:plMbmaHczZbP+1rtV56YCYs5lkmpdRNpj0KZb9BWLus= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go index 7904acc508..012ee4bcef 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/cs3org/reva/v2/pkg/storagespace" + "google.golang.org/genproto/protobuf/field_mask" "google.golang.org/grpc" codes "google.golang.org/grpc/codes" gstatus "google.golang.org/grpc/status" @@ -397,7 +398,7 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora var shareInfo map[string]*provider.ResourceInfo var err error if fetchShares { - receivedShares, shareInfo, err = s.fetchShares(ctx) + receivedShares, shareInfo, err = s.fetchShares(ctx, req.Opaque, []string{}, &fieldmaskpb.FieldMask{ /*TODO mtime and etag only?*/ }) if err != nil { return nil, errors.Wrap(err, "sharesstorageprovider: error calling ListReceivedSharesRequest") } @@ -708,7 +709,7 @@ func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provide if !ok { return nil, fmt.Errorf("missing user in context") } - receivedShares, shareMd, err := s.fetchShares(ctx) + receivedShares, shareMd, err := s.fetchShares(ctx, req.Opaque, req.ArbitraryMetadataKeys, req.FieldMask) if err != nil { return nil, err } @@ -804,7 +805,7 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer // The root is empty, it is filled by mountpoints // so, when accessing the root via /dav/spaces, we need to list the accepted shares with their mountpoint - receivedShares, _, err := s.fetchShares(ctx) + receivedShares, shareMd, err := s.fetchShares(ctx, req.Opaque, req.ArbitraryMetadataKeys, req.FieldMask) if err != nil { return nil, errors.Wrap(err, "sharesstorageprovider: error calling ListReceivedSharesRequest") } @@ -820,31 +821,38 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer continue } - statRes, err := gatewayClient.Stat(ctx, &provider.StatRequest{ - Opaque: req.Opaque, - Ref: &provider.Reference{ - ResourceId: share.Share.ResourceId, - Path: ".", - }, - ArbitraryMetadataKeys: req.ArbitraryMetadataKeys, - }) - switch { - case err != nil: - appctx.GetLogger(ctx).Error(). - Err(err). - Interface("share", share). - Msg("sharesstorageprovider: could not make stat request when listing virtual root, skipping") - continue - case statRes.Status.Code != rpc.Code_CODE_OK: - appctx.GetLogger(ctx).Debug(). - Interface("share", share). - Interface("status", statRes.Status). - Msg("sharesstorageprovider: could not stat share when listing virtual root, skipping") - continue + info := shareMd[share.GetShare().GetId().GetOpaqueId()] + if info == nil { + if share.GetShare().GetResourceId().GetSpaceId() == "" { + // convert backwards compatible share id + share.Share.ResourceId.StorageId, share.Share.ResourceId.SpaceId = storagespace.SplitStorageID(share.GetShare().GetResourceId().GetSpaceId()) + } + statRes, err := gatewayClient.Stat(ctx, &provider.StatRequest{ + Opaque: req.Opaque, + Ref: &provider.Reference{ + ResourceId: share.Share.ResourceId, + Path: ".", + }, + ArbitraryMetadataKeys: req.ArbitraryMetadataKeys, + }) + switch { + case err != nil: + appctx.GetLogger(ctx).Error(). + Err(err). + Interface("share", share). + Msg("sharesstorageprovider: could not make stat request when listing virtual root, skipping") + continue + case statRes.Status.Code != rpc.Code_CODE_OK: + appctx.GetLogger(ctx).Debug(). + Interface("share", share). + Interface("status", statRes.Status). + Msg("sharesstorageprovider: could not stat share when listing virtual root, skipping") + continue + } + info = statRes.Info } - // override info - info := statRes.Info + // override resource id info info.Id = &provider.ResourceId{ StorageId: utils.ShareStorageProviderID, SpaceId: utils.ShareStorageSpaceID, @@ -1067,7 +1075,13 @@ func (s *service) resolveAcceptedShare(ctx context.Context, ref *provider.Refere // look up share for this resourceid lsRes, err := sharingCollaborationClient.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{ Filters: []*collaboration.Filter{ - // FIXME filter by accepted ... and by mountpoint? + { + Type: collaboration.Filter_TYPE_STATE, + Term: &collaboration.Filter_State{ + State: collaboration.ShareState_SHARE_STATE_ACCEPTED, + }, + }, + // TODO filter by mountpoint? }, }) if err != nil { @@ -1077,6 +1091,7 @@ func (s *service) resolveAcceptedShare(ctx context.Context, ref *provider.Refere return nil, lsRes.Status, nil } for _, receivedShare := range lsRes.Shares { + // make sure to skip unaccepted shares if receivedShare.State != collaboration.ShareState_SHARE_STATE_ACCEPTED { continue } @@ -1121,7 +1136,7 @@ func (s *service) rejectReceivedShare(ctx context.Context, receivedShare *collab return errtypes.NewErrtypeFromStatus(res.Status) } -func (s *service) fetchShares(ctx context.Context) ([]*collaboration.ReceivedShare, map[string]*provider.ResourceInfo, error) { +func (s *service) fetchShares(ctx context.Context, opaque *typesv1beta1.Opaque, arbitraryMetadataKeys []string, fieldMask *field_mask.FieldMask) ([]*collaboration.ReceivedShare, map[string]*provider.ResourceInfo, error) { sharingCollaborationClient, err := s.sharingCollaborationSelector.Next() if err != nil { return nil, nil, err @@ -1152,7 +1167,12 @@ func (s *service) fetchShares(ctx context.Context) ([]*collaboration.ReceivedSha // convert backwards compatible share id rs.Share.ResourceId.StorageId, rs.Share.ResourceId.SpaceId = storagespace.SplitStorageID(rs.Share.ResourceId.StorageId) } - sRes, err := gatewayClient.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{ResourceId: rs.Share.ResourceId}}) + sRes, err := gatewayClient.Stat(ctx, &provider.StatRequest{ + Opaque: opaque, + Ref: &provider.Reference{ResourceId: rs.Share.ResourceId}, + ArbitraryMetadataKeys: arbitraryMetadataKeys, + FieldMask: fieldMask, + }) if err != nil { appctx.GetLogger(ctx).Error(). Err(err). diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/storageprovider/storageprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/storageprovider/storageprovider.go index 532854a290..c125698c0b 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/storageprovider/storageprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/storageprovider/storageprovider.go @@ -702,13 +702,27 @@ func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*pro } } - md, err := s.storage.GetMD(ctx, req.Ref, []string{}, []string{"id"}) + md, err := s.storage.GetMD(ctx, req.Ref, []string{}, []string{"id", "status"}) if err != nil { return &provider.DeleteResponse{ Status: status.NewStatusFromErrType(ctx, "can't stat resource to delete", err), }, nil } + if utils.ReadPlainFromOpaque(md.GetOpaque(), "status") == "processing" { + return &provider.DeleteResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_UNAVAILABLE, + Message: "file is processing", + }, + Opaque: &typesv1beta1.Opaque{ + Map: map[string]*typesv1beta1.OpaqueEntry{ + "status": {Decoder: "plain", Value: []byte("processing")}, + }, + }, + }, nil + } + err = s.storage.Delete(ctx, req.Ref) return &provider.DeleteResponse{ diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/put.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/put.go index cb52ea695a..7a6324ce38 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/put.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/put.go @@ -292,58 +292,58 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ } // ony send actual PUT request if file has bytes. Otherwise the initiate file upload request creates the file - // if length != 0 { // FIXME bring back 0 byte file upload handling, see https://github.com/owncloud/ocis/issues/2609 - - var ep, token string - for _, p := range uRes.Protocols { - if p.Protocol == "simple" { - ep, token = p.UploadEndpoint, p.Token + if length != 0 { + var ep, token string + for _, p := range uRes.Protocols { + if p.Protocol == "simple" { + ep, token = p.UploadEndpoint, p.Token + } } - } - httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, ep, r.Body) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return - } - Propagator.Inject(ctx, propagation.HeaderCarrier(httpReq.Header)) - httpReq.Header.Set(datagateway.TokenTransportHeader, token) - - httpRes, err := s.client.Do(httpReq) - if err != nil { - log.Error().Err(err).Msg("error doing PUT request to data service") - w.WriteHeader(http.StatusInternalServerError) - return - } - defer httpRes.Body.Close() - if httpRes.StatusCode != http.StatusOK { - if httpRes.StatusCode == http.StatusPartialContent { - w.WriteHeader(http.StatusPartialContent) + httpReq, err := rhttp.NewRequest(ctx, http.MethodPut, ep, r.Body) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) return } - if httpRes.StatusCode == errtypes.StatusChecksumMismatch { - w.WriteHeader(http.StatusBadRequest) - b, err := errors.Marshal(http.StatusBadRequest, "The computed checksum does not match the one received from the client.", "") - errors.HandleWebdavError(&log, w, b, err) + Propagator.Inject(ctx, propagation.HeaderCarrier(httpReq.Header)) + httpReq.Header.Set(datagateway.TokenTransportHeader, token) + + httpRes, err := s.client.Do(httpReq) + if err != nil { + log.Error().Err(err).Msg("error doing PUT request to data service") + w.WriteHeader(http.StatusInternalServerError) + return + } + defer httpRes.Body.Close() + if httpRes.StatusCode != http.StatusOK { + if httpRes.StatusCode == http.StatusPartialContent { + w.WriteHeader(http.StatusPartialContent) + return + } + if httpRes.StatusCode == errtypes.StatusChecksumMismatch { + w.WriteHeader(http.StatusBadRequest) + b, err := errors.Marshal(http.StatusBadRequest, "The computed checksum does not match the one received from the client.", "") + errors.HandleWebdavError(&log, w, b, err) + return + } + log.Error().Err(err).Msg("PUT request to data server failed") + w.WriteHeader(httpRes.StatusCode) return } - log.Error().Err(err).Msg("PUT request to data server failed") - w.WriteHeader(httpRes.StatusCode) - return - } - // copy headers if they are present - if httpRes.Header.Get(net.HeaderETag) != "" { - w.Header().Set(net.HeaderETag, httpRes.Header.Get(net.HeaderETag)) - } - if httpRes.Header.Get(net.HeaderOCETag) != "" { - w.Header().Set(net.HeaderOCETag, httpRes.Header.Get(net.HeaderOCETag)) - } - if httpRes.Header.Get(net.HeaderOCFileID) != "" { - w.Header().Set(net.HeaderOCFileID, httpRes.Header.Get(net.HeaderOCFileID)) - } - if httpRes.Header.Get(net.HeaderLastModified) != "" { - w.Header().Set(net.HeaderLastModified, httpRes.Header.Get(net.HeaderLastModified)) + // copy headers if they are present + if httpRes.Header.Get(net.HeaderETag) != "" { + w.Header().Set(net.HeaderETag, httpRes.Header.Get(net.HeaderETag)) + } + if httpRes.Header.Get(net.HeaderOCETag) != "" { + w.Header().Set(net.HeaderOCETag, httpRes.Header.Get(net.HeaderOCETag)) + } + if httpRes.Header.Get(net.HeaderOCFileID) != "" { + w.Header().Set(net.HeaderOCFileID, httpRes.Header.Get(net.HeaderOCFileID)) + } + if httpRes.Header.Get(net.HeaderLastModified) != "" { + w.Header().Set(net.HeaderLastModified, httpRes.Header.Get(net.HeaderLastModified)) + } } // file was new diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go index d3592f1ab7..c32f4022a6 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go @@ -252,56 +252,58 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. // for creation-with-upload extension forward bytes to dataprovider // TODO check this really streams if r.Header.Get(net.HeaderContentType) == "application/offset+octet-stream" { - length, err := strconv.ParseInt(r.Header.Get(net.HeaderContentLength), 10, 64) - if err != nil { - log.Debug().Err(err).Msg("wrong request") - w.WriteHeader(http.StatusBadRequest) - return - } - var httpRes *http.Response + finishUpload := true + if uploadLength > 0 { + var httpRes *http.Response - httpReq, err := rhttp.NewRequest(ctx, http.MethodPatch, ep, r.Body) - if err != nil { - log.Debug().Err(err).Msg("wrong request") - w.WriteHeader(http.StatusInternalServerError) - return - } - Propagator.Inject(ctx, propagation.HeaderCarrier(httpReq.Header)) + httpReq, err := rhttp.NewRequest(ctx, http.MethodPatch, ep, r.Body) + if err != nil { + log.Debug().Err(err).Msg("wrong request") + w.WriteHeader(http.StatusInternalServerError) + return + } + Propagator.Inject(ctx, propagation.HeaderCarrier(httpReq.Header)) - httpReq.Header.Set(net.HeaderContentType, r.Header.Get(net.HeaderContentType)) - httpReq.Header.Set(net.HeaderContentLength, r.Header.Get(net.HeaderContentLength)) - if r.Header.Get(net.HeaderUploadOffset) != "" { - httpReq.Header.Set(net.HeaderUploadOffset, r.Header.Get(net.HeaderUploadOffset)) - } else { - httpReq.Header.Set(net.HeaderUploadOffset, "0") - } - httpReq.Header.Set(net.HeaderTusResumable, r.Header.Get(net.HeaderTusResumable)) + httpReq.Header.Set(net.HeaderContentType, r.Header.Get(net.HeaderContentType)) + httpReq.Header.Set(net.HeaderContentLength, r.Header.Get(net.HeaderContentLength)) + if r.Header.Get(net.HeaderUploadOffset) != "" { + httpReq.Header.Set(net.HeaderUploadOffset, r.Header.Get(net.HeaderUploadOffset)) + } else { + httpReq.Header.Set(net.HeaderUploadOffset, "0") + } + httpReq.Header.Set(net.HeaderTusResumable, r.Header.Get(net.HeaderTusResumable)) - httpRes, err = s.client.Do(httpReq) - if err != nil { - log.Error().Err(err).Msg("error doing PATCH request to data gateway") - w.WriteHeader(http.StatusInternalServerError) - return - } - defer httpRes.Body.Close() + httpRes, err = s.client.Do(httpReq) + if err != nil || httpRes == nil { + log.Error().Err(err).Msg("error doing PATCH request to data gateway") + w.WriteHeader(http.StatusInternalServerError) + return + } + defer httpRes.Body.Close() - w.Header().Set(net.HeaderUploadOffset, httpRes.Header.Get(net.HeaderUploadOffset)) - w.Header().Set(net.HeaderTusResumable, httpRes.Header.Get(net.HeaderTusResumable)) - w.Header().Set(net.HeaderTusUploadExpires, httpRes.Header.Get(net.HeaderTusUploadExpires)) - if httpRes.StatusCode != http.StatusNoContent { - w.WriteHeader(httpRes.StatusCode) - return - } + if httpRes.StatusCode != http.StatusNoContent { + w.WriteHeader(httpRes.StatusCode) + return + } - // check if upload was fully completed - if length == 0 || httpRes.Header.Get(net.HeaderUploadOffset) == r.Header.Get(net.HeaderUploadLength) { - // get uploaded file metadata + w.Header().Set(net.HeaderUploadOffset, httpRes.Header.Get(net.HeaderUploadOffset)) + w.Header().Set(net.HeaderTusResumable, httpRes.Header.Get(net.HeaderTusResumable)) + w.Header().Set(net.HeaderTusUploadExpires, httpRes.Header.Get(net.HeaderTusUploadExpires)) + if httpRes.Header.Get(net.HeaderOCMtime) != "" { + w.Header().Set(net.HeaderOCMtime, httpRes.Header.Get(net.HeaderOCMtime)) + } if resid, err := storagespace.ParseID(httpRes.Header.Get(net.HeaderOCFileID)); err == nil { sReq.Ref = &provider.Reference{ ResourceId: &resid, } } + finishUpload = httpRes.Header.Get(net.HeaderUploadOffset) == r.Header.Get(net.HeaderUploadLength) + } + + // check if upload was fully completed + if uploadLength == 0 || finishUpload { + // get uploaded file metadata sRes, err := client.Stat(ctx, sReq) if err != nil { @@ -311,7 +313,6 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. } if sRes.Status.Code != rpc.Code_CODE_OK && sRes.Status.Code != rpc.Code_CODE_NOT_FOUND { - if sRes.Status.Code == rpc.Code_CODE_PERMISSION_DENIED { // the token expired during upload, so the stat failed // and we can't do anything about it. @@ -330,10 +331,6 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. w.WriteHeader(http.StatusInternalServerError) return } - if httpRes != nil && httpRes.Header != nil && httpRes.Header.Get(net.HeaderOCMtime) != "" { - // set the "accepted" value if returned in the upload response headers - w.Header().Set(net.HeaderOCMtime, httpRes.Header.Get(net.HeaderOCMtime)) - } // get WebDav permissions for file isPublic := false diff --git a/vendor/github.com/cs3org/reva/v2/pkg/share/manager/jsoncs3/sharecache/sharecache.go b/vendor/github.com/cs3org/reva/v2/pkg/share/manager/jsoncs3/sharecache/sharecache.go index fe6dfde338..d75061ae04 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/share/manager/jsoncs3/sharecache/sharecache.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/share/manager/jsoncs3/sharecache/sharecache.go @@ -31,6 +31,7 @@ import ( "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/share/manager/jsoncs3/shareid" + "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/mtimesyncedcache" "github.com/cs3org/reva/v2/pkg/storage/utils/metadata" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -45,7 +46,7 @@ const tracerName = "sharecache" type Cache struct { lockMap sync.Map - UserShares map[string]*UserShareCache + UserShares mtimesyncedcache.Map[string, *UserShareCache] storage metadata.Storage namespace string @@ -76,7 +77,7 @@ func (c *Cache) lockUser(userID string) func() { // New returns a new Cache instance func New(s metadata.Storage, namespace, filename string, ttl time.Duration) Cache { return Cache{ - UserShares: map[string]*UserShareCache{}, + UserShares: mtimesyncedcache.Map[string, *UserShareCache]{}, storage: s, namespace: namespace, filename: filename, @@ -93,7 +94,7 @@ func (c *Cache) Add(ctx context.Context, userid, shareID string) error { span.SetAttributes(attribute.String("cs3.userid", userid)) defer unlock() - if c.UserShares[userid] == nil { + if _, ok := c.UserShares.Load(userid); !ok { err := c.syncWithLock(ctx, userid) if err != nil { return err @@ -111,7 +112,8 @@ func (c *Cache) Add(ctx context.Context, userid, shareID string) error { c.initializeIfNeeded(userid, ssid) // add share id - c.UserShares[userid].UserShares[ssid].IDs[shareID] = struct{}{} + us, _ := c.UserShares.Load(userid) + us.UserShares[ssid].IDs[shareID] = struct{}{} return c.Persist(ctx, userid) } @@ -158,7 +160,7 @@ func (c *Cache) Remove(ctx context.Context, userid, shareID string) error { span.SetAttributes(attribute.String("cs3.userid", userid)) defer unlock() - if c.UserShares[userid] == nil { + if _, ok := c.UserShares.Load(userid); ok { err := c.syncWithLock(ctx, userid) if err != nil { return err @@ -173,15 +175,13 @@ func (c *Cache) Remove(ctx context.Context, userid, shareID string) error { ssid := storageid + shareid.IDDelimiter + spaceid persistFunc := func() error { - if c.UserShares[userid] == nil { - c.UserShares[userid] = &UserShareCache{ - UserShares: map[string]*SpaceShareIDs{}, - } - } + us, loaded := c.UserShares.LoadOrStore(userid, &UserShareCache{ + UserShares: map[string]*SpaceShareIDs{}, + }) - if c.UserShares[userid].UserShares[ssid] != nil { + if loaded { // remove share id - delete(c.UserShares[userid].UserShares[ssid].IDs, shareID) + delete(us.UserShares[ssid].IDs, shareID) } return c.Persist(ctx, userid) @@ -234,11 +234,12 @@ func (c *Cache) List(ctx context.Context, userid string) (map[string]SpaceShareI } r := map[string]SpaceShareIDs{} - if c.UserShares[userid] == nil { + us, ok := c.UserShares.Load(userid) + if !ok { return r, nil } - for ssid, cached := range c.UserShares[userid].UserShares { + for ssid, cached := range us.UserShares { r[ssid] = SpaceShareIDs{ IDs: cached.IDs, } @@ -261,8 +262,8 @@ func (c *Cache) syncWithLock(ctx context.Context, userID string) error { dlreq := metadata.DownloadRequest{ Path: userCreatedPath, } - if c.UserShares[userID].Etag != "" { - dlreq.IfNoneMatch = []string{c.UserShares[userID].Etag} + if us, ok := c.UserShares.Load(userID); ok && us.Etag != "" { + dlreq.IfNoneMatch = []string{us.Etag} } dlres, err := c.storage.Download(ctx, dlreq) @@ -290,7 +291,7 @@ func (c *Cache) syncWithLock(ctx context.Context, userID string) error { } newShareCache.Etag = dlres.Etag - c.UserShares[userID] = newShareCache + c.UserShares.Store(userID, newShareCache) span.SetStatus(codes.Ok, "") return nil } @@ -301,7 +302,12 @@ func (c *Cache) Persist(ctx context.Context, userid string) error { defer span.End() span.SetAttributes(attribute.String("cs3.userid", userid)) - createdBytes, err := json.Marshal(c.UserShares[userid]) + us, ok := c.UserShares.Load(userid) + if !ok { + span.SetStatus(codes.Ok, "no user shares") + return nil + } + createdBytes, err := json.Marshal(us) if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) @@ -317,11 +323,11 @@ func (c *Cache) Persist(ctx context.Context, userid string) error { ur := metadata.UploadRequest{ Path: jsonPath, Content: createdBytes, - IfMatchEtag: c.UserShares[userid].Etag, + IfMatchEtag: us.Etag, } // when there is no etag in memory make sure the file has not been created on the server, see https://www.rfc-editor.org/rfc/rfc9110#field.if-match // > If the field value is "*", the condition is false if the origin server has a current representation for the target resource. - if c.UserShares[userid].Etag == "" { + if us.Etag == "" { ur.IfNoneMatch = []string{"*"} } res, err := c.storage.Upload(ctx, ur) @@ -330,7 +336,7 @@ func (c *Cache) Persist(ctx context.Context, userid string) error { span.SetStatus(codes.Error, err.Error()) return err } - c.UserShares[userid].Etag = res.Etag + us.Etag = res.Etag span.SetStatus(codes.Ok, "") return nil } @@ -340,13 +346,11 @@ func (c *Cache) userCreatedPath(userid string) string { } func (c *Cache) initializeIfNeeded(userid, ssid string) { - if c.UserShares[userid] == nil { - c.UserShares[userid] = &UserShareCache{ - UserShares: map[string]*SpaceShareIDs{}, - } - } - if ssid != "" && c.UserShares[userid].UserShares[ssid] == nil { - c.UserShares[userid].UserShares[ssid] = &SpaceShareIDs{ + us, _ := c.UserShares.LoadOrStore(userid, &UserShareCache{ + UserShares: map[string]*SpaceShareIDs{}, + }) + if ssid != "" && us.UserShares[ssid] == nil { + us.UserShares[ssid] = &SpaceShareIDs{ IDs: map[string]struct{}{}, } } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud/nextcloud_server_mock.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud/nextcloud_server_mock.go index 3bb95e02a9..a23b5533f2 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud/nextcloud_server_mock.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/nextcloud/nextcloud_server_mock.go @@ -113,7 +113,8 @@ var responses = map[string]Response{ `POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/GetMD {"ref":{"path":"/file"},"mdKeys":null}`: {404, ``, serverStateEmpty}, `POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/InitiateUpload {"ref":{"path":"/file"},"uploadLength":0,"metadata":{"providerID":""}}`: {200, `{"simple": "yes","tus": "yes"}`, serverStateEmpty}, - `POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/InitiateUpload {"ref":{"resource_id":{"storage_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c"},"path":"/versionedFile"},"uploadLength":0,"metadata":{}}`: {200, `{"simple": "yes","tus": "yes"}`, serverStateEmpty}, + `POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/InitiateUpload {"ref":{"resource_id":{"storage_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c"},"path":"/versionedFile"},"uploadLength":1,"metadata":{}}`: {200, `{"simple": "yes","tus": "yes"}`, serverStateEmpty}, + `POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/InitiateUpload {"ref":{"resource_id":{"storage_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c"},"path":"/versionedFile"},"uploadLength":2,"metadata":{}}`: {200, `{"simple": "yes","tus": "yes"}`, serverStateEmpty}, `POST /apps/sciencemesh/~f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c/api/storage/GetMD {"ref":{"path":"/yes"},"mdKeys":[]}`: {200, `{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/yes"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/yes","permission_set":{},"size":1,"canonical_metadata":{},"arbitrary_metadata":{}}`, serverStateEmpty}, diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go index 7a4e0f173c..6e709dfad7 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -122,7 +122,7 @@ type SessionStore interface { New(ctx context.Context) *upload.OcisSession List(ctx context.Context) ([]*upload.OcisSession, error) Get(ctx context.Context, id string) (*upload.OcisSession, error) - Cleanup(ctx context.Context, session upload.Session, failure bool, keepUpload bool) + Cleanup(ctx context.Context, session upload.Session, revertNodeMetadata, keepUpload, unmarkPostprocessing bool) } // Decomposedfs provides the base for decomposed filesystem implementations @@ -281,7 +281,7 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) { } if !n.Exists { log.Debug().Str("uploadID", ev.UploadID).Str("nodeID", session.NodeID()).Msg("node no longer exists") - fs.sessionStore.Cleanup(ctx, session, false, false) + fs.sessionStore.Cleanup(ctx, session, false, false, false) continue } @@ -289,6 +289,7 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) { failed bool keepUpload bool ) + unmarkPostprocessing := true switch ev.Outcome { default: @@ -301,8 +302,10 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) { case events.PPOutcomeContinue: if err := session.Finalize(); err != nil { log.Error().Err(err).Str("uploadID", ev.UploadID).Msg("could not finalize upload") - keepUpload = true // should we keep the upload when assembling failed? failed = true + keepUpload = true + // keep postprocessing status so the upload is not deleted during housekeeping + unmarkPostprocessing = false } else { metrics.UploadSessionsFinalized.Inc() } @@ -334,7 +337,7 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) { } } - fs.sessionStore.Cleanup(ctx, session, failed, keepUpload) + fs.sessionStore.Cleanup(ctx, session, failed, keepUpload, unmarkPostprocessing) // remove cache entry in gateway fs.cache.RemoveStatContext(ctx, ev.ExecutingUser.GetId(), &provider.ResourceId{SpaceId: n.SpaceID, OpaqueId: n.ID}) diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/revisions.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/revisions.go index 68022aa9f7..c079c3bddb 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/revisions.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/revisions.go @@ -263,10 +263,6 @@ func (fs *Decomposedfs) RestoreRevision(ctx context.Context, ref *provider.Refer // copy blob metadata from restored revision to node restoredRevisionPath := fs.lu.InternalPath(spaceID, revisionKey) err = fs.lu.CopyMetadata(ctx, restoredRevisionPath, nodePath, func(attributeName string, value []byte) (newValue []byte, copy bool) { - if attributeName == prefixes.MTimeAttr { - // update mtime - return []byte(time.Now().UTC().Format(time.RFC3339Nano)), true - } return value, strings.HasPrefix(attributeName, prefixes.ChecksumPrefix) || attributeName == prefixes.TypeAttr || attributeName == prefixes.BlobIDAttr || @@ -275,6 +271,15 @@ func (fs *Decomposedfs) RestoreRevision(ctx context.Context, ref *provider.Refer if err != nil { return errtypes.InternalError("failed to copy blob xattrs to old revision to node: " + err.Error()) } + // always set the node mtime to the current time + err = fs.lu.MetadataBackend().SetMultiple(ctx, nodePath, + map[string][]byte{ + prefixes.MTimeAttr: []byte(time.Now().UTC().Format(time.RFC3339Nano)), + }, + false) + if err != nil { + return errtypes.InternalError("failed to set mtime attribute on node: " + err.Error()) + } revisionSize, err := fs.lu.MetadataBackend().GetInt64(ctx, restoredRevisionPath, prefixes.BlobsizeAttr) if err != nil { diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go index 136a8fb812..dc8643fd28 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go @@ -152,6 +152,11 @@ func (t *Tree) TouchFile(ctx context.Context, n *node.Node, markprocessing bool, if err := n.SetMtimeString(ctx, mtime); err != nil { return errors.Wrap(err, "Decomposedfs: could not set mtime") } + } else { + now := time.Now() + if err := n.SetMtime(ctx, &now); err != nil { + return errors.Wrap(err, "Decomposedfs: could not set mtime") + } } err = n.SetXattrsWithContext(ctx, attributes, true) if err != nil { diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go index 73dfd5496a..d3af49b90a 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go @@ -299,6 +299,14 @@ func (fs *Decomposedfs) InitiateUpload(ctx context.Context, ref *provider.Refere metrics.UploadSessionsInitiated.Inc() + if uploadLength == 0 { + // Directly finish this upload + err = session.FinishUpload(ctx) + if err != nil { + return nil, err + } + } + return map[string]string{ "simple": session.ID(), "tus": session.ID(), diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go index fc6bd47080..ce47905642 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go @@ -150,25 +150,27 @@ type Session interface { ID() string Node(ctx context.Context) (*node.Node, error) Context(ctx context.Context) context.Context - Cleanup(cleanNode, cleanBin, cleanInfo bool) + Cleanup(revertNodeMetadata, cleanBin, cleanInfo bool) } // Cleanup cleans upload metadata, binary data and processing status as necessary -func (store OcisStore) Cleanup(ctx context.Context, session Session, failure bool, keepUpload bool) { +func (store OcisStore) Cleanup(ctx context.Context, session Session, revertNodeMetadata, keepUpload, unmarkPostprocessing bool) { ctx, span := tracer.Start(session.Context(ctx), "Cleanup") defer span.End() - session.Cleanup(failure, !keepUpload, !keepUpload) + session.Cleanup(revertNodeMetadata, !keepUpload, !keepUpload) // unset processing status - n, err := session.Node(ctx) - if err != nil { - appctx.GetLogger(ctx).Info().Str("session", session.ID()).Err(err).Msg("could not read node") - return - } - // FIXME: after cleanup the node might already be deleted ... - if n != nil { // node can be nil when there was an error before it was created (eg. checksum-mismatch) - if err := n.UnmarkProcessing(ctx, session.ID()); err != nil { - appctx.GetLogger(ctx).Info().Str("path", n.InternalPath()).Err(err).Msg("unmarking processing failed") + if unmarkPostprocessing { + n, err := session.Node(ctx) + if err != nil { + appctx.GetLogger(ctx).Info().Str("session", session.ID()).Err(err).Msg("could not read node") + return + } + // FIXME: after cleanup the node might already be deleted ... + if n != nil { // node can be nil when there was an error before it was created (eg. checksum-mismatch) + if err := n.UnmarkProcessing(ctx, session.ID()); err != nil { + appctx.GetLogger(ctx).Info().Str("path", n.InternalPath()).Err(err).Msg("unmarking processing failed") + } } } } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go index 53551696fc..64c3cb047c 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go @@ -177,7 +177,7 @@ func (session *OcisSession) FinishUpload(ctx context.Context) error { err = errtypes.BadRequest("unsupported checksum algorithm: " + parts[0]) } if err != nil { - session.store.Cleanup(ctx, session, true, false) + session.store.Cleanup(ctx, session, true, false, false) return err } } @@ -191,7 +191,7 @@ func (session *OcisSession) FinishUpload(ctx context.Context) error { n, err := session.store.CreateNodeForUpload(session, attrs) if err != nil { - session.store.Cleanup(ctx, session, true, false) + session.store.Cleanup(ctx, session, true, false, true) return err } @@ -223,7 +223,7 @@ func (session *OcisSession) FinishUpload(ctx context.Context) error { if !session.store.async { // handle postprocessing synchronously err = session.Finalize() - session.store.Cleanup(ctx, session, err != nil, false) + session.store.Cleanup(ctx, session, err != nil, false, err == nil) if err != nil { log.Error().Err(err).Msg("failed to upload") return err @@ -312,10 +312,10 @@ func (session *OcisSession) removeNode(ctx context.Context) { } // cleanup cleans up after the upload is finished -func (session *OcisSession) Cleanup(cleanNode, cleanBin, cleanInfo bool) { +func (session *OcisSession) Cleanup(revertNodeMetadata, cleanBin, cleanInfo bool) { ctx := session.Context(context.Background()) - if cleanNode { + if revertNodeMetadata { if session.NodeExists() { p := session.info.MetaData["versionsPath"] n, err := session.Node(ctx) diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/metadata/cs3.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/metadata/cs3.go index 2f0fed087e..c39cae9e0e 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/metadata/cs3.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/metadata/cs3.go @@ -181,6 +181,8 @@ func (cs3 *CS3) Upload(ctx context.Context, req UploadRequest) (*UploadResponse, ifuReq.Opaque = utils.AppendPlainToOpaque(ifuReq.Opaque, "X-OC-Mtime", strconv.Itoa(int(req.MTime.Unix()))+"."+strconv.Itoa(req.MTime.Nanosecond())) } + ifuReq.Opaque = utils.AppendPlainToOpaque(ifuReq.Opaque, net.HeaderUploadLength, strconv.FormatInt(int64(len(req.Content)), 10)) + res, err := client.InitiateFileUpload(ctx, ifuReq) if err != nil { return nil, err diff --git a/vendor/modules.txt b/vendor/modules.txt index 01f00a5f0d..ff3980e056 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -362,7 +362,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1 github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1 github.com/cs3org/go-cs3apis/cs3/tx/v1beta1 github.com/cs3org/go-cs3apis/cs3/types/v1beta1 -# github.com/cs3org/reva/v2 v2.18.1-0.20240104084554-e85441869c2b +# github.com/cs3org/reva/v2 v2.18.1-0.20240115094008-bde86a38bd77 ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime From ab17f4e6d762992e95bf2bc7627df3f26a5c705b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Duffeck?= Date: Tue, 16 Jan 2024 08:50:43 +0100 Subject: [PATCH 03/73] Bump cs3api-validator --- .drone.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.star b/.drone.star index bc6e810c64..d791f28ef2 100644 --- a/.drone.star +++ b/.drone.star @@ -16,7 +16,7 @@ OC_CI_GOLANG = "owncloudci/golang:1.21" OC_CI_NODEJS = "owncloudci/nodejs:%s" OC_CI_PHP = "owncloudci/php:%s" OC_CI_WAIT_FOR = "owncloudci/wait-for:latest" -OC_CS3_API_VALIDATOR = "owncloud/cs3api-validator:0.2.0" +OC_CS3_API_VALIDATOR = "owncloud/cs3api-validator:0.2.1" OC_LITMUS = "owncloudci/litmus:latest" OC_OC_TEST_MIDDLEWARE = "owncloud/owncloud-test-middleware:1.8.8" OC_UBUNTU = "owncloud/ubuntu:20.04" From f1a6f228d8989ad9aa47f14cb2aa60b8a65e2da0 Mon Sep 17 00:00:00 2001 From: Roman Perekhod <2403905@gmail.com> Date: Wed, 17 Jan 2024 08:10:32 +0000 Subject: [PATCH 04/73] Automated changelog update [skip ci] --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26940185a4..e526b04577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ The following sections list the changes for unreleased. * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) * Enhancement - Update reva to latest edge version: [#8100](https://github.com/owncloud/ocis/pull/8100) * Enhancement - Remove deprecated environment variables: [#8149](https://github.com/owncloud/ocis/pull/8149) +* Enhancement - Disable the password policy: [#8152](https://github.com/owncloud/ocis/pull/8152) ## Details @@ -145,6 +146,15 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/issues/8025 https://github.com/owncloud/ocis/pull/8149 +* Enhancement - Disable the password policy: [#8152](https://github.com/owncloud/ocis/pull/8152) + + We reworked and moved disabling the password policy logic from the reva to the + ocis. + + https://github.com/owncloud/ocis/issues/7916 + https://github.com/owncloud/ocis/pull/8152 + https://github.com/cs3org/reva/pull/4453 + # Changelog for [5.0.0-rc.1] (2023-12-27) The following sections list the changes for 5.0.0-rc.1. From 8d7656207ee3b5d692a3a91edf80ec7f54b566d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 06:35:47 +0000 Subject: [PATCH 05/73] build(deps): bump github.com/onsi/ginkgo/v2 from 2.13.2 to 2.14.0 Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.13.2 to 2.14.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.13.2...v2.14.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 6 +- go.sum | 12 +- vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md | 25 + .../github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go | 105 +++- .../v2/internal/output_interceptor_wasm.go | 7 + .../v2/internal/progress_report_wasm.go | 10 + .../onsi/ginkgo/v2/internal/suite.go | 2 +- vendor/github.com/onsi/ginkgo/v2/table_dsl.go | 113 +++- .../github.com/onsi/ginkgo/v2/types/errors.go | 9 + .../onsi/ginkgo/v2/types/version.go | 2 +- .../x/tools/go/ast/astutil/enclosing.go | 8 +- .../x/tools/go/ast/astutil/rewrite.go | 8 +- .../x/tools/go/ast/inspector/typeof.go | 4 +- .../tools/go/internal/packagesdriver/sizes.go | 15 +- vendor/golang.org/x/tools/go/packages/doc.go | 32 +- .../x/tools/go/packages/external.go | 2 +- .../golang.org/x/tools/go/packages/golist.go | 76 +-- .../x/tools/go/packages/golist_overlay.go | 492 ------------------ .../x/tools/go/packages/packages.go | 176 ++++--- .../x/tools/go/types/objectpath/objectpath.go | 131 +---- .../x/tools/internal/event/keys/util.go | 21 + .../x/tools/internal/fastwalk/fastwalk.go | 196 ------- .../internal/fastwalk/fastwalk_darwin.go | 119 ----- .../fastwalk/fastwalk_dirent_fileno.go | 14 - .../internal/fastwalk/fastwalk_dirent_ino.go | 15 - .../fastwalk/fastwalk_dirent_namlen_bsd.go | 14 - .../fastwalk/fastwalk_dirent_namlen_linux.go | 29 -- .../internal/fastwalk/fastwalk_portable.go | 41 -- .../tools/internal/fastwalk/fastwalk_unix.go | 153 ------ .../x/tools/internal/gcimporter/iexport.go | 31 +- .../x/tools/internal/gcimporter/iimport.go | 39 +- .../x/tools/internal/gocommand/invoke.go | 29 +- .../x/tools/internal/gopathwalk/walk.go | 239 ++++++--- .../x/tools/internal/imports/fix.go | 56 +- .../internal/packagesinternal/packages.go | 8 - .../x/tools/internal/typeparams/common.go | 24 +- .../x/tools/internal/typeparams/coretype.go | 8 +- .../internal/typeparams/enabled_go117.go | 12 - .../internal/typeparams/enabled_go118.go | 15 - .../x/tools/internal/typeparams/normalize.go | 20 +- .../internal/typeparams/typeparams_go117.go | 197 ------- .../internal/typeparams/typeparams_go118.go | 151 ------ .../internal/typesinternal/objectpath.go | 24 - .../x/tools/internal/versions/gover.go | 172 ++++++ .../x/tools/internal/versions/types.go | 19 + .../x/tools/internal/versions/types_go121.go | 20 + .../x/tools/internal/versions/types_go122.go | 24 + .../tools/internal/versions/versions_go121.go | 49 ++ .../tools/internal/versions/versions_go122.go | 38 ++ vendor/modules.txt | 8 +- 50 files changed, 1023 insertions(+), 1997 deletions(-) create mode 100644 vendor/github.com/onsi/ginkgo/v2/internal/output_interceptor_wasm.go create mode 100644 vendor/github.com/onsi/ginkgo/v2/internal/progress_report_wasm.go create mode 100644 vendor/golang.org/x/tools/internal/event/keys/util.go delete mode 100644 vendor/golang.org/x/tools/internal/fastwalk/fastwalk.go delete mode 100644 vendor/golang.org/x/tools/internal/fastwalk/fastwalk_darwin.go delete mode 100644 vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_fileno.go delete mode 100644 vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_ino.go delete mode 100644 vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_bsd.go delete mode 100644 vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_linux.go delete mode 100644 vendor/golang.org/x/tools/internal/fastwalk/fastwalk_portable.go delete mode 100644 vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go delete mode 100644 vendor/golang.org/x/tools/internal/typesinternal/objectpath.go create mode 100644 vendor/golang.org/x/tools/internal/versions/gover.go create mode 100644 vendor/golang.org/x/tools/internal/versions/types.go create mode 100644 vendor/golang.org/x/tools/internal/versions/types_go121.go create mode 100644 vendor/golang.org/x/tools/internal/versions/types_go122.go create mode 100644 vendor/golang.org/x/tools/internal/versions/versions_go121.go create mode 100644 vendor/golang.org/x/tools/internal/versions/versions_go122.go diff --git a/go.mod b/go.mod index 7191b66142..c7899f4808 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,7 @@ require ( github.com/oklog/run v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/ginkgo/v2 v2.13.2 + github.com/onsi/ginkgo/v2 v2.14.0 github.com/onsi/gomega v1.30.0 github.com/open-policy-agent/opa v0.60.0 github.com/orcaman/concurrent-map v1.0.0 @@ -334,10 +334,10 @@ require ( go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.23.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/mod v0.13.0 // indirect + golang.org/x/mod v0.14.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.14.0 // indirect + golang.org/x/tools v0.16.1 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect diff --git a/go.sum b/go.sum index 8dd0c246a9..866581d454 100644 --- a/go.sum +++ b/go.sum @@ -1770,8 +1770,8 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= -github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= +github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= +github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= @@ -2229,8 +2229,8 @@ golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2621,8 +2621,8 @@ golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= -golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md index ec91408f99..fbe515639e 100644 --- a/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md +++ b/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md @@ -1,3 +1,28 @@ +## 2.14.0 + +### Features +You can now use `GinkgoTB()` when you need an instance of `testing.TB` to pass to a library. + +Prior to this release table testing only supported generating individual `It`s for each test entry. `DescribeTableSubtree` extends table testing support to entire testing subtrees - under the hood `DescrieTableSubtree` generates a new container for each entry and invokes your function to fill our the container. See the [docs](https://onsi.github.io/ginkgo/#generating-subtree-tables) to learn more. + +- Introduce DescribeTableSubtree [65ec56d] +- add GinkgoTB() to docs [4a2c832] +- Add GinkgoTB() function (#1333) [92b6744] + +### Fixes +- Fix typo in internal/suite.go (#1332) [beb9507] +- Fix typo in docs/index.md (#1319) [4ac3a13] +- allow wasm to compile with ginkgo present (#1311) [b2e5bc5] + +### Maintenance +- Bump golang.org/x/tools from 0.16.0 to 0.16.1 (#1316) [465a8ec] +- Bump actions/setup-go from 4 to 5 (#1313) [eab0e40] +- Bump github/codeql-action from 2 to 3 (#1317) [fbf9724] +- Bump golang.org/x/crypto (#1318) [3ee80ee] +- Bump golang.org/x/tools from 0.14.0 to 0.16.0 (#1306) [123e1d5] +- Bump github.com/onsi/gomega from 1.29.0 to 1.30.0 (#1297) [558f6e0] +- Bump golang.org/x/net from 0.17.0 to 0.19.0 (#1307) [84ff7f3] + ## 2.13.2 ### Fixes diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go index 28447ffdd2..639541a16c 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go @@ -1,7 +1,10 @@ package ginkgo import ( + "testing" + "github.com/onsi/ginkgo/v2/internal/testingtproxy" + "github.com/onsi/ginkgo/v2/types" ) /* @@ -15,7 +18,7 @@ correct line number associated with the failure - though you do not need to use You can learn more here: https://onsi.github.io/ginkgo/#using-third-party-libraries */ func GinkgoT(optionalOffset ...int) FullGinkgoTInterface { - offset := 3 + offset := 1 if len(optionalOffset) > 0 { offset = optionalOffset[0] } @@ -41,21 +44,21 @@ The portion of the interface returned by GinkgoT() that maps onto methods in the type GinkgoTInterface interface { Cleanup(func()) Setenv(kev, value string) - Error(args ...interface{}) - Errorf(format string, args ...interface{}) + Error(args ...any) + Errorf(format string, args ...any) Fail() FailNow() Failed() bool - Fatal(args ...interface{}) - Fatalf(format string, args ...interface{}) + Fatal(args ...any) + Fatalf(format string, args ...any) Helper() - Log(args ...interface{}) - Logf(format string, args ...interface{}) + Log(args ...any) + Logf(format string, args ...any) Name() string Parallel() - Skip(args ...interface{}) + Skip(args ...any) SkipNow() - Skipf(format string, args ...interface{}) + Skipf(format string, args ...any) Skipped() bool TempDir() string } @@ -71,9 +74,9 @@ type FullGinkgoTInterface interface { AddReportEntryVisibilityNever(name string, args ...any) //Prints to the GinkgoWriter - Print(a ...interface{}) - Printf(format string, a ...interface{}) - Println(a ...interface{}) + Print(a ...any) + Printf(format string, a ...any) + Println(a ...any) //Provides access to Ginkgo's color formatting, correctly configured to match the color settings specified in the invocation of ginkgo F(format string, args ...any) string @@ -92,3 +95,81 @@ type FullGinkgoTInterface interface { AttachProgressReporter(func() string) func() } + +/* +GinkgoTB() implements a wrapper that exactly matches the testing.TB interface. + +In go 1.18 a new private() function was added to the testing.TB interface. Any function which accepts testing.TB as input needs to be passed in something that directly implements testing.TB. + +This wrapper satisfies the testing.TB interface and intended to be used as a drop-in replacement with third party libraries that accept testing.TB. + +Similar to GinkgoT(), GinkgoTB() takes an optional offset argument that can be used to get the +correct line number associated with the failure - though you do not need to use this if you call GinkgoHelper() or GinkgoT().Helper() appropriately +*/ +func GinkgoTB(optionalOffset ...int) *GinkgoTBWrapper { + offset := 2 + if len(optionalOffset) > 0 { + offset = optionalOffset[0] + } + return &GinkgoTBWrapper{GinkgoT: GinkgoT(offset)} +} + +type GinkgoTBWrapper struct { + testing.TB + GinkgoT FullGinkgoTInterface +} + +func (g *GinkgoTBWrapper) Cleanup(f func()) { + g.GinkgoT.Cleanup(f) +} +func (g *GinkgoTBWrapper) Error(args ...any) { + g.GinkgoT.Error(args...) +} +func (g *GinkgoTBWrapper) Errorf(format string, args ...any) { + g.GinkgoT.Errorf(format, args...) +} +func (g *GinkgoTBWrapper) Fail() { + g.GinkgoT.Fail() +} +func (g *GinkgoTBWrapper) FailNow() { + g.GinkgoT.FailNow() +} +func (g *GinkgoTBWrapper) Failed() bool { + return g.GinkgoT.Failed() +} +func (g *GinkgoTBWrapper) Fatal(args ...any) { + g.GinkgoT.Fatal(args...) +} +func (g *GinkgoTBWrapper) Fatalf(format string, args ...any) { + g.GinkgoT.Fatalf(format, args...) +} +func (g *GinkgoTBWrapper) Helper() { + types.MarkAsHelper(1) +} +func (g *GinkgoTBWrapper) Log(args ...any) { + g.GinkgoT.Log(args...) +} +func (g *GinkgoTBWrapper) Logf(format string, args ...any) { + g.GinkgoT.Logf(format, args...) +} +func (g *GinkgoTBWrapper) Name() string { + return g.GinkgoT.Name() +} +func (g *GinkgoTBWrapper) Setenv(key, value string) { + g.GinkgoT.Setenv(key, value) +} +func (g *GinkgoTBWrapper) Skip(args ...any) { + g.GinkgoT.Skip(args...) +} +func (g *GinkgoTBWrapper) SkipNow() { + g.GinkgoT.SkipNow() +} +func (g *GinkgoTBWrapper) Skipf(format string, args ...any) { + g.GinkgoT.Skipf(format, args...) +} +func (g *GinkgoTBWrapper) Skipped() bool { + return g.GinkgoT.Skipped() +} +func (g *GinkgoTBWrapper) TempDir() string { + return g.GinkgoT.TempDir() +} diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/output_interceptor_wasm.go b/vendor/github.com/onsi/ginkgo/v2/internal/output_interceptor_wasm.go new file mode 100644 index 0000000000..4c374935b8 --- /dev/null +++ b/vendor/github.com/onsi/ginkgo/v2/internal/output_interceptor_wasm.go @@ -0,0 +1,7 @@ +//go:build wasm + +package internal + +func NewOutputInterceptor() OutputInterceptor { + return &NoopOutputInterceptor{} +} diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/progress_report_wasm.go b/vendor/github.com/onsi/ginkgo/v2/internal/progress_report_wasm.go new file mode 100644 index 0000000000..8c53fe0ada --- /dev/null +++ b/vendor/github.com/onsi/ginkgo/v2/internal/progress_report_wasm.go @@ -0,0 +1,10 @@ +//go:build wasm + +package internal + +import ( + "os" + "syscall" +) + +var PROGRESS_SIGNALS = []os.Signal{syscall.SIGUSR1} diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/suite.go b/vendor/github.com/onsi/ginkgo/v2/internal/suite.go index fe6e8288ad..6746152ec9 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/suite.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/suite.go @@ -79,7 +79,7 @@ func NewSuite() *Suite { func (suite *Suite) Clone() (*Suite, error) { if suite.phase != PhaseBuildTopLevel { - return nil, fmt.Errorf("cnanot clone suite after tree has been built") + return nil, fmt.Errorf("cannot clone suite after tree has been built") } return &Suite{ tree: &TreeNode{}, diff --git a/vendor/github.com/onsi/ginkgo/v2/table_dsl.go b/vendor/github.com/onsi/ginkgo/v2/table_dsl.go index ac9b7abb5e..a3aef821bf 100644 --- a/vendor/github.com/onsi/ginkgo/v2/table_dsl.go +++ b/vendor/github.com/onsi/ginkgo/v2/table_dsl.go @@ -46,7 +46,7 @@ And can explore some Table patterns here: https://onsi.github.io/ginkgo/#table-s */ func DescribeTable(description string, args ...interface{}) bool { GinkgoHelper() - generateTable(description, args...) + generateTable(description, false, args...) return true } @@ -56,7 +56,7 @@ You can focus a table with `FDescribeTable`. This is equivalent to `FDescribe`. func FDescribeTable(description string, args ...interface{}) bool { GinkgoHelper() args = append(args, internal.Focus) - generateTable(description, args...) + generateTable(description, false, args...) return true } @@ -66,7 +66,7 @@ You can mark a table as pending with `PDescribeTable`. This is equivalent to `P func PDescribeTable(description string, args ...interface{}) bool { GinkgoHelper() args = append(args, internal.Pending) - generateTable(description, args...) + generateTable(description, false, args...) return true } @@ -75,6 +75,71 @@ You can mark a table as pending with `XDescribeTable`. This is equivalent to `X */ var XDescribeTable = PDescribeTable +/* +DescribeTableSubtree describes a table-driven spec that generates a set of tests for each entry. + +For example: + + DescribeTableSubtree("a subtree table", + func(url string, code int, message string) { + var resp *http.Response + BeforeEach(func() { + var err error + resp, err = http.Get(url) + Expect(err).NotTo(HaveOccurred()) + DeferCleanup(resp.Body.Close) + }) + + It("should return the expected status code", func() { + Expect(resp.StatusCode).To(Equal(code)) + }) + + It("should return the expected message", func() { + body, err := ioutil.ReadAll(resp.Body) + Expect(err).NotTo(HaveOccurred()) + Expect(string(body)).To(Equal(message)) + }) + }, + Entry("default response", "example.com/response", http.StatusOK, "hello world"), + Entry("missing response", "example.com/missing", http.StatusNotFound, "wat?"), + ) + +Note that you **must** place define an It inside the body function. + +You can learn more about DescribeTableSubtree here: https://onsi.github.io/ginkgo/#table-specs +And can explore some Table patterns here: https://onsi.github.io/ginkgo/#table-specs-patterns +*/ +func DescribeTableSubtree(description string, args ...interface{}) bool { + GinkgoHelper() + generateTable(description, true, args...) + return true +} + +/* +You can focus a table with `FDescribeTableSubtree`. This is equivalent to `FDescribe`. +*/ +func FDescribeTableSubtree(description string, args ...interface{}) bool { + GinkgoHelper() + args = append(args, internal.Focus) + generateTable(description, true, args...) + return true +} + +/* +You can mark a table as pending with `PDescribeTableSubtree`. This is equivalent to `PDescribe`. +*/ +func PDescribeTableSubtree(description string, args ...interface{}) bool { + GinkgoHelper() + args = append(args, internal.Pending) + generateTable(description, true, args...) + return true +} + +/* +You can mark a table as pending with `XDescribeTableSubtree`. This is equivalent to `XDescribe`. +*/ +var XDescribeTableSubtree = PDescribeTableSubtree + /* TableEntry represents an entry in a table test. You generally use the `Entry` constructor. */ @@ -131,14 +196,14 @@ var XEntry = PEntry var contextType = reflect.TypeOf(new(context.Context)).Elem() var specContextType = reflect.TypeOf(new(SpecContext)).Elem() -func generateTable(description string, args ...interface{}) { +func generateTable(description string, isSubtree bool, args ...interface{}) { GinkgoHelper() cl := types.NewCodeLocation(0) containerNodeArgs := []interface{}{cl} entries := []TableEntry{} - var itBody interface{} - var itBodyType reflect.Type + var internalBody interface{} + var internalBodyType reflect.Type var tableLevelEntryDescription interface{} tableLevelEntryDescription = func(args ...interface{}) string { @@ -166,11 +231,11 @@ func generateTable(description string, args ...interface{}) { case t.Kind() == reflect.Func && t.NumOut() == 1 && t.Out(0) == reflect.TypeOf(""): tableLevelEntryDescription = arg case t.Kind() == reflect.Func: - if itBody != nil { + if internalBody != nil { exitIfErr(types.GinkgoErrors.MultipleEntryBodyFunctionsForTable(cl)) } - itBody = arg - itBodyType = reflect.TypeOf(itBody) + internalBody = arg + internalBodyType = reflect.TypeOf(internalBody) default: containerNodeArgs = append(containerNodeArgs, arg) } @@ -200,39 +265,47 @@ func generateTable(description string, args ...interface{}) { err = types.GinkgoErrors.InvalidEntryDescription(entry.codeLocation) } - itNodeArgs := []interface{}{entry.codeLocation} - itNodeArgs = append(itNodeArgs, entry.decorations...) + internalNodeArgs := []interface{}{entry.codeLocation} + internalNodeArgs = append(internalNodeArgs, entry.decorations...) hasContext := false - if itBodyType.NumIn() > 0. { - if itBodyType.In(0).Implements(specContextType) { + if internalBodyType.NumIn() > 0. { + if internalBodyType.In(0).Implements(specContextType) { hasContext = true - } else if itBodyType.In(0).Implements(contextType) && (len(entry.parameters) == 0 || !reflect.TypeOf(entry.parameters[0]).Implements(contextType)) { + } else if internalBodyType.In(0).Implements(contextType) && (len(entry.parameters) == 0 || !reflect.TypeOf(entry.parameters[0]).Implements(contextType)) { hasContext = true } } if err == nil { - err = validateParameters(itBody, entry.parameters, "Table Body function", entry.codeLocation, hasContext) + err = validateParameters(internalBody, entry.parameters, "Table Body function", entry.codeLocation, hasContext) } if hasContext { - itNodeArgs = append(itNodeArgs, func(c SpecContext) { + internalNodeArgs = append(internalNodeArgs, func(c SpecContext) { if err != nil { panic(err) } - invokeFunction(itBody, append([]interface{}{c}, entry.parameters...)) + invokeFunction(internalBody, append([]interface{}{c}, entry.parameters...)) }) + if isSubtree { + exitIfErr(types.GinkgoErrors.ContextsCannotBeUsedInSubtreeTables(cl)) + } } else { - itNodeArgs = append(itNodeArgs, func() { + internalNodeArgs = append(internalNodeArgs, func() { if err != nil { panic(err) } - invokeFunction(itBody, entry.parameters) + invokeFunction(internalBody, entry.parameters) }) } - pushNode(internal.NewNode(deprecationTracker, types.NodeTypeIt, description, itNodeArgs...)) + internalNodeType := types.NodeTypeIt + if isSubtree { + internalNodeType = types.NodeTypeContainer + } + + pushNode(internal.NewNode(deprecationTracker, internalNodeType, description, internalNodeArgs...)) } }) diff --git a/vendor/github.com/onsi/ginkgo/v2/types/errors.go b/vendor/github.com/onsi/ginkgo/v2/types/errors.go index 4fbdc3e9b1..6bb72d00cc 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/errors.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/errors.go @@ -505,6 +505,15 @@ func (g ginkgoErrors) IncorrectVariadicParameterTypeToTableFunction(expected, ac } } +func (g ginkgoErrors) ContextsCannotBeUsedInSubtreeTables(cl CodeLocation) error { + return GinkgoError{ + Heading: "Contexts cannot be used in subtree tables", + Message: "You''ve defined a subtree body function that accepts a context but did not provide one in the table entry. Ginkgo SpecContexts can only be passed in to subject and setup nodes - so if you are trying to implement a spec timeout you should request a context in the It function within your subtree body function, not in the subtree body function itself.", + CodeLocation: cl, + DocLink: "table-specs", + } +} + /* Parallel Synchronization errors */ func (g ginkgoErrors) AggregatedReportUnavailableDueToNodeDisappearing() error { diff --git a/vendor/github.com/onsi/ginkgo/v2/types/version.go b/vendor/github.com/onsi/ginkgo/v2/types/version.go index a4a1524b4f..7015be1286 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/version.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/version.go @@ -1,3 +1,3 @@ package types -const VERSION = "2.13.2" +const VERSION = "2.14.0" diff --git a/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go b/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go index 9fa5aa192c..2c4c4e2328 100644 --- a/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go +++ b/vendor/golang.org/x/tools/go/ast/astutil/enclosing.go @@ -11,8 +11,6 @@ import ( "go/ast" "go/token" "sort" - - "golang.org/x/tools/internal/typeparams" ) // PathEnclosingInterval returns the node that encloses the source @@ -322,7 +320,7 @@ func childrenOf(n ast.Node) []ast.Node { children = append(children, n.Recv) } children = append(children, n.Name) - if tparams := typeparams.ForFuncType(n.Type); tparams != nil { + if tparams := n.Type.TypeParams; tparams != nil { children = append(children, tparams) } if n.Type.Params != nil { @@ -377,7 +375,7 @@ func childrenOf(n ast.Node) []ast.Node { tok(n.Lbrack, len("[")), tok(n.Rbrack, len("]"))) - case *typeparams.IndexListExpr: + case *ast.IndexListExpr: children = append(children, tok(n.Lbrack, len("[")), tok(n.Rbrack, len("]"))) @@ -588,7 +586,7 @@ func NodeDescription(n ast.Node) string { return "decrement statement" case *ast.IndexExpr: return "index expression" - case *typeparams.IndexListExpr: + case *ast.IndexListExpr: return "index list expression" case *ast.InterfaceType: return "interface type" diff --git a/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index f430b21b9b..58934f7663 100644 --- a/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -9,8 +9,6 @@ import ( "go/ast" "reflect" "sort" - - "golang.org/x/tools/internal/typeparams" ) // An ApplyFunc is invoked by Apply for each node n, even if n is nil, @@ -252,7 +250,7 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast. a.apply(n, "X", nil, n.X) a.apply(n, "Index", nil, n.Index) - case *typeparams.IndexListExpr: + case *ast.IndexListExpr: a.apply(n, "X", nil, n.X) a.applyList(n, "Indices") @@ -293,7 +291,7 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast. a.apply(n, "Fields", nil, n.Fields) case *ast.FuncType: - if tparams := typeparams.ForFuncType(n); tparams != nil { + if tparams := n.TypeParams; tparams != nil { a.apply(n, "TypeParams", nil, tparams) } a.apply(n, "Params", nil, n.Params) @@ -408,7 +406,7 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast. case *ast.TypeSpec: a.apply(n, "Doc", nil, n.Doc) a.apply(n, "Name", nil, n.Name) - if tparams := typeparams.ForTypeSpec(n); tparams != nil { + if tparams := n.TypeParams; tparams != nil { a.apply(n, "TypeParams", nil, tparams) } a.apply(n, "Type", nil, n.Type) diff --git a/vendor/golang.org/x/tools/go/ast/inspector/typeof.go b/vendor/golang.org/x/tools/go/ast/inspector/typeof.go index 703c813954..2a872f89d4 100644 --- a/vendor/golang.org/x/tools/go/ast/inspector/typeof.go +++ b/vendor/golang.org/x/tools/go/ast/inspector/typeof.go @@ -12,8 +12,6 @@ package inspector import ( "go/ast" "math" - - "golang.org/x/tools/internal/typeparams" ) const ( @@ -171,7 +169,7 @@ func typeOf(n ast.Node) uint64 { return 1 << nIncDecStmt case *ast.IndexExpr: return 1 << nIndexExpr - case *typeparams.IndexListExpr: + case *ast.IndexListExpr: return 1 << nIndexListExpr case *ast.InterfaceType: return 1 << nInterfaceType diff --git a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go index 0454cdd78e..333676b7cf 100644 --- a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go +++ b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go @@ -13,16 +13,17 @@ import ( "golang.org/x/tools/internal/gocommand" ) -var debug = false - func GetSizesForArgsGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (string, string, error) { inv.Verb = "list" inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"} stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv) var goarch, compiler string if rawErr != nil { - if rawErrMsg := rawErr.Error(); strings.Contains(rawErrMsg, "cannot find main module") || strings.Contains(rawErrMsg, "go.mod file not found") { - // User's running outside of a module. All bets are off. Get GOARCH and guess compiler is gc. + rawErrMsg := rawErr.Error() + if strings.Contains(rawErrMsg, "cannot find main module") || + strings.Contains(rawErrMsg, "go.mod file not found") { + // User's running outside of a module. + // All bets are off. Get GOARCH and guess compiler is gc. // TODO(matloob): Is this a problem in practice? inv.Verb = "env" inv.Args = []string{"GOARCH"} @@ -32,8 +33,12 @@ func GetSizesForArgsGolist(ctx context.Context, inv gocommand.Invocation, gocmdR } goarch = strings.TrimSpace(envout.String()) compiler = "gc" - } else { + } else if friendlyErr != nil { return "", "", friendlyErr + } else { + // This should be unreachable, but be defensive + // in case RunRaw's error results are inconsistent. + return "", "", rawErr } } else { fields := strings.Fields(stdout.String()) diff --git a/vendor/golang.org/x/tools/go/packages/doc.go b/vendor/golang.org/x/tools/go/packages/doc.go index a7a8f73e3d..b2a0b7c6a6 100644 --- a/vendor/golang.org/x/tools/go/packages/doc.go +++ b/vendor/golang.org/x/tools/go/packages/doc.go @@ -5,12 +5,32 @@ /* Package packages loads Go packages for inspection and analysis. -The Load function takes as input a list of patterns and return a list of Package -structs describing individual packages matched by those patterns. -The LoadMode controls the amount of detail in the loaded packages. +The [Load] function takes as input a list of patterns and returns a +list of [Package] values describing individual packages matched by those +patterns. +A [Config] specifies configuration options, the most important of which is +the [LoadMode], which controls the amount of detail in the loaded packages. -Load passes most patterns directly to the underlying build tool, -but all patterns with the prefix "query=", where query is a +Load passes most patterns directly to the underlying build tool. +The default build tool is the go command. +Its supported patterns are described at +https://pkg.go.dev/cmd/go#hdr-Package_lists_and_patterns. + +Load may be used in Go projects that use alternative build systems, by +installing an appropriate "driver" program for the build system and +specifying its location in the GOPACKAGESDRIVER environment variable. +For example, +https://github.com/bazelbuild/rules_go/wiki/Editor-and-tool-integration +explains how to use the driver for Bazel. +The driver program is responsible for interpreting patterns in its +preferred notation and reporting information about the packages that +they identify. +(See driverRequest and driverResponse types for the JSON +schema used by the protocol. +Though the protocol is supported, these types are currently unexported; +see #64608 for a proposal to publish them.) + +Regardless of driver, all patterns with the prefix "query=", where query is a non-empty string of letters from [a-z], are reserved and may be interpreted as query operators. @@ -64,7 +84,7 @@ reported about the loaded packages. See the documentation for type LoadMode for details. Most tools should pass their command-line arguments (after any flags) -uninterpreted to the loader, so that the loader can interpret them +uninterpreted to [Load], so that it can interpret them according to the conventions of the underlying build system. See the Example function for typical usage. */ diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go index 7242a0a7d2..7db1d1293a 100644 --- a/vendor/golang.org/x/tools/go/packages/external.go +++ b/vendor/golang.org/x/tools/go/packages/external.go @@ -12,8 +12,8 @@ import ( "bytes" "encoding/json" "fmt" - exec "golang.org/x/sys/execabs" "os" + "os/exec" "strings" ) diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go index 1f1eade0ac..cd375fbc3c 100644 --- a/vendor/golang.org/x/tools/go/packages/golist.go +++ b/vendor/golang.org/x/tools/go/packages/golist.go @@ -11,6 +11,7 @@ import ( "fmt" "log" "os" + "os/exec" "path" "path/filepath" "reflect" @@ -20,7 +21,6 @@ import ( "sync" "unicode" - exec "golang.org/x/sys/execabs" "golang.org/x/tools/go/internal/packagesdriver" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/packagesinternal" @@ -208,62 +208,6 @@ extractQueries: } } - // Only use go/packages' overlay processing if we're using a Go version - // below 1.16. Otherwise, go list handles it. - if goVersion, err := state.getGoVersion(); err == nil && goVersion < 16 { - modifiedPkgs, needPkgs, err := state.processGolistOverlay(response) - if err != nil { - return nil, err - } - - var containsCandidates []string - if len(containFiles) > 0 { - containsCandidates = append(containsCandidates, modifiedPkgs...) - containsCandidates = append(containsCandidates, needPkgs...) - } - if err := state.addNeededOverlayPackages(response, needPkgs); err != nil { - return nil, err - } - // Check candidate packages for containFiles. - if len(containFiles) > 0 { - for _, id := range containsCandidates { - pkg, ok := response.seenPackages[id] - if !ok { - response.addPackage(&Package{ - ID: id, - Errors: []Error{{ - Kind: ListError, - Msg: fmt.Sprintf("package %s expected but not seen", id), - }}, - }) - continue - } - for _, f := range containFiles { - for _, g := range pkg.GoFiles { - if sameFile(f, g) { - response.addRoot(id) - } - } - } - } - } - // Add root for any package that matches a pattern. This applies only to - // packages that are modified by overlays, since they are not added as - // roots automatically. - for _, pattern := range restPatterns { - match := matchPattern(pattern) - for _, pkgID := range modifiedPkgs { - pkg, ok := response.seenPackages[pkgID] - if !ok { - continue - } - if match(pkg.PkgPath) { - response.addRoot(pkg.ID) - } - } - } - } - sizeswg.Wait() if sizeserr != nil { return nil, sizeserr @@ -271,24 +215,6 @@ extractQueries: return response.dr, nil } -func (state *golistState) addNeededOverlayPackages(response *responseDeduper, pkgs []string) error { - if len(pkgs) == 0 { - return nil - } - dr, err := state.createDriverResponse(pkgs...) - if err != nil { - return err - } - for _, pkg := range dr.Packages { - response.addPackage(pkg) - } - _, needPkgs, err := state.processGolistOverlay(response) - if err != nil { - return err - } - return state.addNeededOverlayPackages(response, needPkgs) -} - func (state *golistState) runContainsQueries(response *responseDeduper, queries []string) error { for _, query := range queries { // TODO(matloob): Do only one query per directory. diff --git a/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/vendor/golang.org/x/tools/go/packages/golist_overlay.go index 9576b472f9..d823c474ad 100644 --- a/vendor/golang.org/x/tools/go/packages/golist_overlay.go +++ b/vendor/golang.org/x/tools/go/packages/golist_overlay.go @@ -6,314 +6,11 @@ package packages import ( "encoding/json" - "fmt" - "go/parser" - "go/token" - "os" "path/filepath" - "regexp" - "sort" - "strconv" - "strings" "golang.org/x/tools/internal/gocommand" ) -// processGolistOverlay provides rudimentary support for adding -// files that don't exist on disk to an overlay. The results can be -// sometimes incorrect. -// TODO(matloob): Handle unsupported cases, including the following: -// - determining the correct package to add given a new import path -func (state *golistState) processGolistOverlay(response *responseDeduper) (modifiedPkgs, needPkgs []string, err error) { - havePkgs := make(map[string]string) // importPath -> non-test package ID - needPkgsSet := make(map[string]bool) - modifiedPkgsSet := make(map[string]bool) - - pkgOfDir := make(map[string][]*Package) - for _, pkg := range response.dr.Packages { - // This is an approximation of import path to id. This can be - // wrong for tests, vendored packages, and a number of other cases. - havePkgs[pkg.PkgPath] = pkg.ID - dir, err := commonDir(pkg.GoFiles) - if err != nil { - return nil, nil, err - } - if dir != "" { - pkgOfDir[dir] = append(pkgOfDir[dir], pkg) - } - } - - // If no new imports are added, it is safe to avoid loading any needPkgs. - // Otherwise, it's hard to tell which package is actually being loaded - // (due to vendoring) and whether any modified package will show up - // in the transitive set of dependencies (because new imports are added, - // potentially modifying the transitive set of dependencies). - var overlayAddsImports bool - - // If both a package and its test package are created by the overlay, we - // need the real package first. Process all non-test files before test - // files, and make the whole process deterministic while we're at it. - var overlayFiles []string - for opath := range state.cfg.Overlay { - overlayFiles = append(overlayFiles, opath) - } - sort.Slice(overlayFiles, func(i, j int) bool { - iTest := strings.HasSuffix(overlayFiles[i], "_test.go") - jTest := strings.HasSuffix(overlayFiles[j], "_test.go") - if iTest != jTest { - return !iTest // non-tests are before tests. - } - return overlayFiles[i] < overlayFiles[j] - }) - for _, opath := range overlayFiles { - contents := state.cfg.Overlay[opath] - base := filepath.Base(opath) - dir := filepath.Dir(opath) - var pkg *Package // if opath belongs to both a package and its test variant, this will be the test variant - var testVariantOf *Package // if opath is a test file, this is the package it is testing - var fileExists bool - isTestFile := strings.HasSuffix(opath, "_test.go") - pkgName, ok := extractPackageName(opath, contents) - if !ok { - // Don't bother adding a file that doesn't even have a parsable package statement - // to the overlay. - continue - } - // If all the overlay files belong to a different package, change the - // package name to that package. - maybeFixPackageName(pkgName, isTestFile, pkgOfDir[dir]) - nextPackage: - for _, p := range response.dr.Packages { - if pkgName != p.Name && p.ID != "command-line-arguments" { - continue - } - for _, f := range p.GoFiles { - if !sameFile(filepath.Dir(f), dir) { - continue - } - // Make sure to capture information on the package's test variant, if needed. - if isTestFile && !hasTestFiles(p) { - // TODO(matloob): Are there packages other than the 'production' variant - // of a package that this can match? This shouldn't match the test main package - // because the file is generated in another directory. - testVariantOf = p - continue nextPackage - } else if !isTestFile && hasTestFiles(p) { - // We're examining a test variant, but the overlaid file is - // a non-test file. Because the overlay implementation - // (currently) only adds a file to one package, skip this - // package, so that we can add the file to the production - // variant of the package. (https://golang.org/issue/36857 - // tracks handling overlays on both the production and test - // variant of a package). - continue nextPackage - } - if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath { - // We have already seen the production version of the - // for which p is a test variant. - if hasTestFiles(p) { - testVariantOf = pkg - } - } - pkg = p - if filepath.Base(f) == base { - fileExists = true - } - } - } - // The overlay could have included an entirely new package or an - // ad-hoc package. An ad-hoc package is one that we have manually - // constructed from inadequate `go list` results for a file= query. - // It will have the ID command-line-arguments. - if pkg == nil || pkg.ID == "command-line-arguments" { - // Try to find the module or gopath dir the file is contained in. - // Then for modules, add the module opath to the beginning. - pkgPath, ok, err := state.getPkgPath(dir) - if err != nil { - return nil, nil, err - } - if !ok { - break - } - var forTest string // only set for x tests - isXTest := strings.HasSuffix(pkgName, "_test") - if isXTest { - forTest = pkgPath - pkgPath += "_test" - } - id := pkgPath - if isTestFile { - if isXTest { - id = fmt.Sprintf("%s [%s.test]", pkgPath, forTest) - } else { - id = fmt.Sprintf("%s [%s.test]", pkgPath, pkgPath) - } - } - if pkg != nil { - // TODO(rstambler): We should change the package's path and ID - // here. The only issue is that this messes with the roots. - } else { - // Try to reclaim a package with the same ID, if it exists in the response. - for _, p := range response.dr.Packages { - if reclaimPackage(p, id, opath, contents) { - pkg = p - break - } - } - // Otherwise, create a new package. - if pkg == nil { - pkg = &Package{ - PkgPath: pkgPath, - ID: id, - Name: pkgName, - Imports: make(map[string]*Package), - } - response.addPackage(pkg) - havePkgs[pkg.PkgPath] = id - // Add the production package's sources for a test variant. - if isTestFile && !isXTest && testVariantOf != nil { - pkg.GoFiles = append(pkg.GoFiles, testVariantOf.GoFiles...) - pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, testVariantOf.CompiledGoFiles...) - // Add the package under test and its imports to the test variant. - pkg.forTest = testVariantOf.PkgPath - for k, v := range testVariantOf.Imports { - pkg.Imports[k] = &Package{ID: v.ID} - } - } - if isXTest { - pkg.forTest = forTest - } - } - } - } - if !fileExists { - pkg.GoFiles = append(pkg.GoFiles, opath) - // TODO(matloob): Adding the file to CompiledGoFiles can exhibit the wrong behavior - // if the file will be ignored due to its build tags. - pkg.CompiledGoFiles = append(pkg.CompiledGoFiles, opath) - modifiedPkgsSet[pkg.ID] = true - } - imports, err := extractImports(opath, contents) - if err != nil { - // Let the parser or type checker report errors later. - continue - } - for _, imp := range imports { - // TODO(rstambler): If the package is an x test and the import has - // a test variant, make sure to replace it. - if _, found := pkg.Imports[imp]; found { - continue - } - overlayAddsImports = true - id, ok := havePkgs[imp] - if !ok { - var err error - id, err = state.resolveImport(dir, imp) - if err != nil { - return nil, nil, err - } - } - pkg.Imports[imp] = &Package{ID: id} - // Add dependencies to the non-test variant version of this package as well. - if testVariantOf != nil { - testVariantOf.Imports[imp] = &Package{ID: id} - } - } - } - - // toPkgPath guesses the package path given the id. - toPkgPath := func(sourceDir, id string) (string, error) { - if i := strings.IndexByte(id, ' '); i >= 0 { - return state.resolveImport(sourceDir, id[:i]) - } - return state.resolveImport(sourceDir, id) - } - - // Now that new packages have been created, do another pass to determine - // the new set of missing packages. - for _, pkg := range response.dr.Packages { - for _, imp := range pkg.Imports { - if len(pkg.GoFiles) == 0 { - return nil, nil, fmt.Errorf("cannot resolve imports for package %q with no Go files", pkg.PkgPath) - } - pkgPath, err := toPkgPath(filepath.Dir(pkg.GoFiles[0]), imp.ID) - if err != nil { - return nil, nil, err - } - if _, ok := havePkgs[pkgPath]; !ok { - needPkgsSet[pkgPath] = true - } - } - } - - if overlayAddsImports { - needPkgs = make([]string, 0, len(needPkgsSet)) - for pkg := range needPkgsSet { - needPkgs = append(needPkgs, pkg) - } - } - modifiedPkgs = make([]string, 0, len(modifiedPkgsSet)) - for pkg := range modifiedPkgsSet { - modifiedPkgs = append(modifiedPkgs, pkg) - } - return modifiedPkgs, needPkgs, err -} - -// resolveImport finds the ID of a package given its import path. -// In particular, it will find the right vendored copy when in GOPATH mode. -func (state *golistState) resolveImport(sourceDir, importPath string) (string, error) { - env, err := state.getEnv() - if err != nil { - return "", err - } - if env["GOMOD"] != "" { - return importPath, nil - } - - searchDir := sourceDir - for { - vendorDir := filepath.Join(searchDir, "vendor") - exists, ok := state.vendorDirs[vendorDir] - if !ok { - info, err := os.Stat(vendorDir) - exists = err == nil && info.IsDir() - state.vendorDirs[vendorDir] = exists - } - - if exists { - vendoredPath := filepath.Join(vendorDir, importPath) - if info, err := os.Stat(vendoredPath); err == nil && info.IsDir() { - // We should probably check for .go files here, but shame on anyone who fools us. - path, ok, err := state.getPkgPath(vendoredPath) - if err != nil { - return "", err - } - if ok { - return path, nil - } - } - } - - // We know we've hit the top of the filesystem when we Dir / and get /, - // or C:\ and get C:\, etc. - next := filepath.Dir(searchDir) - if next == searchDir { - break - } - searchDir = next - } - return importPath, nil -} - -func hasTestFiles(p *Package) bool { - for _, f := range p.GoFiles { - if strings.HasSuffix(f, "_test.go") { - return true - } - } - return false -} - // determineRootDirs returns a mapping from absolute directories that could // contain code to their corresponding import path prefixes. func (state *golistState) determineRootDirs() (map[string]string, error) { @@ -384,192 +81,3 @@ func (state *golistState) determineRootDirsGOPATH() (map[string]string, error) { } return m, nil } - -func extractImports(filename string, contents []byte) ([]string, error) { - f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.ImportsOnly) // TODO(matloob): reuse fileset? - if err != nil { - return nil, err - } - var res []string - for _, imp := range f.Imports { - quotedPath := imp.Path.Value - path, err := strconv.Unquote(quotedPath) - if err != nil { - return nil, err - } - res = append(res, path) - } - return res, nil -} - -// reclaimPackage attempts to reuse a package that failed to load in an overlay. -// -// If the package has errors and has no Name, GoFiles, or Imports, -// then it's possible that it doesn't yet exist on disk. -func reclaimPackage(pkg *Package, id string, filename string, contents []byte) bool { - // TODO(rstambler): Check the message of the actual error? - // It differs between $GOPATH and module mode. - if pkg.ID != id { - return false - } - if len(pkg.Errors) != 1 { - return false - } - if pkg.Name != "" || pkg.ExportFile != "" { - return false - } - if len(pkg.GoFiles) > 0 || len(pkg.CompiledGoFiles) > 0 || len(pkg.OtherFiles) > 0 { - return false - } - if len(pkg.Imports) > 0 { - return false - } - pkgName, ok := extractPackageName(filename, contents) - if !ok { - return false - } - pkg.Name = pkgName - pkg.Errors = nil - return true -} - -func extractPackageName(filename string, contents []byte) (string, bool) { - // TODO(rstambler): Check the message of the actual error? - // It differs between $GOPATH and module mode. - f, err := parser.ParseFile(token.NewFileSet(), filename, contents, parser.PackageClauseOnly) // TODO(matloob): reuse fileset? - if err != nil { - return "", false - } - return f.Name.Name, true -} - -// commonDir returns the directory that all files are in, "" if files is empty, -// or an error if they aren't in the same directory. -func commonDir(files []string) (string, error) { - seen := make(map[string]bool) - for _, f := range files { - seen[filepath.Dir(f)] = true - } - if len(seen) > 1 { - return "", fmt.Errorf("files (%v) are in more than one directory: %v", files, seen) - } - for k := range seen { - // seen has only one element; return it. - return k, nil - } - return "", nil // no files -} - -// It is possible that the files in the disk directory dir have a different package -// name from newName, which is deduced from the overlays. If they all have a different -// package name, and they all have the same package name, then that name becomes -// the package name. -// It returns true if it changes the package name, false otherwise. -func maybeFixPackageName(newName string, isTestFile bool, pkgsOfDir []*Package) { - names := make(map[string]int) - for _, p := range pkgsOfDir { - names[p.Name]++ - } - if len(names) != 1 { - // some files are in different packages - return - } - var oldName string - for k := range names { - oldName = k - } - if newName == oldName { - return - } - // We might have a case where all of the package names in the directory are - // the same, but the overlay file is for an x test, which belongs to its - // own package. If the x test does not yet exist on disk, we may not yet - // have its package name on disk, but we should not rename the packages. - // - // We use a heuristic to determine if this file belongs to an x test: - // The test file should have a package name whose package name has a _test - // suffix or looks like "newName_test". - maybeXTest := strings.HasPrefix(oldName+"_test", newName) || strings.HasSuffix(newName, "_test") - if isTestFile && maybeXTest { - return - } - for _, p := range pkgsOfDir { - p.Name = newName - } -} - -// This function is copy-pasted from -// https://github.com/golang/go/blob/9706f510a5e2754595d716bd64be8375997311fb/src/cmd/go/internal/search/search.go#L360. -// It should be deleted when we remove support for overlays from go/packages. -// -// NOTE: This does not handle any ./... or ./ style queries, as this function -// doesn't know the working directory. -// -// matchPattern(pattern)(name) reports whether -// name matches pattern. Pattern is a limited glob -// pattern in which '...' means 'any string' and there -// is no other special syntax. -// Unfortunately, there are two special cases. Quoting "go help packages": -// -// First, /... at the end of the pattern can match an empty string, -// so that net/... matches both net and packages in its subdirectories, like net/http. -// Second, any slash-separated pattern element containing a wildcard never -// participates in a match of the "vendor" element in the path of a vendored -// package, so that ./... does not match packages in subdirectories of -// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. -// Note, however, that a directory named vendor that itself contains code -// is not a vendored package: cmd/vendor would be a command named vendor, -// and the pattern cmd/... matches it. -func matchPattern(pattern string) func(name string) bool { - // Convert pattern to regular expression. - // The strategy for the trailing /... is to nest it in an explicit ? expression. - // The strategy for the vendor exclusion is to change the unmatchable - // vendor strings to a disallowed code point (vendorChar) and to use - // "(anything but that codepoint)*" as the implementation of the ... wildcard. - // This is a bit complicated but the obvious alternative, - // namely a hand-written search like in most shell glob matchers, - // is too easy to make accidentally exponential. - // Using package regexp guarantees linear-time matching. - - const vendorChar = "\x00" - - if strings.Contains(pattern, vendorChar) { - return func(name string) bool { return false } - } - - re := regexp.QuoteMeta(pattern) - re = replaceVendor(re, vendorChar) - switch { - case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`): - re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)` - case re == vendorChar+`/\.\.\.`: - re = `(/vendor|/` + vendorChar + `/\.\.\.)` - case strings.HasSuffix(re, `/\.\.\.`): - re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?` - } - re = strings.ReplaceAll(re, `\.\.\.`, `[^`+vendorChar+`]*`) - - reg := regexp.MustCompile(`^` + re + `$`) - - return func(name string) bool { - if strings.Contains(name, vendorChar) { - return false - } - return reg.MatchString(replaceVendor(name, vendorChar)) - } -} - -// replaceVendor returns the result of replacing -// non-trailing vendor path elements in x with repl. -func replaceVendor(x, repl string) string { - if !strings.Contains(x, "vendor") { - return x - } - elem := strings.Split(x, "/") - for i := 0; i < len(elem)-1; i++ { - if elem[i] == "vendor" { - elem[i] = repl - } - } - return strings.Join(elem, "/") -} diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go index ece0e7c603..81e9e6a727 100644 --- a/vendor/golang.org/x/tools/go/packages/packages.go +++ b/vendor/golang.org/x/tools/go/packages/packages.go @@ -27,8 +27,8 @@ import ( "golang.org/x/tools/go/gcexportdata" "golang.org/x/tools/internal/gocommand" "golang.org/x/tools/internal/packagesinternal" - "golang.org/x/tools/internal/typeparams" "golang.org/x/tools/internal/typesinternal" + "golang.org/x/tools/internal/versions" ) // A LoadMode controls the amount of detail to return when loading. @@ -258,31 +258,52 @@ type driverResponse struct { // proceeding with further analysis. The PrintErrors function is // provided for convenient display of all errors. func Load(cfg *Config, patterns ...string) ([]*Package, error) { - l := newLoader(cfg) - response, err := defaultDriver(&l.Config, patterns...) + ld := newLoader(cfg) + response, external, err := defaultDriver(&ld.Config, patterns...) if err != nil { return nil, err } - l.sizes = types.SizesFor(response.Compiler, response.Arch) - return l.refine(response) + + ld.sizes = types.SizesFor(response.Compiler, response.Arch) + if ld.sizes == nil && ld.Config.Mode&(NeedTypes|NeedTypesSizes|NeedTypesInfo) != 0 { + // Type size information is needed but unavailable. + if external { + // An external driver may fail to populate the Compiler/GOARCH fields, + // especially since they are relatively new (see #63700). + // Provide a sensible fallback in this case. + ld.sizes = types.SizesFor("gc", runtime.GOARCH) + if ld.sizes == nil { // gccgo-only arch + ld.sizes = types.SizesFor("gc", "amd64") + } + } else { + // Go list should never fail to deliver accurate size information. + // Reject the whole Load since the error is the same for every package. + return nil, fmt.Errorf("can't determine type sizes for compiler %q on GOARCH %q", + response.Compiler, response.Arch) + } + } + + return ld.refine(response) } // defaultDriver is a driver that implements go/packages' fallback behavior. // It will try to request to an external driver, if one exists. If there's // no external driver, or the driver returns a response with NotHandled set, // defaultDriver will fall back to the go list driver. -func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, error) { - driver := findExternalDriver(cfg) - if driver == nil { - driver = goListDriver +// The boolean result indicates that an external driver handled the request. +func defaultDriver(cfg *Config, patterns ...string) (*driverResponse, bool, error) { + if driver := findExternalDriver(cfg); driver != nil { + response, err := driver(cfg, patterns...) + if err != nil { + return nil, false, err + } else if !response.NotHandled { + return response, true, nil + } + // (fall through) } - response, err := driver(cfg, patterns...) - if err != nil { - return response, err - } else if response.NotHandled { - return goListDriver(cfg, patterns...) - } - return response, nil + + response, err := goListDriver(cfg, patterns...) + return response, false, err } // A Package describes a loaded Go package. @@ -411,12 +432,6 @@ func init() { packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError { return p.(*Package).depsErrors } - packagesinternal.GetGoCmdRunner = func(config interface{}) *gocommand.Runner { - return config.(*Config).gocmdRunner - } - packagesinternal.SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) { - config.(*Config).gocmdRunner = runner - } packagesinternal.SetModFile = func(config interface{}, value string) { config.(*Config).modFile = value } @@ -553,7 +568,7 @@ type loaderPackage struct { type loader struct { pkgs map[string]*loaderPackage Config - sizes types.Sizes + sizes types.Sizes // non-nil if needed by mode parseCache map[string]*parseValue parseCacheMu sync.Mutex exportMu sync.Mutex // enforces mutual exclusion of exportdata operations @@ -678,39 +693,38 @@ func (ld *loader) refine(response *driverResponse) ([]*Package, error) { } } - // Materialize the import graph. + if ld.Mode&NeedImports != 0 { + // Materialize the import graph. - const ( - white = 0 // new - grey = 1 // in progress - black = 2 // complete - ) + const ( + white = 0 // new + grey = 1 // in progress + black = 2 // complete + ) - // visit traverses the import graph, depth-first, - // and materializes the graph as Packages.Imports. - // - // Valid imports are saved in the Packages.Import map. - // Invalid imports (cycles and missing nodes) are saved in the importErrors map. - // Thus, even in the presence of both kinds of errors, the Import graph remains a DAG. - // - // visit returns whether the package needs src or has a transitive - // dependency on a package that does. These are the only packages - // for which we load source code. - var stack []*loaderPackage - var visit func(lpkg *loaderPackage) bool - var srcPkgs []*loaderPackage - visit = func(lpkg *loaderPackage) bool { - switch lpkg.color { - case black: - return lpkg.needsrc - case grey: - panic("internal error: grey node") - } - lpkg.color = grey - stack = append(stack, lpkg) // push - stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports - // If NeedImports isn't set, the imports fields will all be zeroed out. - if ld.Mode&NeedImports != 0 { + // visit traverses the import graph, depth-first, + // and materializes the graph as Packages.Imports. + // + // Valid imports are saved in the Packages.Import map. + // Invalid imports (cycles and missing nodes) are saved in the importErrors map. + // Thus, even in the presence of both kinds of errors, + // the Import graph remains a DAG. + // + // visit returns whether the package needs src or has a transitive + // dependency on a package that does. These are the only packages + // for which we load source code. + var stack []*loaderPackage + var visit func(lpkg *loaderPackage) bool + visit = func(lpkg *loaderPackage) bool { + switch lpkg.color { + case black: + return lpkg.needsrc + case grey: + panic("internal error: grey node") + } + lpkg.color = grey + stack = append(stack, lpkg) // push + stubs := lpkg.Imports // the structure form has only stubs with the ID in the Imports lpkg.Imports = make(map[string]*Package, len(stubs)) for importPath, ipkg := range stubs { var importErr error @@ -734,40 +748,39 @@ func (ld *loader) refine(response *driverResponse) ([]*Package, error) { } lpkg.Imports[importPath] = imp.Package } - } - if lpkg.needsrc { - srcPkgs = append(srcPkgs, lpkg) - } - if ld.Mode&NeedTypesSizes != 0 { - lpkg.TypesSizes = ld.sizes - } - stack = stack[:len(stack)-1] // pop - lpkg.color = black - return lpkg.needsrc - } + // Complete type information is required for the + // immediate dependencies of each source package. + if lpkg.needsrc && ld.Mode&NeedTypes != 0 { + for _, ipkg := range lpkg.Imports { + ld.pkgs[ipkg.ID].needtypes = true + } + } - if ld.Mode&NeedImports == 0 { - // We do this to drop the stub import packages that we are not even going to try to resolve. - for _, lpkg := range initial { - lpkg.Imports = nil + // NeedTypeSizes causes TypeSizes to be set even + // on packages for which types aren't needed. + if ld.Mode&NeedTypesSizes != 0 { + lpkg.TypesSizes = ld.sizes + } + stack = stack[:len(stack)-1] // pop + lpkg.color = black + + return lpkg.needsrc } - } else { + // For each initial package, create its import DAG. for _, lpkg := range initial { visit(lpkg) } - } - if ld.Mode&NeedImports != 0 && ld.Mode&NeedTypes != 0 { - for _, lpkg := range srcPkgs { - // Complete type information is required for the - // immediate dependencies of each source package. - for _, ipkg := range lpkg.Imports { - imp := ld.pkgs[ipkg.ID] - imp.needtypes = true - } + + } else { + // !NeedImports: drop the stub (ID-only) import packages + // that we are not even going to try to resolve. + for _, lpkg := range initial { + lpkg.Imports = nil } } + // Load type data and syntax if needed, starting at // the initial packages (roots of the import DAG). if ld.Mode&NeedTypes != 0 || ld.Mode&NeedSyntax != 0 { @@ -1001,10 +1014,11 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { Defs: make(map[*ast.Ident]types.Object), Uses: make(map[*ast.Ident]types.Object), Implicits: make(map[ast.Node]types.Object), + Instances: make(map[*ast.Ident]types.Instance), Scopes: make(map[ast.Node]*types.Scope), Selections: make(map[*ast.SelectorExpr]*types.Selection), } - typeparams.InitInstanceInfo(lpkg.TypesInfo) + versions.InitFileVersions(lpkg.TypesInfo) lpkg.TypesSizes = ld.sizes importer := importerFunc(func(path string) (*types.Package, error) { @@ -1042,7 +1056,7 @@ func (ld *loader) loadPackage(lpkg *loaderPackage) { IgnoreFuncBodies: ld.Mode&NeedDeps == 0 && !lpkg.initial, Error: appendError, - Sizes: ld.sizes, + Sizes: ld.sizes, // may be nil } if lpkg.Module != nil && lpkg.Module.GoVersion != "" { typesinternal.SetGoVersion(tc, "go"+lpkg.Module.GoVersion) diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index fa5834baf7..11d5c8c3ad 100644 --- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -26,13 +26,10 @@ package objectpath import ( "fmt" "go/types" - "sort" "strconv" "strings" - _ "unsafe" "golang.org/x/tools/internal/typeparams" - "golang.org/x/tools/internal/typesinternal" ) // A Path is an opaque name that identifies a types.Object @@ -123,20 +120,7 @@ func For(obj types.Object) (Path, error) { // An Encoder amortizes the cost of encoding the paths of multiple objects. // The zero value of an Encoder is ready to use. type Encoder struct { - scopeMemo map[*types.Scope][]types.Object // memoization of scopeObjects - namedMethodsMemo map[*types.Named][]*types.Func // memoization of namedMethods() - skipMethodSorting bool -} - -// Expose back doors so that gopls can avoid method sorting, which can dominate -// analysis on certain repositories. -// -// TODO(golang/go#61443): remove this. -func init() { - typesinternal.SkipEncoderMethodSorting = func(enc interface{}) { - enc.(*Encoder).skipMethodSorting = true - } - typesinternal.ObjectpathObject = object + scopeMemo map[*types.Scope][]types.Object // memoization of scopeObjects } // For returns the path to an object relative to its package, @@ -239,7 +223,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { // Reject obviously non-viable cases. switch obj := obj.(type) { case *types.TypeName: - if _, ok := obj.Type().(*typeparams.TypeParam); !ok { + if _, ok := obj.Type().(*types.TypeParam); !ok { // With the exception of type parameters, only package-level type names // have a path. return "", fmt.Errorf("no path for %v", obj) @@ -299,7 +283,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { } } else { if named, _ := T.(*types.Named); named != nil { - if r := findTypeParam(obj, typeparams.ForNamed(named), path, nil); r != nil { + if r := findTypeParam(obj, named.TypeParams(), path, nil); r != nil { // generic named type return Path(r), nil } @@ -328,31 +312,18 @@ func (enc *Encoder) For(obj types.Object) (Path, error) { // Inspect declared methods of defined types. if T, ok := o.Type().(*types.Named); ok { path = append(path, opType) - if !enc.skipMethodSorting { - // Note that method index here is always with respect - // to canonical ordering of methods, regardless of how - // they appear in the underlying type. - for i, m := range enc.namedMethods(T) { - path2 := appendOpArg(path, opMethod, i) - if m == obj { - return Path(path2), nil // found declared method - } - if r := find(obj, m.Type(), append(path2, opType), nil); r != nil { - return Path(r), nil - } + // The method index here is always with respect + // to the underlying go/types data structures, + // which ultimately derives from source order + // and must be preserved by export data. + for i := 0; i < T.NumMethods(); i++ { + m := T.Method(i) + path2 := appendOpArg(path, opMethod, i) + if m == obj { + return Path(path2), nil // found declared method } - } else { - // This branch must match the logic in the branch above, using go/types - // APIs without sorting. - for i := 0; i < T.NumMethods(); i++ { - m := T.Method(i) - path2 := appendOpArg(path, opMethod, i) - if m == obj { - return Path(path2), nil // found declared method - } - if r := find(obj, m.Type(), append(path2, opType), nil); r != nil { - return Path(r), nil - } + if r := find(obj, m.Type(), append(path2, opType), nil); r != nil { + return Path(r), nil } } } @@ -448,22 +419,13 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) { path = append(path, name...) path = append(path, opType) - if !enc.skipMethodSorting { - for i, m := range enc.namedMethods(named) { - if m == meth { - path = appendOpArg(path, opMethod, i) - return Path(path), true - } - } - } else { - // This branch must match the logic of the branch above, using go/types - // APIs without sorting. - for i := 0; i < named.NumMethods(); i++ { - m := named.Method(i) - if m == meth { - path = appendOpArg(path, opMethod, i) - return Path(path), true - } + // Method indices are w.r.t. the go/types data structures, + // ultimately deriving from source order, + // which is preserved by export data. + for i := 0; i < named.NumMethods(); i++ { + if named.Method(i) == meth { + path = appendOpArg(path, opMethod, i) + return Path(path), true } } @@ -500,7 +462,7 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] } return find(obj, T.Elem(), append(path, opElem), seen) case *types.Signature: - if r := findTypeParam(obj, typeparams.ForSignature(T), path, seen); r != nil { + if r := findTypeParam(obj, T.TypeParams(), path, seen); r != nil { return r } if r := find(obj, T.Params(), append(path, opParams), seen); r != nil { @@ -543,7 +505,7 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] } } return nil - case *typeparams.TypeParam: + case *types.TypeParam: name := T.Obj() if name == obj { return append(path, opObj) @@ -563,7 +525,7 @@ func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName] panic(T) } -func findTypeParam(obj types.Object, list *typeparams.TypeParamList, path []byte, seen map[*types.TypeName]bool) []byte { +func findTypeParam(obj types.Object, list *types.TypeParamList, path []byte, seen map[*types.TypeName]bool) []byte { for i := 0; i < list.Len(); i++ { tparam := list.At(i) path2 := appendOpArg(path, opTypeParam, i) @@ -576,12 +538,7 @@ func findTypeParam(obj types.Object, list *typeparams.TypeParamList, path []byte // Object returns the object denoted by path p within the package pkg. func Object(pkg *types.Package, p Path) (types.Object, error) { - return object(pkg, string(p), false) -} - -// Note: the skipMethodSorting parameter must match the value of -// Encoder.skipMethodSorting used during encoding. -func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.Object, error) { + pathstr := string(p) if pathstr == "" { return nil, fmt.Errorf("empty path") } @@ -605,7 +562,7 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O } // abstraction of *types.{Named,Signature} type hasTypeParams interface { - TypeParams() *typeparams.TypeParamList + TypeParams() *types.TypeParamList } // abstraction of *types.{Named,TypeParam} type hasObj interface { @@ -707,7 +664,7 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O t = tparams.At(index) case opConstraint: - tparam, ok := t.(*typeparams.TypeParam) + tparam, ok := t.(*types.TypeParam) if !ok { return nil, fmt.Errorf("cannot apply %q to %s (got %T, want type parameter)", code, t, t) } @@ -747,12 +704,7 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O if index >= t.NumMethods() { return nil, fmt.Errorf("method index %d out of range [0-%d)", index, t.NumMethods()) } - if skipMethodSorting { - obj = t.Method(index) - } else { - methods := namedMethods(t) // (unmemoized) - obj = methods[index] // Id-ordered - } + obj = t.Method(index) default: return nil, fmt.Errorf("cannot apply %q to %s (got %T, want interface or named)", code, t, t) @@ -779,33 +731,6 @@ func object(pkg *types.Package, pathstr string, skipMethodSorting bool) (types.O return obj, nil // success } -// namedMethods returns the methods of a Named type in ascending Id order. -func namedMethods(named *types.Named) []*types.Func { - methods := make([]*types.Func, named.NumMethods()) - for i := range methods { - methods[i] = named.Method(i) - } - sort.Slice(methods, func(i, j int) bool { - return methods[i].Id() < methods[j].Id() - }) - return methods -} - -// namedMethods is a memoization of the namedMethods function. Callers must not modify the result. -func (enc *Encoder) namedMethods(named *types.Named) []*types.Func { - m := enc.namedMethodsMemo - if m == nil { - m = make(map[*types.Named][]*types.Func) - enc.namedMethodsMemo = m - } - methods, ok := m[named] - if !ok { - methods = namedMethods(named) // allocates and sorts - m[named] = methods - } - return methods -} - // scopeObjects is a memoization of scope objects. // Callers must not modify the result. func (enc *Encoder) scopeObjects(scope *types.Scope) []types.Object { diff --git a/vendor/golang.org/x/tools/internal/event/keys/util.go b/vendor/golang.org/x/tools/internal/event/keys/util.go new file mode 100644 index 0000000000..c0e8e731c9 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/event/keys/util.go @@ -0,0 +1,21 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package keys + +import ( + "sort" + "strings" +) + +// Join returns a canonical join of the keys in S: +// a sorted comma-separated string list. +func Join[S ~[]T, T ~string](s S) string { + strs := make([]string, 0, len(s)) + for _, v := range s { + strs = append(strs, string(v)) + } + sort.Strings(strs) + return strings.Join(strs, ",") +} diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk.go deleted file mode 100644 index c40c7e9310..0000000000 --- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk.go +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package fastwalk provides a faster version of [filepath.Walk] for file system -// scanning tools. -package fastwalk - -import ( - "errors" - "os" - "path/filepath" - "runtime" - "sync" -) - -// ErrTraverseLink is used as a return value from WalkFuncs to indicate that the -// symlink named in the call may be traversed. -var ErrTraverseLink = errors.New("fastwalk: traverse symlink, assuming target is a directory") - -// ErrSkipFiles is a used as a return value from WalkFuncs to indicate that the -// callback should not be called for any other files in the current directory. -// Child directories will still be traversed. -var ErrSkipFiles = errors.New("fastwalk: skip remaining files in directory") - -// Walk is a faster implementation of [filepath.Walk]. -// -// [filepath.Walk]'s design necessarily calls [os.Lstat] on each file, -// even if the caller needs less info. -// Many tools need only the type of each file. -// On some platforms, this information is provided directly by the readdir -// system call, avoiding the need to stat each file individually. -// fastwalk_unix.go contains a fork of the syscall routines. -// -// See golang.org/issue/16399. -// -// Walk walks the file tree rooted at root, calling walkFn for -// each file or directory in the tree, including root. -// -// If Walk returns [filepath.SkipDir], the directory is skipped. -// -// Unlike [filepath.Walk]: -// - file stat calls must be done by the user. -// The only provided metadata is the file type, which does not include -// any permission bits. -// - multiple goroutines stat the filesystem concurrently. The provided -// walkFn must be safe for concurrent use. -// - Walk can follow symlinks if walkFn returns the TraverseLink -// sentinel error. It is the walkFn's responsibility to prevent -// Walk from going into symlink cycles. -func Walk(root string, walkFn func(path string, typ os.FileMode) error) error { - // TODO(bradfitz): make numWorkers configurable? We used a - // minimum of 4 to give the kernel more info about multiple - // things we want, in hopes its I/O scheduling can take - // advantage of that. Hopefully most are in cache. Maybe 4 is - // even too low of a minimum. Profile more. - numWorkers := 4 - if n := runtime.NumCPU(); n > numWorkers { - numWorkers = n - } - - // Make sure to wait for all workers to finish, otherwise - // walkFn could still be called after returning. This Wait call - // runs after close(e.donec) below. - var wg sync.WaitGroup - defer wg.Wait() - - w := &walker{ - fn: walkFn, - enqueuec: make(chan walkItem, numWorkers), // buffered for performance - workc: make(chan walkItem, numWorkers), // buffered for performance - donec: make(chan struct{}), - - // buffered for correctness & not leaking goroutines: - resc: make(chan error, numWorkers), - } - defer close(w.donec) - - for i := 0; i < numWorkers; i++ { - wg.Add(1) - go w.doWork(&wg) - } - todo := []walkItem{{dir: root}} - out := 0 - for { - workc := w.workc - var workItem walkItem - if len(todo) == 0 { - workc = nil - } else { - workItem = todo[len(todo)-1] - } - select { - case workc <- workItem: - todo = todo[:len(todo)-1] - out++ - case it := <-w.enqueuec: - todo = append(todo, it) - case err := <-w.resc: - out-- - if err != nil { - return err - } - if out == 0 && len(todo) == 0 { - // It's safe to quit here, as long as the buffered - // enqueue channel isn't also readable, which might - // happen if the worker sends both another unit of - // work and its result before the other select was - // scheduled and both w.resc and w.enqueuec were - // readable. - select { - case it := <-w.enqueuec: - todo = append(todo, it) - default: - return nil - } - } - } - } -} - -// doWork reads directories as instructed (via workc) and runs the -// user's callback function. -func (w *walker) doWork(wg *sync.WaitGroup) { - defer wg.Done() - for { - select { - case <-w.donec: - return - case it := <-w.workc: - select { - case <-w.donec: - return - case w.resc <- w.walk(it.dir, !it.callbackDone): - } - } - } -} - -type walker struct { - fn func(path string, typ os.FileMode) error - - donec chan struct{} // closed on fastWalk's return - workc chan walkItem // to workers - enqueuec chan walkItem // from workers - resc chan error // from workers -} - -type walkItem struct { - dir string - callbackDone bool // callback already called; don't do it again -} - -func (w *walker) enqueue(it walkItem) { - select { - case w.enqueuec <- it: - case <-w.donec: - } -} - -func (w *walker) onDirEnt(dirName, baseName string, typ os.FileMode) error { - joined := dirName + string(os.PathSeparator) + baseName - if typ == os.ModeDir { - w.enqueue(walkItem{dir: joined}) - return nil - } - - err := w.fn(joined, typ) - if typ == os.ModeSymlink { - if err == ErrTraverseLink { - // Set callbackDone so we don't call it twice for both the - // symlink-as-symlink and the symlink-as-directory later: - w.enqueue(walkItem{dir: joined, callbackDone: true}) - return nil - } - if err == filepath.SkipDir { - // Permit SkipDir on symlinks too. - return nil - } - } - return err -} - -func (w *walker) walk(root string, runUserCallback bool) error { - if runUserCallback { - err := w.fn(root, os.ModeDir) - if err == filepath.SkipDir { - return nil - } - if err != nil { - return err - } - } - - return readDir(root, w.onDirEnt) -} diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_darwin.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_darwin.go deleted file mode 100644 index 0ca55e0d56..0000000000 --- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_darwin.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build darwin && cgo -// +build darwin,cgo - -package fastwalk - -/* -#include - -// fastwalk_readdir_r wraps readdir_r so that we don't have to pass a dirent** -// result pointer which triggers CGO's "Go pointer to Go pointer" check unless -// we allocat the result dirent* with malloc. -// -// fastwalk_readdir_r returns 0 on success, -1 upon reaching the end of the -// directory, or a positive error number to indicate failure. -static int fastwalk_readdir_r(DIR *fd, struct dirent *entry) { - struct dirent *result; - int ret = readdir_r(fd, entry, &result); - if (ret == 0 && result == NULL) { - ret = -1; // EOF - } - return ret; -} -*/ -import "C" - -import ( - "os" - "syscall" - "unsafe" -) - -func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error { - fd, err := openDir(dirName) - if err != nil { - return &os.PathError{Op: "opendir", Path: dirName, Err: err} - } - defer C.closedir(fd) - - skipFiles := false - var dirent syscall.Dirent - for { - ret := int(C.fastwalk_readdir_r(fd, (*C.struct_dirent)(unsafe.Pointer(&dirent)))) - if ret != 0 { - if ret == -1 { - break // EOF - } - if ret == int(syscall.EINTR) { - continue - } - return &os.PathError{Op: "readdir", Path: dirName, Err: syscall.Errno(ret)} - } - if dirent.Ino == 0 { - continue - } - typ := dtToType(dirent.Type) - if skipFiles && typ.IsRegular() { - continue - } - name := (*[len(syscall.Dirent{}.Name)]byte)(unsafe.Pointer(&dirent.Name))[:] - name = name[:dirent.Namlen] - for i, c := range name { - if c == 0 { - name = name[:i] - break - } - } - // Check for useless names before allocating a string. - if string(name) == "." || string(name) == ".." { - continue - } - if err := fn(dirName, string(name), typ); err != nil { - if err != ErrSkipFiles { - return err - } - skipFiles = true - } - } - - return nil -} - -func dtToType(typ uint8) os.FileMode { - switch typ { - case syscall.DT_BLK: - return os.ModeDevice - case syscall.DT_CHR: - return os.ModeDevice | os.ModeCharDevice - case syscall.DT_DIR: - return os.ModeDir - case syscall.DT_FIFO: - return os.ModeNamedPipe - case syscall.DT_LNK: - return os.ModeSymlink - case syscall.DT_REG: - return 0 - case syscall.DT_SOCK: - return os.ModeSocket - } - return ^os.FileMode(0) -} - -// openDir wraps opendir(3) and handles any EINTR errors. The returned *DIR -// needs to be closed with closedir(3). -func openDir(path string) (*C.DIR, error) { - name, err := syscall.BytePtrFromString(path) - if err != nil { - return nil, err - } - for { - fd, err := C.opendir((*C.char)(unsafe.Pointer(name))) - if err != syscall.EINTR { - return fd, err - } - } -} diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_fileno.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_fileno.go deleted file mode 100644 index d58595dbd3..0000000000 --- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_fileno.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build freebsd || openbsd || netbsd -// +build freebsd openbsd netbsd - -package fastwalk - -import "syscall" - -func direntInode(dirent *syscall.Dirent) uint64 { - return uint64(dirent.Fileno) -} diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_ino.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_ino.go deleted file mode 100644 index d3922890b0..0000000000 --- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_ino.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (linux || (darwin && !cgo)) && !appengine -// +build linux darwin,!cgo -// +build !appengine - -package fastwalk - -import "syscall" - -func direntInode(dirent *syscall.Dirent) uint64 { - return dirent.Ino -} diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_bsd.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_bsd.go deleted file mode 100644 index 38a4db6af3..0000000000 --- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_bsd.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (darwin && !cgo) || freebsd || openbsd || netbsd -// +build darwin,!cgo freebsd openbsd netbsd - -package fastwalk - -import "syscall" - -func direntNamlen(dirent *syscall.Dirent) uint64 { - return uint64(dirent.Namlen) -} diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_linux.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_linux.go deleted file mode 100644 index c82e57df85..0000000000 --- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_dirent_namlen_linux.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux && !appengine -// +build linux,!appengine - -package fastwalk - -import ( - "bytes" - "syscall" - "unsafe" -) - -func direntNamlen(dirent *syscall.Dirent) uint64 { - const fixedHdr = uint16(unsafe.Offsetof(syscall.Dirent{}.Name)) - nameBuf := (*[unsafe.Sizeof(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])) - const nameBufLen = uint16(len(nameBuf)) - limit := dirent.Reclen - fixedHdr - if limit > nameBufLen { - limit = nameBufLen - } - nameLen := bytes.IndexByte(nameBuf[:limit], 0) - if nameLen < 0 { - panic("failed to find terminating 0 byte in dirent") - } - return uint64(nameLen) -} diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_portable.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_portable.go deleted file mode 100644 index 27e860243e..0000000000 --- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_portable.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build appengine || (!linux && !darwin && !freebsd && !openbsd && !netbsd) -// +build appengine !linux,!darwin,!freebsd,!openbsd,!netbsd - -package fastwalk - -import ( - "os" -) - -// readDir calls fn for each directory entry in dirName. -// It does not descend into directories or follow symlinks. -// If fn returns a non-nil error, readDir returns with that error -// immediately. -func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error { - fis, err := os.ReadDir(dirName) - if err != nil { - return err - } - skipFiles := false - for _, fi := range fis { - info, err := fi.Info() - if err != nil { - return err - } - if info.Mode().IsRegular() && skipFiles { - continue - } - if err := fn(dirName, fi.Name(), info.Mode()&os.ModeType); err != nil { - if err == ErrSkipFiles { - skipFiles = true - continue - } - return err - } - } - return nil -} diff --git a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go b/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go deleted file mode 100644 index f12f1a734c..0000000000 --- a/vendor/golang.org/x/tools/internal/fastwalk/fastwalk_unix.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build (linux || freebsd || openbsd || netbsd || (darwin && !cgo)) && !appengine -// +build linux freebsd openbsd netbsd darwin,!cgo -// +build !appengine - -package fastwalk - -import ( - "fmt" - "os" - "syscall" - "unsafe" -) - -const blockSize = 8 << 10 - -// unknownFileMode is a sentinel (and bogus) os.FileMode -// value used to represent a syscall.DT_UNKNOWN Dirent.Type. -const unknownFileMode os.FileMode = os.ModeNamedPipe | os.ModeSocket | os.ModeDevice - -func readDir(dirName string, fn func(dirName, entName string, typ os.FileMode) error) error { - fd, err := open(dirName, 0, 0) - if err != nil { - return &os.PathError{Op: "open", Path: dirName, Err: err} - } - defer syscall.Close(fd) - - // The buffer must be at least a block long. - buf := make([]byte, blockSize) // stack-allocated; doesn't escape - bufp := 0 // starting read position in buf - nbuf := 0 // end valid data in buf - skipFiles := false - for { - if bufp >= nbuf { - bufp = 0 - nbuf, err = readDirent(fd, buf) - if err != nil { - return os.NewSyscallError("readdirent", err) - } - if nbuf <= 0 { - return nil - } - } - consumed, name, typ := parseDirEnt(buf[bufp:nbuf]) - bufp += consumed - if name == "" || name == "." || name == ".." { - continue - } - // Fallback for filesystems (like old XFS) that don't - // support Dirent.Type and have DT_UNKNOWN (0) there - // instead. - if typ == unknownFileMode { - fi, err := os.Lstat(dirName + "/" + name) - if err != nil { - // It got deleted in the meantime. - if os.IsNotExist(err) { - continue - } - return err - } - typ = fi.Mode() & os.ModeType - } - if skipFiles && typ.IsRegular() { - continue - } - if err := fn(dirName, name, typ); err != nil { - if err == ErrSkipFiles { - skipFiles = true - continue - } - return err - } - } -} - -func parseDirEnt(buf []byte) (consumed int, name string, typ os.FileMode) { - // golang.org/issue/37269 - dirent := &syscall.Dirent{} - copy((*[unsafe.Sizeof(syscall.Dirent{})]byte)(unsafe.Pointer(dirent))[:], buf) - if v := unsafe.Offsetof(dirent.Reclen) + unsafe.Sizeof(dirent.Reclen); uintptr(len(buf)) < v { - panic(fmt.Sprintf("buf size of %d smaller than dirent header size %d", len(buf), v)) - } - if len(buf) < int(dirent.Reclen) { - panic(fmt.Sprintf("buf size %d < record length %d", len(buf), dirent.Reclen)) - } - consumed = int(dirent.Reclen) - if direntInode(dirent) == 0 { // File absent in directory. - return - } - switch dirent.Type { - case syscall.DT_REG: - typ = 0 - case syscall.DT_DIR: - typ = os.ModeDir - case syscall.DT_LNK: - typ = os.ModeSymlink - case syscall.DT_BLK: - typ = os.ModeDevice - case syscall.DT_FIFO: - typ = os.ModeNamedPipe - case syscall.DT_SOCK: - typ = os.ModeSocket - case syscall.DT_UNKNOWN: - typ = unknownFileMode - default: - // Skip weird things. - // It's probably a DT_WHT (http://lwn.net/Articles/325369/) - // or something. Revisit if/when this package is moved outside - // of goimports. goimports only cares about regular files, - // symlinks, and directories. - return - } - - nameBuf := (*[unsafe.Sizeof(dirent.Name)]byte)(unsafe.Pointer(&dirent.Name[0])) - nameLen := direntNamlen(dirent) - - // Special cases for common things: - if nameLen == 1 && nameBuf[0] == '.' { - name = "." - } else if nameLen == 2 && nameBuf[0] == '.' && nameBuf[1] == '.' { - name = ".." - } else { - name = string(nameBuf[:nameLen]) - } - return -} - -// According to https://golang.org/doc/go1.14#runtime -// A consequence of the implementation of preemption is that on Unix systems, including Linux and macOS -// systems, programs built with Go 1.14 will receive more signals than programs built with earlier releases. -// -// This causes syscall.Open and syscall.ReadDirent sometimes fail with EINTR errors. -// We need to retry in this case. -func open(path string, mode int, perm uint32) (fd int, err error) { - for { - fd, err := syscall.Open(path, mode, perm) - if err != syscall.EINTR { - return fd, err - } - } -} - -func readDirent(fd int, buf []byte) (n int, err error) { - for { - nbuf, err := syscall.ReadDirent(fd, buf) - if err != syscall.EINTR { - return nbuf, err - } - } -} diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go index 6103dd7102..2ee8c70164 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iexport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iexport.go @@ -24,7 +24,6 @@ import ( "golang.org/x/tools/go/types/objectpath" "golang.org/x/tools/internal/tokeninternal" - "golang.org/x/tools/internal/typeparams" ) // IExportShallow encodes "shallow" export data for the specified package. @@ -481,7 +480,7 @@ func (p *iexporter) doDecl(obj types.Object) { } // Function. - if typeparams.ForSignature(sig).Len() == 0 { + if sig.TypeParams().Len() == 0 { w.tag('F') } else { w.tag('G') @@ -494,7 +493,7 @@ func (p *iexporter) doDecl(obj types.Object) { // // While importing the type parameters, tparamList computes and records // their export name, so that it can be later used when writing the index. - if tparams := typeparams.ForSignature(sig); tparams.Len() > 0 { + if tparams := sig.TypeParams(); tparams.Len() > 0 { w.tparamList(obj.Name(), tparams, obj.Pkg()) } w.signature(sig) @@ -507,14 +506,14 @@ func (p *iexporter) doDecl(obj types.Object) { case *types.TypeName: t := obj.Type() - if tparam, ok := t.(*typeparams.TypeParam); ok { + if tparam, ok := t.(*types.TypeParam); ok { w.tag('P') w.pos(obj.Pos()) constraint := tparam.Constraint() if p.version >= iexportVersionGo1_18 { implicit := false if iface, _ := constraint.(*types.Interface); iface != nil { - implicit = typeparams.IsImplicit(iface) + implicit = iface.IsImplicit() } w.bool(implicit) } @@ -535,17 +534,17 @@ func (p *iexporter) doDecl(obj types.Object) { panic(internalErrorf("%s is not a defined type", t)) } - if typeparams.ForNamed(named).Len() == 0 { + if named.TypeParams().Len() == 0 { w.tag('T') } else { w.tag('U') } w.pos(obj.Pos()) - if typeparams.ForNamed(named).Len() > 0 { + if named.TypeParams().Len() > 0 { // While importing the type parameters, tparamList computes and records // their export name, so that it can be later used when writing the index. - w.tparamList(obj.Name(), typeparams.ForNamed(named), obj.Pkg()) + w.tparamList(obj.Name(), named.TypeParams(), obj.Pkg()) } underlying := obj.Type().Underlying() @@ -565,7 +564,7 @@ func (p *iexporter) doDecl(obj types.Object) { // Receiver type parameters are type arguments of the receiver type, so // their name must be qualified before exporting recv. - if rparams := typeparams.RecvTypeParams(sig); rparams.Len() > 0 { + if rparams := sig.RecvTypeParams(); rparams.Len() > 0 { prefix := obj.Name() + "." + m.Name() for i := 0; i < rparams.Len(); i++ { rparam := rparams.At(i) @@ -740,19 +739,19 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { } switch t := t.(type) { case *types.Named: - if targs := typeparams.NamedTypeArgs(t); targs.Len() > 0 { + if targs := t.TypeArgs(); targs.Len() > 0 { w.startType(instanceType) // TODO(rfindley): investigate if this position is correct, and if it // matters. w.pos(t.Obj().Pos()) w.typeList(targs, pkg) - w.typ(typeparams.NamedTypeOrigin(t), pkg) + w.typ(t.Origin(), pkg) return } w.startType(definedType) w.qualifiedType(t.Obj()) - case *typeparams.TypeParam: + case *types.TypeParam: w.startType(typeParamType) w.qualifiedType(t.Obj()) @@ -868,7 +867,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { w.signature(sig) } - case *typeparams.Union: + case *types.Union: w.startType(unionType) nt := t.Len() w.uint64(uint64(nt)) @@ -948,14 +947,14 @@ func (w *exportWriter) signature(sig *types.Signature) { } } -func (w *exportWriter) typeList(ts *typeparams.TypeList, pkg *types.Package) { +func (w *exportWriter) typeList(ts *types.TypeList, pkg *types.Package) { w.uint64(uint64(ts.Len())) for i := 0; i < ts.Len(); i++ { w.typ(ts.At(i), pkg) } } -func (w *exportWriter) tparamList(prefix string, list *typeparams.TypeParamList, pkg *types.Package) { +func (w *exportWriter) tparamList(prefix string, list *types.TypeParamList, pkg *types.Package) { ll := uint64(list.Len()) w.uint64(ll) for i := 0; i < list.Len(); i++ { @@ -973,7 +972,7 @@ const blankMarker = "$" // differs from its actual object name: it is prefixed with a qualifier, and // blank type parameter names are disambiguated by their index in the type // parameter list. -func tparamExportName(prefix string, tparam *typeparams.TypeParam) string { +func tparamExportName(prefix string, tparam *types.TypeParam) string { assert(prefix != "") name := tparam.Obj().Name() if name == "_" { diff --git a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go index 8e64cf644f..9bde15e3bc 100644 --- a/vendor/golang.org/x/tools/internal/gcimporter/iimport.go +++ b/vendor/golang.org/x/tools/internal/gcimporter/iimport.go @@ -22,7 +22,6 @@ import ( "strings" "golang.org/x/tools/go/types/objectpath" - "golang.org/x/tools/internal/typeparams" ) type intReader struct { @@ -321,7 +320,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte // Therefore, we defer calling SetConstraint there, and call it here instead // after all types are complete. for _, d := range p.later { - typeparams.SetTypeParamConstraint(d.t, d.constraint) + d.t.SetConstraint(d.constraint) } for _, typ := range p.interfaceList { @@ -339,7 +338,7 @@ func iimportCommon(fset *token.FileSet, getPackages GetPackagesFunc, data []byte } type setConstraintArgs struct { - t *typeparams.TypeParam + t *types.TypeParam constraint types.Type } @@ -549,7 +548,7 @@ func (r *importReader) obj(name string) { r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) case 'F', 'G': - var tparams []*typeparams.TypeParam + var tparams []*types.TypeParam if tag == 'G' { tparams = r.tparamList() } @@ -566,7 +565,7 @@ func (r *importReader) obj(name string) { r.declare(obj) if tag == 'U' { tparams := r.tparamList() - typeparams.SetForNamed(named, tparams) + named.SetTypeParams(tparams) } underlying := r.p.typAt(r.uint64(), named).Underlying() @@ -583,12 +582,12 @@ func (r *importReader) obj(name string) { // typeparams being used in the method sig/body). base := baseType(recv.Type()) assert(base != nil) - targs := typeparams.NamedTypeArgs(base) - var rparams []*typeparams.TypeParam + targs := base.TypeArgs() + var rparams []*types.TypeParam if targs.Len() > 0 { - rparams = make([]*typeparams.TypeParam, targs.Len()) + rparams = make([]*types.TypeParam, targs.Len()) for i := range rparams { - rparams[i] = targs.At(i).(*typeparams.TypeParam) + rparams[i] = targs.At(i).(*types.TypeParam) } } msig := r.signature(recv, rparams, nil) @@ -606,7 +605,7 @@ func (r *importReader) obj(name string) { } name0 := tparamName(name) tn := types.NewTypeName(pos, r.currPkg, name0, nil) - t := typeparams.NewTypeParam(tn, nil) + t := types.NewTypeParam(tn, nil) // To handle recursive references to the typeparam within its // bound, save the partial type in tparamIndex before reading the bounds. @@ -622,7 +621,7 @@ func (r *importReader) obj(name string) { if iface == nil { errorf("non-interface constraint marked implicit") } - typeparams.MarkImplicit(iface) + iface.MarkImplicit() } // The constraint type may not be complete, if we // are in the middle of a type recursion involving type @@ -966,7 +965,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { // The imported instantiated type doesn't include any methods, so // we must always use the methods of the base (orig) type. // TODO provide a non-nil *Environment - t, _ := typeparams.Instantiate(nil, baseType, targs, false) + t, _ := types.Instantiate(nil, baseType, targs, false) // Workaround for golang/go#61561. See the doc for instanceList for details. r.p.instanceList = append(r.p.instanceList, t) @@ -976,11 +975,11 @@ func (r *importReader) doType(base *types.Named) (res types.Type) { if r.p.version < iexportVersionGenerics { errorf("unexpected instantiation type") } - terms := make([]*typeparams.Term, r.uint64()) + terms := make([]*types.Term, r.uint64()) for i := range terms { - terms[i] = typeparams.NewTerm(r.bool(), r.typ()) + terms[i] = types.NewTerm(r.bool(), r.typ()) } - return typeparams.NewUnion(terms) + return types.NewUnion(terms) } } @@ -1008,23 +1007,23 @@ func (r *importReader) objectPathObject() types.Object { return obj } -func (r *importReader) signature(recv *types.Var, rparams []*typeparams.TypeParam, tparams []*typeparams.TypeParam) *types.Signature { +func (r *importReader) signature(recv *types.Var, rparams []*types.TypeParam, tparams []*types.TypeParam) *types.Signature { params := r.paramList() results := r.paramList() variadic := params.Len() > 0 && r.bool() - return typeparams.NewSignatureType(recv, rparams, tparams, params, results, variadic) + return types.NewSignatureType(recv, rparams, tparams, params, results, variadic) } -func (r *importReader) tparamList() []*typeparams.TypeParam { +func (r *importReader) tparamList() []*types.TypeParam { n := r.uint64() if n == 0 { return nil } - xs := make([]*typeparams.TypeParam, n) + xs := make([]*types.TypeParam, n) for i := range xs { // Note: the standard library importer is tolerant of nil types here, // though would panic in SetTypeParams. - xs[i] = r.typ().(*typeparams.TypeParam) + xs[i] = r.typ().(*types.TypeParam) } return xs } diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go index 53cf66da01..55312522dc 100644 --- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go +++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go @@ -13,6 +13,7 @@ import ( "io" "log" "os" + "os/exec" "reflect" "regexp" "runtime" @@ -21,8 +22,6 @@ import ( "sync" "time" - exec "golang.org/x/sys/execabs" - "golang.org/x/tools/internal/event" "golang.org/x/tools/internal/event/keys" "golang.org/x/tools/internal/event/label" @@ -85,6 +84,7 @@ func (runner *Runner) RunPiped(ctx context.Context, inv Invocation, stdout, stde // RunRaw runs the invocation, serializing requests only if they fight over // go.mod changes. +// Postcondition: both error results have same nilness. func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) { ctx, done := event.Start(ctx, "gocommand.Runner.RunRaw", invLabels(inv)...) defer done() @@ -95,23 +95,24 @@ func (runner *Runner) RunRaw(ctx context.Context, inv Invocation) (*bytes.Buffer stdout, stderr, friendlyErr, err := runner.runConcurrent(ctx, inv) // If we encounter a load concurrency error, we need to retry serially. - if friendlyErr == nil || !modConcurrencyError.MatchString(friendlyErr.Error()) { - return stdout, stderr, friendlyErr, err - } - event.Error(ctx, "Load concurrency error, will retry serially", err) + if friendlyErr != nil && modConcurrencyError.MatchString(friendlyErr.Error()) { + event.Error(ctx, "Load concurrency error, will retry serially", err) + + // Run serially by calling runPiped. + stdout.Reset() + stderr.Reset() + friendlyErr, err = runner.runPiped(ctx, inv, stdout, stderr) + } - // Run serially by calling runPiped. - stdout.Reset() - stderr.Reset() - friendlyErr, err = runner.runPiped(ctx, inv, stdout, stderr) return stdout, stderr, friendlyErr, err } +// Postcondition: both error results have same nilness. func (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes.Buffer, *bytes.Buffer, error, error) { // Wait for 1 worker to become available. select { case <-ctx.Done(): - return nil, nil, nil, ctx.Err() + return nil, nil, ctx.Err(), ctx.Err() case runner.inFlight <- struct{}{}: defer func() { <-runner.inFlight }() } @@ -121,6 +122,7 @@ func (runner *Runner) runConcurrent(ctx context.Context, inv Invocation) (*bytes return stdout, stderr, friendlyErr, err } +// Postcondition: both error results have same nilness. func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stderr io.Writer) (error, error) { // Make sure the runner is always initialized. runner.initialize() @@ -129,7 +131,7 @@ func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stde // runPiped commands. select { case <-ctx.Done(): - return nil, ctx.Err() + return ctx.Err(), ctx.Err() case runner.serialized <- struct{}{}: defer func() { <-runner.serialized }() } @@ -139,7 +141,7 @@ func (runner *Runner) runPiped(ctx context.Context, inv Invocation, stdout, stde for i := 0; i < maxInFlight; i++ { select { case <-ctx.Done(): - return nil, ctx.Err() + return ctx.Err(), ctx.Err() case runner.inFlight <- struct{}{}: // Make sure we always "return" any workers we took. defer func() { <-runner.inFlight }() @@ -172,6 +174,7 @@ type Invocation struct { Logf func(format string, args ...interface{}) } +// Postcondition: both error results have same nilness. func (i *Invocation) runWithFriendlyError(ctx context.Context, stdout, stderr io.Writer) (friendlyError error, rawError error) { rawError = i.run(ctx, stdout, stderr) if rawError != nil { diff --git a/vendor/golang.org/x/tools/internal/gopathwalk/walk.go b/vendor/golang.org/x/tools/internal/gopathwalk/walk.go index 452e342c55..52f74e643b 100644 --- a/vendor/golang.org/x/tools/internal/gopathwalk/walk.go +++ b/vendor/golang.org/x/tools/internal/gopathwalk/walk.go @@ -9,13 +9,12 @@ package gopathwalk import ( "bufio" "bytes" + "io/fs" "log" "os" "path/filepath" "strings" "time" - - "golang.org/x/tools/internal/fastwalk" ) // Options controls the behavior of a Walk call. @@ -45,21 +44,18 @@ type Root struct { } // Walk walks Go source directories ($GOROOT, $GOPATH, etc) to find packages. -// For each package found, add will be called (concurrently) with the absolute +// For each package found, add will be called with the absolute // paths of the containing source directory and the package directory. -// add will be called concurrently. func Walk(roots []Root, add func(root Root, dir string), opts Options) { WalkSkip(roots, add, func(Root, string) bool { return false }, opts) } // WalkSkip walks Go source directories ($GOROOT, $GOPATH, etc) to find packages. -// For each package found, add will be called (concurrently) with the absolute +// For each package found, add will be called with the absolute // paths of the containing source directory and the package directory. -// For each directory that will be scanned, skip will be called (concurrently) +// For each directory that will be scanned, skip will be called // with the absolute paths of the containing source directory and the directory. // If skip returns false on a directory it will be processed. -// add will be called concurrently. -// skip will be called concurrently. func WalkSkip(roots []Root, add func(root Root, dir string), skip func(root Root, dir string) bool, opts Options) { for _, root := range roots { walkDir(root, add, skip, opts) @@ -78,14 +74,25 @@ func walkDir(root Root, add func(Root, string), skip func(root Root, dir string) if opts.Logf != nil { opts.Logf("scanning %s", root.Path) } + w := &walker{ - root: root, - add: add, - skip: skip, - opts: opts, + root: root, + add: add, + skip: skip, + opts: opts, + added: make(map[string]bool), } w.init() - if err := fastwalk.Walk(root.Path, w.walk); err != nil { + + // Add a trailing path separator to cause filepath.WalkDir to traverse symlinks. + path := root.Path + if len(path) == 0 { + path = "." + string(filepath.Separator) + } else if !os.IsPathSeparator(path[len(path)-1]) { + path = path + string(filepath.Separator) + } + + if err := filepath.WalkDir(path, w.walk); err != nil { logf := opts.Logf if logf == nil { logf = log.Printf @@ -105,7 +112,10 @@ type walker struct { skip func(Root, string) bool // The callback that will be invoked for every dir. dir is skipped if it returns true. opts Options // Options passed to Walk by the user. - ignoredDirs []os.FileInfo // The ignored directories, loaded from .goimportsignore files. + pathSymlinks []os.FileInfo + ignoredDirs []string + + added map[string]bool } // init initializes the walker based on its Options @@ -121,13 +131,9 @@ func (w *walker) init() { for _, p := range ignoredPaths { full := filepath.Join(w.root.Path, p) - if fi, err := os.Stat(full); err == nil { - w.ignoredDirs = append(w.ignoredDirs, fi) - if w.opts.Logf != nil { - w.opts.Logf("Directory added to ignore list: %s", full) - } - } else if w.opts.Logf != nil { - w.opts.Logf("Error statting ignored directory: %v", err) + w.ignoredDirs = append(w.ignoredDirs, full) + if w.opts.Logf != nil { + w.opts.Logf("Directory added to ignore list: %s", full) } } } @@ -162,9 +168,9 @@ func (w *walker) getIgnoredDirs(path string) []string { } // shouldSkipDir reports whether the file should be skipped or not. -func (w *walker) shouldSkipDir(fi os.FileInfo, dir string) bool { +func (w *walker) shouldSkipDir(dir string) bool { for _, ignoredDir := range w.ignoredDirs { - if os.SameFile(fi, ignoredDir) { + if dir == ignoredDir { return true } } @@ -176,85 +182,150 @@ func (w *walker) shouldSkipDir(fi os.FileInfo, dir string) bool { } // walk walks through the given path. -func (w *walker) walk(path string, typ os.FileMode) error { - if typ.IsRegular() { - dir := filepath.Dir(path) - if dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) { - // Doesn't make sense to have regular files - // directly in your $GOPATH/src or $GOROOT/src. - return fastwalk.ErrSkipFiles +// +// Errors are logged if w.opts.Logf is non-nil, but otherwise ignored: +// walk returns only nil or fs.SkipDir. +func (w *walker) walk(path string, d fs.DirEntry, err error) error { + if err != nil { + // We have no way to report errors back through Walk or WalkSkip, + // so just log and ignore them. + if w.opts.Logf != nil { + w.opts.Logf("%v", err) } + if d == nil { + // Nothing more to do: the error prevents us from knowing + // what path even represents. + return nil + } + } + + if d.Type().IsRegular() { if !strings.HasSuffix(path, ".go") { return nil } - w.add(w.root, dir) - return fastwalk.ErrSkipFiles + dir := filepath.Dir(path) + if dir == w.root.Path && (w.root.Type == RootGOROOT || w.root.Type == RootGOPATH) { + // Doesn't make sense to have regular files + // directly in your $GOPATH/src or $GOROOT/src. + return nil + } + + if !w.added[dir] { + w.add(w.root, dir) + w.added[dir] = true + } + return nil } - if typ == os.ModeDir { + + if d.IsDir() { base := filepath.Base(path) if base == "" || base[0] == '.' || base[0] == '_' || base == "testdata" || (w.root.Type == RootGOROOT && w.opts.ModulesEnabled && base == "vendor") || (!w.opts.ModulesEnabled && base == "node_modules") { - return filepath.SkipDir + return fs.SkipDir } - fi, err := os.Lstat(path) - if err == nil && w.shouldSkipDir(fi, path) { - return filepath.SkipDir + if w.shouldSkipDir(path) { + return fs.SkipDir } return nil } - if typ == os.ModeSymlink { - base := filepath.Base(path) - if strings.HasPrefix(base, ".#") { - // Emacs noise. + + if d.Type()&os.ModeSymlink != 0 { + // TODO(bcmills): 'go list all' itself ignores symlinks within GOROOT/src + // and GOPATH/src. Do we really need to traverse them here? If so, why? + + fi, err := os.Stat(path) + if err != nil || !fi.IsDir() { + // Not a directory. Just walk the file (or broken link) and be done. + return w.walk(path, fs.FileInfoToDirEntry(fi), err) + } + + // Avoid walking symlink cycles: if we have already followed a symlink to + // this directory as a parent of itself, don't follow it again. + // + // This doesn't catch the first time through a cycle, but it also minimizes + // the number of extra stat calls we make if we *don't* encounter a cycle. + // Since we don't actually expect to encounter symlink cycles in practice, + // this seems like the right tradeoff. + for _, parent := range w.pathSymlinks { + if os.SameFile(fi, parent) { + return nil + } + } + + w.pathSymlinks = append(w.pathSymlinks, fi) + defer func() { + w.pathSymlinks = w.pathSymlinks[:len(w.pathSymlinks)-1] + }() + + // On some platforms the OS (or the Go os package) sometimes fails to + // resolve directory symlinks before a trailing slash + // (even though POSIX requires it to do so). + // + // On macOS that failure may be caused by a known libc/kernel bug; + // see https://go.dev/issue/59586. + // + // On Windows before Go 1.21, it may be caused by a bug in + // os.Lstat (fixed in https://go.dev/cl/463177). + // + // Since we need to handle this explicitly on broken platforms anyway, + // it is simplest to just always do that and not rely on POSIX pathname + // resolution to walk the directory (such as by calling WalkDir with + // a trailing slash appended to the path). + // + // Instead, we make a sequence of walk calls — directly and through + // recursive calls to filepath.WalkDir — simulating what WalkDir would do + // if the symlink were a regular directory. + + // First we call walk on the path as a directory + // (instead of a symlink). + err = w.walk(path, fs.FileInfoToDirEntry(fi), nil) + if err == fs.SkipDir { return nil + } else if err != nil { + // This should be impossible, but handle it anyway in case + // walk is changed to return other errors. + return err } - if w.shouldTraverse(path) { - return fastwalk.ErrTraverseLink + + // Now read the directory and walk its entries. + ents, err := os.ReadDir(path) + if err != nil { + // Report the ReadDir error, as filepath.WalkDir would do. + err = w.walk(path, fs.FileInfoToDirEntry(fi), err) + if err == fs.SkipDir { + return nil + } else if err != nil { + return err // Again, should be impossible. + } + // Fall through and iterate over whatever entries we did manage to get. } + + for _, d := range ents { + nextPath := filepath.Join(path, d.Name()) + if d.IsDir() { + // We want to walk the whole directory tree rooted at nextPath, + // not just the single entry for the directory. + err := filepath.WalkDir(nextPath, w.walk) + if err != nil && w.opts.Logf != nil { + w.opts.Logf("%v", err) + } + } else { + err := w.walk(nextPath, d, nil) + if err == fs.SkipDir { + // Skip the rest of the entries in the parent directory of nextPath + // (that is, path itself). + break + } else if err != nil { + return err // Again, should be impossible. + } + } + } + return nil } + + // Not a file, regular directory, or symlink; skip. return nil } - -// shouldTraverse reports whether the symlink fi, found in dir, -// should be followed. It makes sure symlinks were never visited -// before to avoid symlink loops. -func (w *walker) shouldTraverse(path string) bool { - ts, err := os.Stat(path) - if err != nil { - logf := w.opts.Logf - if logf == nil { - logf = log.Printf - } - logf("%v", err) - return false - } - if !ts.IsDir() { - return false - } - if w.shouldSkipDir(ts, filepath.Dir(path)) { - return false - } - // Check for symlink loops by statting each directory component - // and seeing if any are the same file as ts. - for { - parent := filepath.Dir(path) - if parent == path { - // Made it to the root without seeing a cycle. - // Use this symlink. - return true - } - parentInfo, err := os.Stat(parent) - if err != nil { - return false - } - if os.SameFile(ts, parentInfo) { - // Cycle. Don't traverse. - return false - } - path = parent - } - -} diff --git a/vendor/golang.org/x/tools/internal/imports/fix.go b/vendor/golang.org/x/tools/internal/imports/fix.go index 01e8ba5fa2..dd369c072e 100644 --- a/vendor/golang.org/x/tools/internal/imports/fix.go +++ b/vendor/golang.org/x/tools/internal/imports/fix.go @@ -254,7 +254,7 @@ type pass struct { otherFiles []*ast.File // sibling files. // Intermediate state, generated by load. - existingImports map[string]*ImportInfo + existingImports map[string][]*ImportInfo allRefs references missingRefs references @@ -319,7 +319,7 @@ func (p *pass) importIdentifier(imp *ImportInfo) string { func (p *pass) load() ([]*ImportFix, bool) { p.knownPackages = map[string]*packageInfo{} p.missingRefs = references{} - p.existingImports = map[string]*ImportInfo{} + p.existingImports = map[string][]*ImportInfo{} // Load basic information about the file in question. p.allRefs = collectReferences(p.f) @@ -350,7 +350,7 @@ func (p *pass) load() ([]*ImportFix, bool) { } } for _, imp := range imports { - p.existingImports[p.importIdentifier(imp)] = imp + p.existingImports[p.importIdentifier(imp)] = append(p.existingImports[p.importIdentifier(imp)], imp) } // Find missing references. @@ -389,31 +389,33 @@ func (p *pass) fix() ([]*ImportFix, bool) { // Found everything, or giving up. Add the new imports and remove any unused. var fixes []*ImportFix - for _, imp := range p.existingImports { - // We deliberately ignore globals here, because we can't be sure - // they're in the same package. People do things like put multiple - // main packages in the same directory, and we don't want to - // remove imports if they happen to have the same name as a var in - // a different package. - if _, ok := p.allRefs[p.importIdentifier(imp)]; !ok { - fixes = append(fixes, &ImportFix{ - StmtInfo: *imp, - IdentName: p.importIdentifier(imp), - FixType: DeleteImport, - }) - continue - } + for _, identifierImports := range p.existingImports { + for _, imp := range identifierImports { + // We deliberately ignore globals here, because we can't be sure + // they're in the same package. People do things like put multiple + // main packages in the same directory, and we don't want to + // remove imports if they happen to have the same name as a var in + // a different package. + if _, ok := p.allRefs[p.importIdentifier(imp)]; !ok { + fixes = append(fixes, &ImportFix{ + StmtInfo: *imp, + IdentName: p.importIdentifier(imp), + FixType: DeleteImport, + }) + continue + } - // An existing import may need to update its import name to be correct. - if name := p.importSpecName(imp); name != imp.Name { - fixes = append(fixes, &ImportFix{ - StmtInfo: ImportInfo{ - Name: name, - ImportPath: imp.ImportPath, - }, - IdentName: p.importIdentifier(imp), - FixType: SetImportName, - }) + // An existing import may need to update its import name to be correct. + if name := p.importSpecName(imp); name != imp.Name { + fixes = append(fixes, &ImportFix{ + StmtInfo: ImportInfo{ + Name: name, + ImportPath: imp.ImportPath, + }, + IdentName: p.importIdentifier(imp), + FixType: SetImportName, + }) + } } } // Collecting fixes involved map iteration, so sort for stability. See diff --git a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go index d9950b1f0b..44719de173 100644 --- a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go +++ b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go @@ -5,10 +5,6 @@ // Package packagesinternal exposes internal-only fields from go/packages. package packagesinternal -import ( - "golang.org/x/tools/internal/gocommand" -) - var GetForTest = func(p interface{}) string { return "" } var GetDepsErrors = func(p interface{}) []*PackageError { return nil } @@ -18,10 +14,6 @@ type PackageError struct { Err string // the error itself } -var GetGoCmdRunner = func(config interface{}) *gocommand.Runner { return nil } - -var SetGoCmdRunner = func(config interface{}, runner *gocommand.Runner) {} - var TypecheckCgo int var DepsErrors int // must be set as a LoadMode to call GetDepsErrors var ForTest int // must be set as a LoadMode to call GetForTest diff --git a/vendor/golang.org/x/tools/internal/typeparams/common.go b/vendor/golang.org/x/tools/internal/typeparams/common.go index d0d0649fe2..cdab988531 100644 --- a/vendor/golang.org/x/tools/internal/typeparams/common.go +++ b/vendor/golang.org/x/tools/internal/typeparams/common.go @@ -42,7 +42,7 @@ func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Ex switch e := n.(type) { case *ast.IndexExpr: return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack - case *IndexListExpr: + case *ast.IndexListExpr: return e.X, e.Lbrack, e.Indices, e.Rbrack } return nil, token.NoPos, nil, token.NoPos @@ -63,7 +63,7 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke Rbrack: rbrack, } default: - return &IndexListExpr{ + return &ast.IndexListExpr{ X: x, Lbrack: lbrack, Indices: indices, @@ -74,7 +74,7 @@ func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack toke // IsTypeParam reports whether t is a type parameter. func IsTypeParam(t types.Type) bool { - _, ok := t.(*TypeParam) + _, ok := t.(*types.TypeParam) return ok } @@ -100,11 +100,11 @@ func OriginMethod(fn *types.Func) *types.Func { // Receiver is a *types.Interface. return fn } - if ForNamed(named).Len() == 0 { + if named.TypeParams().Len() == 0 { // Receiver base has no type parameters, so we can avoid the lookup below. return fn } - orig := NamedTypeOrigin(named) + orig := named.Origin() gfn, _, _ := types.LookupFieldOrMethod(orig, true, fn.Pkg(), fn.Name()) // This is a fix for a gopls crash (#60628) due to a go/types bug (#60634). In: @@ -157,7 +157,7 @@ func OriginMethod(fn *types.Func) *types.Func { // // In this case, GenericAssignableTo reports that instantiations of Container // are assignable to the corresponding instantiation of Interface. -func GenericAssignableTo(ctxt *Context, V, T types.Type) bool { +func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool { // If V and T are not both named, or do not have matching non-empty type // parameter lists, fall back on types.AssignableTo. @@ -167,9 +167,9 @@ func GenericAssignableTo(ctxt *Context, V, T types.Type) bool { return types.AssignableTo(V, T) } - vtparams := ForNamed(VN) - ttparams := ForNamed(TN) - if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || NamedTypeArgs(VN).Len() != 0 || NamedTypeArgs(TN).Len() != 0 { + vtparams := VN.TypeParams() + ttparams := TN.TypeParams() + if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || VN.TypeArgs().Len() != 0 || TN.TypeArgs().Len() != 0 { return types.AssignableTo(V, T) } @@ -182,7 +182,7 @@ func GenericAssignableTo(ctxt *Context, V, T types.Type) bool { // Minor optimization: ensure we share a context across the two // instantiations below. if ctxt == nil { - ctxt = NewContext() + ctxt = types.NewContext() } var targs []types.Type @@ -190,12 +190,12 @@ func GenericAssignableTo(ctxt *Context, V, T types.Type) bool { targs = append(targs, vtparams.At(i)) } - vinst, err := Instantiate(ctxt, V, targs, true) + vinst, err := types.Instantiate(ctxt, V, targs, true) if err != nil { panic("type parameters should satisfy their own constraints") } - tinst, err := Instantiate(ctxt, T, targs, true) + tinst, err := types.Instantiate(ctxt, T, targs, true) if err != nil { return false } diff --git a/vendor/golang.org/x/tools/internal/typeparams/coretype.go b/vendor/golang.org/x/tools/internal/typeparams/coretype.go index 71248209ee..7ea8840eab 100644 --- a/vendor/golang.org/x/tools/internal/typeparams/coretype.go +++ b/vendor/golang.org/x/tools/internal/typeparams/coretype.go @@ -108,15 +108,15 @@ func CoreType(T types.Type) types.Type { // // _NormalTerms makes no guarantees about the order of terms, except that it // is deterministic. -func _NormalTerms(typ types.Type) ([]*Term, error) { +func _NormalTerms(typ types.Type) ([]*types.Term, error) { switch typ := typ.(type) { - case *TypeParam: + case *types.TypeParam: return StructuralTerms(typ) - case *Union: + case *types.Union: return UnionTermSet(typ) case *types.Interface: return InterfaceTermSet(typ) default: - return []*Term{NewTerm(false, typ)}, nil + return []*types.Term{types.NewTerm(false, typ)}, nil } } diff --git a/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go b/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go deleted file mode 100644 index 18212390e1..0000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.18 -// +build !go1.18 - -package typeparams - -// Enabled reports whether type parameters are enabled in the current build -// environment. -const Enabled = false diff --git a/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go b/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go deleted file mode 100644 index d67148823c..0000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.18 -// +build go1.18 - -package typeparams - -// Note: this constant is in a separate file as this is the only acceptable -// diff between the <1.18 API of this package and the 1.18 API. - -// Enabled reports whether type parameters are enabled in the current build -// environment. -const Enabled = true diff --git a/vendor/golang.org/x/tools/internal/typeparams/normalize.go b/vendor/golang.org/x/tools/internal/typeparams/normalize.go index 9c631b6512..93c80fdc96 100644 --- a/vendor/golang.org/x/tools/internal/typeparams/normalize.go +++ b/vendor/golang.org/x/tools/internal/typeparams/normalize.go @@ -60,7 +60,7 @@ var ErrEmptyTypeSet = errors.New("empty type set") // // StructuralTerms makes no guarantees about the order of terms, except that it // is deterministic. -func StructuralTerms(tparam *TypeParam) ([]*Term, error) { +func StructuralTerms(tparam *types.TypeParam) ([]*types.Term, error) { constraint := tparam.Constraint() if constraint == nil { return nil, fmt.Errorf("%s has nil constraint", tparam) @@ -78,7 +78,7 @@ func StructuralTerms(tparam *TypeParam) ([]*Term, error) { // // See the documentation of StructuralTerms for more information on // normalization. -func InterfaceTermSet(iface *types.Interface) ([]*Term, error) { +func InterfaceTermSet(iface *types.Interface) ([]*types.Term, error) { return computeTermSet(iface) } @@ -88,11 +88,11 @@ func InterfaceTermSet(iface *types.Interface) ([]*Term, error) { // // See the documentation of StructuralTerms for more information on // normalization. -func UnionTermSet(union *Union) ([]*Term, error) { +func UnionTermSet(union *types.Union) ([]*types.Term, error) { return computeTermSet(union) } -func computeTermSet(typ types.Type) ([]*Term, error) { +func computeTermSet(typ types.Type) ([]*types.Term, error) { tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0) if err != nil { return nil, err @@ -103,9 +103,9 @@ func computeTermSet(typ types.Type) ([]*Term, error) { if tset.terms.isAll() { return nil, nil } - var terms []*Term + var terms []*types.Term for _, term := range tset.terms { - terms = append(terms, NewTerm(term.tilde, term.typ)) + terms = append(terms, types.NewTerm(term.tilde, term.typ)) } return terms, nil } @@ -162,7 +162,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in tset.terms = allTermlist for i := 0; i < u.NumEmbeddeds(); i++ { embedded := u.EmbeddedType(i) - if _, ok := embedded.Underlying().(*TypeParam); ok { + if _, ok := embedded.Underlying().(*types.TypeParam); ok { return nil, fmt.Errorf("invalid embedded type %T", embedded) } tset2, err := computeTermSetInternal(embedded, seen, depth+1) @@ -171,7 +171,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in } tset.terms = tset.terms.intersect(tset2.terms) } - case *Union: + case *types.Union: // The term set of a union is the union of term sets of its terms. tset.terms = nil for i := 0; i < u.Len(); i++ { @@ -184,7 +184,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in return nil, err } terms = tset2.terms - case *TypeParam, *Union: + case *types.TypeParam, *types.Union: // A stand-alone type parameter or union is not permitted as union // term. return nil, fmt.Errorf("invalid union term %T", t) @@ -199,7 +199,7 @@ func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth in return nil, fmt.Errorf("exceeded max term count %d", maxTermCount) } } - case *TypeParam: + case *types.TypeParam: panic("unreachable") default: // For all other types, the term set is just a single non-tilde term diff --git a/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go b/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go deleted file mode 100644 index 7ed86e1711..0000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !go1.18 -// +build !go1.18 - -package typeparams - -import ( - "go/ast" - "go/token" - "go/types" -) - -func unsupported() { - panic("type parameters are unsupported at this go version") -} - -// IndexListExpr is a placeholder type, as type parameters are not supported at -// this Go version. Its methods panic on use. -type IndexListExpr struct { - ast.Expr - X ast.Expr // expression - Lbrack token.Pos // position of "[" - Indices []ast.Expr // index expressions - Rbrack token.Pos // position of "]" -} - -// ForTypeSpec returns an empty field list, as type parameters on not supported -// at this Go version. -func ForTypeSpec(*ast.TypeSpec) *ast.FieldList { - return nil -} - -// ForFuncType returns an empty field list, as type parameters are not -// supported at this Go version. -func ForFuncType(*ast.FuncType) *ast.FieldList { - return nil -} - -// TypeParam is a placeholder type, as type parameters are not supported at -// this Go version. Its methods panic on use. -type TypeParam struct{ types.Type } - -func (*TypeParam) Index() int { unsupported(); return 0 } -func (*TypeParam) Constraint() types.Type { unsupported(); return nil } -func (*TypeParam) Obj() *types.TypeName { unsupported(); return nil } - -// TypeParamList is a placeholder for an empty type parameter list. -type TypeParamList struct{} - -func (*TypeParamList) Len() int { return 0 } -func (*TypeParamList) At(int) *TypeParam { unsupported(); return nil } - -// TypeList is a placeholder for an empty type list. -type TypeList struct{} - -func (*TypeList) Len() int { return 0 } -func (*TypeList) At(int) types.Type { unsupported(); return nil } - -// NewTypeParam is unsupported at this Go version, and panics. -func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam { - unsupported() - return nil -} - -// SetTypeParamConstraint is unsupported at this Go version, and panics. -func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) { - unsupported() -} - -// NewSignatureType calls types.NewSignature, panicking if recvTypeParams or -// typeParams is non-empty. -func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature { - if len(recvTypeParams) != 0 || len(typeParams) != 0 { - panic("signatures cannot have type parameters at this Go version") - } - return types.NewSignature(recv, params, results, variadic) -} - -// ForSignature returns an empty slice. -func ForSignature(*types.Signature) *TypeParamList { - return nil -} - -// RecvTypeParams returns a nil slice. -func RecvTypeParams(sig *types.Signature) *TypeParamList { - return nil -} - -// IsComparable returns false, as no interfaces are type-restricted at this Go -// version. -func IsComparable(*types.Interface) bool { - return false -} - -// IsMethodSet returns true, as no interfaces are type-restricted at this Go -// version. -func IsMethodSet(*types.Interface) bool { - return true -} - -// IsImplicit returns false, as no interfaces are implicit at this Go version. -func IsImplicit(*types.Interface) bool { - return false -} - -// MarkImplicit does nothing, because this Go version does not have implicit -// interfaces. -func MarkImplicit(*types.Interface) {} - -// ForNamed returns an empty type parameter list, as type parameters are not -// supported at this Go version. -func ForNamed(*types.Named) *TypeParamList { - return nil -} - -// SetForNamed panics if tparams is non-empty. -func SetForNamed(_ *types.Named, tparams []*TypeParam) { - if len(tparams) > 0 { - unsupported() - } -} - -// NamedTypeArgs returns nil. -func NamedTypeArgs(*types.Named) *TypeList { - return nil -} - -// NamedTypeOrigin is the identity method at this Go version. -func NamedTypeOrigin(named *types.Named) *types.Named { - return named -} - -// Term holds information about a structural type restriction. -type Term struct { - tilde bool - typ types.Type -} - -func (m *Term) Tilde() bool { return m.tilde } -func (m *Term) Type() types.Type { return m.typ } -func (m *Term) String() string { - pre := "" - if m.tilde { - pre = "~" - } - return pre + m.typ.String() -} - -// NewTerm is unsupported at this Go version, and panics. -func NewTerm(tilde bool, typ types.Type) *Term { - return &Term{tilde, typ} -} - -// Union is a placeholder type, as type parameters are not supported at this Go -// version. Its methods panic on use. -type Union struct{ types.Type } - -func (*Union) Len() int { return 0 } -func (*Union) Term(i int) *Term { unsupported(); return nil } - -// NewUnion is unsupported at this Go version, and panics. -func NewUnion(terms []*Term) *Union { - unsupported() - return nil -} - -// InitInstanceInfo is a noop at this Go version. -func InitInstanceInfo(*types.Info) {} - -// Instance is a placeholder type, as type parameters are not supported at this -// Go version. -type Instance struct { - TypeArgs *TypeList - Type types.Type -} - -// GetInstances returns a nil map, as type parameters are not supported at this -// Go version. -func GetInstances(info *types.Info) map[*ast.Ident]Instance { return nil } - -// Context is a placeholder type, as type parameters are not supported at -// this Go version. -type Context struct{} - -// NewContext returns a placeholder Context instance. -func NewContext() *Context { - return &Context{} -} - -// Instantiate is unsupported on this Go version, and panics. -func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) { - unsupported() - return nil, nil -} diff --git a/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go b/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go deleted file mode 100644 index cf301af1db..0000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.18 -// +build go1.18 - -package typeparams - -import ( - "go/ast" - "go/types" -) - -// IndexListExpr is an alias for ast.IndexListExpr. -type IndexListExpr = ast.IndexListExpr - -// ForTypeSpec returns n.TypeParams. -func ForTypeSpec(n *ast.TypeSpec) *ast.FieldList { - if n == nil { - return nil - } - return n.TypeParams -} - -// ForFuncType returns n.TypeParams. -func ForFuncType(n *ast.FuncType) *ast.FieldList { - if n == nil { - return nil - } - return n.TypeParams -} - -// TypeParam is an alias for types.TypeParam -type TypeParam = types.TypeParam - -// TypeParamList is an alias for types.TypeParamList -type TypeParamList = types.TypeParamList - -// TypeList is an alias for types.TypeList -type TypeList = types.TypeList - -// NewTypeParam calls types.NewTypeParam. -func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam { - return types.NewTypeParam(name, constraint) -} - -// SetTypeParamConstraint calls tparam.SetConstraint(constraint). -func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) { - tparam.SetConstraint(constraint) -} - -// NewSignatureType calls types.NewSignatureType. -func NewSignatureType(recv *types.Var, recvTypeParams, typeParams []*TypeParam, params, results *types.Tuple, variadic bool) *types.Signature { - return types.NewSignatureType(recv, recvTypeParams, typeParams, params, results, variadic) -} - -// ForSignature returns sig.TypeParams() -func ForSignature(sig *types.Signature) *TypeParamList { - return sig.TypeParams() -} - -// RecvTypeParams returns sig.RecvTypeParams(). -func RecvTypeParams(sig *types.Signature) *TypeParamList { - return sig.RecvTypeParams() -} - -// IsComparable calls iface.IsComparable(). -func IsComparable(iface *types.Interface) bool { - return iface.IsComparable() -} - -// IsMethodSet calls iface.IsMethodSet(). -func IsMethodSet(iface *types.Interface) bool { - return iface.IsMethodSet() -} - -// IsImplicit calls iface.IsImplicit(). -func IsImplicit(iface *types.Interface) bool { - return iface.IsImplicit() -} - -// MarkImplicit calls iface.MarkImplicit(). -func MarkImplicit(iface *types.Interface) { - iface.MarkImplicit() -} - -// ForNamed extracts the (possibly empty) type parameter object list from -// named. -func ForNamed(named *types.Named) *TypeParamList { - return named.TypeParams() -} - -// SetForNamed sets the type params tparams on n. Each tparam must be of -// dynamic type *types.TypeParam. -func SetForNamed(n *types.Named, tparams []*TypeParam) { - n.SetTypeParams(tparams) -} - -// NamedTypeArgs returns named.TypeArgs(). -func NamedTypeArgs(named *types.Named) *TypeList { - return named.TypeArgs() -} - -// NamedTypeOrigin returns named.Orig(). -func NamedTypeOrigin(named *types.Named) *types.Named { - return named.Origin() -} - -// Term is an alias for types.Term. -type Term = types.Term - -// NewTerm calls types.NewTerm. -func NewTerm(tilde bool, typ types.Type) *Term { - return types.NewTerm(tilde, typ) -} - -// Union is an alias for types.Union -type Union = types.Union - -// NewUnion calls types.NewUnion. -func NewUnion(terms []*Term) *Union { - return types.NewUnion(terms) -} - -// InitInstanceInfo initializes info to record information about type and -// function instances. -func InitInstanceInfo(info *types.Info) { - info.Instances = make(map[*ast.Ident]types.Instance) -} - -// Instance is an alias for types.Instance. -type Instance = types.Instance - -// GetInstances returns info.Instances. -func GetInstances(info *types.Info) map[*ast.Ident]Instance { - return info.Instances -} - -// Context is an alias for types.Context. -type Context = types.Context - -// NewContext calls types.NewContext. -func NewContext() *Context { - return types.NewContext() -} - -// Instantiate calls types.Instantiate. -func Instantiate(ctxt *Context, typ types.Type, targs []types.Type, validate bool) (types.Type, error) { - return types.Instantiate(ctxt, typ, targs, validate) -} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/objectpath.go b/vendor/golang.org/x/tools/internal/typesinternal/objectpath.go deleted file mode 100644 index 5e96e89557..0000000000 --- a/vendor/golang.org/x/tools/internal/typesinternal/objectpath.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2023 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package typesinternal - -import "go/types" - -// This file contains back doors that allow gopls to avoid method sorting when -// using the objectpath package. -// -// This is performance-critical in certain repositories, but changing the -// behavior of the objectpath package is still being discussed in -// golang/go#61443. If we decide to remove the sorting in objectpath we can -// simply delete these back doors. Otherwise, we should add a new API to -// objectpath that allows controlling the sorting. - -// SkipEncoderMethodSorting marks enc (which must be an *objectpath.Encoder) as -// not requiring sorted methods. -var SkipEncoderMethodSorting func(enc interface{}) - -// ObjectpathObject is like objectpath.Object, but allows suppressing method -// sorting. -var ObjectpathObject func(pkg *types.Package, p string, skipMethodSorting bool) (types.Object, error) diff --git a/vendor/golang.org/x/tools/internal/versions/gover.go b/vendor/golang.org/x/tools/internal/versions/gover.go new file mode 100644 index 0000000000..bbabcd22e9 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/gover.go @@ -0,0 +1,172 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This is a fork of internal/gover for use by x/tools until +// go1.21 and earlier are no longer supported by x/tools. + +package versions + +import "strings" + +// A gover is a parsed Go gover: major[.Minor[.Patch]][kind[pre]] +// The numbers are the original decimal strings to avoid integer overflows +// and since there is very little actual math. (Probably overflow doesn't matter in practice, +// but at the time this code was written, there was an existing test that used +// go1.99999999999, which does not fit in an int on 32-bit platforms. +// The "big decimal" representation avoids the problem entirely.) +type gover struct { + major string // decimal + minor string // decimal or "" + patch string // decimal or "" + kind string // "", "alpha", "beta", "rc" + pre string // decimal or "" +} + +// compare returns -1, 0, or +1 depending on whether +// x < y, x == y, or x > y, interpreted as toolchain versions. +// The versions x and y must not begin with a "go" prefix: just "1.21" not "go1.21". +// Malformed versions compare less than well-formed versions and equal to each other. +// The language version "1.21" compares less than the release candidate and eventual releases "1.21rc1" and "1.21.0". +func compare(x, y string) int { + vx := parse(x) + vy := parse(y) + + if c := cmpInt(vx.major, vy.major); c != 0 { + return c + } + if c := cmpInt(vx.minor, vy.minor); c != 0 { + return c + } + if c := cmpInt(vx.patch, vy.patch); c != 0 { + return c + } + if c := strings.Compare(vx.kind, vy.kind); c != 0 { // "" < alpha < beta < rc + return c + } + if c := cmpInt(vx.pre, vy.pre); c != 0 { + return c + } + return 0 +} + +// lang returns the Go language version. For example, lang("1.2.3") == "1.2". +func lang(x string) string { + v := parse(x) + if v.minor == "" || v.major == "1" && v.minor == "0" { + return v.major + } + return v.major + "." + v.minor +} + +// isValid reports whether the version x is valid. +func isValid(x string) bool { + return parse(x) != gover{} +} + +// parse parses the Go version string x into a version. +// It returns the zero version if x is malformed. +func parse(x string) gover { + var v gover + + // Parse major version. + var ok bool + v.major, x, ok = cutInt(x) + if !ok { + return gover{} + } + if x == "" { + // Interpret "1" as "1.0.0". + v.minor = "0" + v.patch = "0" + return v + } + + // Parse . before minor version. + if x[0] != '.' { + return gover{} + } + + // Parse minor version. + v.minor, x, ok = cutInt(x[1:]) + if !ok { + return gover{} + } + if x == "" { + // Patch missing is same as "0" for older versions. + // Starting in Go 1.21, patch missing is different from explicit .0. + if cmpInt(v.minor, "21") < 0 { + v.patch = "0" + } + return v + } + + // Parse patch if present. + if x[0] == '.' { + v.patch, x, ok = cutInt(x[1:]) + if !ok || x != "" { + // Note that we are disallowing prereleases (alpha, beta, rc) for patch releases here (x != ""). + // Allowing them would be a bit confusing because we already have: + // 1.21 < 1.21rc1 + // But a prerelease of a patch would have the opposite effect: + // 1.21.3rc1 < 1.21.3 + // We've never needed them before, so let's not start now. + return gover{} + } + return v + } + + // Parse prerelease. + i := 0 + for i < len(x) && (x[i] < '0' || '9' < x[i]) { + if x[i] < 'a' || 'z' < x[i] { + return gover{} + } + i++ + } + if i == 0 { + return gover{} + } + v.kind, x = x[:i], x[i:] + if x == "" { + return v + } + v.pre, x, ok = cutInt(x) + if !ok || x != "" { + return gover{} + } + + return v +} + +// cutInt scans the leading decimal number at the start of x to an integer +// and returns that value and the rest of the string. +func cutInt(x string) (n, rest string, ok bool) { + i := 0 + for i < len(x) && '0' <= x[i] && x[i] <= '9' { + i++ + } + if i == 0 || x[0] == '0' && i != 1 { // no digits or unnecessary leading zero + return "", "", false + } + return x[:i], x[i:], true +} + +// cmpInt returns cmp.Compare(x, y) interpreting x and y as decimal numbers. +// (Copied from golang.org/x/mod/semver's compareInt.) +func cmpInt(x, y string) int { + if x == y { + return 0 + } + if len(x) < len(y) { + return -1 + } + if len(x) > len(y) { + return +1 + } + if x < y { + return -1 + } else { + return +1 + } +} diff --git a/vendor/golang.org/x/tools/internal/versions/types.go b/vendor/golang.org/x/tools/internal/versions/types.go new file mode 100644 index 0000000000..562eef21fa --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/types.go @@ -0,0 +1,19 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package versions + +import ( + "go/types" +) + +// GoVersion returns the Go version of the type package. +// It returns zero if no version can be determined. +func GoVersion(pkg *types.Package) string { + // TODO(taking): x/tools can call GoVersion() [from 1.21] after 1.25. + if pkg, ok := any(pkg).(interface{ GoVersion() string }); ok { + return pkg.GoVersion() + } + return "" +} diff --git a/vendor/golang.org/x/tools/internal/versions/types_go121.go b/vendor/golang.org/x/tools/internal/versions/types_go121.go new file mode 100644 index 0000000000..a7b79207ae --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/types_go121.go @@ -0,0 +1,20 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.22 +// +build !go1.22 + +package versions + +import ( + "go/ast" + "go/types" +) + +// FileVersions always reports the a file's Go version as the +// zero version at this Go version. +func FileVersions(info *types.Info, file *ast.File) string { return "" } + +// InitFileVersions is a noop at this Go version. +func InitFileVersions(*types.Info) {} diff --git a/vendor/golang.org/x/tools/internal/versions/types_go122.go b/vendor/golang.org/x/tools/internal/versions/types_go122.go new file mode 100644 index 0000000000..7b9ba89a82 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/types_go122.go @@ -0,0 +1,24 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.22 +// +build go1.22 + +package versions + +import ( + "go/ast" + "go/types" +) + +// FileVersions maps a file to the file's semantic Go version. +// The reported version is the zero version if a version cannot be determined. +func FileVersions(info *types.Info, file *ast.File) string { + return info.FileVersions[file] +} + +// InitFileVersions initializes info to record Go versions for Go files. +func InitFileVersions(info *types.Info) { + info.FileVersions = make(map[*ast.File]string) +} diff --git a/vendor/golang.org/x/tools/internal/versions/versions_go121.go b/vendor/golang.org/x/tools/internal/versions/versions_go121.go new file mode 100644 index 0000000000..cf4a7d0360 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/versions_go121.go @@ -0,0 +1,49 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !go1.22 +// +build !go1.22 + +package versions + +// Lang returns the Go language version for version x. +// If x is not a valid version, Lang returns the empty string. +// For example: +// +// Lang("go1.21rc2") = "go1.21" +// Lang("go1.21.2") = "go1.21" +// Lang("go1.21") = "go1.21" +// Lang("go1") = "go1" +// Lang("bad") = "" +// Lang("1.21") = "" +func Lang(x string) string { + v := lang(stripGo(x)) + if v == "" { + return "" + } + return x[:2+len(v)] // "go"+v without allocation +} + +// Compare returns -1, 0, or +1 depending on whether +// x < y, x == y, or x > y, interpreted as Go versions. +// The versions x and y must begin with a "go" prefix: "go1.21" not "1.21". +// Invalid versions, including the empty string, compare less than +// valid versions and equal to each other. +// The language version "go1.21" compares less than the +// release candidate and eventual releases "go1.21rc1" and "go1.21.0". +// Custom toolchain suffixes are ignored during comparison: +// "go1.21.0" and "go1.21.0-bigcorp" are equal. +func Compare(x, y string) int { return compare(stripGo(x), stripGo(y)) } + +// IsValid reports whether the version x is valid. +func IsValid(x string) bool { return isValid(stripGo(x)) } + +// stripGo converts from a "go1.21" version to a "1.21" version. +// If v does not start with "go", stripGo returns the empty string (a known invalid version). +func stripGo(v string) string { + if len(v) < 2 || v[:2] != "go" { + return "" + } + return v[2:] +} diff --git a/vendor/golang.org/x/tools/internal/versions/versions_go122.go b/vendor/golang.org/x/tools/internal/versions/versions_go122.go new file mode 100644 index 0000000000..c1c1814b28 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/versions/versions_go122.go @@ -0,0 +1,38 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.22 +// +build go1.22 + +package versions + +import ( + "go/version" +) + +// Lang returns the Go language version for version x. +// If x is not a valid version, Lang returns the empty string. +// For example: +// +// Lang("go1.21rc2") = "go1.21" +// Lang("go1.21.2") = "go1.21" +// Lang("go1.21") = "go1.21" +// Lang("go1") = "go1" +// Lang("bad") = "" +// Lang("1.21") = "" +func Lang(x string) string { return version.Lang(x) } + +// Compare returns -1, 0, or +1 depending on whether +// x < y, x == y, or x > y, interpreted as Go versions. +// The versions x and y must begin with a "go" prefix: "go1.21" not "1.21". +// Invalid versions, including the empty string, compare less than +// valid versions and equal to each other. +// The language version "go1.21" compares less than the +// release candidate and eventual releases "go1.21rc1" and "go1.21.0". +// Custom toolchain suffixes are ignored during comparison: +// "go1.21.0" and "go1.21.0-bigcorp" are equal. +func Compare(x, y string) int { return version.Compare(x, y) } + +// IsValid reports whether the version x is valid. +func IsValid(x string) bool { return version.IsValid(x) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 22c1a082b7..9804860347 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1456,7 +1456,7 @@ github.com/onsi/ginkgo/reporters/stenographer github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty github.com/onsi/ginkgo/types -# github.com/onsi/ginkgo/v2 v2.13.2 +# github.com/onsi/ginkgo/v2 v2.14.0 ## explicit; go 1.18 github.com/onsi/ginkgo/v2 github.com/onsi/ginkgo/v2/config @@ -2047,7 +2047,7 @@ golang.org/x/image/math/fixed golang.org/x/image/tiff golang.org/x/image/tiff/lzw golang.org/x/image/vector -# golang.org/x/mod v0.13.0 +# golang.org/x/mod v0.14.0 ## explicit; go 1.18 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/module @@ -2126,7 +2126,7 @@ golang.org/x/text/width # golang.org/x/time v0.5.0 ## explicit; go 1.18 golang.org/x/time/rate -# golang.org/x/tools v0.14.0 +# golang.org/x/tools v0.16.1 ## explicit; go 1.18 golang.org/x/tools/cmd/stringer golang.org/x/tools/go/ast/astutil @@ -2141,7 +2141,6 @@ golang.org/x/tools/internal/event/core golang.org/x/tools/internal/event/keys golang.org/x/tools/internal/event/label golang.org/x/tools/internal/event/tag -golang.org/x/tools/internal/fastwalk golang.org/x/tools/internal/gcimporter golang.org/x/tools/internal/gocommand golang.org/x/tools/internal/gopathwalk @@ -2151,6 +2150,7 @@ golang.org/x/tools/internal/pkgbits golang.org/x/tools/internal/tokeninternal golang.org/x/tools/internal/typeparams golang.org/x/tools/internal/typesinternal +golang.org/x/tools/internal/versions # golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 ## explicit; go 1.17 golang.org/x/xerrors From 0c2a5c620195355ad31adc23755283603d1030de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 06:36:09 +0000 Subject: [PATCH 06/73] build(deps): bump github.com/go-playground/validator/v10 Bumps [github.com/go-playground/validator/v10](https://github.com/go-playground/validator) from 10.16.0 to 10.17.0. - [Release notes](https://github.com/go-playground/validator/releases) - [Commits](https://github.com/go-playground/validator/compare/v10.16.0...v10.17.0) --- updated-dependencies: - dependency-name: github.com/go-playground/validator/v10 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- .../go-playground/validator/v10/README.md | 2 +- .../go-playground/validator/v10/errors.go | 8 ++- .../validator/v10/translations/en/en.go | 60 +++++++++++++++++++ vendor/modules.txt | 2 +- 6 files changed, 71 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index c7899f4808..d6fc1d5bbe 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( github.com/go-micro/plugins/v4/wrapper/monitoring/prometheus v1.2.0 github.com/go-micro/plugins/v4/wrapper/trace/opentelemetry v1.2.0 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 - github.com/go-playground/validator/v10 v10.16.0 + github.com/go-playground/validator/v10 v10.17.0 github.com/gofrs/uuid v4.4.0+incompatible github.com/golang-jwt/jwt/v4 v4.5.0 github.com/golang/protobuf v1.5.3 diff --git a/go.sum b/go.sum index 866581d454..0b17d066d2 100644 --- a/go.sum +++ b/go.sum @@ -1235,8 +1235,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= -github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74= +github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8= diff --git a/vendor/github.com/go-playground/validator/v10/README.md b/vendor/github.com/go-playground/validator/v10/README.md index dbbafc3e34..810097b3a9 100644 --- a/vendor/github.com/go-playground/validator/v10/README.md +++ b/vendor/github.com/go-playground/validator/v10/README.md @@ -1,7 +1,7 @@ Package validator ================= [![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -![Project status](https://img.shields.io/badge/version-10.16.0-green.svg) +![Project status](https://img.shields.io/badge/version-10.17.0-green.svg) [![Build Status](https://travis-ci.org/go-playground/validator.svg?branch=master)](https://travis-ci.org/go-playground/validator) [![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=master&service=github)](https://coveralls.io/github/go-playground/validator?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator) diff --git a/vendor/github.com/go-playground/validator/v10/errors.go b/vendor/github.com/go-playground/validator/v10/errors.go index 5856d57c8c..be2676e9e1 100644 --- a/vendor/github.com/go-playground/validator/v10/errors.go +++ b/vendor/github.com/go-playground/validator/v10/errors.go @@ -257,15 +257,19 @@ func (fe *fieldError) Error() string { // NOTE: if no registered translation can be found, it returns the original // untranslated error message. func (fe *fieldError) Translate(ut ut.Translator) string { + var fn TranslationFunc m, ok := fe.v.transTagFunc[ut] if !ok { return fe.Error() } - fn, ok := m[fe.tag] + fn, ok = m[fe.tag] if !ok { - return fe.Error() + fn, ok = m[fe.actualTag] + if !ok { + return fe.Error() + } } return fn(ut, fe) diff --git a/vendor/github.com/go-playground/validator/v10/translations/en/en.go b/vendor/github.com/go-playground/validator/v10/translations/en/en.go index 4c34dedbf5..9cef10ee3e 100644 --- a/vendor/github.com/go-playground/validator/v10/translations/en/en.go +++ b/vendor/github.com/go-playground/validator/v10/translations/en/en.go @@ -34,6 +34,66 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er translation: "{0} is a required field", override: false, }, + { + tag: "required_unless", + translation: "{0} is a required field", + override: false, + }, + { + tag: "required_with", + translation: "{0} is a required field", + override: false, + }, + { + tag: "required_with_all", + translation: "{0} is a required field", + override: false, + }, + { + tag: "required_without", + translation: "{0} is a required field", + override: false, + }, + { + tag: "required_without_all", + translation: "{0} is a required field", + override: false, + }, + { + tag: "excluded_if", + translation: "{0} is an excluded field", + override: false, + }, + { + tag: "excluded_unless", + translation: "{0} is an excluded field", + override: false, + }, + { + tag: "excluded_with", + translation: "{0} is an excluded field", + override: false, + }, + { + tag: "excluded_with_all", + translation: "{0} is an excluded field", + override: false, + }, + { + tag: "excluded_without", + translation: "{0} is an excluded field", + override: false, + }, + { + tag: "excluded_without_all", + translation: "{0} is an excluded field", + override: false, + }, + { + tag: "isdefault", + translation: "{0} must be default value", + override: false, + }, { tag: "len", customRegisFunc: func(ut ut.Translator) (err error) { diff --git a/vendor/modules.txt b/vendor/modules.txt index 9804860347..8feed6370a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -974,7 +974,7 @@ github.com/go-playground/locales/en # github.com/go-playground/universal-translator v0.18.1 ## explicit; go 1.18 github.com/go-playground/universal-translator -# github.com/go-playground/validator/v10 v10.16.0 +# github.com/go-playground/validator/v10 v10.17.0 ## explicit; go 1.18 github.com/go-playground/validator/v10 github.com/go-playground/validator/v10/translations/en From d14935ad781850f48693730749bdbc7ff6985639 Mon Sep 17 00:00:00 2001 From: Nalem7 <61624650+nabim777@users.noreply.github.com> Date: Wed, 17 Jan 2024 15:42:31 +0545 Subject: [PATCH 07/73] [tests-only][full-ci] Restructure the steps implementation for group delete to use graph API endpoint (#8006) * remove ocs endpoint from delete group * remove adminHasDeletedGroupUsingTheGraphApi * adressing reviews --- tests/TestHelpers/UserHelper.php | 62 ---------- .../features/bootstrap/GraphContext.php | 33 +----- .../features/bootstrap/Provisioning.php | 111 +----------------- .../createShareToSharesFolder.feature | 10 +- 4 files changed, 15 insertions(+), 201 deletions(-) diff --git a/tests/TestHelpers/UserHelper.php b/tests/TestHelpers/UserHelper.php index 33de75b374..e38e05981a 100644 --- a/tests/TestHelpers/UserHelper.php +++ b/tests/TestHelpers/UserHelper.php @@ -188,68 +188,6 @@ class UserHelper { ); } - /** - * - * @param string|null $baseUrl - * @param string|null $group - * @param string|null $adminUser - * @param string|null $adminPassword - * @param string|null $xRequestId - * - * @return ResponseInterface - * @throws GuzzleException - */ - public static function createGroup( - ?string $baseUrl, - ?string $group, - ?string $adminUser, - ?string $adminPassword, - ?string $xRequestId = '' - ):ResponseInterface { - return OcsApiHelper::sendRequest( - $baseUrl, - $adminUser, - $adminPassword, - "POST", - "/cloud/groups", - $xRequestId, - ['groupid' => $group] - ); - } - - /** - * - * @param string|null $baseUrl - * @param string|null $group - * @param string|null $adminUser - * @param string|null $adminPassword - * @param string|null $xRequestId - * @param int|null $ocsApiVersion - * - * @return ResponseInterface - * @throws GuzzleException - */ - public static function deleteGroup( - ?string $baseUrl, - ?string $group, - ?string $adminUser, - ?string $adminPassword, - ?string $xRequestId = '', - ?int $ocsApiVersion = 2 - ):ResponseInterface { - $group = \rawurlencode($group); - return OcsApiHelper::sendRequest( - $baseUrl, - $adminUser, - $adminPassword, - "DELETE", - "/cloud/groups/" . $group, - $xRequestId, - [], - $ocsApiVersion - ); - } - /** * * @param string|null $baseUrl diff --git a/tests/acceptance/features/bootstrap/GraphContext.php b/tests/acceptance/features/bootstrap/GraphContext.php index 729a492b45..4c0d76215c 100644 --- a/tests/acceptance/features/bootstrap/GraphContext.php +++ b/tests/acceptance/features/bootstrap/GraphContext.php @@ -287,21 +287,15 @@ class GraphContext implements Context { /** * @param string $groupId - * @param bool $checkResult * * @return void * @throws GuzzleException */ public function adminDeletesGroupWithGroupId( - string $groupId, - bool $checkResult = false + string $groupId ): void { - $this->featureContext->setResponse( - $this->userDeletesGroupWithGroupId($groupId) - ); - if ($checkResult) { - $this->featureContext->thenTheHTTPStatusCodeShouldBe(204); - } + $response = $this->userDeletesGroupWithGroupId($groupId); + $this->featureContext->theHTTPStatusCodeShouldBe(204, "", $response); } /** @@ -315,26 +309,7 @@ class GraphContext implements Context { string $group ): void { $groupId = $this->featureContext->getAttributeOfCreatedGroup($group, "id"); - if ($groupId) { - $this->adminDeletesGroupWithGroupId($groupId); - } else { - throw new Exception( - "Group id does not exist for '$group' in the created list." - . " Cannot delete group without id when using the Graph API." - ); - } - } - - /** - * @param string $group - * - * @return void - * @throws Exception - * @throws GuzzleException - */ - public function adminHasDeletedGroupUsingTheGraphApi(string $group): void { - $this->adminDeletesGroupUsingTheGraphApi($group); - $this->featureContext->thenTheHTTPStatusCodeShouldBe(204); + $this->adminDeletesGroupWithGroupId($groupId); } /** diff --git a/tests/acceptance/features/bootstrap/Provisioning.php b/tests/acceptance/features/bootstrap/Provisioning.php index 04bbad86c4..1ef51bd4bf 100644 --- a/tests/acceptance/features/bootstrap/Provisioning.php +++ b/tests/acceptance/features/bootstrap/Provisioning.php @@ -2672,10 +2672,10 @@ trait Provisioning { */ public function cleanupGroup(string $group):void { try { - if (OcisHelper::isTestingWithGraphApi()) { - $this->graphContext->adminHasDeletedGroupUsingTheGraphApi($group); + if ($this->isTestingWithLdap()) { + $this->deleteLdapGroup($group); } else { - $this->deleteTheGroupUsingTheProvisioningApi($group); + $this->graphContext->adminDeletesGroupUsingTheGraphApi($group); } } catch (Exception $e) { \error_log( @@ -3467,23 +3467,6 @@ trait Provisioning { return $response; } - /** - * @param string $group group name - * - * @return void - * @throws Exception - * @throws LdapException - */ - public function deleteGroup(string $group):void { - if ($this->groupExists($group)) { - if ($this->isTestingWithLdap() && \in_array($group, $this->ldapCreatedGroups)) { - $this->deleteLdapGroup($group); - } else { - $this->deleteTheGroupUsingTheProvisioningApi($group); - } - } - } - /** * @Given /^group "([^"]*)" has been deleted$/ * @@ -3494,96 +3477,14 @@ trait Provisioning { * @throws GuzzleException */ public function groupHasBeenDeleted(string $group):void { - if (OcisHelper::isTestingWithGraphApi()) { - $this->graphContext->adminHasDeletedGroupUsingTheGraphApi($group); + if ($this->isTestingWithLdap()) { + $this->deleteLdapGroup($group); } else { - $this->deleteGroup($group); + $this->graphContext->adminDeletesGroupUsingTheGraphApi($group); } $this->groupShouldNotExist($group); } - /** - * @When /^the administrator deletes group "([^"]*)" from the default user backend$/ - * - * @param string $group - * - * @return void - * @throws Exception - */ - public function adminDeletesGroup(string $group):void { - $this->deleteGroup($group); - $this->pushToLastStatusCodesArrays(); - } - - /** - * @When /^the administrator deletes group "([^"]*)" using the provisioning API$/ - * - * @param string $group - * - * @return void - * @throws Exception - */ - public function deleteTheGroupUsingTheProvisioningApi(string $group):void { - $this->emptyLastHTTPStatusCodesArray(); - $this->emptyLastOCSStatusCodesArray(); - $this->response = UserHelper::deleteGroup( - $this->getBaseUrl(), - $group, - $this->getAdminUsername(), - $this->getAdminPassword(), - $this->getStepLineRef(), - $this->ocsApiVersion - ); - $this->pushToLastStatusCodesArrays(); - if ($this->theGroupShouldExist($group) - && $this->theGroupShouldBeAbleToBeDeleted($group) - && ($this->response->getStatusCode() !== 200) - ) { - \error_log( - "INFORMATION: could not delete group '$group'" - . $this->response->getStatusCode() . " " . $this->response->getBody() - ); - } - - $this->rememberThatGroupIsNotExpectedToExist($group); - } - - /** - * @When the administrator deletes the following groups using the provisioning API - * - * @param TableNode $table - * - * @return void - * @throws Exception - */ - public function theAdministratorDeletesTheFollowingGroupsUsingTheProvisioningApi(TableNode $table):void { - $this->verifyTableNodeColumns($table, ["groupname"]); - $groups = $table->getHash(); - foreach ($groups as $group) { - $this->deleteTheGroupUsingTheProvisioningApi($group["groupname"]); - } - } - - /** - * @When user :user tries to delete group :group using the provisioning API - * - * @param string $user - * @param string $group - * - * @return void - * @throws JsonException - */ - public function userTriesToDeleteGroupUsingTheProvisioningApi(string $user, string $group):void { - $this->response = UserHelper::deleteGroup( - $this->getBaseUrl(), - $group, - $this->getActualUsername($user), - $this->getActualPassword($user), - $this->getStepLineRef(), - $this->ocsApiVersion - ); - } - /** * @param string $group * diff --git a/tests/acceptance/features/coreApiShareManagementBasicToShares/createShareToSharesFolder.feature b/tests/acceptance/features/coreApiShareManagementBasicToShares/createShareToSharesFolder.feature index bc35b8aed3..8ea802c838 100644 --- a/tests/acceptance/features/coreApiShareManagementBasicToShares/createShareToSharesFolder.feature +++ b/tests/acceptance/features/coreApiShareManagementBasicToShares/createShareToSharesFolder.feature @@ -452,13 +452,13 @@ Feature: sharing Then the OCS status code should be "" And the HTTP status code should be "200" And the fields of the last response to user "Alice" sharing with group "grp1" should include - | share_with | grp1 | - | file_target | /textfile0.txt | - | path | /textfile0.txt | - | uid_owner | %username% | + | share_with | grp1 | + | file_target | /Shares/textfile0.txt | + | path | /textfile0.txt | + | uid_owner | %username% | Then as "Brian" file "/Shares/textfile0.txt" should exist And as "Carol" file "/Shares/textfile0.txt" should exist - When the administrator deletes group "grp1" using the provisioning API + When the administrator deletes group "grp1" using the Graph API And user "Alice" sends HTTP method "GET" to OCS API endpoint "/apps/files_sharing/api/v1/shares" Then the OCS status code should be "" And the HTTP status code should be "200" From 386e37cbdc8060bbd22ecb5f626a94a69df1257e Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 17 Jan 2024 11:58:56 +0100 Subject: [PATCH 08/73] cleanup graph/.../driveitems.go Signed-off-by: jkoberg --- .../unreleased/cleanup-graph-driveitemsgo.md | 5 + services/graph/pkg/service/v0/driveitems.go | 233 +++++++++--------- 2 files changed, 121 insertions(+), 117 deletions(-) create mode 100644 changelog/unreleased/cleanup-graph-driveitemsgo.md diff --git a/changelog/unreleased/cleanup-graph-driveitemsgo.md b/changelog/unreleased/cleanup-graph-driveitemsgo.md new file mode 100644 index 0000000000..aa6ddf2804 --- /dev/null +++ b/changelog/unreleased/cleanup-graph-driveitemsgo.md @@ -0,0 +1,5 @@ +Bugfix: Cleanup graph/pkg/service/v0/driveitems.go + +Main fix is using proto getters to avoid panics. But some other code improvements were also done + +https://github.com/owncloud/ocis/pull/8228 diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go index c686e78bdc..f469ed42ab 100644 --- a/services/graph/pkg/service/v0/driveitems.go +++ b/services/graph/pkg/service/v0/driveitems.go @@ -2,6 +2,7 @@ package svc import ( "context" + "encoding/hex" "encoding/json" "errors" "fmt" @@ -41,7 +42,6 @@ import ( "github.com/owncloud/ocis/v2/services/graph/pkg/validate" ) -// From https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0 // CreateUploadSession create an upload session to allow your app to upload files up to the maximum file size. // An upload session allows your app to upload ranges of the file in sequential API requests, which allows the // transfer to be resumed if a connection is dropped while the upload is in progress. @@ -55,6 +55,7 @@ import ( // } // // ``` +// From https://learn.microsoft.com/en-us/graph/api/driveitem-createuploadsession?view=graph-rest-1.0 func (g Graph) CreateUploadSession(w http.ResponseWriter, r *http.Request) { g.logger.Info().Msg("Calling CreateUploadSession") @@ -68,7 +69,7 @@ func (g Graph) CreateUploadSession(w http.ResponseWriter, r *http.Request) { errorcode.RenderError(w, r, err) return } - if driveID.StorageId != driveItemID.StorageId || driveID.SpaceId != driveItemID.SpaceId { + if driveID.GetStorageId() != driveItemID.GetStorageId() || driveID.GetSpaceId() != driveItemID.GetSpaceId() { errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, "Item does not exist") return } @@ -101,27 +102,27 @@ func (g Graph) CreateUploadSession(w http.ResponseWriter, r *http.Request) { case err != nil: errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return - case res.Status.Code == cs3rpc.Code_CODE_OK: + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_OK: // ok - case res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND: - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_NOT_FOUND: + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.GetStatus().GetMessage()) return - case res.Status.Code == cs3rpc.Code_CODE_PERMISSION_DENIED: - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) // do not leak existence? check what graph does + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_PERMISSION_DENIED: + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.GetStatus().GetMessage()) // do not leak existence? check what graph does return - case res.Status.Code == cs3rpc.Code_CODE_UNAUTHENTICATED: - errorcode.Unauthenticated.Render(w, r, http.StatusUnauthorized, res.Status.Message) // do not leak existence? check what graph does + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_UNAUTHENTICATED: + errorcode.Unauthenticated.Render(w, r, http.StatusUnauthorized, res.GetStatus().GetMessage()) // do not leak existence? check what graph does return default: - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.GetStatus().GetMessage()) return } uploadSession := uploadSession{ - CS3Protocols: res.Protocols, + CS3Protocols: res.GetProtocols(), } - for _, p := range res.Protocols { - if p.Protocol == "simple" { - uploadSession.UploadUrl = p.UploadEndpoint + "/" + p.Token + for _, p := range res.GetProtocols() { + if p.GetProtocol() == "simple" { + uploadSession.UploadURL = p.GetUploadEndpoint() + "/" + p.GetToken() } } render.Status(r, http.StatusOK) @@ -129,18 +130,18 @@ func (g Graph) CreateUploadSession(w http.ResponseWriter, r *http.Request) { } type createUploadSessionRequest struct { - DeferCommit bool - Item driveItemUploadableProperties + DeferCommit bool `json:"deferCommit"` + Item driveItemUploadableProperties `json:"item"` } type driveItemUploadableProperties struct { // ConflictBehavior "@microsoft.graph.conflictBehavior" //Description string - FileSize int64 + FileSize int64 `json:"fileSize"` // fileSystemInfo - Name string + Name string `json:"name"` } type uploadSession struct { - UploadUrl string + UploadURL string //"expirationDateTime": "2015-01-29T09:21:55.523Z", //"nextExpectedRanges": ["0-"] CS3Protocols []*gateway.FileUploadProtocol @@ -161,7 +162,7 @@ func (g Graph) GetRootDriveChildren(w http.ResponseWriter, r *http.Request) { currentUser := revactx.ContextMustGetUser(r.Context()) // do we need to list all or only the personal drive filters := []*storageprovider.ListStorageSpacesRequest_Filter{} - filters = append(filters, listStorageSpacesUserFilter(currentUser.GetId().OpaqueId)) + filters = append(filters, listStorageSpacesUserFilter(currentUser.GetId().GetOpaqueId())) filters = append(filters, listStorageSpacesTypeFilter("personal")) res, err := gatewayClient.ListStorageSpaces(ctx, &storageprovider.ListStorageSpacesRequest{ @@ -172,47 +173,47 @@ func (g Graph) GetRootDriveChildren(w http.ResponseWriter, r *http.Request) { g.logger.Error().Err(err).Msg("error making ListStorageSpaces grpc call") errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) return - case res.Status.Code != cs3rpc.Code_CODE_OK: - if res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) + case res.GetStatus().GetCode() != cs3rpc.Code_CODE_OK: + if res.GetStatus().GetCode() == cs3rpc.Code_CODE_NOT_FOUND { + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.GetStatus().GetMessage()) return } g.logger.Error().Err(err).Msg("error sending ListStorageSpaces grpc request") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.GetStatus().GetMessage()) return } var space *storageprovider.StorageSpace - for _, s := range res.StorageSpaces { + for _, s := range res.GetStorageSpaces() { if utils.UserIDEqual(currentUser.GetId(), s.GetOwner().GetId()) { space = s } } lRes, err := gatewayClient.ListContainer(ctx, &storageprovider.ListContainerRequest{ - Ref: &storageprovider.Reference{ResourceId: space.Root}, + Ref: &storageprovider.Reference{ResourceId: space.GetRoot()}, }) switch { case err != nil: g.logger.Error().Err(err).Msg("error making ListContainer grpc call") errorcode.ServiceNotAvailable.Render(w, r, http.StatusInternalServerError, err.Error()) return - case lRes.Status.Code != cs3rpc.Code_CODE_OK: - if lRes.Status.Code == cs3rpc.Code_CODE_NOT_FOUND { - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, lRes.Status.Message) + case lRes.GetStatus().GetCode() != cs3rpc.Code_CODE_OK: + if lRes.GetStatus().GetCode() == cs3rpc.Code_CODE_NOT_FOUND { + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, lRes.GetStatus().GetMessage()) return } - if lRes.Status.Code == cs3rpc.Code_CODE_PERMISSION_DENIED { + if lRes.GetStatus().GetCode() == cs3rpc.Code_CODE_PERMISSION_DENIED { // TODO check if we should return 404 to not disclose existing items - errorcode.AccessDenied.Render(w, r, http.StatusForbidden, lRes.Status.Message) + errorcode.AccessDenied.Render(w, r, http.StatusForbidden, lRes.GetStatus().GetMessage()) return } g.logger.Error().Err(err).Msg("error sending list container grpc request") - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.GetStatus().GetMessage()) return } - files, err := formatDriveItems(g.logger, lRes.Infos) + files, err := formatDriveItems(g.logger, lRes.GetInfos()) if err != nil { g.logger.Error().Err(err).Msg("error encoding response as json") errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) @@ -238,7 +239,7 @@ func (g Graph) GetDriveItem(w http.ResponseWriter, r *http.Request) { errorcode.RenderError(w, r, err) return } - if driveID.StorageId != driveItemID.StorageId || driveID.SpaceId != driveItemID.SpaceId { + if driveID.GetStorageId() != driveItemID.GetStorageId() || driveID.GetSpaceId() != driveItemID.GetSpaceId() { errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, "Item does not exist") return } @@ -262,22 +263,22 @@ func (g Graph) GetDriveItem(w http.ResponseWriter, r *http.Request) { case err != nil: errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return - case res.Status.Code == cs3rpc.Code_CODE_OK: + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_OK: // ok - case res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND: - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_NOT_FOUND: + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.GetStatus().GetMessage()) return - case res.Status.Code == cs3rpc.Code_CODE_PERMISSION_DENIED: - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) // do not leak existence? check what graph does + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_PERMISSION_DENIED: + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.GetStatus().GetMessage()) // do not leak existence? check what graph does return - case res.Status.Code == cs3rpc.Code_CODE_UNAUTHENTICATED: - errorcode.Unauthenticated.Render(w, r, http.StatusUnauthorized, res.Status.Message) // do not leak existence? check what graph does + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_UNAUTHENTICATED: + errorcode.Unauthenticated.Render(w, r, http.StatusUnauthorized, res.GetStatus().GetMessage()) // do not leak existence? check what graph does return default: - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.GetStatus().GetMessage()) return } - driveItem, err := cs3ResourceToDriveItem(g.logger, res.Info) + driveItem, err := cs3ResourceToDriveItem(g.logger, res.GetInfo()) if err != nil { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return @@ -302,7 +303,7 @@ func (g Graph) GetDriveItemChildren(w http.ResponseWriter, r *http.Request) { errorcode.RenderError(w, r, err) return } - if driveID.StorageId != driveItemID.StorageId || driveID.SpaceId != driveItemID.SpaceId { + if driveID.GetStorageId() != driveItemID.GetStorageId() || driveID.GetSpaceId() != driveItemID.GetSpaceId() { errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, "Item does not exist") return } @@ -329,23 +330,23 @@ func (g Graph) GetDriveItemChildren(w http.ResponseWriter, r *http.Request) { case err != nil: errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return - case res.Status.Code == cs3rpc.Code_CODE_OK: + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_OK: // ok - case res.Status.Code == cs3rpc.Code_CODE_NOT_FOUND: - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_NOT_FOUND: + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.GetStatus().GetMessage()) return - case res.Status.Code == cs3rpc.Code_CODE_PERMISSION_DENIED: - errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.Status.Message) // do not leak existence? check what graph does + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_PERMISSION_DENIED: + errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, res.GetStatus().GetMessage()) // do not leak existence? check what graph does return - case res.Status.Code == cs3rpc.Code_CODE_UNAUTHENTICATED: - errorcode.Unauthenticated.Render(w, r, http.StatusUnauthorized, res.Status.Message) // do not leak existence? check what graph does + case res.GetStatus().GetCode() == cs3rpc.Code_CODE_UNAUTHENTICATED: + errorcode.Unauthenticated.Render(w, r, http.StatusUnauthorized, res.GetStatus().GetMessage()) // do not leak existence? check what graph does return default: - errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.Status.Message) + errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, res.GetStatus().GetMessage()) return } - files, err := formatDriveItems(g.logger, res.Infos) + files, err := formatDriveItems(g.logger, res.GetInfos()) if err != nil { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, err.Error()) return @@ -372,7 +373,7 @@ func (g Graph) ListPermissions(w http.ResponseWriter, r *http.Request) { statResponse, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: &itemID}}) if errCode := errorcode.FromStat(statResponse, err); errCode != nil { - g.logger.Warn().Err(errCode).Interface("stat.res", statResponse) + g.logger.Warn().Err(errCode).Interface("stat.res", statResponse).Msg("stat failed") errCode.Render(w, r) return } @@ -452,8 +453,8 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { } unifiedRolePermissions := []*libregraph.UnifiedRolePermission{{AllowedResourceActions: driveItemInvite.LibreGraphPermissionsActions}} - for _, roleId := range driveItemInvite.GetRoles() { - role, err := unifiedrole.NewUnifiedRoleFromID(roleId, g.config.FilesSharing.EnableResharing) + for _, roleID := range driveItemInvite.GetRoles() { + role, err := unifiedrole.NewUnifiedRoleFromID(roleID, g.config.FilesSharing.EnableResharing) if err != nil { g.logger.Debug().Err(err).Interface("role", driveItemInvite.GetRoles()[0]).Msg("unable to convert requested role") errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) @@ -465,14 +466,14 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { statResponse, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: &itemID}}) if errCode := errorcode.FromStat(statResponse, err); errCode != nil { - g.logger.Warn().Err(errCode).Interface("stat.res", statResponse) + g.logger.Warn().Err(errCode).Interface("stat.res", statResponse).Msg("stat failed") errCode.Render(w, r) return } driveRecipient := driveItemInvite.GetRecipients()[0] - objectId := driveRecipient.GetObjectId() + objectID := driveRecipient.GetObjectId() cs3ResourcePermissions := unifiedrole.PermissionsToCS3ResourcePermissions(unifiedRolePermissions) createShareRequest := &collaboration.CreateShareRequest{ @@ -495,9 +496,9 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { switch driveRecipient.GetLibreGraphRecipientType() { case "group": - group, err := g.identityCache.GetGroup(ctx, objectId) + group, err := g.identityCache.GetGroup(ctx, objectID) if err != nil { - g.logger.Debug().Err(err).Interface("groupId", objectId).Msg("failed group lookup") + g.logger.Debug().Err(err).Interface("groupId", objectID).Msg("failed group lookup") errorcode.GeneralException.Render(w, r, http.StatusBadRequest, err.Error()) return } @@ -514,9 +515,9 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { }, } default: - user, err := g.identityCache.GetUser(ctx, objectId) + user, err := g.identityCache.GetUser(ctx, objectID) if err != nil { - g.logger.Debug().Err(err).Interface("userId", objectId).Msg("failed user lookup") + g.logger.Debug().Err(err).Interface("userId", objectID).Msg("failed user lookup") errorcode.GeneralException.Render(w, r, http.StatusBadRequest, err.Error()) return } @@ -588,7 +589,7 @@ func (g Graph) UpdatePermission(w http.ResponseWriter, r *http.Request) { return } - oldPermission, sharedResourceId, err := g.getPermissionByID(ctx, permissionID) + oldPermission, sharedResourceID, err := g.getPermissionByID(ctx, permissionID) if err != nil { errorcode.RenderError(w, r, err) return @@ -596,7 +597,7 @@ func (g Graph) UpdatePermission(w http.ResponseWriter, r *http.Request) { // The resourceID of the shared resource need to match the item ID from the Request Path // otherwise this is an invalid Request. - if !utils.ResourceIDEqual(sharedResourceId, &itemID) { + if !utils.ResourceIDEqual(sharedResourceID, &itemID) { g.logger.Debug().Msg("resourceID of shared does not match itemID") errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "permissionID and itemID do not match") return @@ -622,7 +623,6 @@ func (g Graph) UpdatePermission(w http.ResponseWriter, r *http.Request) { } render.Status(r, http.StatusOK) render.JSON(w, r, &updatedPermission) - return } // DeletePermission removes a Permission from a Drive item @@ -643,13 +643,13 @@ func (g Graph) DeletePermission(w http.ResponseWriter, r *http.Request) { ctx := r.Context() isUserPermission := true - // Check if the id is refering to a User Share - sharedResourceId, err := g.getUserPermissionResourceID(ctx, permissionID) + // Check if the id is referring to a User Share + sharedResourceID, err := g.getUserPermissionResourceID(ctx, permissionID) var errcode errorcode.Error if err != nil && errors.As(err, &errcode) && errcode.GetCode() == errorcode.ItemNotFound { // there is no user share with that ID, so lets check if it is referring to a public link isUserPermission = false - sharedResourceId, err = g.getLinkPermissionResourceID(ctx, permissionID) + sharedResourceID, err = g.getLinkPermissionResourceID(ctx, permissionID) } if err != nil { @@ -659,7 +659,7 @@ func (g Graph) DeletePermission(w http.ResponseWriter, r *http.Request) { // The resourceID of the shared resource need to match the item ID from the Request Path // otherwise this is an invalid Request. - if !utils.ResourceIDEqual(sharedResourceId, &itemID) { + if !utils.ResourceIDEqual(sharedResourceID, &itemID) { g.logger.Debug().Msg("resourceID of shared does not match itemID") errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "permissionID and itemID do not match") return @@ -679,7 +679,6 @@ func (g Graph) DeletePermission(w http.ResponseWriter, r *http.Request) { render.Status(r, http.StatusNoContent) render.NoContent(w, r) - return } func (g Graph) getPermissionByID(ctx context.Context, permissionID string) (*libregraph.Permission, *storageprovider.ResourceId, error) { @@ -741,7 +740,7 @@ func (g Graph) getCS3UserShareByID(ctx context.Context, permissionID string) (*c return getShareResp.GetShare(), nil } -func (g Graph) updateUserShare(ctx context.Context, permissionID string, oldPermission, newPermission *libregraph.Permission) (*libregraph.Permission, error) { +func (g Graph) updateUserShare(ctx context.Context, permissionID string, _, newPermission *libregraph.Permission) (*libregraph.Permission, error) { gatewayClient, err := g.gatewaySelector.Next() if err != nil { g.logger.Debug().Err(err).Msg("selecting gatewaySelector failed") @@ -765,8 +764,8 @@ func (g Graph) updateUserShare(ctx context.Context, permissionID string, oldPerm var roles, allowedResourceActions []string var permissionsUpdated, ok bool if roles, ok = newPermission.GetRolesOk(); ok && len(roles) > 0 { - for _, roleId := range roles { - role, err := unifiedrole.NewUnifiedRoleFromID(roleId, g.config.FilesSharing.EnableResharing) + for _, roleID := range roles { + role, err := unifiedrole.NewUnifiedRoleFromID(roleID, g.config.FilesSharing.EnableResharing) if err != nil { g.logger.Debug().Err(err).Interface("role", role).Msg("unable to convert requested role") return nil, err @@ -906,11 +905,11 @@ func (g Graph) getDriveItem(ctx context.Context, ref storageprovider.Reference) if err != nil { return nil, err } - if res.Status.Code != cs3rpc.Code_CODE_OK { + if res.GetStatus().GetCode() != cs3rpc.Code_CODE_OK { refStr, _ := storagespace.FormatReference(&ref) - return nil, fmt.Errorf("could not stat %s: %s", refStr, res.Status.Message) + return nil, fmt.Errorf("could not stat %s: %s", refStr, res.GetStatus().GetMessage()) } - return cs3ResourceToDriveItem(g.logger, res.Info) + return cs3ResourceToDriveItem(g.logger, res.GetInfo()) } func (g Graph) getRemoteItem(ctx context.Context, root *storageprovider.ResourceId, baseURL *url.URL) (*libregraph.RemoteItem, error) { @@ -926,12 +925,12 @@ func (g Graph) getRemoteItem(ctx context.Context, root *storageprovider.Resource if err != nil { return nil, err } - if res.Status.Code != cs3rpc.Code_CODE_OK { + if res.GetStatus().GetCode() != cs3rpc.Code_CODE_OK { // Only log this, there could be mountpoints which have no grant - g.logger.Debug().Msg(res.Status.Message) + g.logger.Debug().Msg(res.GetStatus().GetMessage()) return nil, errors.New("could not fetch grant resource for the mountpoint") } - item, err := cs3ResourceToRemoteItem(res.Info) + item, err := cs3ResourceToRemoteItem(res.GetInfo()) if err != nil { return nil, err } @@ -965,46 +964,46 @@ func formatDriveItems(logger *log.Logger, mds []*storageprovider.ResourceInfo) ( } func cs3TimestampToTime(t *types.Timestamp) time.Time { - return time.Unix(int64(t.Seconds), int64(t.Nanos)) + return time.Unix(int64(t.GetSeconds()), int64(t.GetNanos())) } func cs3ResourceToDriveItem(logger *log.Logger, res *storageprovider.ResourceInfo) (*libregraph.DriveItem, error) { size := new(int64) - *size = int64(res.Size) // TODO lurking overflow: make size of libregraph drive item use uint64 + *size = int64(res.GetSize()) // TODO lurking overflow: make size of libregraph drive item use uint64 driveItem := &libregraph.DriveItem{ - Id: libregraph.PtrString(storagespace.FormatResourceID(*res.Id)), + Id: libregraph.PtrString(storagespace.FormatResourceID(*res.GetId())), Size: size, } - if name := path.Base(res.Path); name != "" { + if name := path.Base(res.GetPath()); name != "" { driveItem.Name = &name } - if res.Etag != "" { + if res.GetEtag() != "" { driveItem.ETag = &res.Etag } - if res.Mtime != nil { - lastModified := cs3TimestampToTime(res.Mtime) + if res.GetMtime() != nil { + lastModified := cs3TimestampToTime(res.GetMtime()) driveItem.LastModifiedDateTime = &lastModified } - if res.ParentId != nil { + if res.GetParentId() != nil { parentRef := libregraph.NewItemReference() - parentRef.SetDriveType(res.Space.SpaceType) - parentRef.SetDriveId(storagespace.FormatStorageID(res.ParentId.StorageId, res.ParentId.SpaceId)) - parentRef.SetId(storagespace.FormatResourceID(*res.ParentId)) + parentRef.SetDriveType(res.GetSpace().GetSpaceType()) + parentRef.SetDriveId(storagespace.FormatStorageID(res.GetParentId().GetStorageId(), res.GetParentId().GetSpaceId())) + parentRef.SetId(storagespace.FormatResourceID(*res.GetParentId())) driveItem.ParentReference = parentRef } - if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_FILE && res.MimeType != "" { + if res.GetType() == storageprovider.ResourceType_RESOURCE_TYPE_FILE && res.GetMimeType() != "" { // We cannot use a libregraph.File here because the openapi codegenerator autodetects 'File' as a go type ... driveItem.File = &libregraph.OpenGraphFile{ MimeType: &res.MimeType, } } - if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER { + if res.GetType() == storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER { driveItem.Folder = &libregraph.Folder{} } - if res.ArbitraryMetadata != nil { + if res.GetArbitraryMetadata() != nil { driveItem.Audio = cs3ResourceToDriveItemAudioFacet(logger, res) driveItem.Location = cs3ResourceToDriveItemLocationFacet(logger, res) } @@ -1013,11 +1012,11 @@ func cs3ResourceToDriveItem(logger *log.Logger, res *storageprovider.ResourceInf } func cs3ResourceToDriveItemAudioFacet(logger *log.Logger, res *storageprovider.ResourceInfo) *libregraph.Audio { - if !strings.HasPrefix(res.MimeType, "audio/") { + if !strings.HasPrefix(res.GetMimeType(), "audio/") { return nil } - k := res.ArbitraryMetadata.Metadata + k := res.GetArbitraryMetadata().GetMetadata() if k == nil { return nil } @@ -1031,7 +1030,7 @@ func cs3ResourceToDriveItemAudioFacet(logger *log.Logger, res *storageprovider.R } func cs3ResourceToDriveItemLocationFacet(logger *log.Logger, res *storageprovider.ResourceInfo) *libregraph.GeoCoordinates { - k := res.ArbitraryMetadata.Metadata + k := res.GetArbitraryMetadata().GetMetadata() if k == nil { return nil } @@ -1099,30 +1098,30 @@ func unmarshalStringMap(logger *log.Logger, out any, flatMap map[string]string, func cs3ResourceToRemoteItem(res *storageprovider.ResourceInfo) (*libregraph.RemoteItem, error) { size := new(int64) - *size = int64(res.Size) // TODO lurking overflow: make size of libregraph drive item use uint64 + *size = int64(res.GetSize()) // TODO lurking overflow: make size of libregraph drive item use uint64 remoteItem := &libregraph.RemoteItem{ - Id: libregraph.PtrString(storagespace.FormatResourceID(*res.Id)), + Id: libregraph.PtrString(storagespace.FormatResourceID(*res.GetId())), Size: size, } if res.GetPath() != "" { remoteItem.Path = libregraph.PtrString(path.Clean(res.GetPath())) } - if res.Etag != "" { + if res.GetEtag() != "" { remoteItem.ETag = &res.Etag } - if res.Mtime != nil { - lastModified := cs3TimestampToTime(res.Mtime) + if res.GetMtime() != nil { + lastModified := cs3TimestampToTime(res.GetMtime()) remoteItem.LastModifiedDateTime = &lastModified } - if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_FILE && res.MimeType != "" { + if res.GetType() == storageprovider.ResourceType_RESOURCE_TYPE_FILE && res.GetMimeType() != "" { // We cannot use a libregraph.File here because the openapi codegenerator autodetects 'File' as a go type ... remoteItem.File = &libregraph.OpenGraphFile{ MimeType: &res.MimeType, } } - if res.Type == storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER { + if res.GetType() == storageprovider.ResourceType_RESOURCE_TYPE_CONTAINER { remoteItem.Folder = &libregraph.Folder{} } if res.GetSpace() != nil && res.GetSpace().GetRoot() != nil { @@ -1145,10 +1144,10 @@ func (g Graph) getPathForResource(ctx context.Context, id storageprovider.Resour if err != nil { return "", err } - if res.Status.Code != cs3rpc.Code_CODE_OK { - return "", fmt.Errorf("could not stat %v: %s", id, res.Status.Message) + if res.GetStatus().GetCode() != cs3rpc.Code_CODE_OK { + return "", fmt.Errorf("could not stat %v: %s", id, res.GetStatus().GetMessage()) } - return res.Path, err + return res.GetPath(), err } // getSpecialDriveItems reads properties from the opaque and transforms them into driveItems @@ -1156,20 +1155,20 @@ func (g Graph) getSpecialDriveItems(ctx context.Context, baseURL *url.URL, space if space.GetRoot().GetStorageId() == utils.ShareStorageProviderID { return nil // no point in stating the ShareStorageProvider } - if space.Opaque == nil { + if space.GetOpaque() == nil { return nil } - imageNode := utils.ReadPlainFromOpaque(space.Opaque, SpaceImageSpecialFolderName) - readmeNode := utils.ReadPlainFromOpaque(space.Opaque, ReadmeSpecialFolderName) + imageNode := utils.ReadPlainFromOpaque(space.GetOpaque(), SpaceImageSpecialFolderName) + readmeNode := utils.ReadPlainFromOpaque(space.GetOpaque(), ReadmeSpecialFolderName) - cachekey := spaceRootStatKey(space.Root, imageNode, readmeNode) + cachekey := spaceRootStatKey(space.GetRoot(), imageNode, readmeNode) // if the root is older or equal to our cache we can reuse the cached extended spaces properties if entry := g.specialDriveItemsCache.Get(cachekey); entry != nil { if cached, ok := entry.Value().(specialDriveItemEntry); ok { - if cached.rootMtime != nil && space.Mtime != nil { + if cached.rootMtime != nil && space.GetMtime() != nil { // beware, LaterTS does not handle equalness. it returns t1 if t1 > t2, else t2, so a >= check looks like this - if utils.LaterTS(space.Mtime, cached.rootMtime) == cached.rootMtime { + if utils.LaterTS(space.GetMtime(), cached.rootMtime) == cached.rootMtime { return cached.specialDriveItems } } @@ -1184,7 +1183,7 @@ func (g Graph) getSpecialDriveItems(ctx context.Context, baseURL *url.URL, space // cache properties spacePropertiesEntry := specialDriveItemEntry{ specialDriveItems: spaceItems, - rootMtime: space.Mtime, + rootMtime: space.GetMtime(), } g.specialDriveItemsCache.Set(cachekey, spacePropertiesEntry, time.Duration(g.config.Spaces.ExtendedSpacePropertiesCacheTTL)) @@ -1222,7 +1221,7 @@ func spaceRootStatKey(id *storageprovider.ResourceId, imagenode, readmeNode stri _, _ = shakeHash.Write([]byte(readmeNode)) h := make([]byte, 64) _, _ = shakeHash.Read(h) - return fmt.Sprintf("%x", h) + return hex.EncodeToString(h) } type specialDriveItemEntry struct { @@ -1244,10 +1243,10 @@ func (g Graph) getSpecialDriveItem(ctx context.Context, ref storageprovider.Refe g.logger.Debug().Err(err).Str("ID", ref.GetResourceId().GetOpaqueId()).Str("name", itemName).Msg("Could not get item info") return nil } - itemPath := ref.Path + itemPath := ref.GetPath() if itemPath == "" { // lookup by id - itemPath, err = g.getPathForResource(ctx, *ref.ResourceId) + itemPath, err = g.getPathForResource(ctx, *ref.GetResourceId()) if err != nil { g.logger.Debug().Err(err).Str("ID", ref.GetResourceId().GetOpaqueId()).Str("name", itemName).Msg("Could not get item path") return nil @@ -1255,7 +1254,7 @@ func (g Graph) getSpecialDriveItem(ctx context.Context, ref storageprovider.Refe } spaceItem.SpecialFolder = &libregraph.SpecialFolder{Name: libregraph.PtrString(itemName)} webdavURL := *baseURL - webdavURL.Path = path.Join(webdavURL.Path, space.Id.OpaqueId, itemPath) + webdavURL.Path = path.Join(webdavURL.Path, space.GetId().GetOpaqueId(), itemPath) spaceItem.WebDavUrl = libregraph.PtrString(webdavURL.String()) return spaceItem From 7e750159ca2d464330c20ad738940d8e47ca2a6f Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Wed, 17 Jan 2024 12:25:31 +0100 Subject: [PATCH 09/73] change ocis basepath from home to Signed-off-by: Christian Richter --- docs/helpers/configenvextractor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/helpers/configenvextractor.go b/docs/helpers/configenvextractor.go index 46178d9982..40e76c7134 100644 --- a/docs/helpers/configenvextractor.go +++ b/docs/helpers/configenvextractor.go @@ -63,7 +63,7 @@ func generateIntermediateCode(templatePath string, intermediateCodePath string, func runIntermediateCode(intermediateCodePath string) { fmt.Println("Running intermediate go code for " + intermediateCodePath) - defaultPath := "~/.ocis" + defaultPath := "/etc/ocis" os.Setenv("OCIS_BASE_DATA_PATH", defaultPath) os.Setenv("OCIS_CONFIG_DIR", path.Join(defaultPath, "config")) out, err := exec.Command("go", "run", intermediateCodePath).Output() From aac3a772c5569ff48495ba7ff64bd064382b3ee8 Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Wed, 17 Jan 2024 13:17:12 +0100 Subject: [PATCH 10/73] add variable for defaultDataPath Signed-off-by: Christian Richter --- docs/helpers/configenvextractor.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/helpers/configenvextractor.go b/docs/helpers/configenvextractor.go index 40e76c7134..474a1fee3c 100644 --- a/docs/helpers/configenvextractor.go +++ b/docs/helpers/configenvextractor.go @@ -63,9 +63,10 @@ func generateIntermediateCode(templatePath string, intermediateCodePath string, func runIntermediateCode(intermediateCodePath string) { fmt.Println("Running intermediate go code for " + intermediateCodePath) - defaultPath := "/etc/ocis" - os.Setenv("OCIS_BASE_DATA_PATH", defaultPath) - os.Setenv("OCIS_CONFIG_DIR", path.Join(defaultPath, "config")) + defaultConfigPath := "/etc/ocis" + defaultDataPath := "/var/lib/ocis" + os.Setenv("OCIS_BASE_DATA_PATH", defaultDataPath) + os.Setenv("OCIS_CONFIG_DIR", defaultConfigPath) out, err := exec.Command("go", "run", intermediateCodePath).Output() if err != nil { log.Fatal(err) From a4d71134f5f612e0ebc27ad82749b3bff330f5c7 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 17 Jan 2024 13:21:28 +0100 Subject: [PATCH 11/73] remove unused parameter Signed-off-by: jkoberg --- services/graph/pkg/service/v0/driveitems.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go index f469ed42ab..da010478b4 100644 --- a/services/graph/pkg/service/v0/driveitems.go +++ b/services/graph/pkg/service/v0/driveitems.go @@ -616,7 +616,7 @@ func (g Graph) UpdatePermission(w http.ResponseWriter, r *http.Request) { } // This is a user share - updatedPermission, err := g.updateUserShare(ctx, permissionID, oldPermission, permission) + updatedPermission, err := g.updateUserShare(ctx, permissionID, permission) if err != nil { errorcode.RenderError(w, r, err) return @@ -740,7 +740,7 @@ func (g Graph) getCS3UserShareByID(ctx context.Context, permissionID string) (*c return getShareResp.GetShare(), nil } -func (g Graph) updateUserShare(ctx context.Context, permissionID string, _, newPermission *libregraph.Permission) (*libregraph.Permission, error) { +func (g Graph) updateUserShare(ctx context.Context, permissionID string, newPermission *libregraph.Permission) (*libregraph.Permission, error) { gatewayClient, err := g.gatewaySelector.Next() if err != nil { g.logger.Debug().Err(err).Msg("selecting gatewaySelector failed") From b8b0d0b533701a777d2970c94da0e31e784c6531 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 17 Jan 2024 12:49:02 +0100 Subject: [PATCH 12/73] cleanup search/.../search.go Signed-off-by: jkoberg --- .../unreleased/cleanup-search-searchgo.md | 5 +++ services/search/pkg/search/search.go | 40 +++++++++---------- 2 files changed, 25 insertions(+), 20 deletions(-) create mode 100644 changelog/unreleased/cleanup-search-searchgo.md diff --git a/changelog/unreleased/cleanup-search-searchgo.md b/changelog/unreleased/cleanup-search-searchgo.md new file mode 100644 index 0000000000..4bfa9b2c60 --- /dev/null +++ b/changelog/unreleased/cleanup-search-searchgo.md @@ -0,0 +1,5 @@ +Bugfix: Cleanup `search/pkg/search/search.go` + +Now uses proto getters to avoid panics. + +https://github.com/owncloud/ocis/pull/8230 diff --git a/services/search/pkg/search/search.go b/services/search/pkg/search/search.go index 6bce856ea0..4c53bd0a92 100644 --- a/services/search/pkg/search/search.go +++ b/services/search/pkg/search/search.go @@ -32,9 +32,9 @@ func ResolveReference(ctx context.Context, ref *provider.Reference, ri *provider } gpRes, err := gatewayClient.GetPath(ctx, &provider.GetPathRequest{ - ResourceId: ri.Id, + ResourceId: ri.GetId(), }) - if err != nil || gpRes.Status.Code != rpc.Code_CODE_OK { + if err != nil || gpRes.GetStatus().GetCode() != rpc.Code_CODE_OK { return nil, err } return &provider.Reference{ @@ -43,7 +43,7 @@ func ResolveReference(ctx context.Context, ref *provider.Reference, ri *provider SpaceId: ref.GetResourceId().GetSpaceId(), OpaqueId: ref.GetResourceId().GetSpaceId(), }, - Path: utils.MakeRelativePath(gpRes.Path), + Path: utils.MakeRelativePath(gpRes.GetPath()), }, nil } @@ -56,7 +56,7 @@ func (ma matchArray) Swap(i, j int) { ma[i], ma[j] = ma[j], ma[i] } func (ma matchArray) Less(i, j int) bool { - return ma[i].Score > ma[j].Score + return ma[i].GetScore() > ma[j].GetScore() } func logDocCount(engine engine.Engine, logger log.Logger) { @@ -88,7 +88,7 @@ func statResource(ctx context.Context, ref *provider.Reference, gatewaySelector logger.Error().Err(err).Msg("failed to stat the moved resource") return nil, err } - switch res.Status.Code { + switch res.GetStatus().GetCode() { case rpc.Code_CODE_OK: return res, nil case rpc.Code_CODE_NOT_FOUND: @@ -111,34 +111,34 @@ func convertToWebDAVPermissions(isShared, isMountpoint, isDir bool, p *provider. if isShared { fmt.Fprintf(&b, "S") } - if p.ListContainer && - p.ListFileVersions && - p.ListRecycle && - p.Stat && - p.GetPath && - p.GetQuota && - p.InitiateFileDownload { + if p.GetListContainer() && + p.GetListFileVersions() && + p.GetListRecycle() && + p.GetStat() && + p.GetGetPath() && + p.GetGetQuota() && + p.GetInitiateFileDownload() { fmt.Fprintf(&b, "R") } if isMountpoint { fmt.Fprintf(&b, "M") } - if p.Delete { + if p.GetDelete() { fmt.Fprintf(&b, "D") } - if p.InitiateFileUpload && - p.RestoreFileVersion && - p.RestoreRecycleItem { + if p.GetInitiateFileUpload() && + p.GetRestoreFileVersion() && + p.GetRestoreRecycleItem() { fmt.Fprintf(&b, "NV") if !isDir { fmt.Fprintf(&b, "W") } } if isDir && - p.ListContainer && - p.Stat && - p.CreateContainer && - p.InitiateFileUpload { + p.GetListContainer() && + p.GetStat() && + p.GetCreateContainer() && + p.GetInitiateFileUpload() { fmt.Fprintf(&b, "CK") } return b.String() From 9632a2bb1d3a84a3e12e5e8e6a7ff7fd21c75d90 Mon Sep 17 00:00:00 2001 From: kobergj Date: Wed, 17 Jan 2024 13:41:10 +0000 Subject: [PATCH 13/73] Automated changelog update [skip ci] --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e526b04577..61d845d3e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,8 @@ The following sections list the changes for unreleased. * Bugfix - Fix patching of language: [#8182](https://github.com/owncloud/ocis/pull/8182) * Bugfix - Fix search service to not log expected cases as errors: [#8200](https://github.com/owncloud/ocis/pull/8200) * Bugfix - Updating and reset logo failed: [#8211](https://github.com/owncloud/ocis/pull/8211) +* Bugfix - Cleanup graph/pkg/service/v0/driveitems.go: [#8228](https://github.com/owncloud/ocis/pull/8228) +* Bugfix - Cleanup `search/pkg/search/search.go`: [#8230](https://github.com/owncloud/ocis/pull/8230) * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) * Enhancement - Update reva to latest edge version: [#8100](https://github.com/owncloud/ocis/pull/8100) @@ -112,6 +114,19 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/issues/8101 https://github.com/owncloud/ocis/pull/8211 +* Bugfix - Cleanup graph/pkg/service/v0/driveitems.go: [#8228](https://github.com/owncloud/ocis/pull/8228) + + Main fix is using proto getters to avoid panics. But some other code + improvements were also done + + https://github.com/owncloud/ocis/pull/8228 + +* Bugfix - Cleanup `search/pkg/search/search.go`: [#8230](https://github.com/owncloud/ocis/pull/8230) + + Now uses proto getters to avoid panics. + + https://github.com/owncloud/ocis/pull/8230 + * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) We add the environment variable that allow to disable the password policy. From 348ad20b32002a753f49824f0fb3723585dff8d3 Mon Sep 17 00:00:00 2001 From: ownClouders Date: Thu, 18 Jan 2024 00:49:12 +0000 Subject: [PATCH 14/73] [tx] updated from transifex --- .../userlog/pkg/service/l10n/locale/ru/LC_MESSAGES/userlog.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/userlog/pkg/service/l10n/locale/ru/LC_MESSAGES/userlog.po b/services/userlog/pkg/service/l10n/locale/ru/LC_MESSAGES/userlog.po index 887f62d281..7438cabedc 100644 --- a/services/userlog/pkg/service/l10n/locale/ru/LC_MESSAGES/userlog.po +++ b/services/userlog/pkg/service/l10n/locale/ru/LC_MESSAGES/userlog.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: EMAIL\n" -"POT-Creation-Date: 2023-12-28 00:05+0000\n" +"POT-Creation-Date: 2024-01-18 00:47+0000\n" "PO-Revision-Date: 2023-03-15 08:28+0000\n" "Last-Translator: Roman Perekhod, 2023\n" "Language-Team: Russian (https://app.transifex.com/owncloud-org/teams/6149/ru/)\n" From 575af0f8588292223af861fe9cdd645ae3b9ef02 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 06:50:16 +0000 Subject: [PATCH 15/73] build(deps): bump go.opentelemetry.io/otel/sdk from 1.21.0 to 1.22.0 Bumps [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) from 1.21.0 to 1.22.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.21.0...v1.22.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/sdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 10 +- go.sum | 20 +- vendor/github.com/go-logr/logr/README.md | 67 +- vendor/github.com/go-logr/logr/context.go | 33 + .../github.com/go-logr/logr/context_noslog.go | 49 + .../github.com/go-logr/logr/context_slog.go | 83 + vendor/github.com/go-logr/logr/funcr/funcr.go | 189 +- .../github.com/go-logr/logr/funcr/slogsink.go | 105 + vendor/github.com/go-logr/logr/logr.go | 43 - vendor/github.com/go-logr/logr/sloghandler.go | 192 + vendor/github.com/go-logr/logr/slogr.go | 100 + vendor/github.com/go-logr/logr/slogsink.go | 120 + vendor/go.opentelemetry.io/otel/CHANGELOG.md | 43 +- .../go.opentelemetry.io/otel/CONTRIBUTING.md | 21 + vendor/go.opentelemetry.io/otel/README.md | 2 +- vendor/go.opentelemetry.io/otel/RELEASING.md | 6 +- .../go.opentelemetry.io/otel/attribute/set.go | 91 +- .../otel/baggage/baggage.go | 332 +- vendor/go.opentelemetry.io/otel/doc.go | 2 +- .../otel/propagation/trace_context.go | 96 +- .../otel/sdk/resource/builtin.go | 2 +- .../otel/sdk/resource/container.go | 2 +- .../otel/sdk/resource/env.go | 2 +- .../otel/sdk/resource/host_id.go | 2 +- .../otel/sdk/resource/os.go | 2 +- .../otel/sdk/resource/process.go | 2 +- .../otel/sdk/trace/span.go | 19 +- .../go.opentelemetry.io/otel/sdk/version.go | 2 +- .../otel/semconv/v1.21.0/doc.go | 4 +- .../otel/semconv/v1.24.0/attribute_group.go | 4398 +++++++++++++++++ .../otel/semconv/v1.24.0/doc.go | 20 + .../otel/semconv/v1.24.0/event.go | 211 + .../otel/semconv/v1.24.0/exception.go | 20 + .../otel/semconv/v1.24.0/resource.go | 2556 ++++++++++ .../otel/semconv/v1.24.0/schema.go | 20 + .../otel/semconv/v1.24.0/trace.go | 1334 +++++ .../otel/trace/tracestate.go | 201 +- vendor/go.opentelemetry.io/otel/version.go | 2 +- vendor/go.opentelemetry.io/otel/versions.yaml | 4 +- vendor/modules.txt | 11 +- 40 files changed, 10073 insertions(+), 345 deletions(-) create mode 100644 vendor/github.com/go-logr/logr/context.go create mode 100644 vendor/github.com/go-logr/logr/context_noslog.go create mode 100644 vendor/github.com/go-logr/logr/context_slog.go create mode 100644 vendor/github.com/go-logr/logr/funcr/slogsink.go create mode 100644 vendor/github.com/go-logr/logr/sloghandler.go create mode 100644 vendor/github.com/go-logr/logr/slogr.go create mode 100644 vendor/github.com/go-logr/logr/slogsink.go create mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/attribute_group.go create mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/doc.go create mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/event.go create mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/exception.go create mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/resource.go create mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/schema.go create mode 100644 vendor/go.opentelemetry.io/otel/semconv/v1.24.0/trace.go diff --git a/go.mod b/go.mod index d6fc1d5bbe..b571bddb4e 100644 --- a/go.mod +++ b/go.mod @@ -90,11 +90,11 @@ require ( go.etcd.io/bbolt v1.3.8 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 go.opentelemetry.io/contrib/zpages v0.46.1 - go.opentelemetry.io/otel v1.21.0 + go.opentelemetry.io/otel v1.22.0 go.opentelemetry.io/otel/exporters/jaeger v1.17.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 - go.opentelemetry.io/otel/sdk v1.21.0 - go.opentelemetry.io/otel/trace v1.21.0 + go.opentelemetry.io/otel/sdk v1.22.0 + go.opentelemetry.io/otel/trace v1.22.0 golang.org/x/crypto v0.18.0 golang.org/x/image v0.15.0 golang.org/x/net v0.20.0 @@ -193,7 +193,7 @@ require ( github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-micro/plugins/v4/events/natsjs v1.2.2-0.20231215124540-f7f8d3274bf9 // indirect github.com/go-micro/plugins/v4/store/nats-js v1.2.1-0.20231129143103-d72facc652f0 // indirect @@ -328,7 +328,7 @@ require ( go.opentelemetry.io/contrib v1.0.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect diff --git a/go.sum b/go.sum index 0b17d066d2..a7c1a6fcad 100644 --- a/go.sum +++ b/go.sum @@ -1186,8 +1186,8 @@ github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KE github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= @@ -2094,22 +2094,22 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1: go.opentelemetry.io/contrib/zpages v0.46.1 h1:U8Hh84dc+vJTVgRnL+QKWtWD2iqTSKibrQ85EeQqsNg= go.opentelemetry.io/contrib/zpages v0.46.1/go.mod h1:1Wq9YTzkhr3Jkyi/sVrasFSppVzJQcvFf2Vc2ExZd6c= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U= diff --git a/vendor/github.com/go-logr/logr/README.md b/vendor/github.com/go-logr/logr/README.md index a8c29bfbd5..8969526a6e 100644 --- a/vendor/github.com/go-logr/logr/README.md +++ b/vendor/github.com/go-logr/logr/README.md @@ -91,11 +91,12 @@ logr design but also left out some parts and changed others: | Adding a name to a logger | `WithName` | no API | | Modify verbosity of log entries in a call chain | `V` | no API | | Grouping of key/value pairs | not supported | `WithGroup`, `GroupValue` | +| Pass context for extracting additional values | no API | API variants like `InfoCtx` | The high-level slog API is explicitly meant to be one of many different APIs that can be layered on top of a shared `slog.Handler`. logr is one such -alternative API, with [interoperability](#slog-interoperability) provided by the [`slogr`](slogr) -package. +alternative API, with [interoperability](#slog-interoperability) provided by +some conversion functions. ### Inspiration @@ -145,24 +146,24 @@ There are implementations for the following logging libraries: ## slog interoperability Interoperability goes both ways, using the `logr.Logger` API with a `slog.Handler` -and using the `slog.Logger` API with a `logr.LogSink`. [slogr](./slogr) provides `NewLogr` and -`NewSlogHandler` API calls to convert between a `logr.Logger` and a `slog.Handler`. +and using the `slog.Logger` API with a `logr.LogSink`. `FromSlogHandler` and +`ToSlogHandler` convert between a `logr.Logger` and a `slog.Handler`. As usual, `slog.New` can be used to wrap such a `slog.Handler` in the high-level -slog API. `slogr` itself leaves that to the caller. +slog API. -## Using a `logr.Sink` as backend for slog +### Using a `logr.LogSink` as backend for slog Ideally, a logr sink implementation should support both logr and slog by -implementing both the normal logr interface(s) and `slogr.SlogSink`. Because +implementing both the normal logr interface(s) and `SlogSink`. Because of a conflict in the parameters of the common `Enabled` method, it is [not possible to implement both slog.Handler and logr.Sink in the same type](https://github.com/golang/go/issues/59110). If both are supported, log calls can go from the high-level APIs to the backend -without the need to convert parameters. `NewLogr` and `NewSlogHandler` can +without the need to convert parameters. `FromSlogHandler` and `ToSlogHandler` can convert back and forth without adding additional wrappers, with one exception: when `Logger.V` was used to adjust the verbosity for a `slog.Handler`, then -`NewSlogHandler` has to use a wrapper which adjusts the verbosity for future +`ToSlogHandler` has to use a wrapper which adjusts the verbosity for future log calls. Such an implementation should also support values that implement specific @@ -187,13 +188,13 @@ Not supporting slog has several drawbacks: These drawbacks are severe enough that applications using a mixture of slog and logr should switch to a different backend. -## Using a `slog.Handler` as backend for logr +### Using a `slog.Handler` as backend for logr Using a plain `slog.Handler` without support for logr works better than the other direction: - All logr verbosity levels can be mapped 1:1 to their corresponding slog level by negating them. -- Stack unwinding is done by the `slogr.SlogSink` and the resulting program +- Stack unwinding is done by the `SlogSink` and the resulting program counter is passed to the `slog.Handler`. - Names added via `Logger.WithName` are gathered and recorded in an additional attribute with `logger` as key and the names separated by slash as value. @@ -205,27 +206,39 @@ ideally support both `logr.Marshaler` and `slog.Valuer`. If compatibility with logr implementations without slog support is not important, then `slog.Valuer` is sufficient. -## Context support for slog +### Context support for slog Storing a logger in a `context.Context` is not supported by -slog. `logr.NewContext` and `logr.FromContext` can be used with slog like this -to fill this gap: +slog. `NewContextWithSlogLogger` and `FromContextAsSlogLogger` can be +used to fill this gap. They store and retrieve a `slog.Logger` pointer +under the same context key that is also used by `NewContext` and +`FromContext` for `logr.Logger` value. - func HandlerFromContext(ctx context.Context) slog.Handler { - logger, err := logr.FromContext(ctx) - if err == nil { - return slogr.NewSlogHandler(logger) - } - return slog.Default().Handler() - } +When `NewContextWithSlogLogger` is followed by `FromContext`, the latter will +automatically convert the `slog.Logger` to a +`logr.Logger`. `FromContextAsSlogLogger` does the same for the other direction. - func ContextWithHandler(ctx context.Context, handler slog.Handler) context.Context { - return logr.NewContext(ctx, slogr.NewLogr(handler)) - } +With this approach, binaries which use either slog or logr are as efficient as +possible with no unnecessary allocations. This is also why the API stores a +`slog.Logger` pointer: when storing a `slog.Handler`, creating a `slog.Logger` +on retrieval would need to allocate one. -The downside is that storing and retrieving a `slog.Handler` needs more -allocations compared to using a `logr.Logger`. Therefore the recommendation is -to use the `logr.Logger` API in code which uses contextual logging. +The downside is that switching back and forth needs more allocations. Because +logr is the API that is already in use by different packages, in particular +Kubernetes, the recommendation is to use the `logr.Logger` API in code which +uses contextual logging. + +An alternative to adding values to a logger and storing that logger in the +context is to store the values in the context and to configure a logging +backend to extract those values when emitting log entries. This only works when +log calls are passed the context, which is not supported by the logr API. + +With the slog API, it is possible, but not +required. https://github.com/veqryn/slog-context is a package for slog which +provides additional support code for this approach. It also contains wrappers +for the context functions in logr, so developers who prefer to not use the logr +APIs directly can use those instead and the resulting code will still be +interoperable with logr. ## FAQ diff --git a/vendor/github.com/go-logr/logr/context.go b/vendor/github.com/go-logr/logr/context.go new file mode 100644 index 0000000000..de8bcc3ad8 --- /dev/null +++ b/vendor/github.com/go-logr/logr/context.go @@ -0,0 +1,33 @@ +/* +Copyright 2023 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logr + +// contextKey is how we find Loggers in a context.Context. With Go < 1.21, +// the value is always a Logger value. With Go >= 1.21, the value can be a +// Logger value or a slog.Logger pointer. +type contextKey struct{} + +// notFoundError exists to carry an IsNotFound method. +type notFoundError struct{} + +func (notFoundError) Error() string { + return "no logr.Logger was present" +} + +func (notFoundError) IsNotFound() bool { + return true +} diff --git a/vendor/github.com/go-logr/logr/context_noslog.go b/vendor/github.com/go-logr/logr/context_noslog.go new file mode 100644 index 0000000000..f012f9a18e --- /dev/null +++ b/vendor/github.com/go-logr/logr/context_noslog.go @@ -0,0 +1,49 @@ +//go:build !go1.21 +// +build !go1.21 + +/* +Copyright 2019 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logr + +import ( + "context" +) + +// FromContext returns a Logger from ctx or an error if no Logger is found. +func FromContext(ctx context.Context) (Logger, error) { + if v, ok := ctx.Value(contextKey{}).(Logger); ok { + return v, nil + } + + return Logger{}, notFoundError{} +} + +// FromContextOrDiscard returns a Logger from ctx. If no Logger is found, this +// returns a Logger that discards all log messages. +func FromContextOrDiscard(ctx context.Context) Logger { + if v, ok := ctx.Value(contextKey{}).(Logger); ok { + return v + } + + return Discard() +} + +// NewContext returns a new Context, derived from ctx, which carries the +// provided Logger. +func NewContext(ctx context.Context, logger Logger) context.Context { + return context.WithValue(ctx, contextKey{}, logger) +} diff --git a/vendor/github.com/go-logr/logr/context_slog.go b/vendor/github.com/go-logr/logr/context_slog.go new file mode 100644 index 0000000000..065ef0b828 --- /dev/null +++ b/vendor/github.com/go-logr/logr/context_slog.go @@ -0,0 +1,83 @@ +//go:build go1.21 +// +build go1.21 + +/* +Copyright 2019 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logr + +import ( + "context" + "fmt" + "log/slog" +) + +// FromContext returns a Logger from ctx or an error if no Logger is found. +func FromContext(ctx context.Context) (Logger, error) { + v := ctx.Value(contextKey{}) + if v == nil { + return Logger{}, notFoundError{} + } + + switch v := v.(type) { + case Logger: + return v, nil + case *slog.Logger: + return FromSlogHandler(v.Handler()), nil + default: + // Not reached. + panic(fmt.Sprintf("unexpected value type for logr context key: %T", v)) + } +} + +// FromContextAsSlogLogger returns a slog.Logger from ctx or nil if no such Logger is found. +func FromContextAsSlogLogger(ctx context.Context) *slog.Logger { + v := ctx.Value(contextKey{}) + if v == nil { + return nil + } + + switch v := v.(type) { + case Logger: + return slog.New(ToSlogHandler(v)) + case *slog.Logger: + return v + default: + // Not reached. + panic(fmt.Sprintf("unexpected value type for logr context key: %T", v)) + } +} + +// FromContextOrDiscard returns a Logger from ctx. If no Logger is found, this +// returns a Logger that discards all log messages. +func FromContextOrDiscard(ctx context.Context) Logger { + if logger, err := FromContext(ctx); err == nil { + return logger + } + return Discard() +} + +// NewContext returns a new Context, derived from ctx, which carries the +// provided Logger. +func NewContext(ctx context.Context, logger Logger) context.Context { + return context.WithValue(ctx, contextKey{}, logger) +} + +// NewContextWithSlogLogger returns a new Context, derived from ctx, which carries the +// provided slog.Logger. +func NewContextWithSlogLogger(ctx context.Context, logger *slog.Logger) context.Context { + return context.WithValue(ctx, contextKey{}, logger) +} diff --git a/vendor/github.com/go-logr/logr/funcr/funcr.go b/vendor/github.com/go-logr/logr/funcr/funcr.go index 12e5807cc5..fb2f866f4b 100644 --- a/vendor/github.com/go-logr/logr/funcr/funcr.go +++ b/vendor/github.com/go-logr/logr/funcr/funcr.go @@ -100,6 +100,11 @@ type Options struct { // details, see docs for Go's time.Layout. TimestampFormat string + // LogInfoLevel tells funcr what key to use to log the info level. + // If not specified, the info level will be logged as "level". + // If this is set to "", the info level will not be logged at all. + LogInfoLevel *string + // Verbosity tells funcr which V logs to produce. Higher values enable // more logs. Info logs at or below this level will be written, while logs // above this level will be discarded. @@ -213,6 +218,10 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter { if opts.MaxLogDepth == 0 { opts.MaxLogDepth = defaultMaxLogDepth } + if opts.LogInfoLevel == nil { + opts.LogInfoLevel = new(string) + *opts.LogInfoLevel = "level" + } f := Formatter{ outputFormat: outfmt, prefix: "", @@ -227,12 +236,15 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter { // implementation. It should be constructed with NewFormatter. Some of // its methods directly implement logr.LogSink. type Formatter struct { - outputFormat outputFormat - prefix string - values []any - valuesStr string - depth int - opts *Options + outputFormat outputFormat + prefix string + values []any + valuesStr string + parentValuesStr string + depth int + opts *Options + group string // for slog groups + groupDepth int } // outputFormat indicates which outputFormat to use. @@ -253,33 +265,62 @@ func (f Formatter) render(builtins, args []any) string { // Empirically bytes.Buffer is faster than strings.Builder for this. buf := bytes.NewBuffer(make([]byte, 0, 1024)) if f.outputFormat == outputJSON { - buf.WriteByte('{') + buf.WriteByte('{') // for the whole line } + vals := builtins if hook := f.opts.RenderBuiltinsHook; hook != nil { vals = hook(f.sanitize(vals)) } f.flatten(buf, vals, false, false) // keys are ours, no need to escape continuing := len(builtins) > 0 - if len(f.valuesStr) > 0 { + + if f.parentValuesStr != "" { if continuing { - if f.outputFormat == outputJSON { - buf.WriteByte(',') - } else { - buf.WriteByte(' ') - } + buf.WriteByte(f.comma()) } + buf.WriteString(f.parentValuesStr) continuing = true - buf.WriteString(f.valuesStr) } + + groupDepth := f.groupDepth + if f.group != "" { + if f.valuesStr != "" || len(args) != 0 { + if continuing { + buf.WriteByte(f.comma()) + } + buf.WriteString(f.quoted(f.group, true)) // escape user-provided keys + buf.WriteByte(f.colon()) + buf.WriteByte('{') // for the group + continuing = false + } else { + // The group was empty + groupDepth-- + } + } + + if f.valuesStr != "" { + if continuing { + buf.WriteByte(f.comma()) + } + buf.WriteString(f.valuesStr) + continuing = true + } + vals = args if hook := f.opts.RenderArgsHook; hook != nil { vals = hook(f.sanitize(vals)) } f.flatten(buf, vals, continuing, true) // escape user-provided keys - if f.outputFormat == outputJSON { - buf.WriteByte('}') + + for i := 0; i < groupDepth; i++ { + buf.WriteByte('}') // for the groups } + + if f.outputFormat == outputJSON { + buf.WriteByte('}') // for the whole line + } + return buf.String() } @@ -298,9 +339,16 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, esc if len(kvList)%2 != 0 { kvList = append(kvList, noValue) } + copied := false for i := 0; i < len(kvList); i += 2 { k, ok := kvList[i].(string) if !ok { + if !copied { + newList := make([]any, len(kvList)) + copy(newList, kvList) + kvList = newList + copied = true + } k = f.nonStringKey(kvList[i]) kvList[i] = k } @@ -308,7 +356,7 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, esc if i > 0 || continuing { if f.outputFormat == outputJSON { - buf.WriteByte(',') + buf.WriteByte(f.comma()) } else { // In theory the format could be something we don't understand. In // practice, we control it, so it won't be. @@ -316,24 +364,35 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, esc } } - if escapeKeys { - buf.WriteString(prettyString(k)) - } else { - // this is faster - buf.WriteByte('"') - buf.WriteString(k) - buf.WriteByte('"') - } - if f.outputFormat == outputJSON { - buf.WriteByte(':') - } else { - buf.WriteByte('=') - } + buf.WriteString(f.quoted(k, escapeKeys)) + buf.WriteByte(f.colon()) buf.WriteString(f.pretty(v)) } return kvList } +func (f Formatter) quoted(str string, escape bool) string { + if escape { + return prettyString(str) + } + // this is faster + return `"` + str + `"` +} + +func (f Formatter) comma() byte { + if f.outputFormat == outputJSON { + return ',' + } + return ' ' +} + +func (f Formatter) colon() byte { + if f.outputFormat == outputJSON { + return ':' + } + return '=' +} + func (f Formatter) pretty(value any) string { return f.prettyWithFlags(value, 0, 0) } @@ -407,12 +466,12 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string { } for i := 0; i < len(v); i += 2 { if i > 0 { - buf.WriteByte(',') + buf.WriteByte(f.comma()) } k, _ := v[i].(string) // sanitize() above means no need to check success // arbitrary keys might need escaping buf.WriteString(prettyString(k)) - buf.WriteByte(':') + buf.WriteByte(f.colon()) buf.WriteString(f.prettyWithFlags(v[i+1], 0, depth+1)) } if flags&flagRawStruct == 0 { @@ -481,7 +540,7 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string { continue } if printComma { - buf.WriteByte(',') + buf.WriteByte(f.comma()) } printComma = true // if we got here, we are rendering a field if fld.Anonymous && fld.Type.Kind() == reflect.Struct && name == "" { @@ -492,10 +551,8 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string { name = fld.Name } // field names can't contain characters which need escaping - buf.WriteByte('"') - buf.WriteString(name) - buf.WriteByte('"') - buf.WriteByte(':') + buf.WriteString(f.quoted(name, false)) + buf.WriteByte(f.colon()) buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), 0, depth+1)) } if flags&flagRawStruct == 0 { @@ -520,7 +577,7 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string { buf.WriteByte('[') for i := 0; i < v.Len(); i++ { if i > 0 { - buf.WriteByte(',') + buf.WriteByte(f.comma()) } e := v.Index(i) buf.WriteString(f.prettyWithFlags(e.Interface(), 0, depth+1)) @@ -534,7 +591,7 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string { i := 0 for it.Next() { if i > 0 { - buf.WriteByte(',') + buf.WriteByte(f.comma()) } // If a map key supports TextMarshaler, use it. keystr := "" @@ -556,7 +613,7 @@ func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string { } } buf.WriteString(keystr) - buf.WriteByte(':') + buf.WriteByte(f.colon()) buf.WriteString(f.prettyWithFlags(it.Value().Interface(), 0, depth+1)) i++ } @@ -706,6 +763,53 @@ func (f Formatter) sanitize(kvList []any) []any { return kvList } +// startGroup opens a new group scope (basically a sub-struct), which locks all +// the current saved values and starts them anew. This is needed to satisfy +// slog. +func (f *Formatter) startGroup(group string) { + // Unnamed groups are just inlined. + if group == "" { + return + } + + // Any saved values can no longer be changed. + buf := bytes.NewBuffer(make([]byte, 0, 1024)) + continuing := false + + if f.parentValuesStr != "" { + buf.WriteString(f.parentValuesStr) + continuing = true + } + + if f.group != "" && f.valuesStr != "" { + if continuing { + buf.WriteByte(f.comma()) + } + buf.WriteString(f.quoted(f.group, true)) // escape user-provided keys + buf.WriteByte(f.colon()) + buf.WriteByte('{') // for the group + continuing = false + } + + if f.valuesStr != "" { + if continuing { + buf.WriteByte(f.comma()) + } + buf.WriteString(f.valuesStr) + } + + // NOTE: We don't close the scope here - that's done later, when a log line + // is actually rendered (because we have N scopes to close). + + f.parentValuesStr = buf.String() + + // Start collecting new values. + f.group = group + f.groupDepth++ + f.valuesStr = "" + f.values = nil +} + // Init configures this Formatter from runtime info, such as the call depth // imposed by logr itself. // Note that this receiver is a pointer, so depth can be saved. @@ -740,7 +844,10 @@ func (f Formatter) FormatInfo(level int, msg string, kvList []any) (prefix, args if policy := f.opts.LogCaller; policy == All || policy == Info { args = append(args, "caller", f.caller()) } - args = append(args, "level", level, "msg", msg) + if key := *f.opts.LogInfoLevel; key != "" { + args = append(args, key, level) + } + args = append(args, "msg", msg) return prefix, f.render(args, kvList) } diff --git a/vendor/github.com/go-logr/logr/funcr/slogsink.go b/vendor/github.com/go-logr/logr/funcr/slogsink.go new file mode 100644 index 0000000000..7bd84761e2 --- /dev/null +++ b/vendor/github.com/go-logr/logr/funcr/slogsink.go @@ -0,0 +1,105 @@ +//go:build go1.21 +// +build go1.21 + +/* +Copyright 2023 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package funcr + +import ( + "context" + "log/slog" + + "github.com/go-logr/logr" +) + +var _ logr.SlogSink = &fnlogger{} + +const extraSlogSinkDepth = 3 // 2 for slog, 1 for SlogSink + +func (l fnlogger) Handle(_ context.Context, record slog.Record) error { + kvList := make([]any, 0, 2*record.NumAttrs()) + record.Attrs(func(attr slog.Attr) bool { + kvList = attrToKVs(attr, kvList) + return true + }) + + if record.Level >= slog.LevelError { + l.WithCallDepth(extraSlogSinkDepth).Error(nil, record.Message, kvList...) + } else { + level := l.levelFromSlog(record.Level) + l.WithCallDepth(extraSlogSinkDepth).Info(level, record.Message, kvList...) + } + return nil +} + +func (l fnlogger) WithAttrs(attrs []slog.Attr) logr.SlogSink { + kvList := make([]any, 0, 2*len(attrs)) + for _, attr := range attrs { + kvList = attrToKVs(attr, kvList) + } + l.AddValues(kvList) + return &l +} + +func (l fnlogger) WithGroup(name string) logr.SlogSink { + l.startGroup(name) + return &l +} + +// attrToKVs appends a slog.Attr to a logr-style kvList. It handle slog Groups +// and other details of slog. +func attrToKVs(attr slog.Attr, kvList []any) []any { + attrVal := attr.Value.Resolve() + if attrVal.Kind() == slog.KindGroup { + groupVal := attrVal.Group() + grpKVs := make([]any, 0, 2*len(groupVal)) + for _, attr := range groupVal { + grpKVs = attrToKVs(attr, grpKVs) + } + if attr.Key == "" { + // slog says we have to inline these + kvList = append(kvList, grpKVs...) + } else { + kvList = append(kvList, attr.Key, PseudoStruct(grpKVs)) + } + } else if attr.Key != "" { + kvList = append(kvList, attr.Key, attrVal.Any()) + } + + return kvList +} + +// levelFromSlog adjusts the level by the logger's verbosity and negates it. +// It ensures that the result is >= 0. This is necessary because the result is +// passed to a LogSink and that API did not historically document whether +// levels could be negative or what that meant. +// +// Some example usage: +// +// logrV0 := getMyLogger() +// logrV2 := logrV0.V(2) +// slogV2 := slog.New(logr.ToSlogHandler(logrV2)) +// slogV2.Debug("msg") // =~ logrV2.V(4) =~ logrV0.V(6) +// slogV2.Info("msg") // =~ logrV2.V(0) =~ logrV0.V(2) +// slogv2.Warn("msg") // =~ logrV2.V(-4) =~ logrV0.V(0) +func (l fnlogger) levelFromSlog(level slog.Level) int { + result := -level + if result < 0 { + result = 0 // because LogSink doesn't expect negative V levels + } + return int(result) +} diff --git a/vendor/github.com/go-logr/logr/logr.go b/vendor/github.com/go-logr/logr/logr.go index 2a5075a180..b4428e105b 100644 --- a/vendor/github.com/go-logr/logr/logr.go +++ b/vendor/github.com/go-logr/logr/logr.go @@ -207,10 +207,6 @@ limitations under the License. // those. package logr -import ( - "context" -) - // New returns a new Logger instance. This is primarily used by libraries // implementing LogSink, rather than end users. Passing a nil sink will create // a Logger which discards all log lines. @@ -410,45 +406,6 @@ func (l Logger) IsZero() bool { return l.sink == nil } -// contextKey is how we find Loggers in a context.Context. -type contextKey struct{} - -// FromContext returns a Logger from ctx or an error if no Logger is found. -func FromContext(ctx context.Context) (Logger, error) { - if v, ok := ctx.Value(contextKey{}).(Logger); ok { - return v, nil - } - - return Logger{}, notFoundError{} -} - -// notFoundError exists to carry an IsNotFound method. -type notFoundError struct{} - -func (notFoundError) Error() string { - return "no logr.Logger was present" -} - -func (notFoundError) IsNotFound() bool { - return true -} - -// FromContextOrDiscard returns a Logger from ctx. If no Logger is found, this -// returns a Logger that discards all log messages. -func FromContextOrDiscard(ctx context.Context) Logger { - if v, ok := ctx.Value(contextKey{}).(Logger); ok { - return v - } - - return Discard() -} - -// NewContext returns a new Context, derived from ctx, which carries the -// provided Logger. -func NewContext(ctx context.Context, logger Logger) context.Context { - return context.WithValue(ctx, contextKey{}, logger) -} - // RuntimeInfo holds information that the logr "core" library knows which // LogSinks might want to know. type RuntimeInfo struct { diff --git a/vendor/github.com/go-logr/logr/sloghandler.go b/vendor/github.com/go-logr/logr/sloghandler.go new file mode 100644 index 0000000000..82d1ba4948 --- /dev/null +++ b/vendor/github.com/go-logr/logr/sloghandler.go @@ -0,0 +1,192 @@ +//go:build go1.21 +// +build go1.21 + +/* +Copyright 2023 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logr + +import ( + "context" + "log/slog" +) + +type slogHandler struct { + // May be nil, in which case all logs get discarded. + sink LogSink + // Non-nil if sink is non-nil and implements SlogSink. + slogSink SlogSink + + // groupPrefix collects values from WithGroup calls. It gets added as + // prefix to value keys when handling a log record. + groupPrefix string + + // levelBias can be set when constructing the handler to influence the + // slog.Level of log records. A positive levelBias reduces the + // slog.Level value. slog has no API to influence this value after the + // handler got created, so it can only be set indirectly through + // Logger.V. + levelBias slog.Level +} + +var _ slog.Handler = &slogHandler{} + +// groupSeparator is used to concatenate WithGroup names and attribute keys. +const groupSeparator = "." + +// GetLevel is used for black box unit testing. +func (l *slogHandler) GetLevel() slog.Level { + return l.levelBias +} + +func (l *slogHandler) Enabled(_ context.Context, level slog.Level) bool { + return l.sink != nil && (level >= slog.LevelError || l.sink.Enabled(l.levelFromSlog(level))) +} + +func (l *slogHandler) Handle(ctx context.Context, record slog.Record) error { + if l.slogSink != nil { + // Only adjust verbosity level of log entries < slog.LevelError. + if record.Level < slog.LevelError { + record.Level -= l.levelBias + } + return l.slogSink.Handle(ctx, record) + } + + // No need to check for nil sink here because Handle will only be called + // when Enabled returned true. + + kvList := make([]any, 0, 2*record.NumAttrs()) + record.Attrs(func(attr slog.Attr) bool { + kvList = attrToKVs(attr, l.groupPrefix, kvList) + return true + }) + if record.Level >= slog.LevelError { + l.sinkWithCallDepth().Error(nil, record.Message, kvList...) + } else { + level := l.levelFromSlog(record.Level) + l.sinkWithCallDepth().Info(level, record.Message, kvList...) + } + return nil +} + +// sinkWithCallDepth adjusts the stack unwinding so that when Error or Info +// are called by Handle, code in slog gets skipped. +// +// This offset currently (Go 1.21.0) works for calls through +// slog.New(ToSlogHandler(...)). There's no guarantee that the call +// chain won't change. Wrapping the handler will also break unwinding. It's +// still better than not adjusting at all.... +// +// This cannot be done when constructing the handler because FromSlogHandler needs +// access to the original sink without this adjustment. A second copy would +// work, but then WithAttrs would have to be called for both of them. +func (l *slogHandler) sinkWithCallDepth() LogSink { + if sink, ok := l.sink.(CallDepthLogSink); ok { + return sink.WithCallDepth(2) + } + return l.sink +} + +func (l *slogHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + if l.sink == nil || len(attrs) == 0 { + return l + } + + clone := *l + if l.slogSink != nil { + clone.slogSink = l.slogSink.WithAttrs(attrs) + clone.sink = clone.slogSink + } else { + kvList := make([]any, 0, 2*len(attrs)) + for _, attr := range attrs { + kvList = attrToKVs(attr, l.groupPrefix, kvList) + } + clone.sink = l.sink.WithValues(kvList...) + } + return &clone +} + +func (l *slogHandler) WithGroup(name string) slog.Handler { + if l.sink == nil { + return l + } + if name == "" { + // slog says to inline empty groups + return l + } + clone := *l + if l.slogSink != nil { + clone.slogSink = l.slogSink.WithGroup(name) + clone.sink = clone.slogSink + } else { + clone.groupPrefix = addPrefix(clone.groupPrefix, name) + } + return &clone +} + +// attrToKVs appends a slog.Attr to a logr-style kvList. It handle slog Groups +// and other details of slog. +func attrToKVs(attr slog.Attr, groupPrefix string, kvList []any) []any { + attrVal := attr.Value.Resolve() + if attrVal.Kind() == slog.KindGroup { + groupVal := attrVal.Group() + grpKVs := make([]any, 0, 2*len(groupVal)) + prefix := groupPrefix + if attr.Key != "" { + prefix = addPrefix(groupPrefix, attr.Key) + } + for _, attr := range groupVal { + grpKVs = attrToKVs(attr, prefix, grpKVs) + } + kvList = append(kvList, grpKVs...) + } else if attr.Key != "" { + kvList = append(kvList, addPrefix(groupPrefix, attr.Key), attrVal.Any()) + } + + return kvList +} + +func addPrefix(prefix, name string) string { + if prefix == "" { + return name + } + if name == "" { + return prefix + } + return prefix + groupSeparator + name +} + +// levelFromSlog adjusts the level by the logger's verbosity and negates it. +// It ensures that the result is >= 0. This is necessary because the result is +// passed to a LogSink and that API did not historically document whether +// levels could be negative or what that meant. +// +// Some example usage: +// +// logrV0 := getMyLogger() +// logrV2 := logrV0.V(2) +// slogV2 := slog.New(logr.ToSlogHandler(logrV2)) +// slogV2.Debug("msg") // =~ logrV2.V(4) =~ logrV0.V(6) +// slogV2.Info("msg") // =~ logrV2.V(0) =~ logrV0.V(2) +// slogv2.Warn("msg") // =~ logrV2.V(-4) =~ logrV0.V(0) +func (l *slogHandler) levelFromSlog(level slog.Level) int { + result := -level + result += l.levelBias // in case the original Logger had a V level + if result < 0 { + result = 0 // because LogSink doesn't expect negative V levels + } + return int(result) +} diff --git a/vendor/github.com/go-logr/logr/slogr.go b/vendor/github.com/go-logr/logr/slogr.go new file mode 100644 index 0000000000..28a83d0243 --- /dev/null +++ b/vendor/github.com/go-logr/logr/slogr.go @@ -0,0 +1,100 @@ +//go:build go1.21 +// +build go1.21 + +/* +Copyright 2023 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logr + +import ( + "context" + "log/slog" +) + +// FromSlogHandler returns a Logger which writes to the slog.Handler. +// +// The logr verbosity level is mapped to slog levels such that V(0) becomes +// slog.LevelInfo and V(4) becomes slog.LevelDebug. +func FromSlogHandler(handler slog.Handler) Logger { + if handler, ok := handler.(*slogHandler); ok { + if handler.sink == nil { + return Discard() + } + return New(handler.sink).V(int(handler.levelBias)) + } + return New(&slogSink{handler: handler}) +} + +// ToSlogHandler returns a slog.Handler which writes to the same sink as the Logger. +// +// The returned logger writes all records with level >= slog.LevelError as +// error log entries with LogSink.Error, regardless of the verbosity level of +// the Logger: +// +// logger := +// slog.New(ToSlogHandler(logger.V(10))).Error(...) -> logSink.Error(...) +// +// The level of all other records gets reduced by the verbosity +// level of the Logger and the result is negated. If it happens +// to be negative, then it gets replaced by zero because a LogSink +// is not expected to handled negative levels: +// +// slog.New(ToSlogHandler(logger)).Debug(...) -> logger.GetSink().Info(level=4, ...) +// slog.New(ToSlogHandler(logger)).Warning(...) -> logger.GetSink().Info(level=0, ...) +// slog.New(ToSlogHandler(logger)).Info(...) -> logger.GetSink().Info(level=0, ...) +// slog.New(ToSlogHandler(logger.V(4))).Info(...) -> logger.GetSink().Info(level=4, ...) +func ToSlogHandler(logger Logger) slog.Handler { + if sink, ok := logger.GetSink().(*slogSink); ok && logger.GetV() == 0 { + return sink.handler + } + + handler := &slogHandler{sink: logger.GetSink(), levelBias: slog.Level(logger.GetV())} + if slogSink, ok := handler.sink.(SlogSink); ok { + handler.slogSink = slogSink + } + return handler +} + +// SlogSink is an optional interface that a LogSink can implement to support +// logging through the slog.Logger or slog.Handler APIs better. It then should +// also support special slog values like slog.Group. When used as a +// slog.Handler, the advantages are: +// +// - stack unwinding gets avoided in favor of logging the pre-recorded PC, +// as intended by slog +// - proper grouping of key/value pairs via WithGroup +// - verbosity levels > slog.LevelInfo can be recorded +// - less overhead +// +// Both APIs (Logger and slog.Logger/Handler) then are supported equally +// well. Developers can pick whatever API suits them better and/or mix +// packages which use either API in the same binary with a common logging +// implementation. +// +// This interface is necessary because the type implementing the LogSink +// interface cannot also implement the slog.Handler interface due to the +// different prototype of the common Enabled method. +// +// An implementation could support both interfaces in two different types, but then +// additional interfaces would be needed to convert between those types in FromSlogHandler +// and ToSlogHandler. +type SlogSink interface { + LogSink + + Handle(ctx context.Context, record slog.Record) error + WithAttrs(attrs []slog.Attr) SlogSink + WithGroup(name string) SlogSink +} diff --git a/vendor/github.com/go-logr/logr/slogsink.go b/vendor/github.com/go-logr/logr/slogsink.go new file mode 100644 index 0000000000..4060fcbc2b --- /dev/null +++ b/vendor/github.com/go-logr/logr/slogsink.go @@ -0,0 +1,120 @@ +//go:build go1.21 +// +build go1.21 + +/* +Copyright 2023 The logr Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package logr + +import ( + "context" + "log/slog" + "runtime" + "time" +) + +var ( + _ LogSink = &slogSink{} + _ CallDepthLogSink = &slogSink{} + _ Underlier = &slogSink{} +) + +// Underlier is implemented by the LogSink returned by NewFromLogHandler. +type Underlier interface { + // GetUnderlying returns the Handler used by the LogSink. + GetUnderlying() slog.Handler +} + +const ( + // nameKey is used to log the `WithName` values as an additional attribute. + nameKey = "logger" + + // errKey is used to log the error parameter of Error as an additional attribute. + errKey = "err" +) + +type slogSink struct { + callDepth int + name string + handler slog.Handler +} + +func (l *slogSink) Init(info RuntimeInfo) { + l.callDepth = info.CallDepth +} + +func (l *slogSink) GetUnderlying() slog.Handler { + return l.handler +} + +func (l *slogSink) WithCallDepth(depth int) LogSink { + newLogger := *l + newLogger.callDepth += depth + return &newLogger +} + +func (l *slogSink) Enabled(level int) bool { + return l.handler.Enabled(context.Background(), slog.Level(-level)) +} + +func (l *slogSink) Info(level int, msg string, kvList ...interface{}) { + l.log(nil, msg, slog.Level(-level), kvList...) +} + +func (l *slogSink) Error(err error, msg string, kvList ...interface{}) { + l.log(err, msg, slog.LevelError, kvList...) +} + +func (l *slogSink) log(err error, msg string, level slog.Level, kvList ...interface{}) { + var pcs [1]uintptr + // skip runtime.Callers, this function, Info/Error, and all helper functions above that. + runtime.Callers(3+l.callDepth, pcs[:]) + + record := slog.NewRecord(time.Now(), level, msg, pcs[0]) + if l.name != "" { + record.AddAttrs(slog.String(nameKey, l.name)) + } + if err != nil { + record.AddAttrs(slog.Any(errKey, err)) + } + record.Add(kvList...) + _ = l.handler.Handle(context.Background(), record) +} + +func (l slogSink) WithName(name string) LogSink { + if l.name != "" { + l.name += "/" + } + l.name += name + return &l +} + +func (l slogSink) WithValues(kvList ...interface{}) LogSink { + l.handler = l.handler.WithAttrs(kvListToAttrs(kvList...)) + return &l +} + +func kvListToAttrs(kvList ...interface{}) []slog.Attr { + // We don't need the record itself, only its Add method. + record := slog.NewRecord(time.Time{}, 0, "", 0) + record.Add(kvList...) + attrs := make([]slog.Attr, 0, record.NumAttrs()) + record.Attrs(func(attr slog.Attr) bool { + attrs = append(attrs, attr) + return true + }) + return attrs +} diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md index 24874f856e..fe670d79cc 100644 --- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md +++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md @@ -8,6 +8,46 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +## [1.22.0/0.45.0] 2024-01-17 + +### Added + +- The `go.opentelemetry.io/otel/semconv/v1.22.0` package. + The package contains semantic conventions from the `v1.22.0` version of the OpenTelemetry Semantic Conventions. (#4735) +- The `go.opentelemetry.io/otel/semconv/v1.23.0` package. + The package contains semantic conventions from the `v1.23.0` version of the OpenTelemetry Semantic Conventions. (#4746) +- The `go.opentelemetry.io/otel/semconv/v1.23.1` package. + The package contains semantic conventions from the `v1.23.1` version of the OpenTelemetry Semantic Conventions. (#4749) +- The `go.opentelemetry.io/otel/semconv/v1.24.0` package. + The package contains semantic conventions from the `v1.24.0` version of the OpenTelemetry Semantic Conventions. (#4770) +- Add `WithResourceAsConstantLabels` option to apply resource attributes for every metric emitted by the Prometheus exporter. (#4733) +- Experimental cardinality limiting is added to the metric SDK. + See [metric documentation](./sdk/metric/EXPERIMENTAL.md#cardinality-limit) for more information about this feature and how to enable it. (#4457) +- Add `NewMemberRaw` and `NewKeyValuePropertyRaw` in `go.opentelemetry.io/otel/baggage`. (#4804) + +### Changed + +- Upgrade all use of `go.opentelemetry.io/otel/semconv` to use `v1.24.0`. (#4754) +- Update transformations in `go.opentelemetry.io/otel/exporters/zipkin` to follow `v1.19.0` version of the OpenTelemetry specification. (#4754) +- Record synchronous measurements when the passed context is canceled instead of dropping in `go.opentelemetry.io/otel/sdk/metric`. + If you do not want to make a measurement when the context is cancelled, you need to handle it yourself (e.g `if ctx.Err() != nil`). (#4671) +- Improve `go.opentelemetry.io/otel/trace.TraceState`'s performance. (#4722) +- Improve `go.opentelemetry.io/otel/propagation.TraceContext`'s performance. (#4721) +- Improve `go.opentelemetry.io/otel/baggage` performance. (#4743) +- Improve performance of the `(*Set).Filter` method in `go.opentelemetry.io/otel/attribute` when the passed filter does not filter out any attributes from the set. (#4774) +- `Member.String` in `go.opentelemetry.io/otel/baggage` percent-encodes only when necessary. (#4775) +- Improve `go.opentelemetry.io/otel/trace.Span`'s performance when adding multiple attributes. (#4818) +- `Property.Value` in `go.opentelemetry.io/otel/baggage` now returns a raw string instead of a percent-encoded value. (#4804) + +### Fixed + +- Fix `Parse` in `go.opentelemetry.io/otel/baggage` to validate member value before percent-decoding. (#4755) +- Fix whitespace encoding of `Member.String` in `go.opentelemetry.io/otel/baggage`. (#4756) +- Fix observable not registered error when the asynchronous instrument has a drop aggregation in `go.opentelemetry.io/otel/sdk/metric`. (#4772) +- Fix baggage item key so that it is not canonicalized in `go.opentelemetry.io/otel/bridge/opentracing`. (#4776) +- Fix `go.opentelemetry.io/otel/bridge/opentracing` to properly handle baggage values that requires escaping during propagation. (#4804) +- Fix a bug where using multiple readers resulted in incorrect asynchronous counter values in `go.opentelemetry.io/otel/sdk/metric`. (#4742) + ## [1.21.0/0.44.0] 2023-11-16 ### Removed @@ -2735,7 +2775,8 @@ It contains api and sdk for trace and meter. - CircleCI build CI manifest files. - CODEOWNERS file to track owners of this project. -[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.21.0...HEAD +[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.22.0...HEAD +[1.22.0/0.45.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.22.0 [1.21.0/0.44.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.21.0 [1.20.0/0.43.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.20.0 [1.19.0/0.42.0/0.0.7]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.19.0 diff --git a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md index 850606ae69..31857a6173 100644 --- a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md +++ b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md @@ -591,6 +591,26 @@ this. [^3]: https://github.com/open-telemetry/opentelemetry-go/issues/3548 +### Ignoring context cancellation + +OpenTelemetry API implementations need to ignore the cancellation of the context that are +passed when recording a value (e.g. starting a span, recording a measurement, emitting a log). +Recording methods should not return an error describing the cancellation state of the context +when they complete, nor should they abort any work. + +This rule may not apply if the OpenTelemetry specification defines a timeout mechanism for +the method. In that case the context cancellation can be used for the timeout with the +restriction that this behavior is documented for the method. Otherwise, timeouts +are expected to be handled by the user calling the API, not the implementation. + +Stoppage of the telemetry pipeline is handled by calling the appropriate `Shutdown` method +of a provider. It is assumed the context passed from a user is not used for this purpose. + +Outside of the direct recording of telemetry from the API (e.g. exporting telemetry, +force flushing telemetry, shutting down a signal provider) the context cancellation +should be honored. This means all work done on behalf of the user provided context +should be canceled. + ## Approvers and Maintainers ### Approvers @@ -610,6 +630,7 @@ this. ### Emeritus +- [Liz Fong-Jones](https://github.com/lizthegrey), Honeycomb - [Gustavo Silva Paiva](https://github.com/paivagustavo), LightStep - [Josh MacDonald](https://github.com/jmacd), LightStep diff --git a/vendor/go.opentelemetry.io/otel/README.md b/vendor/go.opentelemetry.io/otel/README.md index 2c5b0cc28a..44e1bfc9b5 100644 --- a/vendor/go.opentelemetry.io/otel/README.md +++ b/vendor/go.opentelemetry.io/otel/README.md @@ -66,7 +66,7 @@ are made for those systems currently. ## Getting Started -You can find a getting started guide on [opentelemetry.io](https://opentelemetry.io/docs/go/getting-started/). +You can find a getting started guide on [opentelemetry.io](https://opentelemetry.io/docs/languages/go/getting-started/). OpenTelemetry's goal is to provide a single set of APIs to capture distributed traces and metrics from your application and send them to an observability diff --git a/vendor/go.opentelemetry.io/otel/RELEASING.md b/vendor/go.opentelemetry.io/otel/RELEASING.md index 82ce3ee46a..d2691d0bd8 100644 --- a/vendor/go.opentelemetry.io/otel/RELEASING.md +++ b/vendor/go.opentelemetry.io/otel/RELEASING.md @@ -123,12 +123,12 @@ Once verified be sure to [make a release for the `contrib` repository](https://g ### Website Documentation -Update the [Go instrumentation documentation] in the OpenTelemetry website under [content/en/docs/instrumentation/go]. +Update the [Go instrumentation documentation] in the OpenTelemetry website under [content/en/docs/languages/go]. Importantly, bump any package versions referenced to be the latest one you just released and ensure all code examples still compile and are accurate. [OpenTelemetry Semantic Conventions]: https://github.com/open-telemetry/semantic-conventions -[Go instrumentation documentation]: https://opentelemetry.io/docs/instrumentation/go/ -[content/en/docs/instrumentation/go]: https://github.com/open-telemetry/opentelemetry.io/tree/main/content/en/docs/instrumentation/go +[Go instrumentation documentation]: https://opentelemetry.io/docs/languages/go/ +[content/en/docs/languages/go]: https://github.com/open-telemetry/opentelemetry.io/tree/main/content/en/docs/languages/go ### Demo Repository diff --git a/vendor/go.opentelemetry.io/otel/attribute/set.go b/vendor/go.opentelemetry.io/otel/attribute/set.go index 9f9303d4f1..7e6765b06b 100644 --- a/vendor/go.opentelemetry.io/otel/attribute/set.go +++ b/vendor/go.opentelemetry.io/otel/attribute/set.go @@ -279,52 +279,75 @@ func NewSetWithSortableFiltered(kvs []KeyValue, tmp *Sortable, filter Filter) (S position-- kvs[offset], kvs[position] = kvs[position], kvs[offset] } + kvs = kvs[position:] + if filter != nil { - return filterSet(kvs[position:], filter) - } - return Set{ - equivalent: computeDistinct(kvs[position:]), - }, nil -} - -// filterSet reorders kvs so that included keys are contiguous at the end of -// the slice, while excluded keys precede the included keys. -func filterSet(kvs []KeyValue, filter Filter) (Set, []KeyValue) { - var excluded []KeyValue - - // Move attributes that do not match the filter so they're adjacent before - // calling computeDistinct(). - distinctPosition := len(kvs) - - // Swap indistinct keys forward and distinct keys toward the - // end of the slice. - offset := len(kvs) - 1 - for ; offset >= 0; offset-- { - if filter(kvs[offset]) { - distinctPosition-- - kvs[offset], kvs[distinctPosition] = kvs[distinctPosition], kvs[offset] - continue + if div := filteredToFront(kvs, filter); div != 0 { + return Set{equivalent: computeDistinct(kvs[div:])}, kvs[:div] } } - excluded = kvs[:distinctPosition] + return Set{equivalent: computeDistinct(kvs)}, nil +} - return Set{ - equivalent: computeDistinct(kvs[distinctPosition:]), - }, excluded +// filteredToFront filters slice in-place using keep function. All KeyValues that need to +// be removed are moved to the front. All KeyValues that need to be kept are +// moved (in-order) to the back. The index for the first KeyValue to be kept is +// returned. +func filteredToFront(slice []KeyValue, keep Filter) int { + n := len(slice) + j := n + for i := n - 1; i >= 0; i-- { + if keep(slice[i]) { + j-- + slice[i], slice[j] = slice[j], slice[i] + } + } + return j } // Filter returns a filtered copy of this Set. See the documentation for // NewSetWithSortableFiltered for more details. func (l *Set) Filter(re Filter) (Set, []KeyValue) { if re == nil { - return Set{ - equivalent: l.equivalent, - }, nil + return *l, nil } - // Note: This could be refactored to avoid the temporary slice - // allocation, if it proves to be expensive. - return filterSet(l.ToSlice(), re) + // Iterate in reverse to the first attribute that will be filtered out. + n := l.Len() + first := n - 1 + for ; first >= 0; first-- { + kv, _ := l.Get(first) + if !re(kv) { + break + } + } + + // No attributes will be dropped, return the immutable Set l and nil. + if first < 0 { + return *l, nil + } + + // Copy now that we know we need to return a modified set. + // + // Do not do this in-place on the underlying storage of *Set l. Sets are + // immutable and filtering should not change this. + slice := l.ToSlice() + + // Don't re-iterate the slice if only slice[0] is filtered. + if first == 0 { + // It is safe to assume len(slice) >= 1 given we found at least one + // attribute above that needs to be filtered out. + return Set{equivalent: computeDistinct(slice[1:])}, slice[:1] + } + + // Move the filtered slice[first] to the front (preserving order). + kv := slice[first] + copy(slice[1:first+1], slice[:first]) + slice[0] = kv + + // Do not re-evaluate re(slice[first+1:]). + div := filteredToFront(slice[1:first+1], re) + 1 + return Set{equivalent: computeDistinct(slice[div:])}, slice[:div] } // computeDistinct returns a Distinct using either the fixed- or diff --git a/vendor/go.opentelemetry.io/otel/baggage/baggage.go b/vendor/go.opentelemetry.io/otel/baggage/baggage.go index 84532cb1da..7d27cf77d5 100644 --- a/vendor/go.opentelemetry.io/otel/baggage/baggage.go +++ b/vendor/go.opentelemetry.io/otel/baggage/baggage.go @@ -18,7 +18,6 @@ import ( "errors" "fmt" "net/url" - "regexp" "strings" "go.opentelemetry.io/otel/internal/baggage" @@ -32,16 +31,6 @@ const ( listDelimiter = "," keyValueDelimiter = "=" propertyDelimiter = ";" - - keyDef = `([\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5a\x5e-\x7a\x7c\x7e]+)` - valueDef = `([\x21\x23-\x2b\x2d-\x3a\x3c-\x5B\x5D-\x7e]*)` - keyValueDef = `\s*` + keyDef + `\s*` + keyValueDelimiter + `\s*` + valueDef + `\s*` -) - -var ( - keyRe = regexp.MustCompile(`^` + keyDef + `$`) - valueRe = regexp.MustCompile(`^` + valueDef + `$`) - propertyRe = regexp.MustCompile(`^(?:\s*` + keyDef + `\s*|` + keyValueDef + `)$`) ) var ( @@ -67,7 +56,7 @@ type Property struct { // // If key is invalid, an error will be returned. func NewKeyProperty(key string) (Property, error) { - if !keyRe.MatchString(key) { + if !validateKey(key) { return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key) } @@ -77,14 +66,29 @@ func NewKeyProperty(key string) (Property, error) { // NewKeyValueProperty returns a new Property for key with value. // -// If key or value are invalid, an error will be returned. +// The passed key must be compliant with W3C Baggage specification. +// The passed value must be precent-encoded as defined in W3C Baggage specification. +// +// Notice: Consider using [NewKeyValuePropertyRaw] instead +// that does not require precent-encoding of the value. func NewKeyValueProperty(key, value string) (Property, error) { - if !keyRe.MatchString(key) { - return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key) - } - if !valueRe.MatchString(value) { + if !validateValue(value) { return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidValue, value) } + decodedValue, err := url.PathUnescape(value) + if err != nil { + return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidValue, value) + } + return NewKeyValuePropertyRaw(key, decodedValue) +} + +// NewKeyValuePropertyRaw returns a new Property for key with value. +// +// The passed key must be compliant with W3C Baggage specification. +func NewKeyValuePropertyRaw(key, value string) (Property, error) { + if !validateKey(key) { + return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key) + } p := Property{ key: key, @@ -106,20 +110,11 @@ func parseProperty(property string) (Property, error) { return newInvalidProperty(), nil } - match := propertyRe.FindStringSubmatch(property) - if len(match) != 4 { + p, ok := parsePropertyInternal(property) + if !ok { return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidProperty, property) } - var p Property - if match[1] != "" { - p.key = match[1] - } else { - p.key = match[2] - p.value = match[3] - p.hasValue = true - } - return p, nil } @@ -130,12 +125,9 @@ func (p Property) validate() error { return fmt.Errorf("invalid property: %w", err) } - if !keyRe.MatchString(p.key) { + if !validateKey(p.key) { return errFunc(fmt.Errorf("%w: %q", errInvalidKey, p.key)) } - if p.hasValue && !valueRe.MatchString(p.value) { - return errFunc(fmt.Errorf("%w: %q", errInvalidValue, p.value)) - } if !p.hasValue && p.value != "" { return errFunc(errors.New("inconsistent value")) } @@ -154,11 +146,11 @@ func (p Property) Value() (string, bool) { return p.value, p.hasValue } -// String encodes Property into a string compliant with the W3C Baggage +// String encodes Property into a header string compliant with the W3C Baggage // specification. func (p Property) String() string { if p.hasValue { - return fmt.Sprintf("%s%s%v", p.key, keyValueDelimiter, p.value) + return fmt.Sprintf("%s%s%v", p.key, keyValueDelimiter, valueEscape(p.value)) } return p.key } @@ -218,7 +210,7 @@ func (p properties) validate() error { return nil } -// String encodes properties into a string compliant with the W3C Baggage +// String encodes properties into a header string compliant with the W3C Baggage // specification. func (p properties) String() string { props := make([]string, len(p)) @@ -240,11 +232,28 @@ type Member struct { hasData bool } -// NewMember returns a new Member from the passed arguments. The key will be -// used directly while the value will be url decoded after validation. An error -// is returned if the created Member would be invalid according to the W3C -// Baggage specification. +// NewMemberRaw returns a new Member from the passed arguments. +// +// The passed key must be compliant with W3C Baggage specification. +// The passed value must be precent-encoded as defined in W3C Baggage specification. +// +// Notice: Consider using [NewMemberRaw] instead +// that does not require precent-encoding of the value. func NewMember(key, value string, props ...Property) (Member, error) { + if !validateValue(value) { + return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value) + } + decodedValue, err := url.PathUnescape(value) + if err != nil { + return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value) + } + return NewMemberRaw(key, decodedValue, props...) +} + +// NewMemberRaw returns a new Member from the passed arguments. +// +// The passed key must be compliant with W3C Baggage specification. +func NewMemberRaw(key, value string, props ...Property) (Member, error) { m := Member{ key: key, value: value, @@ -254,11 +263,6 @@ func NewMember(key, value string, props ...Property) (Member, error) { if err := m.validate(); err != nil { return newInvalidMember(), err } - decodedValue, err := url.PathUnescape(value) - if err != nil { - return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value) - } - m.value = decodedValue return m, nil } @@ -274,11 +278,7 @@ func parseMember(member string) (Member, error) { return newInvalidMember(), fmt.Errorf("%w: %d", errMemberBytes, n) } - var ( - key, value string - props properties - ) - + var props properties keyValue, properties, found := strings.Cut(member, propertyDelimiter) if found { // Parse the member properties. @@ -299,36 +299,34 @@ func parseMember(member string) (Member, error) { } // "Leading and trailing whitespaces are allowed but MUST be trimmed // when converting the header into a data structure." - key = strings.TrimSpace(k) - var err error - value, err = url.PathUnescape(strings.TrimSpace(v)) - if err != nil { - return newInvalidMember(), fmt.Errorf("%w: %q", err, value) - } - if !keyRe.MatchString(key) { + key := strings.TrimSpace(k) + if !validateKey(key) { return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidKey, key) } - if !valueRe.MatchString(value) { - return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, value) + + val := strings.TrimSpace(v) + if !validateValue(val) { + return newInvalidMember(), fmt.Errorf("%w: %q", errInvalidValue, v) } + // Decode a precent-encoded value. + value, err := url.PathUnescape(val) + if err != nil { + return newInvalidMember(), fmt.Errorf("%w: %v", errInvalidValue, err) + } return Member{key: key, value: value, properties: props, hasData: true}, nil } // validate ensures m conforms to the W3C Baggage specification. -// A key is just an ASCII string, but a value must be URL encoded UTF-8, -// returning an error otherwise. +// A key must be an ASCII string, returning an error otherwise. func (m Member) validate() error { if !m.hasData { return fmt.Errorf("%w: %q", errInvalidMember, m) } - if !keyRe.MatchString(m.key) { + if !validateKey(m.key) { return fmt.Errorf("%w: %q", errInvalidKey, m.key) } - if !valueRe.MatchString(m.value) { - return fmt.Errorf("%w: %q", errInvalidValue, m.value) - } return m.properties.validate() } @@ -341,11 +339,13 @@ func (m Member) Value() string { return m.value } // Properties returns a copy of the Member properties. func (m Member) Properties() []Property { return m.properties.Copy() } -// String encodes Member into a string compliant with the W3C Baggage +// String encodes Member into a header string compliant with the W3C Baggage // specification. func (m Member) String() string { - // A key is just an ASCII string, but a value is URL encoded UTF-8. - s := fmt.Sprintf("%s%s%s", m.key, keyValueDelimiter, url.QueryEscape(m.value)) + // A key is just an ASCII string. A value is restricted to be + // US-ASCII characters excluding CTLs, whitespace, + // DQUOTE, comma, semicolon, and backslash. + s := fmt.Sprintf("%s%s%s", m.key, keyValueDelimiter, valueEscape(m.value)) if len(m.properties) > 0 { s = fmt.Sprintf("%s%s%s", s, propertyDelimiter, m.properties.String()) } @@ -536,9 +536,8 @@ func (b Baggage) Len() int { return len(b.list) } -// String encodes Baggage into a string compliant with the W3C Baggage -// specification. The returned string will be invalid if the Baggage contains -// any invalid list-members. +// String encodes Baggage into a header string compliant with the W3C Baggage +// specification. func (b Baggage) String() string { members := make([]string, 0, len(b.list)) for k, v := range b.list { @@ -550,3 +549,196 @@ func (b Baggage) String() string { } return strings.Join(members, listDelimiter) } + +// parsePropertyInternal attempts to decode a Property from the passed string. +// It follows the spec at https://www.w3.org/TR/baggage/#definition. +func parsePropertyInternal(s string) (p Property, ok bool) { + // For the entire function we will use " key = value " as an example. + // Attempting to parse the key. + // First skip spaces at the beginning "< >key = value " (they could be empty). + index := skipSpace(s, 0) + + // Parse the key: " = value ". + keyStart := index + keyEnd := index + for _, c := range s[keyStart:] { + if !validateKeyChar(c) { + break + } + keyEnd++ + } + + // If we couldn't find any valid key character, + // it means the key is either empty or invalid. + if keyStart == keyEnd { + return + } + + // Skip spaces after the key: " key< >= value ". + index = skipSpace(s, keyEnd) + + if index == len(s) { + // A key can have no value, like: " key ". + ok = true + p.key = s[keyStart:keyEnd] + return + } + + // If we have not reached the end and we can't find the '=' delimiter, + // it means the property is invalid. + if s[index] != keyValueDelimiter[0] { + return + } + + // Attempting to parse the value. + // Match: " key =< >value ". + index = skipSpace(s, index+1) + + // Match the value string: " key = ". + // A valid property can be: " key =". + // Therefore, we don't have to check if the value is empty. + valueStart := index + valueEnd := index + for _, c := range s[valueStart:] { + if !validateValueChar(c) { + break + } + valueEnd++ + } + + // Skip all trailing whitespaces: " key = value< >". + index = skipSpace(s, valueEnd) + + // If after looking for the value and skipping whitespaces + // we have not reached the end, it means the property is + // invalid, something like: " key = value value1". + if index != len(s) { + return + } + + // Decode a precent-encoded value. + value, err := url.PathUnescape(s[valueStart:valueEnd]) + if err != nil { + return + } + + ok = true + p.key = s[keyStart:keyEnd] + p.hasValue = true + + p.value = value + return +} + +func skipSpace(s string, offset int) int { + i := offset + for ; i < len(s); i++ { + c := s[i] + if c != ' ' && c != '\t' { + break + } + } + return i +} + +func validateKey(s string) bool { + if len(s) == 0 { + return false + } + + for _, c := range s { + if !validateKeyChar(c) { + return false + } + } + + return true +} + +func validateKeyChar(c int32) bool { + return (c >= 0x23 && c <= 0x27) || + (c >= 0x30 && c <= 0x39) || + (c >= 0x41 && c <= 0x5a) || + (c >= 0x5e && c <= 0x7a) || + c == 0x21 || + c == 0x2a || + c == 0x2b || + c == 0x2d || + c == 0x2e || + c == 0x7c || + c == 0x7e +} + +func validateValue(s string) bool { + for _, c := range s { + if !validateValueChar(c) { + return false + } + } + + return true +} + +func validateValueChar(c int32) bool { + return c == 0x21 || + (c >= 0x23 && c <= 0x2b) || + (c >= 0x2d && c <= 0x3a) || + (c >= 0x3c && c <= 0x5b) || + (c >= 0x5d && c <= 0x7e) +} + +// valueEscape escapes the string so it can be safely placed inside a baggage value, +// replacing special characters with %XX sequences as needed. +// +// The implementation is based on: +// https://github.com/golang/go/blob/f6509cf5cdbb5787061b784973782933c47f1782/src/net/url/url.go#L285. +func valueEscape(s string) string { + hexCount := 0 + for i := 0; i < len(s); i++ { + c := s[i] + if shouldEscape(c) { + hexCount++ + } + } + + if hexCount == 0 { + return s + } + + var buf [64]byte + var t []byte + + required := len(s) + 2*hexCount + if required <= len(buf) { + t = buf[:required] + } else { + t = make([]byte, required) + } + + j := 0 + for i := 0; i < len(s); i++ { + c := s[i] + if shouldEscape(s[i]) { + const upperhex = "0123456789ABCDEF" + t[j] = '%' + t[j+1] = upperhex[c>>4] + t[j+2] = upperhex[c&15] + j += 3 + } else { + t[j] = c + j++ + } + } + + return string(t) +} + +// shouldEscape returns true if the specified byte should be escaped when +// appearing in a baggage value string. +func shouldEscape(c byte) bool { + if c == '%' { + // The percent character must be encoded so that percent-encoding can work. + return true + } + return !validateValueChar(int32(c)) +} diff --git a/vendor/go.opentelemetry.io/otel/doc.go b/vendor/go.opentelemetry.io/otel/doc.go index daa36c89dc..36d7c24e88 100644 --- a/vendor/go.opentelemetry.io/otel/doc.go +++ b/vendor/go.opentelemetry.io/otel/doc.go @@ -22,7 +22,7 @@ transmitted anywhere. An implementation of the OpenTelemetry SDK, like the default SDK implementation (go.opentelemetry.io/otel/sdk), and associated exporters are used to process and transport this data. -To read the getting started guide, see https://opentelemetry.io/docs/go/getting-started/. +To read the getting started guide, see https://opentelemetry.io/docs/languages/go/getting-started/. To read more about tracing, see go.opentelemetry.io/otel/trace. diff --git a/vendor/go.opentelemetry.io/otel/propagation/trace_context.go b/vendor/go.opentelemetry.io/otel/propagation/trace_context.go index 75a8f3435a..63e5d62221 100644 --- a/vendor/go.opentelemetry.io/otel/propagation/trace_context.go +++ b/vendor/go.opentelemetry.io/otel/propagation/trace_context.go @@ -18,7 +18,7 @@ import ( "context" "encoding/hex" "fmt" - "regexp" + "strings" "go.opentelemetry.io/otel/trace" ) @@ -28,6 +28,7 @@ const ( maxVersion = 254 traceparentHeader = "traceparent" tracestateHeader = "tracestate" + delimiter = "-" ) // TraceContext is a propagator that supports the W3C Trace Context format @@ -41,8 +42,8 @@ const ( type TraceContext struct{} var ( - _ TextMapPropagator = TraceContext{} - traceCtxRegExp = regexp.MustCompile("^(?P[0-9a-f]{2})-(?P[a-f0-9]{32})-(?P[a-f0-9]{16})-(?P[a-f0-9]{2})(?:-.*)?$") + _ TextMapPropagator = TraceContext{} + versionPart = fmt.Sprintf("%.2X", supportedVersion) ) // Inject set tracecontext from the Context into the carrier. @@ -59,12 +60,19 @@ func (tc TraceContext) Inject(ctx context.Context, carrier TextMapCarrier) { // Clear all flags other than the trace-context supported sampling bit. flags := sc.TraceFlags() & trace.FlagsSampled - h := fmt.Sprintf("%.2x-%s-%s-%s", - supportedVersion, - sc.TraceID(), - sc.SpanID(), - flags) - carrier.Set(traceparentHeader, h) + var sb strings.Builder + sb.Grow(2 + 32 + 16 + 2 + 3) + _, _ = sb.WriteString(versionPart) + traceID := sc.TraceID() + spanID := sc.SpanID() + flagByte := [1]byte{byte(flags)} + var buf [32]byte + for _, src := range [][]byte{traceID[:], spanID[:], flagByte[:]} { + _ = sb.WriteByte(delimiter[0]) + n := hex.Encode(buf[:], src) + _, _ = sb.Write(buf[:n]) + } + carrier.Set(traceparentHeader, sb.String()) } // Extract reads tracecontext from the carrier into a returned Context. @@ -86,21 +94,8 @@ func (tc TraceContext) extract(carrier TextMapCarrier) trace.SpanContext { return trace.SpanContext{} } - matches := traceCtxRegExp.FindStringSubmatch(h) - - if len(matches) == 0 { - return trace.SpanContext{} - } - - if len(matches) < 5 { // four subgroups plus the overall match - return trace.SpanContext{} - } - - if len(matches[1]) != 2 { - return trace.SpanContext{} - } - ver, err := hex.DecodeString(matches[1]) - if err != nil { + var ver [1]byte + if !extractPart(ver[:], &h, 2) { return trace.SpanContext{} } version := int(ver[0]) @@ -108,36 +103,24 @@ func (tc TraceContext) extract(carrier TextMapCarrier) trace.SpanContext { return trace.SpanContext{} } - if version == 0 && len(matches) != 5 { // four subgroups plus the overall match - return trace.SpanContext{} - } - - if len(matches[2]) != 32 { - return trace.SpanContext{} - } - var scc trace.SpanContextConfig - - scc.TraceID, err = trace.TraceIDFromHex(matches[2][:32]) - if err != nil { + if !extractPart(scc.TraceID[:], &h, 32) { + return trace.SpanContext{} + } + if !extractPart(scc.SpanID[:], &h, 16) { return trace.SpanContext{} } - if len(matches[3]) != 16 { + var opts [1]byte + if !extractPart(opts[:], &h, 2) { return trace.SpanContext{} } - scc.SpanID, err = trace.SpanIDFromHex(matches[3]) - if err != nil { + if version == 0 && (h != "" || opts[0] > 2) { + // version 0 not allow extra + // version 0 not allow other flag return trace.SpanContext{} } - if len(matches[4]) != 2 { - return trace.SpanContext{} - } - opts, err := hex.DecodeString(matches[4]) - if err != nil || len(opts) < 1 || (version == 0 && opts[0] > 2) { - return trace.SpanContext{} - } // Clear all flags other than the trace-context supported sampling bit. scc.TraceFlags = trace.TraceFlags(opts[0]) & trace.FlagsSampled @@ -155,6 +138,29 @@ func (tc TraceContext) extract(carrier TextMapCarrier) trace.SpanContext { return sc } +// upperHex detect hex is upper case Unicode characters. +func upperHex(v string) bool { + for _, c := range v { + if c >= 'A' && c <= 'F' { + return true + } + } + return false +} + +func extractPart(dst []byte, h *string, n int) bool { + part, left, _ := strings.Cut(*h, delimiter) + *h = left + // hex.Decode decodes unsupported upper-case characters, so exclude explicitly. + if len(part) != n || upperHex(part) { + return false + } + if p, err := hex.Decode(dst, []byte(part)); err != nil || p != n/2 { + return false + } + return true +} + // Fields returns the keys who's values are set with Inject. func (tc TraceContext) Fields() []string { return []string{traceparentHeader, tracestateHeader} diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go b/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go index c63a0dd1f8..6a2c08293a 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go @@ -22,7 +22,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) type ( diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/container.go b/vendor/go.opentelemetry.io/otel/sdk/resource/container.go index 3d53622828..c881b2895b 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/container.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/container.go @@ -22,7 +22,7 @@ import ( "os" "regexp" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) type containerIDProvider func() (string, error) diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/env.go b/vendor/go.opentelemetry.io/otel/sdk/resource/env.go index e29ae563a6..be4cbe423e 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/env.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/env.go @@ -23,7 +23,7 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) const ( diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/host_id.go b/vendor/go.opentelemetry.io/otel/sdk/resource/host_id.go index fb1ebf2cab..f579329c2c 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/host_id.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/host_id.go @@ -19,7 +19,7 @@ import ( "errors" "strings" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) type hostIDProvider func() (string, error) diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/os.go b/vendor/go.opentelemetry.io/otel/sdk/resource/os.go index 0cbd559739..8fbf071c17 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/os.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/os.go @@ -19,7 +19,7 @@ import ( "strings" "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) type osDescriptionProvider func() (string, error) diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/process.go b/vendor/go.opentelemetry.io/otel/sdk/resource/process.go index ecdd11dd76..739ea4512a 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/process.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/process.go @@ -22,7 +22,7 @@ import ( "path/filepath" "runtime" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) type ( diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/span.go b/vendor/go.opentelemetry.io/otel/sdk/trace/span.go index 36dbf67764..85bc702a01 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/span.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/span.go @@ -30,7 +30,7 @@ import ( "go.opentelemetry.io/otel/sdk/instrumentation" "go.opentelemetry.io/otel/sdk/internal" "go.opentelemetry.io/otel/sdk/resource" - semconv "go.opentelemetry.io/otel/semconv/v1.21.0" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" "go.opentelemetry.io/otel/trace" "go.opentelemetry.io/otel/trace/embedded" ) @@ -208,6 +208,16 @@ func (s *recordingSpan) SetStatus(code codes.Code, description string) { s.status = status } +// ensureAttributesCapacity inlines functionality from slices.Grow +// so that we can avoid needing to import golang.org/x/exp for go1.20. +// Once support for go1.20 is dropped, we can use slices.Grow available since go1.21 instead. +// Tracking issue: https://github.com/open-telemetry/opentelemetry-go/issues/4819. +func (s *recordingSpan) ensureAttributesCapacity(minCapacity int) { + if n := minCapacity - cap(s.attributes); n > 0 { + s.attributes = append(s.attributes[:cap(s.attributes)], make([]attribute.KeyValue, n)...)[:len(s.attributes)] + } +} + // SetAttributes sets attributes of this span. // // If a key from attributes already exists the value associated with that key @@ -242,6 +252,7 @@ func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) { // Otherwise, add without deduplication. When attributes are read they // will be deduplicated, optimizing the operation. + s.ensureAttributesCapacity(len(s.attributes) + len(attributes)) for _, a := range attributes { if !a.Valid() { // Drop all invalid attributes. @@ -277,6 +288,12 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) { // Now that s.attributes is deduplicated, adding unique attributes up to // the capacity of s will not over allocate s.attributes. + if sum := len(attrs) + len(s.attributes); sum < limit { + // After support for go1.20 is dropped, simplify if-else to min(sum, limit). + s.ensureAttributesCapacity(sum) + } else { + s.ensureAttributesCapacity(limit) + } for _, a := range attrs { if !a.Valid() { // Drop all invalid attributes. diff --git a/vendor/go.opentelemetry.io/otel/sdk/version.go b/vendor/go.opentelemetry.io/otel/sdk/version.go index 422d4c964b..17b16cc796 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/version.go +++ b/vendor/go.opentelemetry.io/otel/sdk/version.go @@ -16,5 +16,5 @@ package sdk // import "go.opentelemetry.io/otel/sdk" // Version is the current release version of the OpenTelemetry SDK in use. func Version() string { - return "1.21.0" + return "1.22.0" } diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.21.0/doc.go b/vendor/go.opentelemetry.io/otel/semconv/v1.21.0/doc.go index 7cf424855e..0318b5ec48 100644 --- a/vendor/go.opentelemetry.io/otel/semconv/v1.21.0/doc.go +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.21.0/doc.go @@ -15,6 +15,6 @@ // Package semconv implements OpenTelemetry semantic conventions. // // OpenTelemetry semantic conventions are agreed standardized naming -// patterns for OpenTelemetry things. This package represents the conventions -// as of the v1.21.0 version of the OpenTelemetry specification. +// patterns for OpenTelemetry things. This package represents the v1.21.0 +// version of the OpenTelemetry semantic conventions. package semconv // import "go.opentelemetry.io/otel/semconv/v1.21.0" diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/attribute_group.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/attribute_group.go new file mode 100644 index 0000000000..31726598d6 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/attribute_group.go @@ -0,0 +1,4398 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" + +import "go.opentelemetry.io/otel/attribute" + +// Describes FaaS attributes. +const ( + // FaaSInvokedNameKey is the attribute Key conforming to the + // "faas.invoked_name" semantic conventions. It represents the name of the + // invoked function. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'my-function' + // Note: SHOULD be equal to the `faas.name` resource attribute of the + // invoked function. + FaaSInvokedNameKey = attribute.Key("faas.invoked_name") + + // FaaSInvokedProviderKey is the attribute Key conforming to the + // "faas.invoked_provider" semantic conventions. It represents the cloud + // provider of the invoked function. + // + // Type: Enum + // RequirementLevel: Required + // Stability: experimental + // Note: SHOULD be equal to the `cloud.provider` resource attribute of the + // invoked function. + FaaSInvokedProviderKey = attribute.Key("faas.invoked_provider") + + // FaaSInvokedRegionKey is the attribute Key conforming to the + // "faas.invoked_region" semantic conventions. It represents the cloud + // region of the invoked function. + // + // Type: string + // RequirementLevel: ConditionallyRequired (For some cloud providers, like + // AWS or GCP, the region in which a function is hosted is essential to + // uniquely identify the function and also part of its endpoint. Since it's + // part of the endpoint being called, the region is always known to + // clients. In these cases, `faas.invoked_region` MUST be set accordingly. + // If the region is unknown to the client or not required for identifying + // the invoked function, setting `faas.invoked_region` is optional.) + // Stability: experimental + // Examples: 'eu-central-1' + // Note: SHOULD be equal to the `cloud.region` resource attribute of the + // invoked function. + FaaSInvokedRegionKey = attribute.Key("faas.invoked_region") + + // FaaSTriggerKey is the attribute Key conforming to the "faas.trigger" + // semantic conventions. It represents the type of the trigger which caused + // this function invocation. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + FaaSTriggerKey = attribute.Key("faas.trigger") +) + +var ( + // Alibaba Cloud + FaaSInvokedProviderAlibabaCloud = FaaSInvokedProviderKey.String("alibaba_cloud") + // Amazon Web Services + FaaSInvokedProviderAWS = FaaSInvokedProviderKey.String("aws") + // Microsoft Azure + FaaSInvokedProviderAzure = FaaSInvokedProviderKey.String("azure") + // Google Cloud Platform + FaaSInvokedProviderGCP = FaaSInvokedProviderKey.String("gcp") + // Tencent Cloud + FaaSInvokedProviderTencentCloud = FaaSInvokedProviderKey.String("tencent_cloud") +) + +var ( + // A response to some data source operation such as a database or filesystem read/write + FaaSTriggerDatasource = FaaSTriggerKey.String("datasource") + // To provide an answer to an inbound HTTP request + FaaSTriggerHTTP = FaaSTriggerKey.String("http") + // A function is set to be executed when messages are sent to a messaging system + FaaSTriggerPubsub = FaaSTriggerKey.String("pubsub") + // A function is scheduled to be executed regularly + FaaSTriggerTimer = FaaSTriggerKey.String("timer") + // If none of the others apply + FaaSTriggerOther = FaaSTriggerKey.String("other") +) + +// FaaSInvokedName returns an attribute KeyValue conforming to the +// "faas.invoked_name" semantic conventions. It represents the name of the +// invoked function. +func FaaSInvokedName(val string) attribute.KeyValue { + return FaaSInvokedNameKey.String(val) +} + +// FaaSInvokedRegion returns an attribute KeyValue conforming to the +// "faas.invoked_region" semantic conventions. It represents the cloud region +// of the invoked function. +func FaaSInvokedRegion(val string) attribute.KeyValue { + return FaaSInvokedRegionKey.String(val) +} + +// Attributes for Events represented using Log Records. +const ( + // EventNameKey is the attribute Key conforming to the "event.name" + // semantic conventions. It represents the identifies the class / type of + // event. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'browser.mouse.click', 'device.app.lifecycle' + // Note: Event names are subject to the same rules as [attribute + // names](https://github.com/open-telemetry/opentelemetry-specification/tree/v1.26.0/specification/common/attribute-naming.md). + // Notably, event names are namespaced to avoid collisions and provide a + // clean separation of semantics for events in separate domains like + // browser, mobile, and kubernetes. + EventNameKey = attribute.Key("event.name") +) + +// EventName returns an attribute KeyValue conforming to the "event.name" +// semantic conventions. It represents the identifies the class / type of +// event. +func EventName(val string) attribute.KeyValue { + return EventNameKey.String(val) +} + +// The attributes described in this section are rather generic. They may be +// used in any Log Record they apply to. +const ( + // LogRecordUIDKey is the attribute Key conforming to the "log.record.uid" + // semantic conventions. It represents a unique identifier for the Log + // Record. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '01ARZ3NDEKTSV4RRFFQ69G5FAV' + // Note: If an id is provided, other log records with the same id will be + // considered duplicates and can be removed safely. This means, that two + // distinguishable log records MUST have different values. + // The id MAY be an [Universally Unique Lexicographically Sortable + // Identifier (ULID)](https://github.com/ulid/spec), but other identifiers + // (e.g. UUID) may be used as needed. + LogRecordUIDKey = attribute.Key("log.record.uid") +) + +// LogRecordUID returns an attribute KeyValue conforming to the +// "log.record.uid" semantic conventions. It represents a unique identifier for +// the Log Record. +func LogRecordUID(val string) attribute.KeyValue { + return LogRecordUIDKey.String(val) +} + +// Describes Log attributes +const ( + // LogIostreamKey is the attribute Key conforming to the "log.iostream" + // semantic conventions. It represents the stream associated with the log. + // See below for a list of well-known values. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + LogIostreamKey = attribute.Key("log.iostream") +) + +var ( + // Logs from stdout stream + LogIostreamStdout = LogIostreamKey.String("stdout") + // Events from stderr stream + LogIostreamStderr = LogIostreamKey.String("stderr") +) + +// A file to which log was emitted. +const ( + // LogFileNameKey is the attribute Key conforming to the "log.file.name" + // semantic conventions. It represents the basename of the file. + // + // Type: string + // RequirementLevel: Recommended + // Stability: experimental + // Examples: 'audit.log' + LogFileNameKey = attribute.Key("log.file.name") + + // LogFileNameResolvedKey is the attribute Key conforming to the + // "log.file.name_resolved" semantic conventions. It represents the + // basename of the file, with symlinks resolved. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'uuid.log' + LogFileNameResolvedKey = attribute.Key("log.file.name_resolved") + + // LogFilePathKey is the attribute Key conforming to the "log.file.path" + // semantic conventions. It represents the full path to the file. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '/var/log/mysql/audit.log' + LogFilePathKey = attribute.Key("log.file.path") + + // LogFilePathResolvedKey is the attribute Key conforming to the + // "log.file.path_resolved" semantic conventions. It represents the full + // path to the file, with symlinks resolved. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '/var/lib/docker/uuid.log' + LogFilePathResolvedKey = attribute.Key("log.file.path_resolved") +) + +// LogFileName returns an attribute KeyValue conforming to the +// "log.file.name" semantic conventions. It represents the basename of the +// file. +func LogFileName(val string) attribute.KeyValue { + return LogFileNameKey.String(val) +} + +// LogFileNameResolved returns an attribute KeyValue conforming to the +// "log.file.name_resolved" semantic conventions. It represents the basename of +// the file, with symlinks resolved. +func LogFileNameResolved(val string) attribute.KeyValue { + return LogFileNameResolvedKey.String(val) +} + +// LogFilePath returns an attribute KeyValue conforming to the +// "log.file.path" semantic conventions. It represents the full path to the +// file. +func LogFilePath(val string) attribute.KeyValue { + return LogFilePathKey.String(val) +} + +// LogFilePathResolved returns an attribute KeyValue conforming to the +// "log.file.path_resolved" semantic conventions. It represents the full path +// to the file, with symlinks resolved. +func LogFilePathResolved(val string) attribute.KeyValue { + return LogFilePathResolvedKey.String(val) +} + +// Describes Database attributes +const ( + // PoolNameKey is the attribute Key conforming to the "pool.name" semantic + // conventions. It represents the name of the connection pool; unique + // within the instrumented application. In case the connection pool + // implementation doesn't provide a name, then the + // [db.connection_string](/docs/database/database-spans.md#connection-level-attributes) + // should be used + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'myDataSource' + PoolNameKey = attribute.Key("pool.name") + + // StateKey is the attribute Key conforming to the "state" semantic + // conventions. It represents the state of a connection in the pool + // + // Type: Enum + // RequirementLevel: Required + // Stability: experimental + // Examples: 'idle' + StateKey = attribute.Key("state") +) + +var ( + // idle + StateIdle = StateKey.String("idle") + // used + StateUsed = StateKey.String("used") +) + +// PoolName returns an attribute KeyValue conforming to the "pool.name" +// semantic conventions. It represents the name of the connection pool; unique +// within the instrumented application. In case the connection pool +// implementation doesn't provide a name, then the +// [db.connection_string](/docs/database/database-spans.md#connection-level-attributes) +// should be used +func PoolName(val string) attribute.KeyValue { + return PoolNameKey.String(val) +} + +// ASP.NET Core attributes +const ( + // AspnetcoreDiagnosticsHandlerTypeKey is the attribute Key conforming to + // the "aspnetcore.diagnostics.handler.type" semantic conventions. It + // represents the full type name of the + // [`IExceptionHandler`](https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.diagnostics.iexceptionhandler) + // implementation that handled the exception. + // + // Type: string + // RequirementLevel: ConditionallyRequired (if and only if the exception + // was handled by this handler.) + // Stability: experimental + // Examples: 'Contoso.MyHandler' + AspnetcoreDiagnosticsHandlerTypeKey = attribute.Key("aspnetcore.diagnostics.handler.type") + + // AspnetcoreRateLimitingPolicyKey is the attribute Key conforming to the + // "aspnetcore.rate_limiting.policy" semantic conventions. It represents + // the rate limiting policy name. + // + // Type: string + // RequirementLevel: ConditionallyRequired (if the matched endpoint for the + // request had a rate-limiting policy.) + // Stability: experimental + // Examples: 'fixed', 'sliding', 'token' + AspnetcoreRateLimitingPolicyKey = attribute.Key("aspnetcore.rate_limiting.policy") + + // AspnetcoreRateLimitingResultKey is the attribute Key conforming to the + // "aspnetcore.rate_limiting.result" semantic conventions. It represents + // the rate-limiting result, shows whether the lease was acquired or + // contains a rejection reason + // + // Type: Enum + // RequirementLevel: Required + // Stability: experimental + // Examples: 'acquired', 'request_canceled' + AspnetcoreRateLimitingResultKey = attribute.Key("aspnetcore.rate_limiting.result") + + // AspnetcoreRequestIsUnhandledKey is the attribute Key conforming to the + // "aspnetcore.request.is_unhandled" semantic conventions. It represents + // the flag indicating if request was handled by the application pipeline. + // + // Type: boolean + // RequirementLevel: ConditionallyRequired (if and only if the request was + // not handled.) + // Stability: experimental + // Examples: True + AspnetcoreRequestIsUnhandledKey = attribute.Key("aspnetcore.request.is_unhandled") + + // AspnetcoreRoutingIsFallbackKey is the attribute Key conforming to the + // "aspnetcore.routing.is_fallback" semantic conventions. It represents a + // value that indicates whether the matched route is a fallback route. + // + // Type: boolean + // RequirementLevel: ConditionallyRequired (If and only if a route was + // successfully matched.) + // Stability: experimental + // Examples: True + AspnetcoreRoutingIsFallbackKey = attribute.Key("aspnetcore.routing.is_fallback") +) + +var ( + // Lease was acquired + AspnetcoreRateLimitingResultAcquired = AspnetcoreRateLimitingResultKey.String("acquired") + // Lease request was rejected by the endpoint limiter + AspnetcoreRateLimitingResultEndpointLimiter = AspnetcoreRateLimitingResultKey.String("endpoint_limiter") + // Lease request was rejected by the global limiter + AspnetcoreRateLimitingResultGlobalLimiter = AspnetcoreRateLimitingResultKey.String("global_limiter") + // Lease request was canceled + AspnetcoreRateLimitingResultRequestCanceled = AspnetcoreRateLimitingResultKey.String("request_canceled") +) + +// AspnetcoreDiagnosticsHandlerType returns an attribute KeyValue conforming +// to the "aspnetcore.diagnostics.handler.type" semantic conventions. It +// represents the full type name of the +// [`IExceptionHandler`](https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.diagnostics.iexceptionhandler) +// implementation that handled the exception. +func AspnetcoreDiagnosticsHandlerType(val string) attribute.KeyValue { + return AspnetcoreDiagnosticsHandlerTypeKey.String(val) +} + +// AspnetcoreRateLimitingPolicy returns an attribute KeyValue conforming to +// the "aspnetcore.rate_limiting.policy" semantic conventions. It represents +// the rate limiting policy name. +func AspnetcoreRateLimitingPolicy(val string) attribute.KeyValue { + return AspnetcoreRateLimitingPolicyKey.String(val) +} + +// AspnetcoreRequestIsUnhandled returns an attribute KeyValue conforming to +// the "aspnetcore.request.is_unhandled" semantic conventions. It represents +// the flag indicating if request was handled by the application pipeline. +func AspnetcoreRequestIsUnhandled(val bool) attribute.KeyValue { + return AspnetcoreRequestIsUnhandledKey.Bool(val) +} + +// AspnetcoreRoutingIsFallback returns an attribute KeyValue conforming to +// the "aspnetcore.routing.is_fallback" semantic conventions. It represents a +// value that indicates whether the matched route is a fallback route. +func AspnetcoreRoutingIsFallback(val bool) attribute.KeyValue { + return AspnetcoreRoutingIsFallbackKey.Bool(val) +} + +// SignalR attributes +const ( + // SignalrConnectionStatusKey is the attribute Key conforming to the + // "signalr.connection.status" semantic conventions. It represents the + // signalR HTTP connection closure status. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'app_shutdown', 'timeout' + SignalrConnectionStatusKey = attribute.Key("signalr.connection.status") + + // SignalrTransportKey is the attribute Key conforming to the + // "signalr.transport" semantic conventions. It represents the [SignalR + // transport + // type](https://github.com/dotnet/aspnetcore/blob/main/src/SignalR/docs/specs/TransportProtocols.md) + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'web_sockets', 'long_polling' + SignalrTransportKey = attribute.Key("signalr.transport") +) + +var ( + // The connection was closed normally + SignalrConnectionStatusNormalClosure = SignalrConnectionStatusKey.String("normal_closure") + // The connection was closed due to a timeout + SignalrConnectionStatusTimeout = SignalrConnectionStatusKey.String("timeout") + // The connection was closed because the app is shutting down + SignalrConnectionStatusAppShutdown = SignalrConnectionStatusKey.String("app_shutdown") +) + +var ( + // ServerSentEvents protocol + SignalrTransportServerSentEvents = SignalrTransportKey.String("server_sent_events") + // LongPolling protocol + SignalrTransportLongPolling = SignalrTransportKey.String("long_polling") + // WebSockets protocol + SignalrTransportWebSockets = SignalrTransportKey.String("web_sockets") +) + +// Describes JVM buffer metric attributes. +const ( + // JvmBufferPoolNameKey is the attribute Key conforming to the + // "jvm.buffer.pool.name" semantic conventions. It represents the name of + // the buffer pool. + // + // Type: string + // RequirementLevel: Recommended + // Stability: experimental + // Examples: 'mapped', 'direct' + // Note: Pool names are generally obtained via + // [BufferPoolMXBean#getName()](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/BufferPoolMXBean.html#getName()). + JvmBufferPoolNameKey = attribute.Key("jvm.buffer.pool.name") +) + +// JvmBufferPoolName returns an attribute KeyValue conforming to the +// "jvm.buffer.pool.name" semantic conventions. It represents the name of the +// buffer pool. +func JvmBufferPoolName(val string) attribute.KeyValue { + return JvmBufferPoolNameKey.String(val) +} + +// Describes JVM memory metric attributes. +const ( + // JvmMemoryPoolNameKey is the attribute Key conforming to the + // "jvm.memory.pool.name" semantic conventions. It represents the name of + // the memory pool. + // + // Type: string + // RequirementLevel: Recommended + // Stability: stable + // Examples: 'G1 Old Gen', 'G1 Eden space', 'G1 Survivor Space' + // Note: Pool names are generally obtained via + // [MemoryPoolMXBean#getName()](https://docs.oracle.com/en/java/javase/11/docs/api/java.management/java/lang/management/MemoryPoolMXBean.html#getName()). + JvmMemoryPoolNameKey = attribute.Key("jvm.memory.pool.name") + + // JvmMemoryTypeKey is the attribute Key conforming to the + // "jvm.memory.type" semantic conventions. It represents the type of + // memory. + // + // Type: Enum + // RequirementLevel: Recommended + // Stability: stable + // Examples: 'heap', 'non_heap' + JvmMemoryTypeKey = attribute.Key("jvm.memory.type") +) + +var ( + // Heap memory + JvmMemoryTypeHeap = JvmMemoryTypeKey.String("heap") + // Non-heap memory + JvmMemoryTypeNonHeap = JvmMemoryTypeKey.String("non_heap") +) + +// JvmMemoryPoolName returns an attribute KeyValue conforming to the +// "jvm.memory.pool.name" semantic conventions. It represents the name of the +// memory pool. +func JvmMemoryPoolName(val string) attribute.KeyValue { + return JvmMemoryPoolNameKey.String(val) +} + +// Describes System metric attributes +const ( + // SystemDeviceKey is the attribute Key conforming to the "system.device" + // semantic conventions. It represents the device identifier + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '(identifier)' + SystemDeviceKey = attribute.Key("system.device") +) + +// SystemDevice returns an attribute KeyValue conforming to the +// "system.device" semantic conventions. It represents the device identifier +func SystemDevice(val string) attribute.KeyValue { + return SystemDeviceKey.String(val) +} + +// Describes System CPU metric attributes +const ( + // SystemCPULogicalNumberKey is the attribute Key conforming to the + // "system.cpu.logical_number" semantic conventions. It represents the + // logical CPU number [0..n-1] + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 1 + SystemCPULogicalNumberKey = attribute.Key("system.cpu.logical_number") + + // SystemCPUStateKey is the attribute Key conforming to the + // "system.cpu.state" semantic conventions. It represents the state of the + // CPU + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'idle', 'interrupt' + SystemCPUStateKey = attribute.Key("system.cpu.state") +) + +var ( + // user + SystemCPUStateUser = SystemCPUStateKey.String("user") + // system + SystemCPUStateSystem = SystemCPUStateKey.String("system") + // nice + SystemCPUStateNice = SystemCPUStateKey.String("nice") + // idle + SystemCPUStateIdle = SystemCPUStateKey.String("idle") + // iowait + SystemCPUStateIowait = SystemCPUStateKey.String("iowait") + // interrupt + SystemCPUStateInterrupt = SystemCPUStateKey.String("interrupt") + // steal + SystemCPUStateSteal = SystemCPUStateKey.String("steal") +) + +// SystemCPULogicalNumber returns an attribute KeyValue conforming to the +// "system.cpu.logical_number" semantic conventions. It represents the logical +// CPU number [0..n-1] +func SystemCPULogicalNumber(val int) attribute.KeyValue { + return SystemCPULogicalNumberKey.Int(val) +} + +// Describes System Memory metric attributes +const ( + // SystemMemoryStateKey is the attribute Key conforming to the + // "system.memory.state" semantic conventions. It represents the memory + // state + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'free', 'cached' + SystemMemoryStateKey = attribute.Key("system.memory.state") +) + +var ( + // used + SystemMemoryStateUsed = SystemMemoryStateKey.String("used") + // free + SystemMemoryStateFree = SystemMemoryStateKey.String("free") + // shared + SystemMemoryStateShared = SystemMemoryStateKey.String("shared") + // buffers + SystemMemoryStateBuffers = SystemMemoryStateKey.String("buffers") + // cached + SystemMemoryStateCached = SystemMemoryStateKey.String("cached") +) + +// Describes System Memory Paging metric attributes +const ( + // SystemPagingDirectionKey is the attribute Key conforming to the + // "system.paging.direction" semantic conventions. It represents the paging + // access direction + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'in' + SystemPagingDirectionKey = attribute.Key("system.paging.direction") + + // SystemPagingStateKey is the attribute Key conforming to the + // "system.paging.state" semantic conventions. It represents the memory + // paging state + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'free' + SystemPagingStateKey = attribute.Key("system.paging.state") + + // SystemPagingTypeKey is the attribute Key conforming to the + // "system.paging.type" semantic conventions. It represents the memory + // paging type + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'minor' + SystemPagingTypeKey = attribute.Key("system.paging.type") +) + +var ( + // in + SystemPagingDirectionIn = SystemPagingDirectionKey.String("in") + // out + SystemPagingDirectionOut = SystemPagingDirectionKey.String("out") +) + +var ( + // used + SystemPagingStateUsed = SystemPagingStateKey.String("used") + // free + SystemPagingStateFree = SystemPagingStateKey.String("free") +) + +var ( + // major + SystemPagingTypeMajor = SystemPagingTypeKey.String("major") + // minor + SystemPagingTypeMinor = SystemPagingTypeKey.String("minor") +) + +// Describes Filesystem metric attributes +const ( + // SystemFilesystemModeKey is the attribute Key conforming to the + // "system.filesystem.mode" semantic conventions. It represents the + // filesystem mode + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'rw, ro' + SystemFilesystemModeKey = attribute.Key("system.filesystem.mode") + + // SystemFilesystemMountpointKey is the attribute Key conforming to the + // "system.filesystem.mountpoint" semantic conventions. It represents the + // filesystem mount path + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '/mnt/data' + SystemFilesystemMountpointKey = attribute.Key("system.filesystem.mountpoint") + + // SystemFilesystemStateKey is the attribute Key conforming to the + // "system.filesystem.state" semantic conventions. It represents the + // filesystem state + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'used' + SystemFilesystemStateKey = attribute.Key("system.filesystem.state") + + // SystemFilesystemTypeKey is the attribute Key conforming to the + // "system.filesystem.type" semantic conventions. It represents the + // filesystem type + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'ext4' + SystemFilesystemTypeKey = attribute.Key("system.filesystem.type") +) + +var ( + // used + SystemFilesystemStateUsed = SystemFilesystemStateKey.String("used") + // free + SystemFilesystemStateFree = SystemFilesystemStateKey.String("free") + // reserved + SystemFilesystemStateReserved = SystemFilesystemStateKey.String("reserved") +) + +var ( + // fat32 + SystemFilesystemTypeFat32 = SystemFilesystemTypeKey.String("fat32") + // exfat + SystemFilesystemTypeExfat = SystemFilesystemTypeKey.String("exfat") + // ntfs + SystemFilesystemTypeNtfs = SystemFilesystemTypeKey.String("ntfs") + // refs + SystemFilesystemTypeRefs = SystemFilesystemTypeKey.String("refs") + // hfsplus + SystemFilesystemTypeHfsplus = SystemFilesystemTypeKey.String("hfsplus") + // ext4 + SystemFilesystemTypeExt4 = SystemFilesystemTypeKey.String("ext4") +) + +// SystemFilesystemMode returns an attribute KeyValue conforming to the +// "system.filesystem.mode" semantic conventions. It represents the filesystem +// mode +func SystemFilesystemMode(val string) attribute.KeyValue { + return SystemFilesystemModeKey.String(val) +} + +// SystemFilesystemMountpoint returns an attribute KeyValue conforming to +// the "system.filesystem.mountpoint" semantic conventions. It represents the +// filesystem mount path +func SystemFilesystemMountpoint(val string) attribute.KeyValue { + return SystemFilesystemMountpointKey.String(val) +} + +// Describes Network metric attributes +const ( + // SystemNetworkStateKey is the attribute Key conforming to the + // "system.network.state" semantic conventions. It represents a stateless + // protocol MUST NOT set this attribute + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'close_wait' + SystemNetworkStateKey = attribute.Key("system.network.state") +) + +var ( + // close + SystemNetworkStateClose = SystemNetworkStateKey.String("close") + // close_wait + SystemNetworkStateCloseWait = SystemNetworkStateKey.String("close_wait") + // closing + SystemNetworkStateClosing = SystemNetworkStateKey.String("closing") + // delete + SystemNetworkStateDelete = SystemNetworkStateKey.String("delete") + // established + SystemNetworkStateEstablished = SystemNetworkStateKey.String("established") + // fin_wait_1 + SystemNetworkStateFinWait1 = SystemNetworkStateKey.String("fin_wait_1") + // fin_wait_2 + SystemNetworkStateFinWait2 = SystemNetworkStateKey.String("fin_wait_2") + // last_ack + SystemNetworkStateLastAck = SystemNetworkStateKey.String("last_ack") + // listen + SystemNetworkStateListen = SystemNetworkStateKey.String("listen") + // syn_recv + SystemNetworkStateSynRecv = SystemNetworkStateKey.String("syn_recv") + // syn_sent + SystemNetworkStateSynSent = SystemNetworkStateKey.String("syn_sent") + // time_wait + SystemNetworkStateTimeWait = SystemNetworkStateKey.String("time_wait") +) + +// Describes System Process metric attributes +const ( + // SystemProcessesStatusKey is the attribute Key conforming to the + // "system.processes.status" semantic conventions. It represents the + // process state, e.g., [Linux Process State + // Codes](https://man7.org/linux/man-pages/man1/ps.1.html#PROCESS_STATE_CODES) + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'running' + SystemProcessesStatusKey = attribute.Key("system.processes.status") +) + +var ( + // running + SystemProcessesStatusRunning = SystemProcessesStatusKey.String("running") + // sleeping + SystemProcessesStatusSleeping = SystemProcessesStatusKey.String("sleeping") + // stopped + SystemProcessesStatusStopped = SystemProcessesStatusKey.String("stopped") + // defunct + SystemProcessesStatusDefunct = SystemProcessesStatusKey.String("defunct") +) + +// These attributes may be used to describe the client in a connection-based +// network interaction where there is one side that initiates the connection +// (the client is the side that initiates the connection). This covers all TCP +// network interactions since TCP is connection-based and one side initiates +// the connection (an exception is made for peer-to-peer communication over TCP +// where the "user-facing" surface of the protocol / API doesn't expose a clear +// notion of client and server). This also covers UDP network interactions +// where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS. +const ( + // ClientAddressKey is the attribute Key conforming to the "client.address" + // semantic conventions. It represents the client address - domain name if + // available without reverse DNS lookup; otherwise, IP address or Unix + // domain socket name. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'client.example.com', '10.1.2.80', '/tmp/my.sock' + // Note: When observed from the server side, and when communicating through + // an intermediary, `client.address` SHOULD represent the client address + // behind any intermediaries, for example proxies, if it's available. + ClientAddressKey = attribute.Key("client.address") + + // ClientPortKey is the attribute Key conforming to the "client.port" + // semantic conventions. It represents the client port number. + // + // Type: int + // RequirementLevel: Optional + // Stability: stable + // Examples: 65123 + // Note: When observed from the server side, and when communicating through + // an intermediary, `client.port` SHOULD represent the client port behind + // any intermediaries, for example proxies, if it's available. + ClientPortKey = attribute.Key("client.port") +) + +// ClientAddress returns an attribute KeyValue conforming to the +// "client.address" semantic conventions. It represents the client address - +// domain name if available without reverse DNS lookup; otherwise, IP address +// or Unix domain socket name. +func ClientAddress(val string) attribute.KeyValue { + return ClientAddressKey.String(val) +} + +// ClientPort returns an attribute KeyValue conforming to the "client.port" +// semantic conventions. It represents the client port number. +func ClientPort(val int) attribute.KeyValue { + return ClientPortKey.Int(val) +} + +// The attributes used to describe telemetry in the context of databases. +const ( + // DBCassandraConsistencyLevelKey is the attribute Key conforming to the + // "db.cassandra.consistency_level" semantic conventions. It represents the + // consistency level of the query. Based on consistency values from + // [CQL](https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/dml/dmlConfigConsistency.html). + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + DBCassandraConsistencyLevelKey = attribute.Key("db.cassandra.consistency_level") + + // DBCassandraCoordinatorDCKey is the attribute Key conforming to the + // "db.cassandra.coordinator.dc" semantic conventions. It represents the + // data center of the coordinating node for a query. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'us-west-2' + DBCassandraCoordinatorDCKey = attribute.Key("db.cassandra.coordinator.dc") + + // DBCassandraCoordinatorIDKey is the attribute Key conforming to the + // "db.cassandra.coordinator.id" semantic conventions. It represents the ID + // of the coordinating node for a query. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'be13faa2-8574-4d71-926d-27f16cf8a7af' + DBCassandraCoordinatorIDKey = attribute.Key("db.cassandra.coordinator.id") + + // DBCassandraIdempotenceKey is the attribute Key conforming to the + // "db.cassandra.idempotence" semantic conventions. It represents the + // whether or not the query is idempotent. + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + DBCassandraIdempotenceKey = attribute.Key("db.cassandra.idempotence") + + // DBCassandraPageSizeKey is the attribute Key conforming to the + // "db.cassandra.page_size" semantic conventions. It represents the fetch + // size used for paging, i.e. how many rows will be returned at once. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 5000 + DBCassandraPageSizeKey = attribute.Key("db.cassandra.page_size") + + // DBCassandraSpeculativeExecutionCountKey is the attribute Key conforming + // to the "db.cassandra.speculative_execution_count" semantic conventions. + // It represents the number of times a query was speculatively executed. + // Not set or `0` if the query was not executed speculatively. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 0, 2 + DBCassandraSpeculativeExecutionCountKey = attribute.Key("db.cassandra.speculative_execution_count") + + // DBCassandraTableKey is the attribute Key conforming to the + // "db.cassandra.table" semantic conventions. It represents the name of the + // primary Cassandra table that the operation is acting upon, including the + // keyspace name (if applicable). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'mytable' + // Note: This mirrors the db.sql.table attribute but references cassandra + // rather than sql. It is not recommended to attempt any client-side + // parsing of `db.statement` just to get this property, but it should be + // set if it is provided by the library being instrumented. If the + // operation is acting upon an anonymous table, or more than one table, + // this value MUST NOT be set. + DBCassandraTableKey = attribute.Key("db.cassandra.table") + + // DBConnectionStringKey is the attribute Key conforming to the + // "db.connection_string" semantic conventions. It represents the + // connection string used to connect to the database. It is recommended to + // remove embedded credentials. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Server=(localdb)\\v11.0;Integrated Security=true;' + DBConnectionStringKey = attribute.Key("db.connection_string") + + // DBCosmosDBClientIDKey is the attribute Key conforming to the + // "db.cosmosdb.client_id" semantic conventions. It represents the unique + // Cosmos client instance id. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '3ba4827d-4422-483f-b59f-85b74211c11d' + DBCosmosDBClientIDKey = attribute.Key("db.cosmosdb.client_id") + + // DBCosmosDBConnectionModeKey is the attribute Key conforming to the + // "db.cosmosdb.connection_mode" semantic conventions. It represents the + // cosmos client connection mode. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + DBCosmosDBConnectionModeKey = attribute.Key("db.cosmosdb.connection_mode") + + // DBCosmosDBContainerKey is the attribute Key conforming to the + // "db.cosmosdb.container" semantic conventions. It represents the cosmos + // DB container name. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'anystring' + DBCosmosDBContainerKey = attribute.Key("db.cosmosdb.container") + + // DBCosmosDBOperationTypeKey is the attribute Key conforming to the + // "db.cosmosdb.operation_type" semantic conventions. It represents the + // cosmosDB Operation Type. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + DBCosmosDBOperationTypeKey = attribute.Key("db.cosmosdb.operation_type") + + // DBCosmosDBRequestChargeKey is the attribute Key conforming to the + // "db.cosmosdb.request_charge" semantic conventions. It represents the rU + // consumed for that operation + // + // Type: double + // RequirementLevel: Optional + // Stability: experimental + // Examples: 46.18, 1.0 + DBCosmosDBRequestChargeKey = attribute.Key("db.cosmosdb.request_charge") + + // DBCosmosDBRequestContentLengthKey is the attribute Key conforming to the + // "db.cosmosdb.request_content_length" semantic conventions. It represents + // the request payload size in bytes + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + DBCosmosDBRequestContentLengthKey = attribute.Key("db.cosmosdb.request_content_length") + + // DBCosmosDBStatusCodeKey is the attribute Key conforming to the + // "db.cosmosdb.status_code" semantic conventions. It represents the cosmos + // DB status code. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 200, 201 + DBCosmosDBStatusCodeKey = attribute.Key("db.cosmosdb.status_code") + + // DBCosmosDBSubStatusCodeKey is the attribute Key conforming to the + // "db.cosmosdb.sub_status_code" semantic conventions. It represents the + // cosmos DB sub status code. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 1000, 1002 + DBCosmosDBSubStatusCodeKey = attribute.Key("db.cosmosdb.sub_status_code") + + // DBElasticsearchClusterNameKey is the attribute Key conforming to the + // "db.elasticsearch.cluster.name" semantic conventions. It represents the + // represents the identifier of an Elasticsearch cluster. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'e9106fc68e3044f0b1475b04bf4ffd5f' + DBElasticsearchClusterNameKey = attribute.Key("db.elasticsearch.cluster.name") + + // DBElasticsearchNodeNameKey is the attribute Key conforming to the + // "db.elasticsearch.node.name" semantic conventions. It represents the + // represents the human-readable identifier of the node/instance to which a + // request was routed. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'instance-0000000001' + DBElasticsearchNodeNameKey = attribute.Key("db.elasticsearch.node.name") + + // DBInstanceIDKey is the attribute Key conforming to the "db.instance.id" + // semantic conventions. It represents an identifier (address, unique name, + // or any other identifier) of the database instance that is executing + // queries or mutations on the current connection. This is useful in cases + // where the database is running in a clustered environment and the + // instrumentation is able to record the node executing the query. The + // client may obtain this value in databases like MySQL using queries like + // `select @@hostname`. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'mysql-e26b99z.example.com' + DBInstanceIDKey = attribute.Key("db.instance.id") + + // DBJDBCDriverClassnameKey is the attribute Key conforming to the + // "db.jdbc.driver_classname" semantic conventions. It represents the + // fully-qualified class name of the [Java Database Connectivity + // (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) + // driver used to connect. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'org.postgresql.Driver', + // 'com.microsoft.sqlserver.jdbc.SQLServerDriver' + DBJDBCDriverClassnameKey = attribute.Key("db.jdbc.driver_classname") + + // DBMongoDBCollectionKey is the attribute Key conforming to the + // "db.mongodb.collection" semantic conventions. It represents the MongoDB + // collection being accessed within the database stated in `db.name`. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'customers', 'products' + DBMongoDBCollectionKey = attribute.Key("db.mongodb.collection") + + // DBMSSQLInstanceNameKey is the attribute Key conforming to the + // "db.mssql.instance_name" semantic conventions. It represents the + // Microsoft SQL Server [instance + // name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) + // connecting to. This name is used to determine the port of a named + // instance. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'MSSQLSERVER' + // Note: If setting a `db.mssql.instance_name`, `server.port` is no longer + // required (but still recommended if non-standard). + DBMSSQLInstanceNameKey = attribute.Key("db.mssql.instance_name") + + // DBNameKey is the attribute Key conforming to the "db.name" semantic + // conventions. It represents the this attribute is used to report the name + // of the database being accessed. For commands that switch the database, + // this should be set to the target database (even if the command fails). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'customers', 'main' + // Note: In some SQL databases, the database name to be used is called + // "schema name". In case there are multiple layers that could be + // considered for database name (e.g. Oracle instance name and schema + // name), the database name to be used is the more specific layer (e.g. + // Oracle schema name). + DBNameKey = attribute.Key("db.name") + + // DBOperationKey is the attribute Key conforming to the "db.operation" + // semantic conventions. It represents the name of the operation being + // executed, e.g. the [MongoDB command + // name](https://docs.mongodb.com/manual/reference/command/#database-operations) + // such as `findAndModify`, or the SQL keyword. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'findAndModify', 'HMSET', 'SELECT' + // Note: When setting this to an SQL keyword, it is not recommended to + // attempt any client-side parsing of `db.statement` just to get this + // property, but it should be set if the operation name is provided by the + // library being instrumented. If the SQL statement has an ambiguous + // operation, or performs more than one operation, this value may be + // omitted. + DBOperationKey = attribute.Key("db.operation") + + // DBRedisDBIndexKey is the attribute Key conforming to the + // "db.redis.database_index" semantic conventions. It represents the index + // of the database being accessed as used in the [`SELECT` + // command](https://redis.io/commands/select), provided as an integer. To + // be used instead of the generic `db.name` attribute. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 0, 1, 15 + DBRedisDBIndexKey = attribute.Key("db.redis.database_index") + + // DBSQLTableKey is the attribute Key conforming to the "db.sql.table" + // semantic conventions. It represents the name of the primary table that + // the operation is acting upon, including the database name (if + // applicable). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'public.users', 'customers' + // Note: It is not recommended to attempt any client-side parsing of + // `db.statement` just to get this property, but it should be set if it is + // provided by the library being instrumented. If the operation is acting + // upon an anonymous table, or more than one table, this value MUST NOT be + // set. + DBSQLTableKey = attribute.Key("db.sql.table") + + // DBStatementKey is the attribute Key conforming to the "db.statement" + // semantic conventions. It represents the database statement being + // executed. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'SELECT * FROM wuser_table', 'SET mykey "WuValue"' + DBStatementKey = attribute.Key("db.statement") + + // DBSystemKey is the attribute Key conforming to the "db.system" semantic + // conventions. It represents an identifier for the database management + // system (DBMS) product being used. See below for a list of well-known + // identifiers. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + DBSystemKey = attribute.Key("db.system") + + // DBUserKey is the attribute Key conforming to the "db.user" semantic + // conventions. It represents the username for accessing the database. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'readonly_user', 'reporting_user' + DBUserKey = attribute.Key("db.user") +) + +var ( + // all + DBCassandraConsistencyLevelAll = DBCassandraConsistencyLevelKey.String("all") + // each_quorum + DBCassandraConsistencyLevelEachQuorum = DBCassandraConsistencyLevelKey.String("each_quorum") + // quorum + DBCassandraConsistencyLevelQuorum = DBCassandraConsistencyLevelKey.String("quorum") + // local_quorum + DBCassandraConsistencyLevelLocalQuorum = DBCassandraConsistencyLevelKey.String("local_quorum") + // one + DBCassandraConsistencyLevelOne = DBCassandraConsistencyLevelKey.String("one") + // two + DBCassandraConsistencyLevelTwo = DBCassandraConsistencyLevelKey.String("two") + // three + DBCassandraConsistencyLevelThree = DBCassandraConsistencyLevelKey.String("three") + // local_one + DBCassandraConsistencyLevelLocalOne = DBCassandraConsistencyLevelKey.String("local_one") + // any + DBCassandraConsistencyLevelAny = DBCassandraConsistencyLevelKey.String("any") + // serial + DBCassandraConsistencyLevelSerial = DBCassandraConsistencyLevelKey.String("serial") + // local_serial + DBCassandraConsistencyLevelLocalSerial = DBCassandraConsistencyLevelKey.String("local_serial") +) + +var ( + // Gateway (HTTP) connections mode + DBCosmosDBConnectionModeGateway = DBCosmosDBConnectionModeKey.String("gateway") + // Direct connection + DBCosmosDBConnectionModeDirect = DBCosmosDBConnectionModeKey.String("direct") +) + +var ( + // invalid + DBCosmosDBOperationTypeInvalid = DBCosmosDBOperationTypeKey.String("Invalid") + // create + DBCosmosDBOperationTypeCreate = DBCosmosDBOperationTypeKey.String("Create") + // patch + DBCosmosDBOperationTypePatch = DBCosmosDBOperationTypeKey.String("Patch") + // read + DBCosmosDBOperationTypeRead = DBCosmosDBOperationTypeKey.String("Read") + // read_feed + DBCosmosDBOperationTypeReadFeed = DBCosmosDBOperationTypeKey.String("ReadFeed") + // delete + DBCosmosDBOperationTypeDelete = DBCosmosDBOperationTypeKey.String("Delete") + // replace + DBCosmosDBOperationTypeReplace = DBCosmosDBOperationTypeKey.String("Replace") + // execute + DBCosmosDBOperationTypeExecute = DBCosmosDBOperationTypeKey.String("Execute") + // query + DBCosmosDBOperationTypeQuery = DBCosmosDBOperationTypeKey.String("Query") + // head + DBCosmosDBOperationTypeHead = DBCosmosDBOperationTypeKey.String("Head") + // head_feed + DBCosmosDBOperationTypeHeadFeed = DBCosmosDBOperationTypeKey.String("HeadFeed") + // upsert + DBCosmosDBOperationTypeUpsert = DBCosmosDBOperationTypeKey.String("Upsert") + // batch + DBCosmosDBOperationTypeBatch = DBCosmosDBOperationTypeKey.String("Batch") + // query_plan + DBCosmosDBOperationTypeQueryPlan = DBCosmosDBOperationTypeKey.String("QueryPlan") + // execute_javascript + DBCosmosDBOperationTypeExecuteJavascript = DBCosmosDBOperationTypeKey.String("ExecuteJavaScript") +) + +var ( + // Some other SQL database. Fallback only. See notes + DBSystemOtherSQL = DBSystemKey.String("other_sql") + // Microsoft SQL Server + DBSystemMSSQL = DBSystemKey.String("mssql") + // Microsoft SQL Server Compact + DBSystemMssqlcompact = DBSystemKey.String("mssqlcompact") + // MySQL + DBSystemMySQL = DBSystemKey.String("mysql") + // Oracle Database + DBSystemOracle = DBSystemKey.String("oracle") + // IBM DB2 + DBSystemDB2 = DBSystemKey.String("db2") + // PostgreSQL + DBSystemPostgreSQL = DBSystemKey.String("postgresql") + // Amazon Redshift + DBSystemRedshift = DBSystemKey.String("redshift") + // Apache Hive + DBSystemHive = DBSystemKey.String("hive") + // Cloudscape + DBSystemCloudscape = DBSystemKey.String("cloudscape") + // HyperSQL DataBase + DBSystemHSQLDB = DBSystemKey.String("hsqldb") + // Progress Database + DBSystemProgress = DBSystemKey.String("progress") + // SAP MaxDB + DBSystemMaxDB = DBSystemKey.String("maxdb") + // SAP HANA + DBSystemHanaDB = DBSystemKey.String("hanadb") + // Ingres + DBSystemIngres = DBSystemKey.String("ingres") + // FirstSQL + DBSystemFirstSQL = DBSystemKey.String("firstsql") + // EnterpriseDB + DBSystemEDB = DBSystemKey.String("edb") + // InterSystems Caché + DBSystemCache = DBSystemKey.String("cache") + // Adabas (Adaptable Database System) + DBSystemAdabas = DBSystemKey.String("adabas") + // Firebird + DBSystemFirebird = DBSystemKey.String("firebird") + // Apache Derby + DBSystemDerby = DBSystemKey.String("derby") + // FileMaker + DBSystemFilemaker = DBSystemKey.String("filemaker") + // Informix + DBSystemInformix = DBSystemKey.String("informix") + // InstantDB + DBSystemInstantDB = DBSystemKey.String("instantdb") + // InterBase + DBSystemInterbase = DBSystemKey.String("interbase") + // MariaDB + DBSystemMariaDB = DBSystemKey.String("mariadb") + // Netezza + DBSystemNetezza = DBSystemKey.String("netezza") + // Pervasive PSQL + DBSystemPervasive = DBSystemKey.String("pervasive") + // PointBase + DBSystemPointbase = DBSystemKey.String("pointbase") + // SQLite + DBSystemSqlite = DBSystemKey.String("sqlite") + // Sybase + DBSystemSybase = DBSystemKey.String("sybase") + // Teradata + DBSystemTeradata = DBSystemKey.String("teradata") + // Vertica + DBSystemVertica = DBSystemKey.String("vertica") + // H2 + DBSystemH2 = DBSystemKey.String("h2") + // ColdFusion IMQ + DBSystemColdfusion = DBSystemKey.String("coldfusion") + // Apache Cassandra + DBSystemCassandra = DBSystemKey.String("cassandra") + // Apache HBase + DBSystemHBase = DBSystemKey.String("hbase") + // MongoDB + DBSystemMongoDB = DBSystemKey.String("mongodb") + // Redis + DBSystemRedis = DBSystemKey.String("redis") + // Couchbase + DBSystemCouchbase = DBSystemKey.String("couchbase") + // CouchDB + DBSystemCouchDB = DBSystemKey.String("couchdb") + // Microsoft Azure Cosmos DB + DBSystemCosmosDB = DBSystemKey.String("cosmosdb") + // Amazon DynamoDB + DBSystemDynamoDB = DBSystemKey.String("dynamodb") + // Neo4j + DBSystemNeo4j = DBSystemKey.String("neo4j") + // Apache Geode + DBSystemGeode = DBSystemKey.String("geode") + // Elasticsearch + DBSystemElasticsearch = DBSystemKey.String("elasticsearch") + // Memcached + DBSystemMemcached = DBSystemKey.String("memcached") + // CockroachDB + DBSystemCockroachdb = DBSystemKey.String("cockroachdb") + // OpenSearch + DBSystemOpensearch = DBSystemKey.String("opensearch") + // ClickHouse + DBSystemClickhouse = DBSystemKey.String("clickhouse") + // Cloud Spanner + DBSystemSpanner = DBSystemKey.String("spanner") + // Trino + DBSystemTrino = DBSystemKey.String("trino") +) + +// DBCassandraCoordinatorDC returns an attribute KeyValue conforming to the +// "db.cassandra.coordinator.dc" semantic conventions. It represents the data +// center of the coordinating node for a query. +func DBCassandraCoordinatorDC(val string) attribute.KeyValue { + return DBCassandraCoordinatorDCKey.String(val) +} + +// DBCassandraCoordinatorID returns an attribute KeyValue conforming to the +// "db.cassandra.coordinator.id" semantic conventions. It represents the ID of +// the coordinating node for a query. +func DBCassandraCoordinatorID(val string) attribute.KeyValue { + return DBCassandraCoordinatorIDKey.String(val) +} + +// DBCassandraIdempotence returns an attribute KeyValue conforming to the +// "db.cassandra.idempotence" semantic conventions. It represents the whether +// or not the query is idempotent. +func DBCassandraIdempotence(val bool) attribute.KeyValue { + return DBCassandraIdempotenceKey.Bool(val) +} + +// DBCassandraPageSize returns an attribute KeyValue conforming to the +// "db.cassandra.page_size" semantic conventions. It represents the fetch size +// used for paging, i.e. how many rows will be returned at once. +func DBCassandraPageSize(val int) attribute.KeyValue { + return DBCassandraPageSizeKey.Int(val) +} + +// DBCassandraSpeculativeExecutionCount returns an attribute KeyValue +// conforming to the "db.cassandra.speculative_execution_count" semantic +// conventions. It represents the number of times a query was speculatively +// executed. Not set or `0` if the query was not executed speculatively. +func DBCassandraSpeculativeExecutionCount(val int) attribute.KeyValue { + return DBCassandraSpeculativeExecutionCountKey.Int(val) +} + +// DBCassandraTable returns an attribute KeyValue conforming to the +// "db.cassandra.table" semantic conventions. It represents the name of the +// primary Cassandra table that the operation is acting upon, including the +// keyspace name (if applicable). +func DBCassandraTable(val string) attribute.KeyValue { + return DBCassandraTableKey.String(val) +} + +// DBConnectionString returns an attribute KeyValue conforming to the +// "db.connection_string" semantic conventions. It represents the connection +// string used to connect to the database. It is recommended to remove embedded +// credentials. +func DBConnectionString(val string) attribute.KeyValue { + return DBConnectionStringKey.String(val) +} + +// DBCosmosDBClientID returns an attribute KeyValue conforming to the +// "db.cosmosdb.client_id" semantic conventions. It represents the unique +// Cosmos client instance id. +func DBCosmosDBClientID(val string) attribute.KeyValue { + return DBCosmosDBClientIDKey.String(val) +} + +// DBCosmosDBContainer returns an attribute KeyValue conforming to the +// "db.cosmosdb.container" semantic conventions. It represents the cosmos DB +// container name. +func DBCosmosDBContainer(val string) attribute.KeyValue { + return DBCosmosDBContainerKey.String(val) +} + +// DBCosmosDBRequestCharge returns an attribute KeyValue conforming to the +// "db.cosmosdb.request_charge" semantic conventions. It represents the rU +// consumed for that operation +func DBCosmosDBRequestCharge(val float64) attribute.KeyValue { + return DBCosmosDBRequestChargeKey.Float64(val) +} + +// DBCosmosDBRequestContentLength returns an attribute KeyValue conforming +// to the "db.cosmosdb.request_content_length" semantic conventions. It +// represents the request payload size in bytes +func DBCosmosDBRequestContentLength(val int) attribute.KeyValue { + return DBCosmosDBRequestContentLengthKey.Int(val) +} + +// DBCosmosDBStatusCode returns an attribute KeyValue conforming to the +// "db.cosmosdb.status_code" semantic conventions. It represents the cosmos DB +// status code. +func DBCosmosDBStatusCode(val int) attribute.KeyValue { + return DBCosmosDBStatusCodeKey.Int(val) +} + +// DBCosmosDBSubStatusCode returns an attribute KeyValue conforming to the +// "db.cosmosdb.sub_status_code" semantic conventions. It represents the cosmos +// DB sub status code. +func DBCosmosDBSubStatusCode(val int) attribute.KeyValue { + return DBCosmosDBSubStatusCodeKey.Int(val) +} + +// DBElasticsearchClusterName returns an attribute KeyValue conforming to +// the "db.elasticsearch.cluster.name" semantic conventions. It represents the +// represents the identifier of an Elasticsearch cluster. +func DBElasticsearchClusterName(val string) attribute.KeyValue { + return DBElasticsearchClusterNameKey.String(val) +} + +// DBElasticsearchNodeName returns an attribute KeyValue conforming to the +// "db.elasticsearch.node.name" semantic conventions. It represents the +// represents the human-readable identifier of the node/instance to which a +// request was routed. +func DBElasticsearchNodeName(val string) attribute.KeyValue { + return DBElasticsearchNodeNameKey.String(val) +} + +// DBInstanceID returns an attribute KeyValue conforming to the +// "db.instance.id" semantic conventions. It represents an identifier (address, +// unique name, or any other identifier) of the database instance that is +// executing queries or mutations on the current connection. This is useful in +// cases where the database is running in a clustered environment and the +// instrumentation is able to record the node executing the query. The client +// may obtain this value in databases like MySQL using queries like `select +// @@hostname`. +func DBInstanceID(val string) attribute.KeyValue { + return DBInstanceIDKey.String(val) +} + +// DBJDBCDriverClassname returns an attribute KeyValue conforming to the +// "db.jdbc.driver_classname" semantic conventions. It represents the +// fully-qualified class name of the [Java Database Connectivity +// (JDBC)](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/) driver +// used to connect. +func DBJDBCDriverClassname(val string) attribute.KeyValue { + return DBJDBCDriverClassnameKey.String(val) +} + +// DBMongoDBCollection returns an attribute KeyValue conforming to the +// "db.mongodb.collection" semantic conventions. It represents the MongoDB +// collection being accessed within the database stated in `db.name`. +func DBMongoDBCollection(val string) attribute.KeyValue { + return DBMongoDBCollectionKey.String(val) +} + +// DBMSSQLInstanceName returns an attribute KeyValue conforming to the +// "db.mssql.instance_name" semantic conventions. It represents the Microsoft +// SQL Server [instance +// name](https://docs.microsoft.com/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15) +// connecting to. This name is used to determine the port of a named instance. +func DBMSSQLInstanceName(val string) attribute.KeyValue { + return DBMSSQLInstanceNameKey.String(val) +} + +// DBName returns an attribute KeyValue conforming to the "db.name" semantic +// conventions. It represents the this attribute is used to report the name of +// the database being accessed. For commands that switch the database, this +// should be set to the target database (even if the command fails). +func DBName(val string) attribute.KeyValue { + return DBNameKey.String(val) +} + +// DBOperation returns an attribute KeyValue conforming to the +// "db.operation" semantic conventions. It represents the name of the operation +// being executed, e.g. the [MongoDB command +// name](https://docs.mongodb.com/manual/reference/command/#database-operations) +// such as `findAndModify`, or the SQL keyword. +func DBOperation(val string) attribute.KeyValue { + return DBOperationKey.String(val) +} + +// DBRedisDBIndex returns an attribute KeyValue conforming to the +// "db.redis.database_index" semantic conventions. It represents the index of +// the database being accessed as used in the [`SELECT` +// command](https://redis.io/commands/select), provided as an integer. To be +// used instead of the generic `db.name` attribute. +func DBRedisDBIndex(val int) attribute.KeyValue { + return DBRedisDBIndexKey.Int(val) +} + +// DBSQLTable returns an attribute KeyValue conforming to the "db.sql.table" +// semantic conventions. It represents the name of the primary table that the +// operation is acting upon, including the database name (if applicable). +func DBSQLTable(val string) attribute.KeyValue { + return DBSQLTableKey.String(val) +} + +// DBStatement returns an attribute KeyValue conforming to the +// "db.statement" semantic conventions. It represents the database statement +// being executed. +func DBStatement(val string) attribute.KeyValue { + return DBStatementKey.String(val) +} + +// DBUser returns an attribute KeyValue conforming to the "db.user" semantic +// conventions. It represents the username for accessing the database. +func DBUser(val string) attribute.KeyValue { + return DBUserKey.String(val) +} + +// Describes deprecated HTTP attributes. +const ( + // HTTPFlavorKey is the attribute Key conforming to the "http.flavor" + // semantic conventions. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: deprecated + // Deprecated: use `network.protocol.name` instead. + HTTPFlavorKey = attribute.Key("http.flavor") + + // HTTPMethodKey is the attribute Key conforming to the "http.method" + // semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 'GET', 'POST', 'HEAD' + // Deprecated: use `http.request.method` instead. + HTTPMethodKey = attribute.Key("http.method") + + // HTTPRequestContentLengthKey is the attribute Key conforming to the + // "http.request_content_length" semantic conventions. + // + // Type: int + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 3495 + // Deprecated: use `http.request.header.content-length` instead. + HTTPRequestContentLengthKey = attribute.Key("http.request_content_length") + + // HTTPResponseContentLengthKey is the attribute Key conforming to the + // "http.response_content_length" semantic conventions. + // + // Type: int + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 3495 + // Deprecated: use `http.response.header.content-length` instead. + HTTPResponseContentLengthKey = attribute.Key("http.response_content_length") + + // HTTPSchemeKey is the attribute Key conforming to the "http.scheme" + // semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 'http', 'https' + // Deprecated: use `url.scheme` instead. + HTTPSchemeKey = attribute.Key("http.scheme") + + // HTTPStatusCodeKey is the attribute Key conforming to the + // "http.status_code" semantic conventions. + // + // Type: int + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 200 + // Deprecated: use `http.response.status_code` instead. + HTTPStatusCodeKey = attribute.Key("http.status_code") + + // HTTPTargetKey is the attribute Key conforming to the "http.target" + // semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: '/search?q=OpenTelemetry#SemConv' + // Deprecated: use `url.path` and `url.query` instead. + HTTPTargetKey = attribute.Key("http.target") + + // HTTPURLKey is the attribute Key conforming to the "http.url" semantic + // conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv' + // Deprecated: use `url.full` instead. + HTTPURLKey = attribute.Key("http.url") + + // HTTPUserAgentKey is the attribute Key conforming to the + // "http.user_agent" semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 'CERN-LineMode/2.15 libwww/2.17b3', 'Mozilla/5.0 (iPhone; CPU + // iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) + // Version/14.1.2 Mobile/15E148 Safari/604.1' + // Deprecated: use `user_agent.original` instead. + HTTPUserAgentKey = attribute.Key("http.user_agent") +) + +var ( + // HTTP/1.0 + // + // Deprecated: use `network.protocol.name` instead. + HTTPFlavorHTTP10 = HTTPFlavorKey.String("1.0") + // HTTP/1.1 + // + // Deprecated: use `network.protocol.name` instead. + HTTPFlavorHTTP11 = HTTPFlavorKey.String("1.1") + // HTTP/2 + // + // Deprecated: use `network.protocol.name` instead. + HTTPFlavorHTTP20 = HTTPFlavorKey.String("2.0") + // HTTP/3 + // + // Deprecated: use `network.protocol.name` instead. + HTTPFlavorHTTP30 = HTTPFlavorKey.String("3.0") + // SPDY protocol + // + // Deprecated: use `network.protocol.name` instead. + HTTPFlavorSPDY = HTTPFlavorKey.String("SPDY") + // QUIC protocol + // + // Deprecated: use `network.protocol.name` instead. + HTTPFlavorQUIC = HTTPFlavorKey.String("QUIC") +) + +// HTTPMethod returns an attribute KeyValue conforming to the "http.method" +// semantic conventions. +// +// Deprecated: use `http.request.method` instead. +func HTTPMethod(val string) attribute.KeyValue { + return HTTPMethodKey.String(val) +} + +// HTTPRequestContentLength returns an attribute KeyValue conforming to the +// "http.request_content_length" semantic conventions. +// +// Deprecated: use `http.request.header.content-length` instead. +func HTTPRequestContentLength(val int) attribute.KeyValue { + return HTTPRequestContentLengthKey.Int(val) +} + +// HTTPResponseContentLength returns an attribute KeyValue conforming to the +// "http.response_content_length" semantic conventions. +// +// Deprecated: use `http.response.header.content-length` instead. +func HTTPResponseContentLength(val int) attribute.KeyValue { + return HTTPResponseContentLengthKey.Int(val) +} + +// HTTPScheme returns an attribute KeyValue conforming to the "http.scheme" +// semantic conventions. +// +// Deprecated: use `url.scheme` instead. +func HTTPScheme(val string) attribute.KeyValue { + return HTTPSchemeKey.String(val) +} + +// HTTPStatusCode returns an attribute KeyValue conforming to the +// "http.status_code" semantic conventions. +// +// Deprecated: use `http.response.status_code` instead. +func HTTPStatusCode(val int) attribute.KeyValue { + return HTTPStatusCodeKey.Int(val) +} + +// HTTPTarget returns an attribute KeyValue conforming to the "http.target" +// semantic conventions. +// +// Deprecated: use `url.path` and `url.query` instead. +func HTTPTarget(val string) attribute.KeyValue { + return HTTPTargetKey.String(val) +} + +// HTTPURL returns an attribute KeyValue conforming to the "http.url" +// semantic conventions. +// +// Deprecated: use `url.full` instead. +func HTTPURL(val string) attribute.KeyValue { + return HTTPURLKey.String(val) +} + +// HTTPUserAgent returns an attribute KeyValue conforming to the +// "http.user_agent" semantic conventions. +// +// Deprecated: use `user_agent.original` instead. +func HTTPUserAgent(val string) attribute.KeyValue { + return HTTPUserAgentKey.String(val) +} + +// These attributes may be used for any network related operation. +const ( + // NetHostNameKey is the attribute Key conforming to the "net.host.name" + // semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 'example.com' + // Deprecated: use `server.address`. + NetHostNameKey = attribute.Key("net.host.name") + + // NetHostPortKey is the attribute Key conforming to the "net.host.port" + // semantic conventions. + // + // Type: int + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 8080 + // Deprecated: use `server.port`. + NetHostPortKey = attribute.Key("net.host.port") + + // NetPeerNameKey is the attribute Key conforming to the "net.peer.name" + // semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 'example.com' + // Deprecated: use `server.address` on client spans and `client.address` on + // server spans. + NetPeerNameKey = attribute.Key("net.peer.name") + + // NetPeerPortKey is the attribute Key conforming to the "net.peer.port" + // semantic conventions. + // + // Type: int + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 8080 + // Deprecated: use `server.port` on client spans and `client.port` on + // server spans. + NetPeerPortKey = attribute.Key("net.peer.port") + + // NetProtocolNameKey is the attribute Key conforming to the + // "net.protocol.name" semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 'amqp', 'http', 'mqtt' + // Deprecated: use `network.protocol.name`. + NetProtocolNameKey = attribute.Key("net.protocol.name") + + // NetProtocolVersionKey is the attribute Key conforming to the + // "net.protocol.version" semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: '3.1.1' + // Deprecated: use `network.protocol.version`. + NetProtocolVersionKey = attribute.Key("net.protocol.version") + + // NetSockFamilyKey is the attribute Key conforming to the + // "net.sock.family" semantic conventions. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: deprecated + // Deprecated: use `network.transport` and `network.type`. + NetSockFamilyKey = attribute.Key("net.sock.family") + + // NetSockHostAddrKey is the attribute Key conforming to the + // "net.sock.host.addr" semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: '/var/my.sock' + // Deprecated: use `network.local.address`. + NetSockHostAddrKey = attribute.Key("net.sock.host.addr") + + // NetSockHostPortKey is the attribute Key conforming to the + // "net.sock.host.port" semantic conventions. + // + // Type: int + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 8080 + // Deprecated: use `network.local.port`. + NetSockHostPortKey = attribute.Key("net.sock.host.port") + + // NetSockPeerAddrKey is the attribute Key conforming to the + // "net.sock.peer.addr" semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: '192.168.0.1' + // Deprecated: use `network.peer.address`. + NetSockPeerAddrKey = attribute.Key("net.sock.peer.addr") + + // NetSockPeerNameKey is the attribute Key conforming to the + // "net.sock.peer.name" semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: '/var/my.sock' + // Deprecated: no replacement at this time. + NetSockPeerNameKey = attribute.Key("net.sock.peer.name") + + // NetSockPeerPortKey is the attribute Key conforming to the + // "net.sock.peer.port" semantic conventions. + // + // Type: int + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 65531 + // Deprecated: use `network.peer.port`. + NetSockPeerPortKey = attribute.Key("net.sock.peer.port") + + // NetTransportKey is the attribute Key conforming to the "net.transport" + // semantic conventions. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: deprecated + // Deprecated: use `network.transport`. + NetTransportKey = attribute.Key("net.transport") +) + +var ( + // IPv4 address + // + // Deprecated: use `network.transport` and `network.type`. + NetSockFamilyInet = NetSockFamilyKey.String("inet") + // IPv6 address + // + // Deprecated: use `network.transport` and `network.type`. + NetSockFamilyInet6 = NetSockFamilyKey.String("inet6") + // Unix domain socket path + // + // Deprecated: use `network.transport` and `network.type`. + NetSockFamilyUnix = NetSockFamilyKey.String("unix") +) + +var ( + // ip_tcp + // + // Deprecated: use `network.transport`. + NetTransportTCP = NetTransportKey.String("ip_tcp") + // ip_udp + // + // Deprecated: use `network.transport`. + NetTransportUDP = NetTransportKey.String("ip_udp") + // Named or anonymous pipe + // + // Deprecated: use `network.transport`. + NetTransportPipe = NetTransportKey.String("pipe") + // In-process communication + // + // Deprecated: use `network.transport`. + NetTransportInProc = NetTransportKey.String("inproc") + // Something else (non IP-based) + // + // Deprecated: use `network.transport`. + NetTransportOther = NetTransportKey.String("other") +) + +// NetHostName returns an attribute KeyValue conforming to the +// "net.host.name" semantic conventions. +// +// Deprecated: use `server.address`. +func NetHostName(val string) attribute.KeyValue { + return NetHostNameKey.String(val) +} + +// NetHostPort returns an attribute KeyValue conforming to the +// "net.host.port" semantic conventions. +// +// Deprecated: use `server.port`. +func NetHostPort(val int) attribute.KeyValue { + return NetHostPortKey.Int(val) +} + +// NetPeerName returns an attribute KeyValue conforming to the +// "net.peer.name" semantic conventions. +// +// Deprecated: use `server.address` on client spans and `client.address` on +// server spans. +func NetPeerName(val string) attribute.KeyValue { + return NetPeerNameKey.String(val) +} + +// NetPeerPort returns an attribute KeyValue conforming to the +// "net.peer.port" semantic conventions. +// +// Deprecated: use `server.port` on client spans and `client.port` on server +// spans. +func NetPeerPort(val int) attribute.KeyValue { + return NetPeerPortKey.Int(val) +} + +// NetProtocolName returns an attribute KeyValue conforming to the +// "net.protocol.name" semantic conventions. +// +// Deprecated: use `network.protocol.name`. +func NetProtocolName(val string) attribute.KeyValue { + return NetProtocolNameKey.String(val) +} + +// NetProtocolVersion returns an attribute KeyValue conforming to the +// "net.protocol.version" semantic conventions. +// +// Deprecated: use `network.protocol.version`. +func NetProtocolVersion(val string) attribute.KeyValue { + return NetProtocolVersionKey.String(val) +} + +// NetSockHostAddr returns an attribute KeyValue conforming to the +// "net.sock.host.addr" semantic conventions. +// +// Deprecated: use `network.local.address`. +func NetSockHostAddr(val string) attribute.KeyValue { + return NetSockHostAddrKey.String(val) +} + +// NetSockHostPort returns an attribute KeyValue conforming to the +// "net.sock.host.port" semantic conventions. +// +// Deprecated: use `network.local.port`. +func NetSockHostPort(val int) attribute.KeyValue { + return NetSockHostPortKey.Int(val) +} + +// NetSockPeerAddr returns an attribute KeyValue conforming to the +// "net.sock.peer.addr" semantic conventions. +// +// Deprecated: use `network.peer.address`. +func NetSockPeerAddr(val string) attribute.KeyValue { + return NetSockPeerAddrKey.String(val) +} + +// NetSockPeerName returns an attribute KeyValue conforming to the +// "net.sock.peer.name" semantic conventions. +// +// Deprecated: no replacement at this time. +func NetSockPeerName(val string) attribute.KeyValue { + return NetSockPeerNameKey.String(val) +} + +// NetSockPeerPort returns an attribute KeyValue conforming to the +// "net.sock.peer.port" semantic conventions. +// +// Deprecated: use `network.peer.port`. +func NetSockPeerPort(val int) attribute.KeyValue { + return NetSockPeerPortKey.Int(val) +} + +// These attributes may be used to describe the receiver of a network +// exchange/packet. These should be used when there is no client/server +// relationship between the two sides, or when that relationship is unknown. +// This covers low-level network interactions (e.g. packet tracing) where you +// don't know if there was a connection or which side initiated it. This also +// covers unidirectional UDP flows and peer-to-peer communication where the +// "user-facing" surface of the protocol / API doesn't expose a clear notion of +// client and server. +const ( + // DestinationAddressKey is the attribute Key conforming to the + // "destination.address" semantic conventions. It represents the + // destination address - domain name if available without reverse DNS + // lookup; otherwise, IP address or Unix domain socket name. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'destination.example.com', '10.1.2.80', '/tmp/my.sock' + // Note: When observed from the source side, and when communicating through + // an intermediary, `destination.address` SHOULD represent the destination + // address behind any intermediaries, for example proxies, if it's + // available. + DestinationAddressKey = attribute.Key("destination.address") + + // DestinationPortKey is the attribute Key conforming to the + // "destination.port" semantic conventions. It represents the destination + // port number + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 3389, 2888 + DestinationPortKey = attribute.Key("destination.port") +) + +// DestinationAddress returns an attribute KeyValue conforming to the +// "destination.address" semantic conventions. It represents the destination +// address - domain name if available without reverse DNS lookup; otherwise, IP +// address or Unix domain socket name. +func DestinationAddress(val string) attribute.KeyValue { + return DestinationAddressKey.String(val) +} + +// DestinationPort returns an attribute KeyValue conforming to the +// "destination.port" semantic conventions. It represents the destination port +// number +func DestinationPort(val int) attribute.KeyValue { + return DestinationPortKey.Int(val) +} + +// These attributes may be used for any disk related operation. +const ( + // DiskIoDirectionKey is the attribute Key conforming to the + // "disk.io.direction" semantic conventions. It represents the disk IO + // operation direction. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'read' + DiskIoDirectionKey = attribute.Key("disk.io.direction") +) + +var ( + // read + DiskIoDirectionRead = DiskIoDirectionKey.String("read") + // write + DiskIoDirectionWrite = DiskIoDirectionKey.String("write") +) + +// The shared attributes used to report an error. +const ( + // ErrorTypeKey is the attribute Key conforming to the "error.type" + // semantic conventions. It represents the describes a class of error the + // operation ended with. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: stable + // Examples: 'timeout', 'java.net.UnknownHostException', + // 'server_certificate_invalid', '500' + // Note: The `error.type` SHOULD be predictable and SHOULD have low + // cardinality. + // Instrumentations SHOULD document the list of errors they report. + // + // The cardinality of `error.type` within one instrumentation library + // SHOULD be low. + // Telemetry consumers that aggregate data from multiple instrumentation + // libraries and applications + // should be prepared for `error.type` to have high cardinality at query + // time when no + // additional filters are applied. + // + // If the operation has completed successfully, instrumentations SHOULD NOT + // set `error.type`. + // + // If a specific domain defines its own set of error identifiers (such as + // HTTP or gRPC status codes), + // it's RECOMMENDED to: + // + // * Use a domain-specific attribute + // * Set `error.type` to capture all errors, regardless of whether they are + // defined within the domain-specific set or not. + ErrorTypeKey = attribute.Key("error.type") +) + +var ( + // A fallback error value to be used when the instrumentation doesn't define a custom value + ErrorTypeOther = ErrorTypeKey.String("_OTHER") +) + +// The shared attributes used to report a single exception associated with a +// span or log. +const ( + // ExceptionEscapedKey is the attribute Key conforming to the + // "exception.escaped" semantic conventions. It represents the sHOULD be + // set to true if the exception event is recorded at a point where it is + // known that the exception is escaping the scope of the span. + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + // Note: An exception is considered to have escaped (or left) the scope of + // a span, + // if that span is ended while the exception is still logically "in + // flight". + // This may be actually "in flight" in some languages (e.g. if the + // exception + // is passed to a Context manager's `__exit__` method in Python) but will + // usually be caught at the point of recording the exception in most + // languages. + // + // It is usually not possible to determine at the point where an exception + // is thrown + // whether it will escape the scope of a span. + // However, it is trivial to know that an exception + // will escape, if one checks for an active exception just before ending + // the span, + // as done in the [example for recording span + // exceptions](#recording-an-exception). + // + // It follows that an exception may still escape the scope of the span + // even if the `exception.escaped` attribute was not set or set to false, + // since the event might have been recorded at a time where it was not + // clear whether the exception will escape. + ExceptionEscapedKey = attribute.Key("exception.escaped") + + // ExceptionMessageKey is the attribute Key conforming to the + // "exception.message" semantic conventions. It represents the exception + // message. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Division by zero', "Can't convert 'int' object to str + // implicitly" + ExceptionMessageKey = attribute.Key("exception.message") + + // ExceptionStacktraceKey is the attribute Key conforming to the + // "exception.stacktrace" semantic conventions. It represents a stacktrace + // as a string in the natural representation for the language runtime. The + // representation is to be determined and documented by each language SIG. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Exception in thread "main" java.lang.RuntimeException: Test + // exception\\n at ' + // 'com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at ' + // 'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at ' + // 'com.example.GenerateTrace.main(GenerateTrace.java:5)' + ExceptionStacktraceKey = attribute.Key("exception.stacktrace") + + // ExceptionTypeKey is the attribute Key conforming to the "exception.type" + // semantic conventions. It represents the type of the exception (its + // fully-qualified class name, if applicable). The dynamic type of the + // exception should be preferred over the static type in languages that + // support it. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'java.net.ConnectException', 'OSError' + ExceptionTypeKey = attribute.Key("exception.type") +) + +// ExceptionEscaped returns an attribute KeyValue conforming to the +// "exception.escaped" semantic conventions. It represents the sHOULD be set to +// true if the exception event is recorded at a point where it is known that +// the exception is escaping the scope of the span. +func ExceptionEscaped(val bool) attribute.KeyValue { + return ExceptionEscapedKey.Bool(val) +} + +// ExceptionMessage returns an attribute KeyValue conforming to the +// "exception.message" semantic conventions. It represents the exception +// message. +func ExceptionMessage(val string) attribute.KeyValue { + return ExceptionMessageKey.String(val) +} + +// ExceptionStacktrace returns an attribute KeyValue conforming to the +// "exception.stacktrace" semantic conventions. It represents a stacktrace as a +// string in the natural representation for the language runtime. The +// representation is to be determined and documented by each language SIG. +func ExceptionStacktrace(val string) attribute.KeyValue { + return ExceptionStacktraceKey.String(val) +} + +// ExceptionType returns an attribute KeyValue conforming to the +// "exception.type" semantic conventions. It represents the type of the +// exception (its fully-qualified class name, if applicable). The dynamic type +// of the exception should be preferred over the static type in languages that +// support it. +func ExceptionType(val string) attribute.KeyValue { + return ExceptionTypeKey.String(val) +} + +// Semantic convention attributes in the HTTP namespace. +const ( + // HTTPRequestBodySizeKey is the attribute Key conforming to the + // "http.request.body.size" semantic conventions. It represents the size of + // the request payload body in bytes. This is the number of bytes + // transferred excluding headers and is often, but not always, present as + // the + // [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) + // header. For requests using transport encoding, this should be the + // compressed size. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 3495 + HTTPRequestBodySizeKey = attribute.Key("http.request.body.size") + + // HTTPRequestMethodKey is the attribute Key conforming to the + // "http.request.method" semantic conventions. It represents the hTTP + // request method. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: stable + // Examples: 'GET', 'POST', 'HEAD' + // Note: HTTP request method value SHOULD be "known" to the + // instrumentation. + // By default, this convention defines "known" methods as the ones listed + // in [RFC9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-methods) + // and the PATCH method defined in + // [RFC5789](https://www.rfc-editor.org/rfc/rfc5789.html). + // + // If the HTTP request method is not known to instrumentation, it MUST set + // the `http.request.method` attribute to `_OTHER`. + // + // If the HTTP instrumentation could end up converting valid HTTP request + // methods to `_OTHER`, then it MUST provide a way to override + // the list of known HTTP methods. If this override is done via environment + // variable, then the environment variable MUST be named + // OTEL_INSTRUMENTATION_HTTP_KNOWN_METHODS and support a comma-separated + // list of case-sensitive known HTTP methods + // (this list MUST be a full override of the default known method, it is + // not a list of known methods in addition to the defaults). + // + // HTTP method names are case-sensitive and `http.request.method` attribute + // value MUST match a known HTTP method name exactly. + // Instrumentations for specific web frameworks that consider HTTP methods + // to be case insensitive, SHOULD populate a canonical equivalent. + // Tracing instrumentations that do so, MUST also set + // `http.request.method_original` to the original value. + HTTPRequestMethodKey = attribute.Key("http.request.method") + + // HTTPRequestMethodOriginalKey is the attribute Key conforming to the + // "http.request.method_original" semantic conventions. It represents the + // original HTTP method sent by the client in the request line. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'GeT', 'ACL', 'foo' + HTTPRequestMethodOriginalKey = attribute.Key("http.request.method_original") + + // HTTPRequestResendCountKey is the attribute Key conforming to the + // "http.request.resend_count" semantic conventions. It represents the + // ordinal number of request resending attempt (for any reason, including + // redirects). + // + // Type: int + // RequirementLevel: Optional + // Stability: stable + // Examples: 3 + // Note: The resend count SHOULD be updated each time an HTTP request gets + // resent by the client, regardless of what was the cause of the resending + // (e.g. redirection, authorization failure, 503 Server Unavailable, + // network issues, or any other). + HTTPRequestResendCountKey = attribute.Key("http.request.resend_count") + + // HTTPResponseBodySizeKey is the attribute Key conforming to the + // "http.response.body.size" semantic conventions. It represents the size + // of the response payload body in bytes. This is the number of bytes + // transferred excluding headers and is often, but not always, present as + // the + // [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) + // header. For requests using transport encoding, this should be the + // compressed size. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 3495 + HTTPResponseBodySizeKey = attribute.Key("http.response.body.size") + + // HTTPResponseStatusCodeKey is the attribute Key conforming to the + // "http.response.status_code" semantic conventions. It represents the + // [HTTP response status + // code](https://tools.ietf.org/html/rfc7231#section-6). + // + // Type: int + // RequirementLevel: Optional + // Stability: stable + // Examples: 200 + HTTPResponseStatusCodeKey = attribute.Key("http.response.status_code") + + // HTTPRouteKey is the attribute Key conforming to the "http.route" + // semantic conventions. It represents the matched route, that is, the path + // template in the format used by the respective server framework. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: '/users/:userID?', '{controller}/{action}/{id?}' + // Note: MUST NOT be populated when this is not supported by the HTTP + // server framework as the route attribute should have low-cardinality and + // the URI path can NOT substitute it. + // SHOULD include the [application + // root](/docs/http/http-spans.md#http-server-definitions) if there is one. + HTTPRouteKey = attribute.Key("http.route") +) + +var ( + // CONNECT method + HTTPRequestMethodConnect = HTTPRequestMethodKey.String("CONNECT") + // DELETE method + HTTPRequestMethodDelete = HTTPRequestMethodKey.String("DELETE") + // GET method + HTTPRequestMethodGet = HTTPRequestMethodKey.String("GET") + // HEAD method + HTTPRequestMethodHead = HTTPRequestMethodKey.String("HEAD") + // OPTIONS method + HTTPRequestMethodOptions = HTTPRequestMethodKey.String("OPTIONS") + // PATCH method + HTTPRequestMethodPatch = HTTPRequestMethodKey.String("PATCH") + // POST method + HTTPRequestMethodPost = HTTPRequestMethodKey.String("POST") + // PUT method + HTTPRequestMethodPut = HTTPRequestMethodKey.String("PUT") + // TRACE method + HTTPRequestMethodTrace = HTTPRequestMethodKey.String("TRACE") + // Any HTTP method that the instrumentation has no prior knowledge of + HTTPRequestMethodOther = HTTPRequestMethodKey.String("_OTHER") +) + +// HTTPRequestBodySize returns an attribute KeyValue conforming to the +// "http.request.body.size" semantic conventions. It represents the size of the +// request payload body in bytes. This is the number of bytes transferred +// excluding headers and is often, but not always, present as the +// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) +// header. For requests using transport encoding, this should be the compressed +// size. +func HTTPRequestBodySize(val int) attribute.KeyValue { + return HTTPRequestBodySizeKey.Int(val) +} + +// HTTPRequestMethodOriginal returns an attribute KeyValue conforming to the +// "http.request.method_original" semantic conventions. It represents the +// original HTTP method sent by the client in the request line. +func HTTPRequestMethodOriginal(val string) attribute.KeyValue { + return HTTPRequestMethodOriginalKey.String(val) +} + +// HTTPRequestResendCount returns an attribute KeyValue conforming to the +// "http.request.resend_count" semantic conventions. It represents the ordinal +// number of request resending attempt (for any reason, including redirects). +func HTTPRequestResendCount(val int) attribute.KeyValue { + return HTTPRequestResendCountKey.Int(val) +} + +// HTTPResponseBodySize returns an attribute KeyValue conforming to the +// "http.response.body.size" semantic conventions. It represents the size of +// the response payload body in bytes. This is the number of bytes transferred +// excluding headers and is often, but not always, present as the +// [Content-Length](https://www.rfc-editor.org/rfc/rfc9110.html#field.content-length) +// header. For requests using transport encoding, this should be the compressed +// size. +func HTTPResponseBodySize(val int) attribute.KeyValue { + return HTTPResponseBodySizeKey.Int(val) +} + +// HTTPResponseStatusCode returns an attribute KeyValue conforming to the +// "http.response.status_code" semantic conventions. It represents the [HTTP +// response status code](https://tools.ietf.org/html/rfc7231#section-6). +func HTTPResponseStatusCode(val int) attribute.KeyValue { + return HTTPResponseStatusCodeKey.Int(val) +} + +// HTTPRoute returns an attribute KeyValue conforming to the "http.route" +// semantic conventions. It represents the matched route, that is, the path +// template in the format used by the respective server framework. +func HTTPRoute(val string) attribute.KeyValue { + return HTTPRouteKey.String(val) +} + +// Attributes describing telemetry around messaging systems and messaging +// activities. +const ( + // MessagingBatchMessageCountKey is the attribute Key conforming to the + // "messaging.batch.message_count" semantic conventions. It represents the + // number of messages sent, received, or processed in the scope of the + // batching operation. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 0, 1, 2 + // Note: Instrumentations SHOULD NOT set `messaging.batch.message_count` on + // spans that operate with a single message. When a messaging client + // library supports both batch and single-message API for the same + // operation, instrumentations SHOULD use `messaging.batch.message_count` + // for batching APIs and SHOULD NOT use it for single-message APIs. + MessagingBatchMessageCountKey = attribute.Key("messaging.batch.message_count") + + // MessagingClientIDKey is the attribute Key conforming to the + // "messaging.client_id" semantic conventions. It represents a unique + // identifier for the client that consumes or produces a message. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'client-5', 'myhost@8742@s8083jm' + MessagingClientIDKey = attribute.Key("messaging.client_id") + + // MessagingDestinationAnonymousKey is the attribute Key conforming to the + // "messaging.destination.anonymous" semantic conventions. It represents a + // boolean that is true if the message destination is anonymous (could be + // unnamed or have auto-generated name). + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + MessagingDestinationAnonymousKey = attribute.Key("messaging.destination.anonymous") + + // MessagingDestinationNameKey is the attribute Key conforming to the + // "messaging.destination.name" semantic conventions. It represents the + // message destination name + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'MyQueue', 'MyTopic' + // Note: Destination name SHOULD uniquely identify a specific queue, topic + // or other entity within the broker. If + // the broker doesn't have such notion, the destination name SHOULD + // uniquely identify the broker. + MessagingDestinationNameKey = attribute.Key("messaging.destination.name") + + // MessagingDestinationTemplateKey is the attribute Key conforming to the + // "messaging.destination.template" semantic conventions. It represents the + // low cardinality representation of the messaging destination name + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '/customers/{customerID}' + // Note: Destination names could be constructed from templates. An example + // would be a destination name involving a user name or product id. + // Although the destination name in this case is of high cardinality, the + // underlying template is of low cardinality and can be effectively used + // for grouping and aggregation. + MessagingDestinationTemplateKey = attribute.Key("messaging.destination.template") + + // MessagingDestinationTemporaryKey is the attribute Key conforming to the + // "messaging.destination.temporary" semantic conventions. It represents a + // boolean that is true if the message destination is temporary and might + // not exist anymore after messages are processed. + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + MessagingDestinationTemporaryKey = attribute.Key("messaging.destination.temporary") + + // MessagingDestinationPublishAnonymousKey is the attribute Key conforming + // to the "messaging.destination_publish.anonymous" semantic conventions. + // It represents a boolean that is true if the publish message destination + // is anonymous (could be unnamed or have auto-generated name). + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + MessagingDestinationPublishAnonymousKey = attribute.Key("messaging.destination_publish.anonymous") + + // MessagingDestinationPublishNameKey is the attribute Key conforming to + // the "messaging.destination_publish.name" semantic conventions. It + // represents the name of the original destination the message was + // published to + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'MyQueue', 'MyTopic' + // Note: The name SHOULD uniquely identify a specific queue, topic, or + // other entity within the broker. If + // the broker doesn't have such notion, the original destination name + // SHOULD uniquely identify the broker. + MessagingDestinationPublishNameKey = attribute.Key("messaging.destination_publish.name") + + // MessagingGCPPubsubMessageOrderingKeyKey is the attribute Key conforming + // to the "messaging.gcp_pubsub.message.ordering_key" semantic conventions. + // It represents the ordering key for a given message. If the attribute is + // not present, the message does not have an ordering key. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'ordering_key' + MessagingGCPPubsubMessageOrderingKeyKey = attribute.Key("messaging.gcp_pubsub.message.ordering_key") + + // MessagingKafkaConsumerGroupKey is the attribute Key conforming to the + // "messaging.kafka.consumer.group" semantic conventions. It represents the + // name of the Kafka Consumer Group that is handling the message. Only + // applies to consumers, not producers. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'my-group' + MessagingKafkaConsumerGroupKey = attribute.Key("messaging.kafka.consumer.group") + + // MessagingKafkaDestinationPartitionKey is the attribute Key conforming to + // the "messaging.kafka.destination.partition" semantic conventions. It + // represents the partition the message is sent to. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 2 + MessagingKafkaDestinationPartitionKey = attribute.Key("messaging.kafka.destination.partition") + + // MessagingKafkaMessageKeyKey is the attribute Key conforming to the + // "messaging.kafka.message.key" semantic conventions. It represents the + // message keys in Kafka are used for grouping alike messages to ensure + // they're processed on the same partition. They differ from + // `messaging.message.id` in that they're not unique. If the key is `null`, + // the attribute MUST NOT be set. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'myKey' + // Note: If the key type is not string, it's string representation has to + // be supplied for the attribute. If the key has no unambiguous, canonical + // string form, don't include its value. + MessagingKafkaMessageKeyKey = attribute.Key("messaging.kafka.message.key") + + // MessagingKafkaMessageOffsetKey is the attribute Key conforming to the + // "messaging.kafka.message.offset" semantic conventions. It represents the + // offset of a record in the corresponding Kafka partition. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 42 + MessagingKafkaMessageOffsetKey = attribute.Key("messaging.kafka.message.offset") + + // MessagingKafkaMessageTombstoneKey is the attribute Key conforming to the + // "messaging.kafka.message.tombstone" semantic conventions. It represents + // a boolean that is true if the message is a tombstone. + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + MessagingKafkaMessageTombstoneKey = attribute.Key("messaging.kafka.message.tombstone") + + // MessagingMessageBodySizeKey is the attribute Key conforming to the + // "messaging.message.body.size" semantic conventions. It represents the + // size of the message body in bytes. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 1439 + // Note: This can refer to both the compressed or uncompressed body size. + // If both sizes are known, the uncompressed + // body size should be used. + MessagingMessageBodySizeKey = attribute.Key("messaging.message.body.size") + + // MessagingMessageConversationIDKey is the attribute Key conforming to the + // "messaging.message.conversation_id" semantic conventions. It represents + // the conversation ID identifying the conversation to which the message + // belongs, represented as a string. Sometimes called "Correlation ID". + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'MyConversationID' + MessagingMessageConversationIDKey = attribute.Key("messaging.message.conversation_id") + + // MessagingMessageEnvelopeSizeKey is the attribute Key conforming to the + // "messaging.message.envelope.size" semantic conventions. It represents + // the size of the message body and metadata in bytes. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 2738 + // Note: This can refer to both the compressed or uncompressed size. If + // both sizes are known, the uncompressed + // size should be used. + MessagingMessageEnvelopeSizeKey = attribute.Key("messaging.message.envelope.size") + + // MessagingMessageIDKey is the attribute Key conforming to the + // "messaging.message.id" semantic conventions. It represents a value used + // by the messaging system as an identifier for the message, represented as + // a string. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '452a7c7c7c7048c2f887f61572b18fc2' + MessagingMessageIDKey = attribute.Key("messaging.message.id") + + // MessagingOperationKey is the attribute Key conforming to the + // "messaging.operation" semantic conventions. It represents a string + // identifying the kind of messaging operation. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Note: If a custom value is used, it MUST be of low cardinality. + MessagingOperationKey = attribute.Key("messaging.operation") + + // MessagingRabbitmqDestinationRoutingKeyKey is the attribute Key + // conforming to the "messaging.rabbitmq.destination.routing_key" semantic + // conventions. It represents the rabbitMQ message routing key. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'myKey' + MessagingRabbitmqDestinationRoutingKeyKey = attribute.Key("messaging.rabbitmq.destination.routing_key") + + // MessagingRocketmqClientGroupKey is the attribute Key conforming to the + // "messaging.rocketmq.client_group" semantic conventions. It represents + // the name of the RocketMQ producer/consumer group that is handling the + // message. The client type is identified by the SpanKind. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'myConsumerGroup' + MessagingRocketmqClientGroupKey = attribute.Key("messaging.rocketmq.client_group") + + // MessagingRocketmqConsumptionModelKey is the attribute Key conforming to + // the "messaging.rocketmq.consumption_model" semantic conventions. It + // represents the model of message consumption. This only applies to + // consumer spans. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + MessagingRocketmqConsumptionModelKey = attribute.Key("messaging.rocketmq.consumption_model") + + // MessagingRocketmqMessageDelayTimeLevelKey is the attribute Key + // conforming to the "messaging.rocketmq.message.delay_time_level" semantic + // conventions. It represents the delay time level for delay message, which + // determines the message delay time. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 3 + MessagingRocketmqMessageDelayTimeLevelKey = attribute.Key("messaging.rocketmq.message.delay_time_level") + + // MessagingRocketmqMessageDeliveryTimestampKey is the attribute Key + // conforming to the "messaging.rocketmq.message.delivery_timestamp" + // semantic conventions. It represents the timestamp in milliseconds that + // the delay message is expected to be delivered to consumer. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 1665987217045 + MessagingRocketmqMessageDeliveryTimestampKey = attribute.Key("messaging.rocketmq.message.delivery_timestamp") + + // MessagingRocketmqMessageGroupKey is the attribute Key conforming to the + // "messaging.rocketmq.message.group" semantic conventions. It represents + // the it is essential for FIFO message. Messages that belong to the same + // message group are always processed one by one within the same consumer + // group. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'myMessageGroup' + MessagingRocketmqMessageGroupKey = attribute.Key("messaging.rocketmq.message.group") + + // MessagingRocketmqMessageKeysKey is the attribute Key conforming to the + // "messaging.rocketmq.message.keys" semantic conventions. It represents + // the key(s) of message, another way to mark message besides message id. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'keyA', 'keyB' + MessagingRocketmqMessageKeysKey = attribute.Key("messaging.rocketmq.message.keys") + + // MessagingRocketmqMessageTagKey is the attribute Key conforming to the + // "messaging.rocketmq.message.tag" semantic conventions. It represents the + // secondary classifier of message besides topic. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'tagA' + MessagingRocketmqMessageTagKey = attribute.Key("messaging.rocketmq.message.tag") + + // MessagingRocketmqMessageTypeKey is the attribute Key conforming to the + // "messaging.rocketmq.message.type" semantic conventions. It represents + // the type of message. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + MessagingRocketmqMessageTypeKey = attribute.Key("messaging.rocketmq.message.type") + + // MessagingRocketmqNamespaceKey is the attribute Key conforming to the + // "messaging.rocketmq.namespace" semantic conventions. It represents the + // namespace of RocketMQ resources, resources in different namespaces are + // individual. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'myNamespace' + MessagingRocketmqNamespaceKey = attribute.Key("messaging.rocketmq.namespace") + + // MessagingSystemKey is the attribute Key conforming to the + // "messaging.system" semantic conventions. It represents an identifier for + // the messaging system being used. See below for a list of well-known + // identifiers. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + MessagingSystemKey = attribute.Key("messaging.system") +) + +var ( + // One or more messages are provided for publishing to an intermediary. If a single message is published, the context of the "Publish" span can be used as the creation context and no "Create" span needs to be created + MessagingOperationPublish = MessagingOperationKey.String("publish") + // A message is created. "Create" spans always refer to a single message and are used to provide a unique creation context for messages in batch publishing scenarios + MessagingOperationCreate = MessagingOperationKey.String("create") + // One or more messages are requested by a consumer. This operation refers to pull-based scenarios, where consumers explicitly call methods of messaging SDKs to receive messages + MessagingOperationReceive = MessagingOperationKey.String("receive") + // One or more messages are passed to a consumer. This operation refers to push-based scenarios, where consumer register callbacks which get called by messaging SDKs + MessagingOperationDeliver = MessagingOperationKey.String("deliver") +) + +var ( + // Clustering consumption model + MessagingRocketmqConsumptionModelClustering = MessagingRocketmqConsumptionModelKey.String("clustering") + // Broadcasting consumption model + MessagingRocketmqConsumptionModelBroadcasting = MessagingRocketmqConsumptionModelKey.String("broadcasting") +) + +var ( + // Normal message + MessagingRocketmqMessageTypeNormal = MessagingRocketmqMessageTypeKey.String("normal") + // FIFO message + MessagingRocketmqMessageTypeFifo = MessagingRocketmqMessageTypeKey.String("fifo") + // Delay message + MessagingRocketmqMessageTypeDelay = MessagingRocketmqMessageTypeKey.String("delay") + // Transaction message + MessagingRocketmqMessageTypeTransaction = MessagingRocketmqMessageTypeKey.String("transaction") +) + +var ( + // Apache ActiveMQ + MessagingSystemActivemq = MessagingSystemKey.String("activemq") + // Amazon Simple Queue Service (SQS) + MessagingSystemAWSSqs = MessagingSystemKey.String("aws_sqs") + // Azure Event Grid + MessagingSystemAzureEventgrid = MessagingSystemKey.String("azure_eventgrid") + // Azure Event Hubs + MessagingSystemAzureEventhubs = MessagingSystemKey.String("azure_eventhubs") + // Azure Service Bus + MessagingSystemAzureServicebus = MessagingSystemKey.String("azure_servicebus") + // Google Cloud Pub/Sub + MessagingSystemGCPPubsub = MessagingSystemKey.String("gcp_pubsub") + // Java Message Service + MessagingSystemJms = MessagingSystemKey.String("jms") + // Apache Kafka + MessagingSystemKafka = MessagingSystemKey.String("kafka") + // RabbitMQ + MessagingSystemRabbitmq = MessagingSystemKey.String("rabbitmq") + // Apache RocketMQ + MessagingSystemRocketmq = MessagingSystemKey.String("rocketmq") +) + +// MessagingBatchMessageCount returns an attribute KeyValue conforming to +// the "messaging.batch.message_count" semantic conventions. It represents the +// number of messages sent, received, or processed in the scope of the batching +// operation. +func MessagingBatchMessageCount(val int) attribute.KeyValue { + return MessagingBatchMessageCountKey.Int(val) +} + +// MessagingClientID returns an attribute KeyValue conforming to the +// "messaging.client_id" semantic conventions. It represents a unique +// identifier for the client that consumes or produces a message. +func MessagingClientID(val string) attribute.KeyValue { + return MessagingClientIDKey.String(val) +} + +// MessagingDestinationAnonymous returns an attribute KeyValue conforming to +// the "messaging.destination.anonymous" semantic conventions. It represents a +// boolean that is true if the message destination is anonymous (could be +// unnamed or have auto-generated name). +func MessagingDestinationAnonymous(val bool) attribute.KeyValue { + return MessagingDestinationAnonymousKey.Bool(val) +} + +// MessagingDestinationName returns an attribute KeyValue conforming to the +// "messaging.destination.name" semantic conventions. It represents the message +// destination name +func MessagingDestinationName(val string) attribute.KeyValue { + return MessagingDestinationNameKey.String(val) +} + +// MessagingDestinationTemplate returns an attribute KeyValue conforming to +// the "messaging.destination.template" semantic conventions. It represents the +// low cardinality representation of the messaging destination name +func MessagingDestinationTemplate(val string) attribute.KeyValue { + return MessagingDestinationTemplateKey.String(val) +} + +// MessagingDestinationTemporary returns an attribute KeyValue conforming to +// the "messaging.destination.temporary" semantic conventions. It represents a +// boolean that is true if the message destination is temporary and might not +// exist anymore after messages are processed. +func MessagingDestinationTemporary(val bool) attribute.KeyValue { + return MessagingDestinationTemporaryKey.Bool(val) +} + +// MessagingDestinationPublishAnonymous returns an attribute KeyValue +// conforming to the "messaging.destination_publish.anonymous" semantic +// conventions. It represents a boolean that is true if the publish message +// destination is anonymous (could be unnamed or have auto-generated name). +func MessagingDestinationPublishAnonymous(val bool) attribute.KeyValue { + return MessagingDestinationPublishAnonymousKey.Bool(val) +} + +// MessagingDestinationPublishName returns an attribute KeyValue conforming +// to the "messaging.destination_publish.name" semantic conventions. It +// represents the name of the original destination the message was published to +func MessagingDestinationPublishName(val string) attribute.KeyValue { + return MessagingDestinationPublishNameKey.String(val) +} + +// MessagingGCPPubsubMessageOrderingKey returns an attribute KeyValue +// conforming to the "messaging.gcp_pubsub.message.ordering_key" semantic +// conventions. It represents the ordering key for a given message. If the +// attribute is not present, the message does not have an ordering key. +func MessagingGCPPubsubMessageOrderingKey(val string) attribute.KeyValue { + return MessagingGCPPubsubMessageOrderingKeyKey.String(val) +} + +// MessagingKafkaConsumerGroup returns an attribute KeyValue conforming to +// the "messaging.kafka.consumer.group" semantic conventions. It represents the +// name of the Kafka Consumer Group that is handling the message. Only applies +// to consumers, not producers. +func MessagingKafkaConsumerGroup(val string) attribute.KeyValue { + return MessagingKafkaConsumerGroupKey.String(val) +} + +// MessagingKafkaDestinationPartition returns an attribute KeyValue +// conforming to the "messaging.kafka.destination.partition" semantic +// conventions. It represents the partition the message is sent to. +func MessagingKafkaDestinationPartition(val int) attribute.KeyValue { + return MessagingKafkaDestinationPartitionKey.Int(val) +} + +// MessagingKafkaMessageKey returns an attribute KeyValue conforming to the +// "messaging.kafka.message.key" semantic conventions. It represents the +// message keys in Kafka are used for grouping alike messages to ensure they're +// processed on the same partition. They differ from `messaging.message.id` in +// that they're not unique. If the key is `null`, the attribute MUST NOT be +// set. +func MessagingKafkaMessageKey(val string) attribute.KeyValue { + return MessagingKafkaMessageKeyKey.String(val) +} + +// MessagingKafkaMessageOffset returns an attribute KeyValue conforming to +// the "messaging.kafka.message.offset" semantic conventions. It represents the +// offset of a record in the corresponding Kafka partition. +func MessagingKafkaMessageOffset(val int) attribute.KeyValue { + return MessagingKafkaMessageOffsetKey.Int(val) +} + +// MessagingKafkaMessageTombstone returns an attribute KeyValue conforming +// to the "messaging.kafka.message.tombstone" semantic conventions. It +// represents a boolean that is true if the message is a tombstone. +func MessagingKafkaMessageTombstone(val bool) attribute.KeyValue { + return MessagingKafkaMessageTombstoneKey.Bool(val) +} + +// MessagingMessageBodySize returns an attribute KeyValue conforming to the +// "messaging.message.body.size" semantic conventions. It represents the size +// of the message body in bytes. +func MessagingMessageBodySize(val int) attribute.KeyValue { + return MessagingMessageBodySizeKey.Int(val) +} + +// MessagingMessageConversationID returns an attribute KeyValue conforming +// to the "messaging.message.conversation_id" semantic conventions. It +// represents the conversation ID identifying the conversation to which the +// message belongs, represented as a string. Sometimes called "Correlation ID". +func MessagingMessageConversationID(val string) attribute.KeyValue { + return MessagingMessageConversationIDKey.String(val) +} + +// MessagingMessageEnvelopeSize returns an attribute KeyValue conforming to +// the "messaging.message.envelope.size" semantic conventions. It represents +// the size of the message body and metadata in bytes. +func MessagingMessageEnvelopeSize(val int) attribute.KeyValue { + return MessagingMessageEnvelopeSizeKey.Int(val) +} + +// MessagingMessageID returns an attribute KeyValue conforming to the +// "messaging.message.id" semantic conventions. It represents a value used by +// the messaging system as an identifier for the message, represented as a +// string. +func MessagingMessageID(val string) attribute.KeyValue { + return MessagingMessageIDKey.String(val) +} + +// MessagingRabbitmqDestinationRoutingKey returns an attribute KeyValue +// conforming to the "messaging.rabbitmq.destination.routing_key" semantic +// conventions. It represents the rabbitMQ message routing key. +func MessagingRabbitmqDestinationRoutingKey(val string) attribute.KeyValue { + return MessagingRabbitmqDestinationRoutingKeyKey.String(val) +} + +// MessagingRocketmqClientGroup returns an attribute KeyValue conforming to +// the "messaging.rocketmq.client_group" semantic conventions. It represents +// the name of the RocketMQ producer/consumer group that is handling the +// message. The client type is identified by the SpanKind. +func MessagingRocketmqClientGroup(val string) attribute.KeyValue { + return MessagingRocketmqClientGroupKey.String(val) +} + +// MessagingRocketmqMessageDelayTimeLevel returns an attribute KeyValue +// conforming to the "messaging.rocketmq.message.delay_time_level" semantic +// conventions. It represents the delay time level for delay message, which +// determines the message delay time. +func MessagingRocketmqMessageDelayTimeLevel(val int) attribute.KeyValue { + return MessagingRocketmqMessageDelayTimeLevelKey.Int(val) +} + +// MessagingRocketmqMessageDeliveryTimestamp returns an attribute KeyValue +// conforming to the "messaging.rocketmq.message.delivery_timestamp" semantic +// conventions. It represents the timestamp in milliseconds that the delay +// message is expected to be delivered to consumer. +func MessagingRocketmqMessageDeliveryTimestamp(val int) attribute.KeyValue { + return MessagingRocketmqMessageDeliveryTimestampKey.Int(val) +} + +// MessagingRocketmqMessageGroup returns an attribute KeyValue conforming to +// the "messaging.rocketmq.message.group" semantic conventions. It represents +// the it is essential for FIFO message. Messages that belong to the same +// message group are always processed one by one within the same consumer +// group. +func MessagingRocketmqMessageGroup(val string) attribute.KeyValue { + return MessagingRocketmqMessageGroupKey.String(val) +} + +// MessagingRocketmqMessageKeys returns an attribute KeyValue conforming to +// the "messaging.rocketmq.message.keys" semantic conventions. It represents +// the key(s) of message, another way to mark message besides message id. +func MessagingRocketmqMessageKeys(val ...string) attribute.KeyValue { + return MessagingRocketmqMessageKeysKey.StringSlice(val) +} + +// MessagingRocketmqMessageTag returns an attribute KeyValue conforming to +// the "messaging.rocketmq.message.tag" semantic conventions. It represents the +// secondary classifier of message besides topic. +func MessagingRocketmqMessageTag(val string) attribute.KeyValue { + return MessagingRocketmqMessageTagKey.String(val) +} + +// MessagingRocketmqNamespace returns an attribute KeyValue conforming to +// the "messaging.rocketmq.namespace" semantic conventions. It represents the +// namespace of RocketMQ resources, resources in different namespaces are +// individual. +func MessagingRocketmqNamespace(val string) attribute.KeyValue { + return MessagingRocketmqNamespaceKey.String(val) +} + +// These attributes may be used for any network related operation. +const ( + // NetworkCarrierIccKey is the attribute Key conforming to the + // "network.carrier.icc" semantic conventions. It represents the ISO 3166-1 + // alpha-2 2-character country code associated with the mobile carrier + // network. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'DE' + NetworkCarrierIccKey = attribute.Key("network.carrier.icc") + + // NetworkCarrierMccKey is the attribute Key conforming to the + // "network.carrier.mcc" semantic conventions. It represents the mobile + // carrier country code. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '310' + NetworkCarrierMccKey = attribute.Key("network.carrier.mcc") + + // NetworkCarrierMncKey is the attribute Key conforming to the + // "network.carrier.mnc" semantic conventions. It represents the mobile + // carrier network code. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '001' + NetworkCarrierMncKey = attribute.Key("network.carrier.mnc") + + // NetworkCarrierNameKey is the attribute Key conforming to the + // "network.carrier.name" semantic conventions. It represents the name of + // the mobile carrier. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'sprint' + NetworkCarrierNameKey = attribute.Key("network.carrier.name") + + // NetworkConnectionSubtypeKey is the attribute Key conforming to the + // "network.connection.subtype" semantic conventions. It represents the + // this describes more details regarding the connection.type. It may be the + // type of cell technology connection, but it could be used for describing + // details about a wifi connection. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'LTE' + NetworkConnectionSubtypeKey = attribute.Key("network.connection.subtype") + + // NetworkConnectionTypeKey is the attribute Key conforming to the + // "network.connection.type" semantic conventions. It represents the + // internet connection type. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'wifi' + NetworkConnectionTypeKey = attribute.Key("network.connection.type") + + // NetworkIoDirectionKey is the attribute Key conforming to the + // "network.io.direction" semantic conventions. It represents the network + // IO operation direction. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'transmit' + NetworkIoDirectionKey = attribute.Key("network.io.direction") + + // NetworkLocalAddressKey is the attribute Key conforming to the + // "network.local.address" semantic conventions. It represents the local + // address of the network connection - IP address or Unix domain socket + // name. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: '10.1.2.80', '/tmp/my.sock' + NetworkLocalAddressKey = attribute.Key("network.local.address") + + // NetworkLocalPortKey is the attribute Key conforming to the + // "network.local.port" semantic conventions. It represents the local port + // number of the network connection. + // + // Type: int + // RequirementLevel: Optional + // Stability: stable + // Examples: 65123 + NetworkLocalPortKey = attribute.Key("network.local.port") + + // NetworkPeerAddressKey is the attribute Key conforming to the + // "network.peer.address" semantic conventions. It represents the peer + // address of the network connection - IP address or Unix domain socket + // name. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: '10.1.2.80', '/tmp/my.sock' + NetworkPeerAddressKey = attribute.Key("network.peer.address") + + // NetworkPeerPortKey is the attribute Key conforming to the + // "network.peer.port" semantic conventions. It represents the peer port + // number of the network connection. + // + // Type: int + // RequirementLevel: Optional + // Stability: stable + // Examples: 65123 + NetworkPeerPortKey = attribute.Key("network.peer.port") + + // NetworkProtocolNameKey is the attribute Key conforming to the + // "network.protocol.name" semantic conventions. It represents the [OSI + // application layer](https://osi-model.com/application-layer/) or non-OSI + // equivalent. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'amqp', 'http', 'mqtt' + // Note: The value SHOULD be normalized to lowercase. + NetworkProtocolNameKey = attribute.Key("network.protocol.name") + + // NetworkProtocolVersionKey is the attribute Key conforming to the + // "network.protocol.version" semantic conventions. It represents the + // version of the protocol specified in `network.protocol.name`. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: '3.1.1' + // Note: `network.protocol.version` refers to the version of the protocol + // used and might be different from the protocol client's version. If the + // HTTP client has a version of `0.27.2`, but sends HTTP version `1.1`, + // this attribute should be set to `1.1`. + NetworkProtocolVersionKey = attribute.Key("network.protocol.version") + + // NetworkTransportKey is the attribute Key conforming to the + // "network.transport" semantic conventions. It represents the [OSI + // transport layer](https://osi-model.com/transport-layer/) or + // [inter-process communication + // method](https://wikipedia.org/wiki/Inter-process_communication). + // + // Type: Enum + // RequirementLevel: Optional + // Stability: stable + // Examples: 'tcp', 'udp' + // Note: The value SHOULD be normalized to lowercase. + // + // Consider always setting the transport when setting a port number, since + // a port number is ambiguous without knowing the transport. For example + // different processes could be listening on TCP port 12345 and UDP port + // 12345. + NetworkTransportKey = attribute.Key("network.transport") + + // NetworkTypeKey is the attribute Key conforming to the "network.type" + // semantic conventions. It represents the [OSI network + // layer](https://osi-model.com/network-layer/) or non-OSI equivalent. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: stable + // Examples: 'ipv4', 'ipv6' + // Note: The value SHOULD be normalized to lowercase. + NetworkTypeKey = attribute.Key("network.type") +) + +var ( + // GPRS + NetworkConnectionSubtypeGprs = NetworkConnectionSubtypeKey.String("gprs") + // EDGE + NetworkConnectionSubtypeEdge = NetworkConnectionSubtypeKey.String("edge") + // UMTS + NetworkConnectionSubtypeUmts = NetworkConnectionSubtypeKey.String("umts") + // CDMA + NetworkConnectionSubtypeCdma = NetworkConnectionSubtypeKey.String("cdma") + // EVDO Rel. 0 + NetworkConnectionSubtypeEvdo0 = NetworkConnectionSubtypeKey.String("evdo_0") + // EVDO Rev. A + NetworkConnectionSubtypeEvdoA = NetworkConnectionSubtypeKey.String("evdo_a") + // CDMA2000 1XRTT + NetworkConnectionSubtypeCdma20001xrtt = NetworkConnectionSubtypeKey.String("cdma2000_1xrtt") + // HSDPA + NetworkConnectionSubtypeHsdpa = NetworkConnectionSubtypeKey.String("hsdpa") + // HSUPA + NetworkConnectionSubtypeHsupa = NetworkConnectionSubtypeKey.String("hsupa") + // HSPA + NetworkConnectionSubtypeHspa = NetworkConnectionSubtypeKey.String("hspa") + // IDEN + NetworkConnectionSubtypeIden = NetworkConnectionSubtypeKey.String("iden") + // EVDO Rev. B + NetworkConnectionSubtypeEvdoB = NetworkConnectionSubtypeKey.String("evdo_b") + // LTE + NetworkConnectionSubtypeLte = NetworkConnectionSubtypeKey.String("lte") + // EHRPD + NetworkConnectionSubtypeEhrpd = NetworkConnectionSubtypeKey.String("ehrpd") + // HSPAP + NetworkConnectionSubtypeHspap = NetworkConnectionSubtypeKey.String("hspap") + // GSM + NetworkConnectionSubtypeGsm = NetworkConnectionSubtypeKey.String("gsm") + // TD-SCDMA + NetworkConnectionSubtypeTdScdma = NetworkConnectionSubtypeKey.String("td_scdma") + // IWLAN + NetworkConnectionSubtypeIwlan = NetworkConnectionSubtypeKey.String("iwlan") + // 5G NR (New Radio) + NetworkConnectionSubtypeNr = NetworkConnectionSubtypeKey.String("nr") + // 5G NRNSA (New Radio Non-Standalone) + NetworkConnectionSubtypeNrnsa = NetworkConnectionSubtypeKey.String("nrnsa") + // LTE CA + NetworkConnectionSubtypeLteCa = NetworkConnectionSubtypeKey.String("lte_ca") +) + +var ( + // wifi + NetworkConnectionTypeWifi = NetworkConnectionTypeKey.String("wifi") + // wired + NetworkConnectionTypeWired = NetworkConnectionTypeKey.String("wired") + // cell + NetworkConnectionTypeCell = NetworkConnectionTypeKey.String("cell") + // unavailable + NetworkConnectionTypeUnavailable = NetworkConnectionTypeKey.String("unavailable") + // unknown + NetworkConnectionTypeUnknown = NetworkConnectionTypeKey.String("unknown") +) + +var ( + // transmit + NetworkIoDirectionTransmit = NetworkIoDirectionKey.String("transmit") + // receive + NetworkIoDirectionReceive = NetworkIoDirectionKey.String("receive") +) + +var ( + // TCP + NetworkTransportTCP = NetworkTransportKey.String("tcp") + // UDP + NetworkTransportUDP = NetworkTransportKey.String("udp") + // Named or anonymous pipe + NetworkTransportPipe = NetworkTransportKey.String("pipe") + // Unix domain socket + NetworkTransportUnix = NetworkTransportKey.String("unix") +) + +var ( + // IPv4 + NetworkTypeIpv4 = NetworkTypeKey.String("ipv4") + // IPv6 + NetworkTypeIpv6 = NetworkTypeKey.String("ipv6") +) + +// NetworkCarrierIcc returns an attribute KeyValue conforming to the +// "network.carrier.icc" semantic conventions. It represents the ISO 3166-1 +// alpha-2 2-character country code associated with the mobile carrier network. +func NetworkCarrierIcc(val string) attribute.KeyValue { + return NetworkCarrierIccKey.String(val) +} + +// NetworkCarrierMcc returns an attribute KeyValue conforming to the +// "network.carrier.mcc" semantic conventions. It represents the mobile carrier +// country code. +func NetworkCarrierMcc(val string) attribute.KeyValue { + return NetworkCarrierMccKey.String(val) +} + +// NetworkCarrierMnc returns an attribute KeyValue conforming to the +// "network.carrier.mnc" semantic conventions. It represents the mobile carrier +// network code. +func NetworkCarrierMnc(val string) attribute.KeyValue { + return NetworkCarrierMncKey.String(val) +} + +// NetworkCarrierName returns an attribute KeyValue conforming to the +// "network.carrier.name" semantic conventions. It represents the name of the +// mobile carrier. +func NetworkCarrierName(val string) attribute.KeyValue { + return NetworkCarrierNameKey.String(val) +} + +// NetworkLocalAddress returns an attribute KeyValue conforming to the +// "network.local.address" semantic conventions. It represents the local +// address of the network connection - IP address or Unix domain socket name. +func NetworkLocalAddress(val string) attribute.KeyValue { + return NetworkLocalAddressKey.String(val) +} + +// NetworkLocalPort returns an attribute KeyValue conforming to the +// "network.local.port" semantic conventions. It represents the local port +// number of the network connection. +func NetworkLocalPort(val int) attribute.KeyValue { + return NetworkLocalPortKey.Int(val) +} + +// NetworkPeerAddress returns an attribute KeyValue conforming to the +// "network.peer.address" semantic conventions. It represents the peer address +// of the network connection - IP address or Unix domain socket name. +func NetworkPeerAddress(val string) attribute.KeyValue { + return NetworkPeerAddressKey.String(val) +} + +// NetworkPeerPort returns an attribute KeyValue conforming to the +// "network.peer.port" semantic conventions. It represents the peer port number +// of the network connection. +func NetworkPeerPort(val int) attribute.KeyValue { + return NetworkPeerPortKey.Int(val) +} + +// NetworkProtocolName returns an attribute KeyValue conforming to the +// "network.protocol.name" semantic conventions. It represents the [OSI +// application layer](https://osi-model.com/application-layer/) or non-OSI +// equivalent. +func NetworkProtocolName(val string) attribute.KeyValue { + return NetworkProtocolNameKey.String(val) +} + +// NetworkProtocolVersion returns an attribute KeyValue conforming to the +// "network.protocol.version" semantic conventions. It represents the version +// of the protocol specified in `network.protocol.name`. +func NetworkProtocolVersion(val string) attribute.KeyValue { + return NetworkProtocolVersionKey.String(val) +} + +// Attributes for remote procedure calls. +const ( + // RPCConnectRPCErrorCodeKey is the attribute Key conforming to the + // "rpc.connect_rpc.error_code" semantic conventions. It represents the + // [error codes](https://connect.build/docs/protocol/#error-codes) of the + // Connect request. Error codes are always string values. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + RPCConnectRPCErrorCodeKey = attribute.Key("rpc.connect_rpc.error_code") + + // RPCGRPCStatusCodeKey is the attribute Key conforming to the + // "rpc.grpc.status_code" semantic conventions. It represents the [numeric + // status + // code](https://github.com/grpc/grpc/blob/v1.33.2/doc/statuscodes.md) of + // the gRPC request. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + RPCGRPCStatusCodeKey = attribute.Key("rpc.grpc.status_code") + + // RPCJsonrpcErrorCodeKey is the attribute Key conforming to the + // "rpc.jsonrpc.error_code" semantic conventions. It represents the + // `error.code` property of response if it is an error response. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: -32700, 100 + RPCJsonrpcErrorCodeKey = attribute.Key("rpc.jsonrpc.error_code") + + // RPCJsonrpcErrorMessageKey is the attribute Key conforming to the + // "rpc.jsonrpc.error_message" semantic conventions. It represents the + // `error.message` property of response if it is an error response. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Parse error', 'User already exists' + RPCJsonrpcErrorMessageKey = attribute.Key("rpc.jsonrpc.error_message") + + // RPCJsonrpcRequestIDKey is the attribute Key conforming to the + // "rpc.jsonrpc.request_id" semantic conventions. It represents the `id` + // property of request or response. Since protocol allows id to be int, + // string, `null` or missing (for notifications), value is expected to be + // cast to string for simplicity. Use empty string in case of `null` value. + // Omit entirely if this is a notification. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '10', 'request-7', '' + RPCJsonrpcRequestIDKey = attribute.Key("rpc.jsonrpc.request_id") + + // RPCJsonrpcVersionKey is the attribute Key conforming to the + // "rpc.jsonrpc.version" semantic conventions. It represents the protocol + // version as in `jsonrpc` property of request/response. Since JSON-RPC 1.0 + // doesn't specify this, the value can be omitted. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2.0', '1.0' + RPCJsonrpcVersionKey = attribute.Key("rpc.jsonrpc.version") + + // RPCMethodKey is the attribute Key conforming to the "rpc.method" + // semantic conventions. It represents the name of the (logical) method + // being called, must be equal to the $method part in the span name. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'exampleMethod' + // Note: This is the logical name of the method from the RPC interface + // perspective, which can be different from the name of any implementing + // method/function. The `code.function` attribute may be used to store the + // latter (e.g., method actually executing the call on the server side, RPC + // client stub method on the client side). + RPCMethodKey = attribute.Key("rpc.method") + + // RPCServiceKey is the attribute Key conforming to the "rpc.service" + // semantic conventions. It represents the full (logical) name of the + // service being called, including its package name, if applicable. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'myservice.EchoService' + // Note: This is the logical name of the service from the RPC interface + // perspective, which can be different from the name of any implementing + // class. The `code.namespace` attribute may be used to store the latter + // (despite the attribute name, it may include a class name; e.g., class + // with method actually executing the call on the server side, RPC client + // stub class on the client side). + RPCServiceKey = attribute.Key("rpc.service") + + // RPCSystemKey is the attribute Key conforming to the "rpc.system" + // semantic conventions. It represents a string identifying the remoting + // system. See below for a list of well-known identifiers. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + RPCSystemKey = attribute.Key("rpc.system") +) + +var ( + // cancelled + RPCConnectRPCErrorCodeCancelled = RPCConnectRPCErrorCodeKey.String("cancelled") + // unknown + RPCConnectRPCErrorCodeUnknown = RPCConnectRPCErrorCodeKey.String("unknown") + // invalid_argument + RPCConnectRPCErrorCodeInvalidArgument = RPCConnectRPCErrorCodeKey.String("invalid_argument") + // deadline_exceeded + RPCConnectRPCErrorCodeDeadlineExceeded = RPCConnectRPCErrorCodeKey.String("deadline_exceeded") + // not_found + RPCConnectRPCErrorCodeNotFound = RPCConnectRPCErrorCodeKey.String("not_found") + // already_exists + RPCConnectRPCErrorCodeAlreadyExists = RPCConnectRPCErrorCodeKey.String("already_exists") + // permission_denied + RPCConnectRPCErrorCodePermissionDenied = RPCConnectRPCErrorCodeKey.String("permission_denied") + // resource_exhausted + RPCConnectRPCErrorCodeResourceExhausted = RPCConnectRPCErrorCodeKey.String("resource_exhausted") + // failed_precondition + RPCConnectRPCErrorCodeFailedPrecondition = RPCConnectRPCErrorCodeKey.String("failed_precondition") + // aborted + RPCConnectRPCErrorCodeAborted = RPCConnectRPCErrorCodeKey.String("aborted") + // out_of_range + RPCConnectRPCErrorCodeOutOfRange = RPCConnectRPCErrorCodeKey.String("out_of_range") + // unimplemented + RPCConnectRPCErrorCodeUnimplemented = RPCConnectRPCErrorCodeKey.String("unimplemented") + // internal + RPCConnectRPCErrorCodeInternal = RPCConnectRPCErrorCodeKey.String("internal") + // unavailable + RPCConnectRPCErrorCodeUnavailable = RPCConnectRPCErrorCodeKey.String("unavailable") + // data_loss + RPCConnectRPCErrorCodeDataLoss = RPCConnectRPCErrorCodeKey.String("data_loss") + // unauthenticated + RPCConnectRPCErrorCodeUnauthenticated = RPCConnectRPCErrorCodeKey.String("unauthenticated") +) + +var ( + // OK + RPCGRPCStatusCodeOk = RPCGRPCStatusCodeKey.Int(0) + // CANCELLED + RPCGRPCStatusCodeCancelled = RPCGRPCStatusCodeKey.Int(1) + // UNKNOWN + RPCGRPCStatusCodeUnknown = RPCGRPCStatusCodeKey.Int(2) + // INVALID_ARGUMENT + RPCGRPCStatusCodeInvalidArgument = RPCGRPCStatusCodeKey.Int(3) + // DEADLINE_EXCEEDED + RPCGRPCStatusCodeDeadlineExceeded = RPCGRPCStatusCodeKey.Int(4) + // NOT_FOUND + RPCGRPCStatusCodeNotFound = RPCGRPCStatusCodeKey.Int(5) + // ALREADY_EXISTS + RPCGRPCStatusCodeAlreadyExists = RPCGRPCStatusCodeKey.Int(6) + // PERMISSION_DENIED + RPCGRPCStatusCodePermissionDenied = RPCGRPCStatusCodeKey.Int(7) + // RESOURCE_EXHAUSTED + RPCGRPCStatusCodeResourceExhausted = RPCGRPCStatusCodeKey.Int(8) + // FAILED_PRECONDITION + RPCGRPCStatusCodeFailedPrecondition = RPCGRPCStatusCodeKey.Int(9) + // ABORTED + RPCGRPCStatusCodeAborted = RPCGRPCStatusCodeKey.Int(10) + // OUT_OF_RANGE + RPCGRPCStatusCodeOutOfRange = RPCGRPCStatusCodeKey.Int(11) + // UNIMPLEMENTED + RPCGRPCStatusCodeUnimplemented = RPCGRPCStatusCodeKey.Int(12) + // INTERNAL + RPCGRPCStatusCodeInternal = RPCGRPCStatusCodeKey.Int(13) + // UNAVAILABLE + RPCGRPCStatusCodeUnavailable = RPCGRPCStatusCodeKey.Int(14) + // DATA_LOSS + RPCGRPCStatusCodeDataLoss = RPCGRPCStatusCodeKey.Int(15) + // UNAUTHENTICATED + RPCGRPCStatusCodeUnauthenticated = RPCGRPCStatusCodeKey.Int(16) +) + +var ( + // gRPC + RPCSystemGRPC = RPCSystemKey.String("grpc") + // Java RMI + RPCSystemJavaRmi = RPCSystemKey.String("java_rmi") + // .NET WCF + RPCSystemDotnetWcf = RPCSystemKey.String("dotnet_wcf") + // Apache Dubbo + RPCSystemApacheDubbo = RPCSystemKey.String("apache_dubbo") + // Connect RPC + RPCSystemConnectRPC = RPCSystemKey.String("connect_rpc") +) + +// RPCJsonrpcErrorCode returns an attribute KeyValue conforming to the +// "rpc.jsonrpc.error_code" semantic conventions. It represents the +// `error.code` property of response if it is an error response. +func RPCJsonrpcErrorCode(val int) attribute.KeyValue { + return RPCJsonrpcErrorCodeKey.Int(val) +} + +// RPCJsonrpcErrorMessage returns an attribute KeyValue conforming to the +// "rpc.jsonrpc.error_message" semantic conventions. It represents the +// `error.message` property of response if it is an error response. +func RPCJsonrpcErrorMessage(val string) attribute.KeyValue { + return RPCJsonrpcErrorMessageKey.String(val) +} + +// RPCJsonrpcRequestID returns an attribute KeyValue conforming to the +// "rpc.jsonrpc.request_id" semantic conventions. It represents the `id` +// property of request or response. Since protocol allows id to be int, string, +// `null` or missing (for notifications), value is expected to be cast to +// string for simplicity. Use empty string in case of `null` value. Omit +// entirely if this is a notification. +func RPCJsonrpcRequestID(val string) attribute.KeyValue { + return RPCJsonrpcRequestIDKey.String(val) +} + +// RPCJsonrpcVersion returns an attribute KeyValue conforming to the +// "rpc.jsonrpc.version" semantic conventions. It represents the protocol +// version as in `jsonrpc` property of request/response. Since JSON-RPC 1.0 +// doesn't specify this, the value can be omitted. +func RPCJsonrpcVersion(val string) attribute.KeyValue { + return RPCJsonrpcVersionKey.String(val) +} + +// RPCMethod returns an attribute KeyValue conforming to the "rpc.method" +// semantic conventions. It represents the name of the (logical) method being +// called, must be equal to the $method part in the span name. +func RPCMethod(val string) attribute.KeyValue { + return RPCMethodKey.String(val) +} + +// RPCService returns an attribute KeyValue conforming to the "rpc.service" +// semantic conventions. It represents the full (logical) name of the service +// being called, including its package name, if applicable. +func RPCService(val string) attribute.KeyValue { + return RPCServiceKey.String(val) +} + +// These attributes may be used to describe the server in a connection-based +// network interaction where there is one side that initiates the connection +// (the client is the side that initiates the connection). This covers all TCP +// network interactions since TCP is connection-based and one side initiates +// the connection (an exception is made for peer-to-peer communication over TCP +// where the "user-facing" surface of the protocol / API doesn't expose a clear +// notion of client and server). This also covers UDP network interactions +// where one side initiates the interaction, e.g. QUIC (HTTP/3) and DNS. +const ( + // ServerAddressKey is the attribute Key conforming to the "server.address" + // semantic conventions. It represents the server domain name if available + // without reverse DNS lookup; otherwise, IP address or Unix domain socket + // name. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'example.com', '10.1.2.80', '/tmp/my.sock' + // Note: When observed from the client side, and when communicating through + // an intermediary, `server.address` SHOULD represent the server address + // behind any intermediaries, for example proxies, if it's available. + ServerAddressKey = attribute.Key("server.address") + + // ServerPortKey is the attribute Key conforming to the "server.port" + // semantic conventions. It represents the server port number. + // + // Type: int + // RequirementLevel: Optional + // Stability: stable + // Examples: 80, 8080, 443 + // Note: When observed from the client side, and when communicating through + // an intermediary, `server.port` SHOULD represent the server port behind + // any intermediaries, for example proxies, if it's available. + ServerPortKey = attribute.Key("server.port") +) + +// ServerAddress returns an attribute KeyValue conforming to the +// "server.address" semantic conventions. It represents the server domain name +// if available without reverse DNS lookup; otherwise, IP address or Unix +// domain socket name. +func ServerAddress(val string) attribute.KeyValue { + return ServerAddressKey.String(val) +} + +// ServerPort returns an attribute KeyValue conforming to the "server.port" +// semantic conventions. It represents the server port number. +func ServerPort(val int) attribute.KeyValue { + return ServerPortKey.Int(val) +} + +// These attributes may be used to describe the sender of a network +// exchange/packet. These should be used when there is no client/server +// relationship between the two sides, or when that relationship is unknown. +// This covers low-level network interactions (e.g. packet tracing) where you +// don't know if there was a connection or which side initiated it. This also +// covers unidirectional UDP flows and peer-to-peer communication where the +// "user-facing" surface of the protocol / API doesn't expose a clear notion of +// client and server. +const ( + // SourceAddressKey is the attribute Key conforming to the "source.address" + // semantic conventions. It represents the source address - domain name if + // available without reverse DNS lookup; otherwise, IP address or Unix + // domain socket name. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'source.example.com', '10.1.2.80', '/tmp/my.sock' + // Note: When observed from the destination side, and when communicating + // through an intermediary, `source.address` SHOULD represent the source + // address behind any intermediaries, for example proxies, if it's + // available. + SourceAddressKey = attribute.Key("source.address") + + // SourcePortKey is the attribute Key conforming to the "source.port" + // semantic conventions. It represents the source port number + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 3389, 2888 + SourcePortKey = attribute.Key("source.port") +) + +// SourceAddress returns an attribute KeyValue conforming to the +// "source.address" semantic conventions. It represents the source address - +// domain name if available without reverse DNS lookup; otherwise, IP address +// or Unix domain socket name. +func SourceAddress(val string) attribute.KeyValue { + return SourceAddressKey.String(val) +} + +// SourcePort returns an attribute KeyValue conforming to the "source.port" +// semantic conventions. It represents the source port number +func SourcePort(val int) attribute.KeyValue { + return SourcePortKey.Int(val) +} + +// Semantic convention attributes in the TLS namespace. +const ( + // TLSCipherKey is the attribute Key conforming to the "tls.cipher" + // semantic conventions. It represents the string indicating the + // [cipher](https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5) + // used during the current connection. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'TLS_RSA_WITH_3DES_EDE_CBC_SHA', + // 'TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256' + // Note: The values allowed for `tls.cipher` MUST be one of the + // `Descriptions` of the [registered TLS Cipher + // Suits](https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#table-tls-parameters-4). + TLSCipherKey = attribute.Key("tls.cipher") + + // TLSClientCertificateKey is the attribute Key conforming to the + // "tls.client.certificate" semantic conventions. It represents the + // pEM-encoded stand-alone certificate offered by the client. This is + // usually mutually-exclusive of `client.certificate_chain` since this + // value also exists in that list. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'MII...' + TLSClientCertificateKey = attribute.Key("tls.client.certificate") + + // TLSClientCertificateChainKey is the attribute Key conforming to the + // "tls.client.certificate_chain" semantic conventions. It represents the + // array of PEM-encoded certificates that make up the certificate chain + // offered by the client. This is usually mutually-exclusive of + // `client.certificate` since that value should be the first certificate in + // the chain. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'MII...', 'MI...' + TLSClientCertificateChainKey = attribute.Key("tls.client.certificate_chain") + + // TLSClientHashMd5Key is the attribute Key conforming to the + // "tls.client.hash.md5" semantic conventions. It represents the + // certificate fingerprint using the MD5 digest of DER-encoded version of + // certificate offered by the client. For consistency with other hash + // values, this value should be formatted as an uppercase hash. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC' + TLSClientHashMd5Key = attribute.Key("tls.client.hash.md5") + + // TLSClientHashSha1Key is the attribute Key conforming to the + // "tls.client.hash.sha1" semantic conventions. It represents the + // certificate fingerprint using the SHA1 digest of DER-encoded version of + // certificate offered by the client. For consistency with other hash + // values, this value should be formatted as an uppercase hash. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '9E393D93138888D288266C2D915214D1D1CCEB2A' + TLSClientHashSha1Key = attribute.Key("tls.client.hash.sha1") + + // TLSClientHashSha256Key is the attribute Key conforming to the + // "tls.client.hash.sha256" semantic conventions. It represents the + // certificate fingerprint using the SHA256 digest of DER-encoded version + // of certificate offered by the client. For consistency with other hash + // values, this value should be formatted as an uppercase hash. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0' + TLSClientHashSha256Key = attribute.Key("tls.client.hash.sha256") + + // TLSClientIssuerKey is the attribute Key conforming to the + // "tls.client.issuer" semantic conventions. It represents the + // distinguished name of + // [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) + // of the issuer of the x.509 certificate presented by the client. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'CN=Example Root CA, OU=Infrastructure Team, DC=example, + // DC=com' + TLSClientIssuerKey = attribute.Key("tls.client.issuer") + + // TLSClientJa3Key is the attribute Key conforming to the "tls.client.ja3" + // semantic conventions. It represents a hash that identifies clients based + // on how they perform an SSL/TLS handshake. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'd4e5b18d6b55c71272893221c96ba240' + TLSClientJa3Key = attribute.Key("tls.client.ja3") + + // TLSClientNotAfterKey is the attribute Key conforming to the + // "tls.client.not_after" semantic conventions. It represents the date/Time + // indicating when client certificate is no longer considered valid. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2021-01-01T00:00:00.000Z' + TLSClientNotAfterKey = attribute.Key("tls.client.not_after") + + // TLSClientNotBeforeKey is the attribute Key conforming to the + // "tls.client.not_before" semantic conventions. It represents the + // date/Time indicating when client certificate is first considered valid. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '1970-01-01T00:00:00.000Z' + TLSClientNotBeforeKey = attribute.Key("tls.client.not_before") + + // TLSClientServerNameKey is the attribute Key conforming to the + // "tls.client.server_name" semantic conventions. It represents the also + // called an SNI, this tells the server which hostname to which the client + // is attempting to connect to. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry.io' + TLSClientServerNameKey = attribute.Key("tls.client.server_name") + + // TLSClientSubjectKey is the attribute Key conforming to the + // "tls.client.subject" semantic conventions. It represents the + // distinguished name of subject of the x.509 certificate presented by the + // client. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'CN=myclient, OU=Documentation Team, DC=example, DC=com' + TLSClientSubjectKey = attribute.Key("tls.client.subject") + + // TLSClientSupportedCiphersKey is the attribute Key conforming to the + // "tls.client.supported_ciphers" semantic conventions. It represents the + // array of ciphers offered by the client during the client hello. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: '"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", + // "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "..."' + TLSClientSupportedCiphersKey = attribute.Key("tls.client.supported_ciphers") + + // TLSCurveKey is the attribute Key conforming to the "tls.curve" semantic + // conventions. It represents the string indicating the curve used for the + // given cipher, when applicable + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'secp256r1' + TLSCurveKey = attribute.Key("tls.curve") + + // TLSEstablishedKey is the attribute Key conforming to the + // "tls.established" semantic conventions. It represents the boolean flag + // indicating if the TLS negotiation was successful and transitioned to an + // encrypted tunnel. + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + // Examples: True + TLSEstablishedKey = attribute.Key("tls.established") + + // TLSNextProtocolKey is the attribute Key conforming to the + // "tls.next_protocol" semantic conventions. It represents the string + // indicating the protocol being tunneled. Per the values in the [IANA + // registry](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids), + // this string should be lower case. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'http/1.1' + TLSNextProtocolKey = attribute.Key("tls.next_protocol") + + // TLSProtocolNameKey is the attribute Key conforming to the + // "tls.protocol.name" semantic conventions. It represents the normalized + // lowercase protocol name parsed from original string of the negotiated + // [SSL/TLS protocol + // version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + TLSProtocolNameKey = attribute.Key("tls.protocol.name") + + // TLSProtocolVersionKey is the attribute Key conforming to the + // "tls.protocol.version" semantic conventions. It represents the numeric + // part of the version parsed from the original string of the negotiated + // [SSL/TLS protocol + // version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '1.2', '3' + TLSProtocolVersionKey = attribute.Key("tls.protocol.version") + + // TLSResumedKey is the attribute Key conforming to the "tls.resumed" + // semantic conventions. It represents the boolean flag indicating if this + // TLS connection was resumed from an existing TLS negotiation. + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + // Examples: True + TLSResumedKey = attribute.Key("tls.resumed") + + // TLSServerCertificateKey is the attribute Key conforming to the + // "tls.server.certificate" semantic conventions. It represents the + // pEM-encoded stand-alone certificate offered by the server. This is + // usually mutually-exclusive of `server.certificate_chain` since this + // value also exists in that list. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'MII...' + TLSServerCertificateKey = attribute.Key("tls.server.certificate") + + // TLSServerCertificateChainKey is the attribute Key conforming to the + // "tls.server.certificate_chain" semantic conventions. It represents the + // array of PEM-encoded certificates that make up the certificate chain + // offered by the server. This is usually mutually-exclusive of + // `server.certificate` since that value should be the first certificate in + // the chain. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'MII...', 'MI...' + TLSServerCertificateChainKey = attribute.Key("tls.server.certificate_chain") + + // TLSServerHashMd5Key is the attribute Key conforming to the + // "tls.server.hash.md5" semantic conventions. It represents the + // certificate fingerprint using the MD5 digest of DER-encoded version of + // certificate offered by the server. For consistency with other hash + // values, this value should be formatted as an uppercase hash. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '0F76C7F2C55BFD7D8E8B8F4BFBF0C9EC' + TLSServerHashMd5Key = attribute.Key("tls.server.hash.md5") + + // TLSServerHashSha1Key is the attribute Key conforming to the + // "tls.server.hash.sha1" semantic conventions. It represents the + // certificate fingerprint using the SHA1 digest of DER-encoded version of + // certificate offered by the server. For consistency with other hash + // values, this value should be formatted as an uppercase hash. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '9E393D93138888D288266C2D915214D1D1CCEB2A' + TLSServerHashSha1Key = attribute.Key("tls.server.hash.sha1") + + // TLSServerHashSha256Key is the attribute Key conforming to the + // "tls.server.hash.sha256" semantic conventions. It represents the + // certificate fingerprint using the SHA256 digest of DER-encoded version + // of certificate offered by the server. For consistency with other hash + // values, this value should be formatted as an uppercase hash. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // '0687F666A054EF17A08E2F2162EAB4CBC0D265E1D7875BE74BF3C712CA92DAF0' + TLSServerHashSha256Key = attribute.Key("tls.server.hash.sha256") + + // TLSServerIssuerKey is the attribute Key conforming to the + // "tls.server.issuer" semantic conventions. It represents the + // distinguished name of + // [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) + // of the issuer of the x.509 certificate presented by the client. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'CN=Example Root CA, OU=Infrastructure Team, DC=example, + // DC=com' + TLSServerIssuerKey = attribute.Key("tls.server.issuer") + + // TLSServerJa3sKey is the attribute Key conforming to the + // "tls.server.ja3s" semantic conventions. It represents a hash that + // identifies servers based on how they perform an SSL/TLS handshake. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'd4e5b18d6b55c71272893221c96ba240' + TLSServerJa3sKey = attribute.Key("tls.server.ja3s") + + // TLSServerNotAfterKey is the attribute Key conforming to the + // "tls.server.not_after" semantic conventions. It represents the date/Time + // indicating when server certificate is no longer considered valid. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2021-01-01T00:00:00.000Z' + TLSServerNotAfterKey = attribute.Key("tls.server.not_after") + + // TLSServerNotBeforeKey is the attribute Key conforming to the + // "tls.server.not_before" semantic conventions. It represents the + // date/Time indicating when server certificate is first considered valid. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '1970-01-01T00:00:00.000Z' + TLSServerNotBeforeKey = attribute.Key("tls.server.not_before") + + // TLSServerSubjectKey is the attribute Key conforming to the + // "tls.server.subject" semantic conventions. It represents the + // distinguished name of subject of the x.509 certificate presented by the + // server. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'CN=myserver, OU=Documentation Team, DC=example, DC=com' + TLSServerSubjectKey = attribute.Key("tls.server.subject") +) + +var ( + // ssl + TLSProtocolNameSsl = TLSProtocolNameKey.String("ssl") + // tls + TLSProtocolNameTLS = TLSProtocolNameKey.String("tls") +) + +// TLSCipher returns an attribute KeyValue conforming to the "tls.cipher" +// semantic conventions. It represents the string indicating the +// [cipher](https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.5) used +// during the current connection. +func TLSCipher(val string) attribute.KeyValue { + return TLSCipherKey.String(val) +} + +// TLSClientCertificate returns an attribute KeyValue conforming to the +// "tls.client.certificate" semantic conventions. It represents the pEM-encoded +// stand-alone certificate offered by the client. This is usually +// mutually-exclusive of `client.certificate_chain` since this value also +// exists in that list. +func TLSClientCertificate(val string) attribute.KeyValue { + return TLSClientCertificateKey.String(val) +} + +// TLSClientCertificateChain returns an attribute KeyValue conforming to the +// "tls.client.certificate_chain" semantic conventions. It represents the array +// of PEM-encoded certificates that make up the certificate chain offered by +// the client. This is usually mutually-exclusive of `client.certificate` since +// that value should be the first certificate in the chain. +func TLSClientCertificateChain(val ...string) attribute.KeyValue { + return TLSClientCertificateChainKey.StringSlice(val) +} + +// TLSClientHashMd5 returns an attribute KeyValue conforming to the +// "tls.client.hash.md5" semantic conventions. It represents the certificate +// fingerprint using the MD5 digest of DER-encoded version of certificate +// offered by the client. For consistency with other hash values, this value +// should be formatted as an uppercase hash. +func TLSClientHashMd5(val string) attribute.KeyValue { + return TLSClientHashMd5Key.String(val) +} + +// TLSClientHashSha1 returns an attribute KeyValue conforming to the +// "tls.client.hash.sha1" semantic conventions. It represents the certificate +// fingerprint using the SHA1 digest of DER-encoded version of certificate +// offered by the client. For consistency with other hash values, this value +// should be formatted as an uppercase hash. +func TLSClientHashSha1(val string) attribute.KeyValue { + return TLSClientHashSha1Key.String(val) +} + +// TLSClientHashSha256 returns an attribute KeyValue conforming to the +// "tls.client.hash.sha256" semantic conventions. It represents the certificate +// fingerprint using the SHA256 digest of DER-encoded version of certificate +// offered by the client. For consistency with other hash values, this value +// should be formatted as an uppercase hash. +func TLSClientHashSha256(val string) attribute.KeyValue { + return TLSClientHashSha256Key.String(val) +} + +// TLSClientIssuer returns an attribute KeyValue conforming to the +// "tls.client.issuer" semantic conventions. It represents the distinguished +// name of +// [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) of +// the issuer of the x.509 certificate presented by the client. +func TLSClientIssuer(val string) attribute.KeyValue { + return TLSClientIssuerKey.String(val) +} + +// TLSClientJa3 returns an attribute KeyValue conforming to the +// "tls.client.ja3" semantic conventions. It represents a hash that identifies +// clients based on how they perform an SSL/TLS handshake. +func TLSClientJa3(val string) attribute.KeyValue { + return TLSClientJa3Key.String(val) +} + +// TLSClientNotAfter returns an attribute KeyValue conforming to the +// "tls.client.not_after" semantic conventions. It represents the date/Time +// indicating when client certificate is no longer considered valid. +func TLSClientNotAfter(val string) attribute.KeyValue { + return TLSClientNotAfterKey.String(val) +} + +// TLSClientNotBefore returns an attribute KeyValue conforming to the +// "tls.client.not_before" semantic conventions. It represents the date/Time +// indicating when client certificate is first considered valid. +func TLSClientNotBefore(val string) attribute.KeyValue { + return TLSClientNotBeforeKey.String(val) +} + +// TLSClientServerName returns an attribute KeyValue conforming to the +// "tls.client.server_name" semantic conventions. It represents the also called +// an SNI, this tells the server which hostname to which the client is +// attempting to connect to. +func TLSClientServerName(val string) attribute.KeyValue { + return TLSClientServerNameKey.String(val) +} + +// TLSClientSubject returns an attribute KeyValue conforming to the +// "tls.client.subject" semantic conventions. It represents the distinguished +// name of subject of the x.509 certificate presented by the client. +func TLSClientSubject(val string) attribute.KeyValue { + return TLSClientSubjectKey.String(val) +} + +// TLSClientSupportedCiphers returns an attribute KeyValue conforming to the +// "tls.client.supported_ciphers" semantic conventions. It represents the array +// of ciphers offered by the client during the client hello. +func TLSClientSupportedCiphers(val ...string) attribute.KeyValue { + return TLSClientSupportedCiphersKey.StringSlice(val) +} + +// TLSCurve returns an attribute KeyValue conforming to the "tls.curve" +// semantic conventions. It represents the string indicating the curve used for +// the given cipher, when applicable +func TLSCurve(val string) attribute.KeyValue { + return TLSCurveKey.String(val) +} + +// TLSEstablished returns an attribute KeyValue conforming to the +// "tls.established" semantic conventions. It represents the boolean flag +// indicating if the TLS negotiation was successful and transitioned to an +// encrypted tunnel. +func TLSEstablished(val bool) attribute.KeyValue { + return TLSEstablishedKey.Bool(val) +} + +// TLSNextProtocol returns an attribute KeyValue conforming to the +// "tls.next_protocol" semantic conventions. It represents the string +// indicating the protocol being tunneled. Per the values in the [IANA +// registry](https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids), +// this string should be lower case. +func TLSNextProtocol(val string) attribute.KeyValue { + return TLSNextProtocolKey.String(val) +} + +// TLSProtocolVersion returns an attribute KeyValue conforming to the +// "tls.protocol.version" semantic conventions. It represents the numeric part +// of the version parsed from the original string of the negotiated [SSL/TLS +// protocol +// version](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html#RETURN-VALUES) +func TLSProtocolVersion(val string) attribute.KeyValue { + return TLSProtocolVersionKey.String(val) +} + +// TLSResumed returns an attribute KeyValue conforming to the "tls.resumed" +// semantic conventions. It represents the boolean flag indicating if this TLS +// connection was resumed from an existing TLS negotiation. +func TLSResumed(val bool) attribute.KeyValue { + return TLSResumedKey.Bool(val) +} + +// TLSServerCertificate returns an attribute KeyValue conforming to the +// "tls.server.certificate" semantic conventions. It represents the pEM-encoded +// stand-alone certificate offered by the server. This is usually +// mutually-exclusive of `server.certificate_chain` since this value also +// exists in that list. +func TLSServerCertificate(val string) attribute.KeyValue { + return TLSServerCertificateKey.String(val) +} + +// TLSServerCertificateChain returns an attribute KeyValue conforming to the +// "tls.server.certificate_chain" semantic conventions. It represents the array +// of PEM-encoded certificates that make up the certificate chain offered by +// the server. This is usually mutually-exclusive of `server.certificate` since +// that value should be the first certificate in the chain. +func TLSServerCertificateChain(val ...string) attribute.KeyValue { + return TLSServerCertificateChainKey.StringSlice(val) +} + +// TLSServerHashMd5 returns an attribute KeyValue conforming to the +// "tls.server.hash.md5" semantic conventions. It represents the certificate +// fingerprint using the MD5 digest of DER-encoded version of certificate +// offered by the server. For consistency with other hash values, this value +// should be formatted as an uppercase hash. +func TLSServerHashMd5(val string) attribute.KeyValue { + return TLSServerHashMd5Key.String(val) +} + +// TLSServerHashSha1 returns an attribute KeyValue conforming to the +// "tls.server.hash.sha1" semantic conventions. It represents the certificate +// fingerprint using the SHA1 digest of DER-encoded version of certificate +// offered by the server. For consistency with other hash values, this value +// should be formatted as an uppercase hash. +func TLSServerHashSha1(val string) attribute.KeyValue { + return TLSServerHashSha1Key.String(val) +} + +// TLSServerHashSha256 returns an attribute KeyValue conforming to the +// "tls.server.hash.sha256" semantic conventions. It represents the certificate +// fingerprint using the SHA256 digest of DER-encoded version of certificate +// offered by the server. For consistency with other hash values, this value +// should be formatted as an uppercase hash. +func TLSServerHashSha256(val string) attribute.KeyValue { + return TLSServerHashSha256Key.String(val) +} + +// TLSServerIssuer returns an attribute KeyValue conforming to the +// "tls.server.issuer" semantic conventions. It represents the distinguished +// name of +// [subject](https://datatracker.ietf.org/doc/html/rfc5280#section-4.1.2.6) of +// the issuer of the x.509 certificate presented by the client. +func TLSServerIssuer(val string) attribute.KeyValue { + return TLSServerIssuerKey.String(val) +} + +// TLSServerJa3s returns an attribute KeyValue conforming to the +// "tls.server.ja3s" semantic conventions. It represents a hash that identifies +// servers based on how they perform an SSL/TLS handshake. +func TLSServerJa3s(val string) attribute.KeyValue { + return TLSServerJa3sKey.String(val) +} + +// TLSServerNotAfter returns an attribute KeyValue conforming to the +// "tls.server.not_after" semantic conventions. It represents the date/Time +// indicating when server certificate is no longer considered valid. +func TLSServerNotAfter(val string) attribute.KeyValue { + return TLSServerNotAfterKey.String(val) +} + +// TLSServerNotBefore returns an attribute KeyValue conforming to the +// "tls.server.not_before" semantic conventions. It represents the date/Time +// indicating when server certificate is first considered valid. +func TLSServerNotBefore(val string) attribute.KeyValue { + return TLSServerNotBeforeKey.String(val) +} + +// TLSServerSubject returns an attribute KeyValue conforming to the +// "tls.server.subject" semantic conventions. It represents the distinguished +// name of subject of the x.509 certificate presented by the server. +func TLSServerSubject(val string) attribute.KeyValue { + return TLSServerSubjectKey.String(val) +} + +// Attributes describing URL. +const ( + // URLFragmentKey is the attribute Key conforming to the "url.fragment" + // semantic conventions. It represents the [URI + // fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'SemConv' + URLFragmentKey = attribute.Key("url.fragment") + + // URLFullKey is the attribute Key conforming to the "url.full" semantic + // conventions. It represents the absolute URL describing a network + // resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'https://www.foo.bar/search?q=OpenTelemetry#SemConv', + // '//localhost' + // Note: For network calls, URL usually has + // `scheme://host[:port][path][?query][#fragment]` format, where the + // fragment is not transmitted over HTTP, but if it is known, it SHOULD be + // included nevertheless. + // `url.full` MUST NOT contain credentials passed via URL in form of + // `https://username:password@www.example.com/`. In such case username and + // password SHOULD be redacted and attribute's value SHOULD be + // `https://REDACTED:REDACTED@www.example.com/`. + // `url.full` SHOULD capture the absolute URL when it is available (or can + // be reconstructed) and SHOULD NOT be validated or modified except for + // sanitizing purposes. + URLFullKey = attribute.Key("url.full") + + // URLPathKey is the attribute Key conforming to the "url.path" semantic + // conventions. It represents the [URI + // path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: '/search' + URLPathKey = attribute.Key("url.path") + + // URLQueryKey is the attribute Key conforming to the "url.query" semantic + // conventions. It represents the [URI + // query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'q=OpenTelemetry' + // Note: Sensitive content provided in query string SHOULD be scrubbed when + // instrumentations can identify it. + URLQueryKey = attribute.Key("url.query") + + // URLSchemeKey is the attribute Key conforming to the "url.scheme" + // semantic conventions. It represents the [URI + // scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component + // identifying the used protocol. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'https', 'ftp', 'telnet' + URLSchemeKey = attribute.Key("url.scheme") +) + +// URLFragment returns an attribute KeyValue conforming to the +// "url.fragment" semantic conventions. It represents the [URI +// fragment](https://www.rfc-editor.org/rfc/rfc3986#section-3.5) component +func URLFragment(val string) attribute.KeyValue { + return URLFragmentKey.String(val) +} + +// URLFull returns an attribute KeyValue conforming to the "url.full" +// semantic conventions. It represents the absolute URL describing a network +// resource according to [RFC3986](https://www.rfc-editor.org/rfc/rfc3986) +func URLFull(val string) attribute.KeyValue { + return URLFullKey.String(val) +} + +// URLPath returns an attribute KeyValue conforming to the "url.path" +// semantic conventions. It represents the [URI +// path](https://www.rfc-editor.org/rfc/rfc3986#section-3.3) component +func URLPath(val string) attribute.KeyValue { + return URLPathKey.String(val) +} + +// URLQuery returns an attribute KeyValue conforming to the "url.query" +// semantic conventions. It represents the [URI +// query](https://www.rfc-editor.org/rfc/rfc3986#section-3.4) component +func URLQuery(val string) attribute.KeyValue { + return URLQueryKey.String(val) +} + +// URLScheme returns an attribute KeyValue conforming to the "url.scheme" +// semantic conventions. It represents the [URI +// scheme](https://www.rfc-editor.org/rfc/rfc3986#section-3.1) component +// identifying the used protocol. +func URLScheme(val string) attribute.KeyValue { + return URLSchemeKey.String(val) +} + +// Describes user-agent attributes. +const ( + // UserAgentOriginalKey is the attribute Key conforming to the + // "user_agent.original" semantic conventions. It represents the value of + // the [HTTP + // User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) + // header sent by the client. + // + // Type: string + // RequirementLevel: Optional + // Stability: stable + // Examples: 'CERN-LineMode/2.15 libwww/2.17b3', 'Mozilla/5.0 (iPhone; CPU + // iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) + // Version/14.1.2 Mobile/15E148 Safari/604.1' + UserAgentOriginalKey = attribute.Key("user_agent.original") +) + +// UserAgentOriginal returns an attribute KeyValue conforming to the +// "user_agent.original" semantic conventions. It represents the value of the +// [HTTP +// User-Agent](https://www.rfc-editor.org/rfc/rfc9110.html#field.user-agent) +// header sent by the client. +func UserAgentOriginal(val string) attribute.KeyValue { + return UserAgentOriginalKey.String(val) +} + +// Session is defined as the period of time encompassing all activities +// performed by the application and the actions executed by the end user. +// Consequently, a Session is represented as a collection of Logs, Events, and +// Spans emitted by the Client Application throughout the Session's duration. +// Each Session is assigned a unique identifier, which is included as an +// attribute in the Logs, Events, and Spans generated during the Session's +// lifecycle. +// When a session reaches end of life, typically due to user inactivity or +// session timeout, a new session identifier will be assigned. The previous +// session identifier may be provided by the instrumentation so that telemetry +// backends can link the two sessions. +const ( + // SessionIDKey is the attribute Key conforming to the "session.id" + // semantic conventions. It represents a unique id to identify a session. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '00112233-4455-6677-8899-aabbccddeeff' + SessionIDKey = attribute.Key("session.id") + + // SessionPreviousIDKey is the attribute Key conforming to the + // "session.previous_id" semantic conventions. It represents the previous + // `session.id` for this user, when known. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '00112233-4455-6677-8899-aabbccddeeff' + SessionPreviousIDKey = attribute.Key("session.previous_id") +) + +// SessionID returns an attribute KeyValue conforming to the "session.id" +// semantic conventions. It represents a unique id to identify a session. +func SessionID(val string) attribute.KeyValue { + return SessionIDKey.String(val) +} + +// SessionPreviousID returns an attribute KeyValue conforming to the +// "session.previous_id" semantic conventions. It represents the previous +// `session.id` for this user, when known. +func SessionPreviousID(val string) attribute.KeyValue { + return SessionPreviousIDKey.String(val) +} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/doc.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/doc.go new file mode 100644 index 0000000000..9b802db272 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/doc.go @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package semconv implements OpenTelemetry semantic conventions. +// +// OpenTelemetry semantic conventions are agreed standardized naming +// patterns for OpenTelemetry things. This package represents the v1.24.0 +// version of the OpenTelemetry semantic conventions. +package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/event.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/event.go new file mode 100644 index 0000000000..cd3c716295 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/event.go @@ -0,0 +1,211 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" + +import "go.opentelemetry.io/otel/attribute" + +// This event represents an occurrence of a lifecycle transition on the iOS +// platform. +const ( + // IosStateKey is the attribute Key conforming to the "ios.state" semantic + // conventions. It represents the this attribute represents the state the + // application has transitioned into at the occurrence of the event. + // + // Type: Enum + // RequirementLevel: Required + // Stability: experimental + // Note: The iOS lifecycle states are defined in the [UIApplicationDelegate + // documentation](https://developer.apple.com/documentation/uikit/uiapplicationdelegate#1656902), + // and from which the `OS terminology` column values are derived. + IosStateKey = attribute.Key("ios.state") +) + +var ( + // The app has become `active`. Associated with UIKit notification `applicationDidBecomeActive` + IosStateActive = IosStateKey.String("active") + // The app is now `inactive`. Associated with UIKit notification `applicationWillResignActive` + IosStateInactive = IosStateKey.String("inactive") + // The app is now in the background. This value is associated with UIKit notification `applicationDidEnterBackground` + IosStateBackground = IosStateKey.String("background") + // The app is now in the foreground. This value is associated with UIKit notification `applicationWillEnterForeground` + IosStateForeground = IosStateKey.String("foreground") + // The app is about to terminate. Associated with UIKit notification `applicationWillTerminate` + IosStateTerminate = IosStateKey.String("terminate") +) + +// This event represents an occurrence of a lifecycle transition on the Android +// platform. +const ( + // AndroidStateKey is the attribute Key conforming to the "android.state" + // semantic conventions. It represents the this attribute represents the + // state the application has transitioned into at the occurrence of the + // event. + // + // Type: Enum + // RequirementLevel: Required + // Stability: experimental + // Note: The Android lifecycle states are defined in [Activity lifecycle + // callbacks](https://developer.android.com/guide/components/activities/activity-lifecycle#lc), + // and from which the `OS identifiers` are derived. + AndroidStateKey = attribute.Key("android.state") +) + +var ( + // Any time before Activity.onResume() or, if the app has no Activity, Context.startService() has been called in the app for the first time + AndroidStateCreated = AndroidStateKey.String("created") + // Any time after Activity.onPause() or, if the app has no Activity, Context.stopService() has been called when the app was in the foreground state + AndroidStateBackground = AndroidStateKey.String("background") + // Any time after Activity.onResume() or, if the app has no Activity, Context.startService() has been called when the app was in either the created or background states + AndroidStateForeground = AndroidStateKey.String("foreground") +) + +// This semantic convention defines the attributes used to represent a feature +// flag evaluation as an event. +const ( + // FeatureFlagKeyKey is the attribute Key conforming to the + // "feature_flag.key" semantic conventions. It represents the unique + // identifier of the feature flag. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'logo-color' + FeatureFlagKeyKey = attribute.Key("feature_flag.key") + + // FeatureFlagProviderNameKey is the attribute Key conforming to the + // "feature_flag.provider_name" semantic conventions. It represents the + // name of the service provider that performs the flag evaluation. + // + // Type: string + // RequirementLevel: Recommended + // Stability: experimental + // Examples: 'Flag Manager' + FeatureFlagProviderNameKey = attribute.Key("feature_flag.provider_name") + + // FeatureFlagVariantKey is the attribute Key conforming to the + // "feature_flag.variant" semantic conventions. It represents the sHOULD be + // a semantic identifier for a value. If one is unavailable, a stringified + // version of the value can be used. + // + // Type: string + // RequirementLevel: Recommended + // Stability: experimental + // Examples: 'red', 'true', 'on' + // Note: A semantic identifier, commonly referred to as a variant, provides + // a means + // for referring to a value without including the value itself. This can + // provide additional context for understanding the meaning behind a value. + // For example, the variant `red` maybe be used for the value `#c05543`. + // + // A stringified version of the value can be used in situations where a + // semantic identifier is unavailable. String representation of the value + // should be determined by the implementer. + FeatureFlagVariantKey = attribute.Key("feature_flag.variant") +) + +// FeatureFlagKey returns an attribute KeyValue conforming to the +// "feature_flag.key" semantic conventions. It represents the unique identifier +// of the feature flag. +func FeatureFlagKey(val string) attribute.KeyValue { + return FeatureFlagKeyKey.String(val) +} + +// FeatureFlagProviderName returns an attribute KeyValue conforming to the +// "feature_flag.provider_name" semantic conventions. It represents the name of +// the service provider that performs the flag evaluation. +func FeatureFlagProviderName(val string) attribute.KeyValue { + return FeatureFlagProviderNameKey.String(val) +} + +// FeatureFlagVariant returns an attribute KeyValue conforming to the +// "feature_flag.variant" semantic conventions. It represents the sHOULD be a +// semantic identifier for a value. If one is unavailable, a stringified +// version of the value can be used. +func FeatureFlagVariant(val string) attribute.KeyValue { + return FeatureFlagVariantKey.String(val) +} + +// RPC received/sent message. +const ( + // MessageCompressedSizeKey is the attribute Key conforming to the + // "message.compressed_size" semantic conventions. It represents the + // compressed size of the message in bytes. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + MessageCompressedSizeKey = attribute.Key("message.compressed_size") + + // MessageIDKey is the attribute Key conforming to the "message.id" + // semantic conventions. It represents the mUST be calculated as two + // different counters starting from `1` one for sent messages and one for + // received message. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Note: This way we guarantee that the values will be consistent between + // different implementations. + MessageIDKey = attribute.Key("message.id") + + // MessageTypeKey is the attribute Key conforming to the "message.type" + // semantic conventions. It represents the whether this is a received or + // sent message. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + MessageTypeKey = attribute.Key("message.type") + + // MessageUncompressedSizeKey is the attribute Key conforming to the + // "message.uncompressed_size" semantic conventions. It represents the + // uncompressed size of the message in bytes. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + MessageUncompressedSizeKey = attribute.Key("message.uncompressed_size") +) + +var ( + // sent + MessageTypeSent = MessageTypeKey.String("SENT") + // received + MessageTypeReceived = MessageTypeKey.String("RECEIVED") +) + +// MessageCompressedSize returns an attribute KeyValue conforming to the +// "message.compressed_size" semantic conventions. It represents the compressed +// size of the message in bytes. +func MessageCompressedSize(val int) attribute.KeyValue { + return MessageCompressedSizeKey.Int(val) +} + +// MessageID returns an attribute KeyValue conforming to the "message.id" +// semantic conventions. It represents the mUST be calculated as two different +// counters starting from `1` one for sent messages and one for received +// message. +func MessageID(val int) attribute.KeyValue { + return MessageIDKey.Int(val) +} + +// MessageUncompressedSize returns an attribute KeyValue conforming to the +// "message.uncompressed_size" semantic conventions. It represents the +// uncompressed size of the message in bytes. +func MessageUncompressedSize(val int) attribute.KeyValue { + return MessageUncompressedSizeKey.Int(val) +} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/exception.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/exception.go new file mode 100644 index 0000000000..ef9bbd37a8 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/exception.go @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" + +const ( + // ExceptionEventName is the name of the Span event representing an exception. + ExceptionEventName = "exception" +) diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/resource.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/resource.go new file mode 100644 index 0000000000..69eda1959f --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/resource.go @@ -0,0 +1,2556 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" + +import "go.opentelemetry.io/otel/attribute" + +// A cloud environment (e.g. GCP, Azure, AWS). +const ( + // CloudAccountIDKey is the attribute Key conforming to the + // "cloud.account.id" semantic conventions. It represents the cloud account + // ID the resource is assigned to. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '111111111111', 'opentelemetry' + CloudAccountIDKey = attribute.Key("cloud.account.id") + + // CloudAvailabilityZoneKey is the attribute Key conforming to the + // "cloud.availability_zone" semantic conventions. It represents the cloud + // regions often have multiple, isolated locations known as zones to + // increase availability. Availability zone represents the zone where the + // resource is running. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'us-east-1c' + // Note: Availability zones are called "zones" on Alibaba Cloud and Google + // Cloud. + CloudAvailabilityZoneKey = attribute.Key("cloud.availability_zone") + + // CloudPlatformKey is the attribute Key conforming to the "cloud.platform" + // semantic conventions. It represents the cloud platform in use. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Note: The prefix of the service SHOULD match the one specified in + // `cloud.provider`. + CloudPlatformKey = attribute.Key("cloud.platform") + + // CloudProviderKey is the attribute Key conforming to the "cloud.provider" + // semantic conventions. It represents the name of the cloud provider. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + CloudProviderKey = attribute.Key("cloud.provider") + + // CloudRegionKey is the attribute Key conforming to the "cloud.region" + // semantic conventions. It represents the geographical region the resource + // is running. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'us-central1', 'us-east-1' + // Note: Refer to your provider's docs to see the available regions, for + // example [Alibaba Cloud + // regions](https://www.alibabacloud.com/help/doc-detail/40654.htm), [AWS + // regions](https://aws.amazon.com/about-aws/global-infrastructure/regions_az/), + // [Azure + // regions](https://azure.microsoft.com/global-infrastructure/geographies/), + // [Google Cloud regions](https://cloud.google.com/about/locations), or + // [Tencent Cloud + // regions](https://www.tencentcloud.com/document/product/213/6091). + CloudRegionKey = attribute.Key("cloud.region") + + // CloudResourceIDKey is the attribute Key conforming to the + // "cloud.resource_id" semantic conventions. It represents the cloud + // provider-specific native identifier of the monitored cloud resource + // (e.g. an + // [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) + // on AWS, a [fully qualified resource + // ID](https://learn.microsoft.com/rest/api/resources/resources/get-by-id) + // on Azure, a [full resource + // name](https://cloud.google.com/apis/design/resource_names#full_resource_name) + // on GCP) + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'arn:aws:lambda:REGION:ACCOUNT_ID:function:my-function', + // '//run.googleapis.com/projects/PROJECT_ID/locations/LOCATION_ID/services/SERVICE_ID', + // '/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/' + // Note: On some cloud providers, it may not be possible to determine the + // full ID at startup, + // so it may be necessary to set `cloud.resource_id` as a span attribute + // instead. + // + // The exact value to use for `cloud.resource_id` depends on the cloud + // provider. + // The following well-known definitions MUST be used if you set this + // attribute and they apply: + // + // * **AWS Lambda:** The function + // [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html). + // Take care not to use the "invoked ARN" directly but replace any + // [alias + // suffix](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html) + // with the resolved function version, as the same runtime instance may + // be invokable with + // multiple different aliases. + // * **GCP:** The [URI of the + // resource](https://cloud.google.com/iam/docs/full-resource-names) + // * **Azure:** The [Fully Qualified Resource + // ID](https://docs.microsoft.com/rest/api/resources/resources/get-by-id) + // of the invoked function, + // *not* the function app, having the form + // `/subscriptions//resourceGroups//providers/Microsoft.Web/sites//functions/`. + // This means that a span attribute MUST be used, as an Azure function + // app can host multiple functions that would usually share + // a TracerProvider. + CloudResourceIDKey = attribute.Key("cloud.resource_id") +) + +var ( + // Alibaba Cloud Elastic Compute Service + CloudPlatformAlibabaCloudECS = CloudPlatformKey.String("alibaba_cloud_ecs") + // Alibaba Cloud Function Compute + CloudPlatformAlibabaCloudFc = CloudPlatformKey.String("alibaba_cloud_fc") + // Red Hat OpenShift on Alibaba Cloud + CloudPlatformAlibabaCloudOpenshift = CloudPlatformKey.String("alibaba_cloud_openshift") + // AWS Elastic Compute Cloud + CloudPlatformAWSEC2 = CloudPlatformKey.String("aws_ec2") + // AWS Elastic Container Service + CloudPlatformAWSECS = CloudPlatformKey.String("aws_ecs") + // AWS Elastic Kubernetes Service + CloudPlatformAWSEKS = CloudPlatformKey.String("aws_eks") + // AWS Lambda + CloudPlatformAWSLambda = CloudPlatformKey.String("aws_lambda") + // AWS Elastic Beanstalk + CloudPlatformAWSElasticBeanstalk = CloudPlatformKey.String("aws_elastic_beanstalk") + // AWS App Runner + CloudPlatformAWSAppRunner = CloudPlatformKey.String("aws_app_runner") + // Red Hat OpenShift on AWS (ROSA) + CloudPlatformAWSOpenshift = CloudPlatformKey.String("aws_openshift") + // Azure Virtual Machines + CloudPlatformAzureVM = CloudPlatformKey.String("azure_vm") + // Azure Container Instances + CloudPlatformAzureContainerInstances = CloudPlatformKey.String("azure_container_instances") + // Azure Kubernetes Service + CloudPlatformAzureAKS = CloudPlatformKey.String("azure_aks") + // Azure Functions + CloudPlatformAzureFunctions = CloudPlatformKey.String("azure_functions") + // Azure App Service + CloudPlatformAzureAppService = CloudPlatformKey.String("azure_app_service") + // Azure Red Hat OpenShift + CloudPlatformAzureOpenshift = CloudPlatformKey.String("azure_openshift") + // Google Bare Metal Solution (BMS) + CloudPlatformGCPBareMetalSolution = CloudPlatformKey.String("gcp_bare_metal_solution") + // Google Cloud Compute Engine (GCE) + CloudPlatformGCPComputeEngine = CloudPlatformKey.String("gcp_compute_engine") + // Google Cloud Run + CloudPlatformGCPCloudRun = CloudPlatformKey.String("gcp_cloud_run") + // Google Cloud Kubernetes Engine (GKE) + CloudPlatformGCPKubernetesEngine = CloudPlatformKey.String("gcp_kubernetes_engine") + // Google Cloud Functions (GCF) + CloudPlatformGCPCloudFunctions = CloudPlatformKey.String("gcp_cloud_functions") + // Google Cloud App Engine (GAE) + CloudPlatformGCPAppEngine = CloudPlatformKey.String("gcp_app_engine") + // Red Hat OpenShift on Google Cloud + CloudPlatformGCPOpenshift = CloudPlatformKey.String("gcp_openshift") + // Red Hat OpenShift on IBM Cloud + CloudPlatformIbmCloudOpenshift = CloudPlatformKey.String("ibm_cloud_openshift") + // Tencent Cloud Cloud Virtual Machine (CVM) + CloudPlatformTencentCloudCvm = CloudPlatformKey.String("tencent_cloud_cvm") + // Tencent Cloud Elastic Kubernetes Service (EKS) + CloudPlatformTencentCloudEKS = CloudPlatformKey.String("tencent_cloud_eks") + // Tencent Cloud Serverless Cloud Function (SCF) + CloudPlatformTencentCloudScf = CloudPlatformKey.String("tencent_cloud_scf") +) + +var ( + // Alibaba Cloud + CloudProviderAlibabaCloud = CloudProviderKey.String("alibaba_cloud") + // Amazon Web Services + CloudProviderAWS = CloudProviderKey.String("aws") + // Microsoft Azure + CloudProviderAzure = CloudProviderKey.String("azure") + // Google Cloud Platform + CloudProviderGCP = CloudProviderKey.String("gcp") + // Heroku Platform as a Service + CloudProviderHeroku = CloudProviderKey.String("heroku") + // IBM Cloud + CloudProviderIbmCloud = CloudProviderKey.String("ibm_cloud") + // Tencent Cloud + CloudProviderTencentCloud = CloudProviderKey.String("tencent_cloud") +) + +// CloudAccountID returns an attribute KeyValue conforming to the +// "cloud.account.id" semantic conventions. It represents the cloud account ID +// the resource is assigned to. +func CloudAccountID(val string) attribute.KeyValue { + return CloudAccountIDKey.String(val) +} + +// CloudAvailabilityZone returns an attribute KeyValue conforming to the +// "cloud.availability_zone" semantic conventions. It represents the cloud +// regions often have multiple, isolated locations known as zones to increase +// availability. Availability zone represents the zone where the resource is +// running. +func CloudAvailabilityZone(val string) attribute.KeyValue { + return CloudAvailabilityZoneKey.String(val) +} + +// CloudRegion returns an attribute KeyValue conforming to the +// "cloud.region" semantic conventions. It represents the geographical region +// the resource is running. +func CloudRegion(val string) attribute.KeyValue { + return CloudRegionKey.String(val) +} + +// CloudResourceID returns an attribute KeyValue conforming to the +// "cloud.resource_id" semantic conventions. It represents the cloud +// provider-specific native identifier of the monitored cloud resource (e.g. an +// [ARN](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) +// on AWS, a [fully qualified resource +// ID](https://learn.microsoft.com/rest/api/resources/resources/get-by-id) on +// Azure, a [full resource +// name](https://cloud.google.com/apis/design/resource_names#full_resource_name) +// on GCP) +func CloudResourceID(val string) attribute.KeyValue { + return CloudResourceIDKey.String(val) +} + +// A container instance. +const ( + // ContainerCommandKey is the attribute Key conforming to the + // "container.command" semantic conventions. It represents the command used + // to run the container (i.e. the command name). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'otelcontribcol' + // Note: If using embedded credentials or sensitive data, it is recommended + // to remove them to prevent potential leakage. + ContainerCommandKey = attribute.Key("container.command") + + // ContainerCommandArgsKey is the attribute Key conforming to the + // "container.command_args" semantic conventions. It represents the all the + // command arguments (including the command/executable itself) run by the + // container. [2] + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'otelcontribcol, --config, config.yaml' + ContainerCommandArgsKey = attribute.Key("container.command_args") + + // ContainerCommandLineKey is the attribute Key conforming to the + // "container.command_line" semantic conventions. It represents the full + // command run by the container as a single string representing the full + // command. [2] + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'otelcontribcol --config config.yaml' + ContainerCommandLineKey = attribute.Key("container.command_line") + + // ContainerIDKey is the attribute Key conforming to the "container.id" + // semantic conventions. It represents the container ID. Usually a UUID, as + // for example used to [identify Docker + // containers](https://docs.docker.com/engine/reference/run/#container-identification). + // The UUID might be abbreviated. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'a3bf90e006b2' + ContainerIDKey = attribute.Key("container.id") + + // ContainerImageIDKey is the attribute Key conforming to the + // "container.image.id" semantic conventions. It represents the runtime + // specific image identifier. Usually a hash algorithm followed by a UUID. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // 'sha256:19c92d0a00d1b66d897bceaa7319bee0dd38a10a851c60bcec9474aa3f01e50f' + // Note: Docker defines a sha256 of the image id; `container.image.id` + // corresponds to the `Image` field from the Docker container inspect + // [API](https://docs.docker.com/engine/api/v1.43/#tag/Container/operation/ContainerInspect) + // endpoint. + // K8S defines a link to the container registry repository with digest + // `"imageID": "registry.azurecr.io + // /namespace/service/dockerfile@sha256:bdeabd40c3a8a492eaf9e8e44d0ebbb84bac7ee25ac0cf8a7159d25f62555625"`. + // The ID is assinged by the container runtime and can vary in different + // environments. Consider using `oci.manifest.digest` if it is important to + // identify the same image in different environments/runtimes. + ContainerImageIDKey = attribute.Key("container.image.id") + + // ContainerImageNameKey is the attribute Key conforming to the + // "container.image.name" semantic conventions. It represents the name of + // the image the container was built on. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'gcr.io/opentelemetry/operator' + ContainerImageNameKey = attribute.Key("container.image.name") + + // ContainerImageRepoDigestsKey is the attribute Key conforming to the + // "container.image.repo_digests" semantic conventions. It represents the + // repo digests of the container image as provided by the container + // runtime. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // 'example@sha256:afcc7f1ac1b49db317a7196c902e61c6c3c4607d63599ee1a82d702d249a0ccb', + // 'internal.registry.example.com:5000/example@sha256:b69959407d21e8a062e0416bf13405bb2b71ed7a84dde4158ebafacfa06f5578' + // Note: + // [Docker](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect) + // and + // [CRI](https://github.com/kubernetes/cri-api/blob/c75ef5b473bbe2d0a4fc92f82235efd665ea8e9f/pkg/apis/runtime/v1/api.proto#L1237-L1238) + // report those under the `RepoDigests` field. + ContainerImageRepoDigestsKey = attribute.Key("container.image.repo_digests") + + // ContainerImageTagsKey is the attribute Key conforming to the + // "container.image.tags" semantic conventions. It represents the container + // image tags. An example can be found in [Docker Image + // Inspect](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect). + // Should be only the `` section of the full name for example from + // `registry.example.com/my-org/my-image:`. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'v1.27.1', '3.5.7-0' + ContainerImageTagsKey = attribute.Key("container.image.tags") + + // ContainerNameKey is the attribute Key conforming to the "container.name" + // semantic conventions. It represents the container name used by container + // runtime. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry-autoconf' + ContainerNameKey = attribute.Key("container.name") + + // ContainerRuntimeKey is the attribute Key conforming to the + // "container.runtime" semantic conventions. It represents the container + // runtime managing this container. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'docker', 'containerd', 'rkt' + ContainerRuntimeKey = attribute.Key("container.runtime") +) + +// ContainerCommand returns an attribute KeyValue conforming to the +// "container.command" semantic conventions. It represents the command used to +// run the container (i.e. the command name). +func ContainerCommand(val string) attribute.KeyValue { + return ContainerCommandKey.String(val) +} + +// ContainerCommandArgs returns an attribute KeyValue conforming to the +// "container.command_args" semantic conventions. It represents the all the +// command arguments (including the command/executable itself) run by the +// container. [2] +func ContainerCommandArgs(val ...string) attribute.KeyValue { + return ContainerCommandArgsKey.StringSlice(val) +} + +// ContainerCommandLine returns an attribute KeyValue conforming to the +// "container.command_line" semantic conventions. It represents the full +// command run by the container as a single string representing the full +// command. [2] +func ContainerCommandLine(val string) attribute.KeyValue { + return ContainerCommandLineKey.String(val) +} + +// ContainerID returns an attribute KeyValue conforming to the +// "container.id" semantic conventions. It represents the container ID. Usually +// a UUID, as for example used to [identify Docker +// containers](https://docs.docker.com/engine/reference/run/#container-identification). +// The UUID might be abbreviated. +func ContainerID(val string) attribute.KeyValue { + return ContainerIDKey.String(val) +} + +// ContainerImageID returns an attribute KeyValue conforming to the +// "container.image.id" semantic conventions. It represents the runtime +// specific image identifier. Usually a hash algorithm followed by a UUID. +func ContainerImageID(val string) attribute.KeyValue { + return ContainerImageIDKey.String(val) +} + +// ContainerImageName returns an attribute KeyValue conforming to the +// "container.image.name" semantic conventions. It represents the name of the +// image the container was built on. +func ContainerImageName(val string) attribute.KeyValue { + return ContainerImageNameKey.String(val) +} + +// ContainerImageRepoDigests returns an attribute KeyValue conforming to the +// "container.image.repo_digests" semantic conventions. It represents the repo +// digests of the container image as provided by the container runtime. +func ContainerImageRepoDigests(val ...string) attribute.KeyValue { + return ContainerImageRepoDigestsKey.StringSlice(val) +} + +// ContainerImageTags returns an attribute KeyValue conforming to the +// "container.image.tags" semantic conventions. It represents the container +// image tags. An example can be found in [Docker Image +// Inspect](https://docs.docker.com/engine/api/v1.43/#tag/Image/operation/ImageInspect). +// Should be only the `` section of the full name for example from +// `registry.example.com/my-org/my-image:`. +func ContainerImageTags(val ...string) attribute.KeyValue { + return ContainerImageTagsKey.StringSlice(val) +} + +// ContainerName returns an attribute KeyValue conforming to the +// "container.name" semantic conventions. It represents the container name used +// by container runtime. +func ContainerName(val string) attribute.KeyValue { + return ContainerNameKey.String(val) +} + +// ContainerRuntime returns an attribute KeyValue conforming to the +// "container.runtime" semantic conventions. It represents the container +// runtime managing this container. +func ContainerRuntime(val string) attribute.KeyValue { + return ContainerRuntimeKey.String(val) +} + +// Describes device attributes. +const ( + // DeviceIDKey is the attribute Key conforming to the "device.id" semantic + // conventions. It represents a unique identifier representing the device + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2ab2916d-a51f-4ac8-80ee-45ac31a28092' + // Note: The device identifier MUST only be defined using the values + // outlined below. This value is not an advertising identifier and MUST NOT + // be used as such. On iOS (Swift or Objective-C), this value MUST be equal + // to the [vendor + // identifier](https://developer.apple.com/documentation/uikit/uidevice/1620059-identifierforvendor). + // On Android (Java or Kotlin), this value MUST be equal to the Firebase + // Installation ID or a globally unique UUID which is persisted across + // sessions in your application. More information can be found + // [here](https://developer.android.com/training/articles/user-data-ids) on + // best practices and exact implementation details. Caution should be taken + // when storing personal data or anything which can identify a user. GDPR + // and data protection laws may apply, ensure you do your own due + // diligence. + DeviceIDKey = attribute.Key("device.id") + + // DeviceManufacturerKey is the attribute Key conforming to the + // "device.manufacturer" semantic conventions. It represents the name of + // the device manufacturer + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Apple', 'Samsung' + // Note: The Android OS provides this field via + // [Build](https://developer.android.com/reference/android/os/Build#MANUFACTURER). + // iOS apps SHOULD hardcode the value `Apple`. + DeviceManufacturerKey = attribute.Key("device.manufacturer") + + // DeviceModelIdentifierKey is the attribute Key conforming to the + // "device.model.identifier" semantic conventions. It represents the model + // identifier for the device + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'iPhone3,4', 'SM-G920F' + // Note: It's recommended this value represents a machine-readable version + // of the model identifier rather than the market or consumer-friendly name + // of the device. + DeviceModelIdentifierKey = attribute.Key("device.model.identifier") + + // DeviceModelNameKey is the attribute Key conforming to the + // "device.model.name" semantic conventions. It represents the marketing + // name for the device model + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'iPhone 6s Plus', 'Samsung Galaxy S6' + // Note: It's recommended this value represents a human-readable version of + // the device model rather than a machine-readable alternative. + DeviceModelNameKey = attribute.Key("device.model.name") +) + +// DeviceID returns an attribute KeyValue conforming to the "device.id" +// semantic conventions. It represents a unique identifier representing the +// device +func DeviceID(val string) attribute.KeyValue { + return DeviceIDKey.String(val) +} + +// DeviceManufacturer returns an attribute KeyValue conforming to the +// "device.manufacturer" semantic conventions. It represents the name of the +// device manufacturer +func DeviceManufacturer(val string) attribute.KeyValue { + return DeviceManufacturerKey.String(val) +} + +// DeviceModelIdentifier returns an attribute KeyValue conforming to the +// "device.model.identifier" semantic conventions. It represents the model +// identifier for the device +func DeviceModelIdentifier(val string) attribute.KeyValue { + return DeviceModelIdentifierKey.String(val) +} + +// DeviceModelName returns an attribute KeyValue conforming to the +// "device.model.name" semantic conventions. It represents the marketing name +// for the device model +func DeviceModelName(val string) attribute.KeyValue { + return DeviceModelNameKey.String(val) +} + +// A host is defined as a computing instance. For example, physical servers, +// virtual machines, switches or disk array. +const ( + // HostArchKey is the attribute Key conforming to the "host.arch" semantic + // conventions. It represents the CPU architecture the host system is + // running on. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + HostArchKey = attribute.Key("host.arch") + + // HostCPUCacheL2SizeKey is the attribute Key conforming to the + // "host.cpu.cache.l2.size" semantic conventions. It represents the amount + // of level 2 memory cache available to the processor (in Bytes). + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 12288000 + HostCPUCacheL2SizeKey = attribute.Key("host.cpu.cache.l2.size") + + // HostCPUFamilyKey is the attribute Key conforming to the + // "host.cpu.family" semantic conventions. It represents the family or + // generation of the CPU. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '6', 'PA-RISC 1.1e' + HostCPUFamilyKey = attribute.Key("host.cpu.family") + + // HostCPUModelIDKey is the attribute Key conforming to the + // "host.cpu.model.id" semantic conventions. It represents the model + // identifier. It provides more granular information about the CPU, + // distinguishing it from other CPUs within the same family. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '6', '9000/778/B180L' + HostCPUModelIDKey = attribute.Key("host.cpu.model.id") + + // HostCPUModelNameKey is the attribute Key conforming to the + // "host.cpu.model.name" semantic conventions. It represents the model + // designation of the processor. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz' + HostCPUModelNameKey = attribute.Key("host.cpu.model.name") + + // HostCPUSteppingKey is the attribute Key conforming to the + // "host.cpu.stepping" semantic conventions. It represents the stepping or + // core revisions. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 1 + HostCPUSteppingKey = attribute.Key("host.cpu.stepping") + + // HostCPUVendorIDKey is the attribute Key conforming to the + // "host.cpu.vendor.id" semantic conventions. It represents the processor + // manufacturer identifier. A maximum 12-character string. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'GenuineIntel' + // Note: [CPUID](https://wiki.osdev.org/CPUID) command returns the vendor + // ID string in EBX, EDX and ECX registers. Writing these to memory in this + // order results in a 12-character string. + HostCPUVendorIDKey = attribute.Key("host.cpu.vendor.id") + + // HostIDKey is the attribute Key conforming to the "host.id" semantic + // conventions. It represents the unique host ID. For Cloud, this must be + // the instance_id assigned by the cloud provider. For non-containerized + // systems, this should be the `machine-id`. See the table below for the + // sources to use to determine the `machine-id` based on operating system. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'fdbf79e8af94cb7f9e8df36789187052' + HostIDKey = attribute.Key("host.id") + + // HostImageIDKey is the attribute Key conforming to the "host.image.id" + // semantic conventions. It represents the vM image ID or host OS image ID. + // For Cloud, this value is from the provider. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'ami-07b06b442921831e5' + HostImageIDKey = attribute.Key("host.image.id") + + // HostImageNameKey is the attribute Key conforming to the + // "host.image.name" semantic conventions. It represents the name of the VM + // image or OS install the host was instantiated from. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'infra-ami-eks-worker-node-7d4ec78312', 'CentOS-8-x86_64-1905' + HostImageNameKey = attribute.Key("host.image.name") + + // HostImageVersionKey is the attribute Key conforming to the + // "host.image.version" semantic conventions. It represents the version + // string of the VM image or host OS as defined in [Version + // Attributes](/docs/resource/README.md#version-attributes). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '0.1' + HostImageVersionKey = attribute.Key("host.image.version") + + // HostIPKey is the attribute Key conforming to the "host.ip" semantic + // conventions. It represents the available IP addresses of the host, + // excluding loopback interfaces. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: '192.168.1.140', 'fe80::abc2:4a28:737a:609e' + // Note: IPv4 Addresses MUST be specified in dotted-quad notation. IPv6 + // addresses MUST be specified in the [RFC + // 5952](https://www.rfc-editor.org/rfc/rfc5952.html) format. + HostIPKey = attribute.Key("host.ip") + + // HostMacKey is the attribute Key conforming to the "host.mac" semantic + // conventions. It represents the available MAC addresses of the host, + // excluding loopback interfaces. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'AC-DE-48-23-45-67', 'AC-DE-48-23-45-67-01-9F' + // Note: MAC Addresses MUST be represented in [IEEE RA hexadecimal + // form](https://standards.ieee.org/wp-content/uploads/import/documents/tutorials/eui.pdf): + // as hyphen-separated octets in uppercase hexadecimal form from most to + // least significant. + HostMacKey = attribute.Key("host.mac") + + // HostNameKey is the attribute Key conforming to the "host.name" semantic + // conventions. It represents the name of the host. On Unix systems, it may + // contain what the hostname command returns, or the fully qualified + // hostname, or another name specified by the user. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry-test' + HostNameKey = attribute.Key("host.name") + + // HostTypeKey is the attribute Key conforming to the "host.type" semantic + // conventions. It represents the type of host. For Cloud, this must be the + // machine type. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'n1-standard-1' + HostTypeKey = attribute.Key("host.type") +) + +var ( + // AMD64 + HostArchAMD64 = HostArchKey.String("amd64") + // ARM32 + HostArchARM32 = HostArchKey.String("arm32") + // ARM64 + HostArchARM64 = HostArchKey.String("arm64") + // Itanium + HostArchIA64 = HostArchKey.String("ia64") + // 32-bit PowerPC + HostArchPPC32 = HostArchKey.String("ppc32") + // 64-bit PowerPC + HostArchPPC64 = HostArchKey.String("ppc64") + // IBM z/Architecture + HostArchS390x = HostArchKey.String("s390x") + // 32-bit x86 + HostArchX86 = HostArchKey.String("x86") +) + +// HostCPUCacheL2Size returns an attribute KeyValue conforming to the +// "host.cpu.cache.l2.size" semantic conventions. It represents the amount of +// level 2 memory cache available to the processor (in Bytes). +func HostCPUCacheL2Size(val int) attribute.KeyValue { + return HostCPUCacheL2SizeKey.Int(val) +} + +// HostCPUFamily returns an attribute KeyValue conforming to the +// "host.cpu.family" semantic conventions. It represents the family or +// generation of the CPU. +func HostCPUFamily(val string) attribute.KeyValue { + return HostCPUFamilyKey.String(val) +} + +// HostCPUModelID returns an attribute KeyValue conforming to the +// "host.cpu.model.id" semantic conventions. It represents the model +// identifier. It provides more granular information about the CPU, +// distinguishing it from other CPUs within the same family. +func HostCPUModelID(val string) attribute.KeyValue { + return HostCPUModelIDKey.String(val) +} + +// HostCPUModelName returns an attribute KeyValue conforming to the +// "host.cpu.model.name" semantic conventions. It represents the model +// designation of the processor. +func HostCPUModelName(val string) attribute.KeyValue { + return HostCPUModelNameKey.String(val) +} + +// HostCPUStepping returns an attribute KeyValue conforming to the +// "host.cpu.stepping" semantic conventions. It represents the stepping or core +// revisions. +func HostCPUStepping(val int) attribute.KeyValue { + return HostCPUSteppingKey.Int(val) +} + +// HostCPUVendorID returns an attribute KeyValue conforming to the +// "host.cpu.vendor.id" semantic conventions. It represents the processor +// manufacturer identifier. A maximum 12-character string. +func HostCPUVendorID(val string) attribute.KeyValue { + return HostCPUVendorIDKey.String(val) +} + +// HostID returns an attribute KeyValue conforming to the "host.id" semantic +// conventions. It represents the unique host ID. For Cloud, this must be the +// instance_id assigned by the cloud provider. For non-containerized systems, +// this should be the `machine-id`. See the table below for the sources to use +// to determine the `machine-id` based on operating system. +func HostID(val string) attribute.KeyValue { + return HostIDKey.String(val) +} + +// HostImageID returns an attribute KeyValue conforming to the +// "host.image.id" semantic conventions. It represents the vM image ID or host +// OS image ID. For Cloud, this value is from the provider. +func HostImageID(val string) attribute.KeyValue { + return HostImageIDKey.String(val) +} + +// HostImageName returns an attribute KeyValue conforming to the +// "host.image.name" semantic conventions. It represents the name of the VM +// image or OS install the host was instantiated from. +func HostImageName(val string) attribute.KeyValue { + return HostImageNameKey.String(val) +} + +// HostImageVersion returns an attribute KeyValue conforming to the +// "host.image.version" semantic conventions. It represents the version string +// of the VM image or host OS as defined in [Version +// Attributes](/docs/resource/README.md#version-attributes). +func HostImageVersion(val string) attribute.KeyValue { + return HostImageVersionKey.String(val) +} + +// HostIP returns an attribute KeyValue conforming to the "host.ip" semantic +// conventions. It represents the available IP addresses of the host, excluding +// loopback interfaces. +func HostIP(val ...string) attribute.KeyValue { + return HostIPKey.StringSlice(val) +} + +// HostMac returns an attribute KeyValue conforming to the "host.mac" +// semantic conventions. It represents the available MAC addresses of the host, +// excluding loopback interfaces. +func HostMac(val ...string) attribute.KeyValue { + return HostMacKey.StringSlice(val) +} + +// HostName returns an attribute KeyValue conforming to the "host.name" +// semantic conventions. It represents the name of the host. On Unix systems, +// it may contain what the hostname command returns, or the fully qualified +// hostname, or another name specified by the user. +func HostName(val string) attribute.KeyValue { + return HostNameKey.String(val) +} + +// HostType returns an attribute KeyValue conforming to the "host.type" +// semantic conventions. It represents the type of host. For Cloud, this must +// be the machine type. +func HostType(val string) attribute.KeyValue { + return HostTypeKey.String(val) +} + +// Kubernetes resource attributes. +const ( + // K8SClusterNameKey is the attribute Key conforming to the + // "k8s.cluster.name" semantic conventions. It represents the name of the + // cluster. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry-cluster' + K8SClusterNameKey = attribute.Key("k8s.cluster.name") + + // K8SClusterUIDKey is the attribute Key conforming to the + // "k8s.cluster.uid" semantic conventions. It represents a pseudo-ID for + // the cluster, set to the UID of the `kube-system` namespace. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '218fc5a9-a5f1-4b54-aa05-46717d0ab26d' + // Note: K8S doesn't have support for obtaining a cluster ID. If this is + // ever + // added, we will recommend collecting the `k8s.cluster.uid` through the + // official APIs. In the meantime, we are able to use the `uid` of the + // `kube-system` namespace as a proxy for cluster ID. Read on for the + // rationale. + // + // Every object created in a K8S cluster is assigned a distinct UID. The + // `kube-system` namespace is used by Kubernetes itself and will exist + // for the lifetime of the cluster. Using the `uid` of the `kube-system` + // namespace is a reasonable proxy for the K8S ClusterID as it will only + // change if the cluster is rebuilt. Furthermore, Kubernetes UIDs are + // UUIDs as standardized by + // [ISO/IEC 9834-8 and ITU-T + // X.667](https://www.itu.int/ITU-T/studygroups/com17/oid.html). + // Which states: + // + // > If generated according to one of the mechanisms defined in Rec. + // ITU-T X.667 | ISO/IEC 9834-8, a UUID is either guaranteed to be + // different from all other UUIDs generated before 3603 A.D., or is + // extremely likely to be different (depending on the mechanism chosen). + // + // Therefore, UIDs between clusters should be extremely unlikely to + // conflict. + K8SClusterUIDKey = attribute.Key("k8s.cluster.uid") + + // K8SContainerNameKey is the attribute Key conforming to the + // "k8s.container.name" semantic conventions. It represents the name of the + // Container from Pod specification, must be unique within a Pod. Container + // runtime usually uses different globally unique name (`container.name`). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'redis' + K8SContainerNameKey = attribute.Key("k8s.container.name") + + // K8SContainerRestartCountKey is the attribute Key conforming to the + // "k8s.container.restart_count" semantic conventions. It represents the + // number of times the container was restarted. This attribute can be used + // to identify a particular container (running or stopped) within a + // container spec. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 0, 2 + K8SContainerRestartCountKey = attribute.Key("k8s.container.restart_count") + + // K8SCronJobNameKey is the attribute Key conforming to the + // "k8s.cronjob.name" semantic conventions. It represents the name of the + // CronJob. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry' + K8SCronJobNameKey = attribute.Key("k8s.cronjob.name") + + // K8SCronJobUIDKey is the attribute Key conforming to the + // "k8s.cronjob.uid" semantic conventions. It represents the UID of the + // CronJob. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + K8SCronJobUIDKey = attribute.Key("k8s.cronjob.uid") + + // K8SDaemonSetNameKey is the attribute Key conforming to the + // "k8s.daemonset.name" semantic conventions. It represents the name of the + // DaemonSet. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry' + K8SDaemonSetNameKey = attribute.Key("k8s.daemonset.name") + + // K8SDaemonSetUIDKey is the attribute Key conforming to the + // "k8s.daemonset.uid" semantic conventions. It represents the UID of the + // DaemonSet. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + K8SDaemonSetUIDKey = attribute.Key("k8s.daemonset.uid") + + // K8SDeploymentNameKey is the attribute Key conforming to the + // "k8s.deployment.name" semantic conventions. It represents the name of + // the Deployment. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry' + K8SDeploymentNameKey = attribute.Key("k8s.deployment.name") + + // K8SDeploymentUIDKey is the attribute Key conforming to the + // "k8s.deployment.uid" semantic conventions. It represents the UID of the + // Deployment. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + K8SDeploymentUIDKey = attribute.Key("k8s.deployment.uid") + + // K8SJobNameKey is the attribute Key conforming to the "k8s.job.name" + // semantic conventions. It represents the name of the Job. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry' + K8SJobNameKey = attribute.Key("k8s.job.name") + + // K8SJobUIDKey is the attribute Key conforming to the "k8s.job.uid" + // semantic conventions. It represents the UID of the Job. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + K8SJobUIDKey = attribute.Key("k8s.job.uid") + + // K8SNamespaceNameKey is the attribute Key conforming to the + // "k8s.namespace.name" semantic conventions. It represents the name of the + // namespace that the pod is running in. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'default' + K8SNamespaceNameKey = attribute.Key("k8s.namespace.name") + + // K8SNodeNameKey is the attribute Key conforming to the "k8s.node.name" + // semantic conventions. It represents the name of the Node. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'node-1' + K8SNodeNameKey = attribute.Key("k8s.node.name") + + // K8SNodeUIDKey is the attribute Key conforming to the "k8s.node.uid" + // semantic conventions. It represents the UID of the Node. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '1eb3a0c6-0477-4080-a9cb-0cb7db65c6a2' + K8SNodeUIDKey = attribute.Key("k8s.node.uid") + + // K8SPodNameKey is the attribute Key conforming to the "k8s.pod.name" + // semantic conventions. It represents the name of the Pod. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry-pod-autoconf' + K8SPodNameKey = attribute.Key("k8s.pod.name") + + // K8SPodUIDKey is the attribute Key conforming to the "k8s.pod.uid" + // semantic conventions. It represents the UID of the Pod. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + K8SPodUIDKey = attribute.Key("k8s.pod.uid") + + // K8SReplicaSetNameKey is the attribute Key conforming to the + // "k8s.replicaset.name" semantic conventions. It represents the name of + // the ReplicaSet. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry' + K8SReplicaSetNameKey = attribute.Key("k8s.replicaset.name") + + // K8SReplicaSetUIDKey is the attribute Key conforming to the + // "k8s.replicaset.uid" semantic conventions. It represents the UID of the + // ReplicaSet. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + K8SReplicaSetUIDKey = attribute.Key("k8s.replicaset.uid") + + // K8SStatefulSetNameKey is the attribute Key conforming to the + // "k8s.statefulset.name" semantic conventions. It represents the name of + // the StatefulSet. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry' + K8SStatefulSetNameKey = attribute.Key("k8s.statefulset.name") + + // K8SStatefulSetUIDKey is the attribute Key conforming to the + // "k8s.statefulset.uid" semantic conventions. It represents the UID of the + // StatefulSet. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '275ecb36-5aa8-4c2a-9c47-d8bb681b9aff' + K8SStatefulSetUIDKey = attribute.Key("k8s.statefulset.uid") +) + +// K8SClusterName returns an attribute KeyValue conforming to the +// "k8s.cluster.name" semantic conventions. It represents the name of the +// cluster. +func K8SClusterName(val string) attribute.KeyValue { + return K8SClusterNameKey.String(val) +} + +// K8SClusterUID returns an attribute KeyValue conforming to the +// "k8s.cluster.uid" semantic conventions. It represents a pseudo-ID for the +// cluster, set to the UID of the `kube-system` namespace. +func K8SClusterUID(val string) attribute.KeyValue { + return K8SClusterUIDKey.String(val) +} + +// K8SContainerName returns an attribute KeyValue conforming to the +// "k8s.container.name" semantic conventions. It represents the name of the +// Container from Pod specification, must be unique within a Pod. Container +// runtime usually uses different globally unique name (`container.name`). +func K8SContainerName(val string) attribute.KeyValue { + return K8SContainerNameKey.String(val) +} + +// K8SContainerRestartCount returns an attribute KeyValue conforming to the +// "k8s.container.restart_count" semantic conventions. It represents the number +// of times the container was restarted. This attribute can be used to identify +// a particular container (running or stopped) within a container spec. +func K8SContainerRestartCount(val int) attribute.KeyValue { + return K8SContainerRestartCountKey.Int(val) +} + +// K8SCronJobName returns an attribute KeyValue conforming to the +// "k8s.cronjob.name" semantic conventions. It represents the name of the +// CronJob. +func K8SCronJobName(val string) attribute.KeyValue { + return K8SCronJobNameKey.String(val) +} + +// K8SCronJobUID returns an attribute KeyValue conforming to the +// "k8s.cronjob.uid" semantic conventions. It represents the UID of the +// CronJob. +func K8SCronJobUID(val string) attribute.KeyValue { + return K8SCronJobUIDKey.String(val) +} + +// K8SDaemonSetName returns an attribute KeyValue conforming to the +// "k8s.daemonset.name" semantic conventions. It represents the name of the +// DaemonSet. +func K8SDaemonSetName(val string) attribute.KeyValue { + return K8SDaemonSetNameKey.String(val) +} + +// K8SDaemonSetUID returns an attribute KeyValue conforming to the +// "k8s.daemonset.uid" semantic conventions. It represents the UID of the +// DaemonSet. +func K8SDaemonSetUID(val string) attribute.KeyValue { + return K8SDaemonSetUIDKey.String(val) +} + +// K8SDeploymentName returns an attribute KeyValue conforming to the +// "k8s.deployment.name" semantic conventions. It represents the name of the +// Deployment. +func K8SDeploymentName(val string) attribute.KeyValue { + return K8SDeploymentNameKey.String(val) +} + +// K8SDeploymentUID returns an attribute KeyValue conforming to the +// "k8s.deployment.uid" semantic conventions. It represents the UID of the +// Deployment. +func K8SDeploymentUID(val string) attribute.KeyValue { + return K8SDeploymentUIDKey.String(val) +} + +// K8SJobName returns an attribute KeyValue conforming to the "k8s.job.name" +// semantic conventions. It represents the name of the Job. +func K8SJobName(val string) attribute.KeyValue { + return K8SJobNameKey.String(val) +} + +// K8SJobUID returns an attribute KeyValue conforming to the "k8s.job.uid" +// semantic conventions. It represents the UID of the Job. +func K8SJobUID(val string) attribute.KeyValue { + return K8SJobUIDKey.String(val) +} + +// K8SNamespaceName returns an attribute KeyValue conforming to the +// "k8s.namespace.name" semantic conventions. It represents the name of the +// namespace that the pod is running in. +func K8SNamespaceName(val string) attribute.KeyValue { + return K8SNamespaceNameKey.String(val) +} + +// K8SNodeName returns an attribute KeyValue conforming to the +// "k8s.node.name" semantic conventions. It represents the name of the Node. +func K8SNodeName(val string) attribute.KeyValue { + return K8SNodeNameKey.String(val) +} + +// K8SNodeUID returns an attribute KeyValue conforming to the "k8s.node.uid" +// semantic conventions. It represents the UID of the Node. +func K8SNodeUID(val string) attribute.KeyValue { + return K8SNodeUIDKey.String(val) +} + +// K8SPodName returns an attribute KeyValue conforming to the "k8s.pod.name" +// semantic conventions. It represents the name of the Pod. +func K8SPodName(val string) attribute.KeyValue { + return K8SPodNameKey.String(val) +} + +// K8SPodUID returns an attribute KeyValue conforming to the "k8s.pod.uid" +// semantic conventions. It represents the UID of the Pod. +func K8SPodUID(val string) attribute.KeyValue { + return K8SPodUIDKey.String(val) +} + +// K8SReplicaSetName returns an attribute KeyValue conforming to the +// "k8s.replicaset.name" semantic conventions. It represents the name of the +// ReplicaSet. +func K8SReplicaSetName(val string) attribute.KeyValue { + return K8SReplicaSetNameKey.String(val) +} + +// K8SReplicaSetUID returns an attribute KeyValue conforming to the +// "k8s.replicaset.uid" semantic conventions. It represents the UID of the +// ReplicaSet. +func K8SReplicaSetUID(val string) attribute.KeyValue { + return K8SReplicaSetUIDKey.String(val) +} + +// K8SStatefulSetName returns an attribute KeyValue conforming to the +// "k8s.statefulset.name" semantic conventions. It represents the name of the +// StatefulSet. +func K8SStatefulSetName(val string) attribute.KeyValue { + return K8SStatefulSetNameKey.String(val) +} + +// K8SStatefulSetUID returns an attribute KeyValue conforming to the +// "k8s.statefulset.uid" semantic conventions. It represents the UID of the +// StatefulSet. +func K8SStatefulSetUID(val string) attribute.KeyValue { + return K8SStatefulSetUIDKey.String(val) +} + +// An OCI image manifest. +const ( + // OciManifestDigestKey is the attribute Key conforming to the + // "oci.manifest.digest" semantic conventions. It represents the digest of + // the OCI image manifest. For container images specifically is the digest + // by which the container image is known. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // 'sha256:e4ca62c0d62f3e886e684806dfe9d4e0cda60d54986898173c1083856cfda0f4' + // Note: Follows [OCI Image Manifest + // Specification](https://github.com/opencontainers/image-spec/blob/main/manifest.md), + // and specifically the [Digest + // property](https://github.com/opencontainers/image-spec/blob/main/descriptor.md#digests). + // An example can be found in [Example Image + // Manifest](https://docs.docker.com/registry/spec/manifest-v2-2/#example-image-manifest). + OciManifestDigestKey = attribute.Key("oci.manifest.digest") +) + +// OciManifestDigest returns an attribute KeyValue conforming to the +// "oci.manifest.digest" semantic conventions. It represents the digest of the +// OCI image manifest. For container images specifically is the digest by which +// the container image is known. +func OciManifestDigest(val string) attribute.KeyValue { + return OciManifestDigestKey.String(val) +} + +// The operating system (OS) on which the process represented by this resource +// is running. +const ( + // OSBuildIDKey is the attribute Key conforming to the "os.build_id" + // semantic conventions. It represents the unique identifier for a + // particular build or compilation of the operating system. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'TQ3C.230805.001.B2', '20E247', '22621' + OSBuildIDKey = attribute.Key("os.build_id") + + // OSDescriptionKey is the attribute Key conforming to the "os.description" + // semantic conventions. It represents the human readable (not intended to + // be parsed) OS version information, like e.g. reported by `ver` or + // `lsb_release -a` commands. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Microsoft Windows [Version 10.0.18363.778]', 'Ubuntu 18.04.1 + // LTS' + OSDescriptionKey = attribute.Key("os.description") + + // OSNameKey is the attribute Key conforming to the "os.name" semantic + // conventions. It represents the human readable operating system name. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'iOS', 'Android', 'Ubuntu' + OSNameKey = attribute.Key("os.name") + + // OSTypeKey is the attribute Key conforming to the "os.type" semantic + // conventions. It represents the operating system type. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + OSTypeKey = attribute.Key("os.type") + + // OSVersionKey is the attribute Key conforming to the "os.version" + // semantic conventions. It represents the version string of the operating + // system as defined in [Version + // Attributes](/docs/resource/README.md#version-attributes). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '14.2.1', '18.04.1' + OSVersionKey = attribute.Key("os.version") +) + +var ( + // Microsoft Windows + OSTypeWindows = OSTypeKey.String("windows") + // Linux + OSTypeLinux = OSTypeKey.String("linux") + // Apple Darwin + OSTypeDarwin = OSTypeKey.String("darwin") + // FreeBSD + OSTypeFreeBSD = OSTypeKey.String("freebsd") + // NetBSD + OSTypeNetBSD = OSTypeKey.String("netbsd") + // OpenBSD + OSTypeOpenBSD = OSTypeKey.String("openbsd") + // DragonFly BSD + OSTypeDragonflyBSD = OSTypeKey.String("dragonflybsd") + // HP-UX (Hewlett Packard Unix) + OSTypeHPUX = OSTypeKey.String("hpux") + // AIX (Advanced Interactive eXecutive) + OSTypeAIX = OSTypeKey.String("aix") + // SunOS, Oracle Solaris + OSTypeSolaris = OSTypeKey.String("solaris") + // IBM z/OS + OSTypeZOS = OSTypeKey.String("z_os") +) + +// OSBuildID returns an attribute KeyValue conforming to the "os.build_id" +// semantic conventions. It represents the unique identifier for a particular +// build or compilation of the operating system. +func OSBuildID(val string) attribute.KeyValue { + return OSBuildIDKey.String(val) +} + +// OSDescription returns an attribute KeyValue conforming to the +// "os.description" semantic conventions. It represents the human readable (not +// intended to be parsed) OS version information, like e.g. reported by `ver` +// or `lsb_release -a` commands. +func OSDescription(val string) attribute.KeyValue { + return OSDescriptionKey.String(val) +} + +// OSName returns an attribute KeyValue conforming to the "os.name" semantic +// conventions. It represents the human readable operating system name. +func OSName(val string) attribute.KeyValue { + return OSNameKey.String(val) +} + +// OSVersion returns an attribute KeyValue conforming to the "os.version" +// semantic conventions. It represents the version string of the operating +// system as defined in [Version +// Attributes](/docs/resource/README.md#version-attributes). +func OSVersion(val string) attribute.KeyValue { + return OSVersionKey.String(val) +} + +// An operating system process. +const ( + // ProcessCommandKey is the attribute Key conforming to the + // "process.command" semantic conventions. It represents the command used + // to launch the process (i.e. the command name). On Linux based systems, + // can be set to the zeroth string in `proc/[pid]/cmdline`. On Windows, can + // be set to the first parameter extracted from `GetCommandLineW`. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'cmd/otelcol' + ProcessCommandKey = attribute.Key("process.command") + + // ProcessCommandArgsKey is the attribute Key conforming to the + // "process.command_args" semantic conventions. It represents the all the + // command arguments (including the command/executable itself) as received + // by the process. On Linux-based systems (and some other Unixoid systems + // supporting procfs), can be set according to the list of null-delimited + // strings extracted from `proc/[pid]/cmdline`. For libc-based executables, + // this would be the full argv vector passed to `main`. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'cmd/otecol', '--config=config.yaml' + ProcessCommandArgsKey = attribute.Key("process.command_args") + + // ProcessCommandLineKey is the attribute Key conforming to the + // "process.command_line" semantic conventions. It represents the full + // command used to launch the process as a single string representing the + // full command. On Windows, can be set to the result of `GetCommandLineW`. + // Do not set this if you have to assemble it just for monitoring; use + // `process.command_args` instead. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'C:\\cmd\\otecol --config="my directory\\config.yaml"' + ProcessCommandLineKey = attribute.Key("process.command_line") + + // ProcessExecutableNameKey is the attribute Key conforming to the + // "process.executable.name" semantic conventions. It represents the name + // of the process executable. On Linux based systems, can be set to the + // `Name` in `proc/[pid]/status`. On Windows, can be set to the base name + // of `GetProcessImageFileNameW`. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'otelcol' + ProcessExecutableNameKey = attribute.Key("process.executable.name") + + // ProcessExecutablePathKey is the attribute Key conforming to the + // "process.executable.path" semantic conventions. It represents the full + // path to the process executable. On Linux based systems, can be set to + // the target of `proc/[pid]/exe`. On Windows, can be set to the result of + // `GetProcessImageFileNameW`. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '/usr/bin/cmd/otelcol' + ProcessExecutablePathKey = attribute.Key("process.executable.path") + + // ProcessOwnerKey is the attribute Key conforming to the "process.owner" + // semantic conventions. It represents the username of the user that owns + // the process. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'root' + ProcessOwnerKey = attribute.Key("process.owner") + + // ProcessParentPIDKey is the attribute Key conforming to the + // "process.parent_pid" semantic conventions. It represents the parent + // Process identifier (PPID). + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 111 + ProcessParentPIDKey = attribute.Key("process.parent_pid") + + // ProcessPIDKey is the attribute Key conforming to the "process.pid" + // semantic conventions. It represents the process identifier (PID). + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 1234 + ProcessPIDKey = attribute.Key("process.pid") + + // ProcessRuntimeDescriptionKey is the attribute Key conforming to the + // "process.runtime.description" semantic conventions. It represents an + // additional description about the runtime of the process, for example a + // specific vendor customization of the runtime environment. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Eclipse OpenJ9 Eclipse OpenJ9 VM openj9-0.21.0' + ProcessRuntimeDescriptionKey = attribute.Key("process.runtime.description") + + // ProcessRuntimeNameKey is the attribute Key conforming to the + // "process.runtime.name" semantic conventions. It represents the name of + // the runtime of this process. For compiled native binaries, this SHOULD + // be the name of the compiler. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'OpenJDK Runtime Environment' + ProcessRuntimeNameKey = attribute.Key("process.runtime.name") + + // ProcessRuntimeVersionKey is the attribute Key conforming to the + // "process.runtime.version" semantic conventions. It represents the + // version of the runtime of this process, as returned by the runtime + // without modification. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '14.0.2' + ProcessRuntimeVersionKey = attribute.Key("process.runtime.version") +) + +// ProcessCommand returns an attribute KeyValue conforming to the +// "process.command" semantic conventions. It represents the command used to +// launch the process (i.e. the command name). On Linux based systems, can be +// set to the zeroth string in `proc/[pid]/cmdline`. On Windows, can be set to +// the first parameter extracted from `GetCommandLineW`. +func ProcessCommand(val string) attribute.KeyValue { + return ProcessCommandKey.String(val) +} + +// ProcessCommandArgs returns an attribute KeyValue conforming to the +// "process.command_args" semantic conventions. It represents the all the +// command arguments (including the command/executable itself) as received by +// the process. On Linux-based systems (and some other Unixoid systems +// supporting procfs), can be set according to the list of null-delimited +// strings extracted from `proc/[pid]/cmdline`. For libc-based executables, +// this would be the full argv vector passed to `main`. +func ProcessCommandArgs(val ...string) attribute.KeyValue { + return ProcessCommandArgsKey.StringSlice(val) +} + +// ProcessCommandLine returns an attribute KeyValue conforming to the +// "process.command_line" semantic conventions. It represents the full command +// used to launch the process as a single string representing the full command. +// On Windows, can be set to the result of `GetCommandLineW`. Do not set this +// if you have to assemble it just for monitoring; use `process.command_args` +// instead. +func ProcessCommandLine(val string) attribute.KeyValue { + return ProcessCommandLineKey.String(val) +} + +// ProcessExecutableName returns an attribute KeyValue conforming to the +// "process.executable.name" semantic conventions. It represents the name of +// the process executable. On Linux based systems, can be set to the `Name` in +// `proc/[pid]/status`. On Windows, can be set to the base name of +// `GetProcessImageFileNameW`. +func ProcessExecutableName(val string) attribute.KeyValue { + return ProcessExecutableNameKey.String(val) +} + +// ProcessExecutablePath returns an attribute KeyValue conforming to the +// "process.executable.path" semantic conventions. It represents the full path +// to the process executable. On Linux based systems, can be set to the target +// of `proc/[pid]/exe`. On Windows, can be set to the result of +// `GetProcessImageFileNameW`. +func ProcessExecutablePath(val string) attribute.KeyValue { + return ProcessExecutablePathKey.String(val) +} + +// ProcessOwner returns an attribute KeyValue conforming to the +// "process.owner" semantic conventions. It represents the username of the user +// that owns the process. +func ProcessOwner(val string) attribute.KeyValue { + return ProcessOwnerKey.String(val) +} + +// ProcessParentPID returns an attribute KeyValue conforming to the +// "process.parent_pid" semantic conventions. It represents the parent Process +// identifier (PPID). +func ProcessParentPID(val int) attribute.KeyValue { + return ProcessParentPIDKey.Int(val) +} + +// ProcessPID returns an attribute KeyValue conforming to the "process.pid" +// semantic conventions. It represents the process identifier (PID). +func ProcessPID(val int) attribute.KeyValue { + return ProcessPIDKey.Int(val) +} + +// ProcessRuntimeDescription returns an attribute KeyValue conforming to the +// "process.runtime.description" semantic conventions. It represents an +// additional description about the runtime of the process, for example a +// specific vendor customization of the runtime environment. +func ProcessRuntimeDescription(val string) attribute.KeyValue { + return ProcessRuntimeDescriptionKey.String(val) +} + +// ProcessRuntimeName returns an attribute KeyValue conforming to the +// "process.runtime.name" semantic conventions. It represents the name of the +// runtime of this process. For compiled native binaries, this SHOULD be the +// name of the compiler. +func ProcessRuntimeName(val string) attribute.KeyValue { + return ProcessRuntimeNameKey.String(val) +} + +// ProcessRuntimeVersion returns an attribute KeyValue conforming to the +// "process.runtime.version" semantic conventions. It represents the version of +// the runtime of this process, as returned by the runtime without +// modification. +func ProcessRuntimeVersion(val string) attribute.KeyValue { + return ProcessRuntimeVersionKey.String(val) +} + +// The Android platform on which the Android application is running. +const ( + // AndroidOSAPILevelKey is the attribute Key conforming to the + // "android.os.api_level" semantic conventions. It represents the uniquely + // identifies the framework API revision offered by a version + // (`os.version`) of the android operating system. More information can be + // found + // [here](https://developer.android.com/guide/topics/manifest/uses-sdk-element#APILevels). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '33', '32' + AndroidOSAPILevelKey = attribute.Key("android.os.api_level") +) + +// AndroidOSAPILevel returns an attribute KeyValue conforming to the +// "android.os.api_level" semantic conventions. It represents the uniquely +// identifies the framework API revision offered by a version (`os.version`) of +// the android operating system. More information can be found +// [here](https://developer.android.com/guide/topics/manifest/uses-sdk-element#APILevels). +func AndroidOSAPILevel(val string) attribute.KeyValue { + return AndroidOSAPILevelKey.String(val) +} + +// The web browser in which the application represented by the resource is +// running. The `browser.*` attributes MUST be used only for resources that +// represent applications running in a web browser (regardless of whether +// running on a mobile or desktop device). +const ( + // BrowserBrandsKey is the attribute Key conforming to the "browser.brands" + // semantic conventions. It represents the array of brand name and version + // separated by a space + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: ' Not A;Brand 99', 'Chromium 99', 'Chrome 99' + // Note: This value is intended to be taken from the [UA client hints + // API](https://wicg.github.io/ua-client-hints/#interface) + // (`navigator.userAgentData.brands`). + BrowserBrandsKey = attribute.Key("browser.brands") + + // BrowserLanguageKey is the attribute Key conforming to the + // "browser.language" semantic conventions. It represents the preferred + // language of the user using the browser + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'en', 'en-US', 'fr', 'fr-FR' + // Note: This value is intended to be taken from the Navigator API + // `navigator.language`. + BrowserLanguageKey = attribute.Key("browser.language") + + // BrowserMobileKey is the attribute Key conforming to the "browser.mobile" + // semantic conventions. It represents a boolean that is true if the + // browser is running on a mobile device + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + // Note: This value is intended to be taken from the [UA client hints + // API](https://wicg.github.io/ua-client-hints/#interface) + // (`navigator.userAgentData.mobile`). If unavailable, this attribute + // SHOULD be left unset. + BrowserMobileKey = attribute.Key("browser.mobile") + + // BrowserPlatformKey is the attribute Key conforming to the + // "browser.platform" semantic conventions. It represents the platform on + // which the browser is running + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Windows', 'macOS', 'Android' + // Note: This value is intended to be taken from the [UA client hints + // API](https://wicg.github.io/ua-client-hints/#interface) + // (`navigator.userAgentData.platform`). If unavailable, the legacy + // `navigator.platform` API SHOULD NOT be used instead and this attribute + // SHOULD be left unset in order for the values to be consistent. + // The list of possible values is defined in the [W3C User-Agent Client + // Hints + // specification](https://wicg.github.io/ua-client-hints/#sec-ch-ua-platform). + // Note that some (but not all) of these values can overlap with values in + // the [`os.type` and `os.name` attributes](./os.md). However, for + // consistency, the values in the `browser.platform` attribute should + // capture the exact value that the user agent provides. + BrowserPlatformKey = attribute.Key("browser.platform") +) + +// BrowserBrands returns an attribute KeyValue conforming to the +// "browser.brands" semantic conventions. It represents the array of brand name +// and version separated by a space +func BrowserBrands(val ...string) attribute.KeyValue { + return BrowserBrandsKey.StringSlice(val) +} + +// BrowserLanguage returns an attribute KeyValue conforming to the +// "browser.language" semantic conventions. It represents the preferred +// language of the user using the browser +func BrowserLanguage(val string) attribute.KeyValue { + return BrowserLanguageKey.String(val) +} + +// BrowserMobile returns an attribute KeyValue conforming to the +// "browser.mobile" semantic conventions. It represents a boolean that is true +// if the browser is running on a mobile device +func BrowserMobile(val bool) attribute.KeyValue { + return BrowserMobileKey.Bool(val) +} + +// BrowserPlatform returns an attribute KeyValue conforming to the +// "browser.platform" semantic conventions. It represents the platform on which +// the browser is running +func BrowserPlatform(val string) attribute.KeyValue { + return BrowserPlatformKey.String(val) +} + +// Resources used by AWS Elastic Container Service (ECS). +const ( + // AWSECSClusterARNKey is the attribute Key conforming to the + // "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an + // [ECS + // cluster](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' + AWSECSClusterARNKey = attribute.Key("aws.ecs.cluster.arn") + + // AWSECSContainerARNKey is the attribute Key conforming to the + // "aws.ecs.container.arn" semantic conventions. It represents the Amazon + // Resource Name (ARN) of an [ECS container + // instance](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // 'arn:aws:ecs:us-west-1:123456789123:container/32624152-9086-4f0e-acae-1a75b14fe4d9' + AWSECSContainerARNKey = attribute.Key("aws.ecs.container.arn") + + // AWSECSLaunchtypeKey is the attribute Key conforming to the + // "aws.ecs.launchtype" semantic conventions. It represents the [launch + // type](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_types.html) + // for an ECS task. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + AWSECSLaunchtypeKey = attribute.Key("aws.ecs.launchtype") + + // AWSECSTaskARNKey is the attribute Key conforming to the + // "aws.ecs.task.arn" semantic conventions. It represents the ARN of an + // [ECS task + // definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // 'arn:aws:ecs:us-west-1:123456789123:task/10838bed-421f-43ef-870a-f43feacbbb5b' + AWSECSTaskARNKey = attribute.Key("aws.ecs.task.arn") + + // AWSECSTaskFamilyKey is the attribute Key conforming to the + // "aws.ecs.task.family" semantic conventions. It represents the task + // definition family this task definition is a member of. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'opentelemetry-family' + AWSECSTaskFamilyKey = attribute.Key("aws.ecs.task.family") + + // AWSECSTaskRevisionKey is the attribute Key conforming to the + // "aws.ecs.task.revision" semantic conventions. It represents the revision + // for this task definition. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '8', '26' + AWSECSTaskRevisionKey = attribute.Key("aws.ecs.task.revision") +) + +var ( + // ec2 + AWSECSLaunchtypeEC2 = AWSECSLaunchtypeKey.String("ec2") + // fargate + AWSECSLaunchtypeFargate = AWSECSLaunchtypeKey.String("fargate") +) + +// AWSECSClusterARN returns an attribute KeyValue conforming to the +// "aws.ecs.cluster.arn" semantic conventions. It represents the ARN of an [ECS +// cluster](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html). +func AWSECSClusterARN(val string) attribute.KeyValue { + return AWSECSClusterARNKey.String(val) +} + +// AWSECSContainerARN returns an attribute KeyValue conforming to the +// "aws.ecs.container.arn" semantic conventions. It represents the Amazon +// Resource Name (ARN) of an [ECS container +// instance](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ECS_instances.html). +func AWSECSContainerARN(val string) attribute.KeyValue { + return AWSECSContainerARNKey.String(val) +} + +// AWSECSTaskARN returns an attribute KeyValue conforming to the +// "aws.ecs.task.arn" semantic conventions. It represents the ARN of an [ECS +// task +// definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html). +func AWSECSTaskARN(val string) attribute.KeyValue { + return AWSECSTaskARNKey.String(val) +} + +// AWSECSTaskFamily returns an attribute KeyValue conforming to the +// "aws.ecs.task.family" semantic conventions. It represents the task +// definition family this task definition is a member of. +func AWSECSTaskFamily(val string) attribute.KeyValue { + return AWSECSTaskFamilyKey.String(val) +} + +// AWSECSTaskRevision returns an attribute KeyValue conforming to the +// "aws.ecs.task.revision" semantic conventions. It represents the revision for +// this task definition. +func AWSECSTaskRevision(val string) attribute.KeyValue { + return AWSECSTaskRevisionKey.String(val) +} + +// Resources used by AWS Elastic Kubernetes Service (EKS). +const ( + // AWSEKSClusterARNKey is the attribute Key conforming to the + // "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an + // EKS cluster. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'arn:aws:ecs:us-west-2:123456789123:cluster/my-cluster' + AWSEKSClusterARNKey = attribute.Key("aws.eks.cluster.arn") +) + +// AWSEKSClusterARN returns an attribute KeyValue conforming to the +// "aws.eks.cluster.arn" semantic conventions. It represents the ARN of an EKS +// cluster. +func AWSEKSClusterARN(val string) attribute.KeyValue { + return AWSEKSClusterARNKey.String(val) +} + +// Resources specific to Amazon Web Services. +const ( + // AWSLogGroupARNsKey is the attribute Key conforming to the + // "aws.log.group.arns" semantic conventions. It represents the Amazon + // Resource Name(s) (ARN) of the AWS log group(s). + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:*' + // Note: See the [log group ARN format + // documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format). + AWSLogGroupARNsKey = attribute.Key("aws.log.group.arns") + + // AWSLogGroupNamesKey is the attribute Key conforming to the + // "aws.log.group.names" semantic conventions. It represents the name(s) of + // the AWS log group(s) an application is writing to. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: '/aws/lambda/my-function', 'opentelemetry-service' + // Note: Multiple log groups must be supported for cases like + // multi-container applications, where a single application has sidecar + // containers, and each write to their own log group. + AWSLogGroupNamesKey = attribute.Key("aws.log.group.names") + + // AWSLogStreamARNsKey is the attribute Key conforming to the + // "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of + // the AWS log stream(s). + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // 'arn:aws:logs:us-west-1:123456789012:log-group:/aws/my/group:log-stream:logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' + // Note: See the [log stream ARN format + // documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/iam-access-control-overview-cwl.html#CWL_ARN_Format). + // One log group can contain several log streams, so these ARNs necessarily + // identify both a log group and a log stream. + AWSLogStreamARNsKey = attribute.Key("aws.log.stream.arns") + + // AWSLogStreamNamesKey is the attribute Key conforming to the + // "aws.log.stream.names" semantic conventions. It represents the name(s) + // of the AWS log stream(s) an application is writing to. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'logs/main/10838bed-421f-43ef-870a-f43feacbbb5b' + AWSLogStreamNamesKey = attribute.Key("aws.log.stream.names") +) + +// AWSLogGroupARNs returns an attribute KeyValue conforming to the +// "aws.log.group.arns" semantic conventions. It represents the Amazon Resource +// Name(s) (ARN) of the AWS log group(s). +func AWSLogGroupARNs(val ...string) attribute.KeyValue { + return AWSLogGroupARNsKey.StringSlice(val) +} + +// AWSLogGroupNames returns an attribute KeyValue conforming to the +// "aws.log.group.names" semantic conventions. It represents the name(s) of the +// AWS log group(s) an application is writing to. +func AWSLogGroupNames(val ...string) attribute.KeyValue { + return AWSLogGroupNamesKey.StringSlice(val) +} + +// AWSLogStreamARNs returns an attribute KeyValue conforming to the +// "aws.log.stream.arns" semantic conventions. It represents the ARN(s) of the +// AWS log stream(s). +func AWSLogStreamARNs(val ...string) attribute.KeyValue { + return AWSLogStreamARNsKey.StringSlice(val) +} + +// AWSLogStreamNames returns an attribute KeyValue conforming to the +// "aws.log.stream.names" semantic conventions. It represents the name(s) of +// the AWS log stream(s) an application is writing to. +func AWSLogStreamNames(val ...string) attribute.KeyValue { + return AWSLogStreamNamesKey.StringSlice(val) +} + +// Resource used by Google Cloud Run. +const ( + // GCPCloudRunJobExecutionKey is the attribute Key conforming to the + // "gcp.cloud_run.job.execution" semantic conventions. It represents the + // name of the Cloud Run + // [execution](https://cloud.google.com/run/docs/managing/job-executions) + // being run for the Job, as set by the + // [`CLOUD_RUN_EXECUTION`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars) + // environment variable. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'job-name-xxxx', 'sample-job-mdw84' + GCPCloudRunJobExecutionKey = attribute.Key("gcp.cloud_run.job.execution") + + // GCPCloudRunJobTaskIndexKey is the attribute Key conforming to the + // "gcp.cloud_run.job.task_index" semantic conventions. It represents the + // index for a task within an execution as provided by the + // [`CLOUD_RUN_TASK_INDEX`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars) + // environment variable. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 0, 1 + GCPCloudRunJobTaskIndexKey = attribute.Key("gcp.cloud_run.job.task_index") +) + +// GCPCloudRunJobExecution returns an attribute KeyValue conforming to the +// "gcp.cloud_run.job.execution" semantic conventions. It represents the name +// of the Cloud Run +// [execution](https://cloud.google.com/run/docs/managing/job-executions) being +// run for the Job, as set by the +// [`CLOUD_RUN_EXECUTION`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars) +// environment variable. +func GCPCloudRunJobExecution(val string) attribute.KeyValue { + return GCPCloudRunJobExecutionKey.String(val) +} + +// GCPCloudRunJobTaskIndex returns an attribute KeyValue conforming to the +// "gcp.cloud_run.job.task_index" semantic conventions. It represents the index +// for a task within an execution as provided by the +// [`CLOUD_RUN_TASK_INDEX`](https://cloud.google.com/run/docs/container-contract#jobs-env-vars) +// environment variable. +func GCPCloudRunJobTaskIndex(val int) attribute.KeyValue { + return GCPCloudRunJobTaskIndexKey.Int(val) +} + +// Resources used by Google Compute Engine (GCE). +const ( + // GCPGceInstanceHostnameKey is the attribute Key conforming to the + // "gcp.gce.instance.hostname" semantic conventions. It represents the + // hostname of a GCE instance. This is the full value of the default or + // [custom + // hostname](https://cloud.google.com/compute/docs/instances/custom-hostname-vm). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'my-host1234.example.com', + // 'sample-vm.us-west1-b.c.my-project.internal' + GCPGceInstanceHostnameKey = attribute.Key("gcp.gce.instance.hostname") + + // GCPGceInstanceNameKey is the attribute Key conforming to the + // "gcp.gce.instance.name" semantic conventions. It represents the instance + // name of a GCE instance. This is the value provided by `host.name`, the + // visible name of the instance in the Cloud Console UI, and the prefix for + // the default hostname of the instance as defined by the [default internal + // DNS + // name](https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'instance-1', 'my-vm-name' + GCPGceInstanceNameKey = attribute.Key("gcp.gce.instance.name") +) + +// GCPGceInstanceHostname returns an attribute KeyValue conforming to the +// "gcp.gce.instance.hostname" semantic conventions. It represents the hostname +// of a GCE instance. This is the full value of the default or [custom +// hostname](https://cloud.google.com/compute/docs/instances/custom-hostname-vm). +func GCPGceInstanceHostname(val string) attribute.KeyValue { + return GCPGceInstanceHostnameKey.String(val) +} + +// GCPGceInstanceName returns an attribute KeyValue conforming to the +// "gcp.gce.instance.name" semantic conventions. It represents the instance +// name of a GCE instance. This is the value provided by `host.name`, the +// visible name of the instance in the Cloud Console UI, and the prefix for the +// default hostname of the instance as defined by the [default internal DNS +// name](https://cloud.google.com/compute/docs/internal-dns#instance-fully-qualified-domain-names). +func GCPGceInstanceName(val string) attribute.KeyValue { + return GCPGceInstanceNameKey.String(val) +} + +// Heroku dyno metadata +const ( + // HerokuAppIDKey is the attribute Key conforming to the "heroku.app.id" + // semantic conventions. It represents the unique identifier for the + // application + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2daa2797-e42b-4624-9322-ec3f968df4da' + HerokuAppIDKey = attribute.Key("heroku.app.id") + + // HerokuReleaseCommitKey is the attribute Key conforming to the + // "heroku.release.commit" semantic conventions. It represents the commit + // hash for the current release + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'e6134959463efd8966b20e75b913cafe3f5ec' + HerokuReleaseCommitKey = attribute.Key("heroku.release.commit") + + // HerokuReleaseCreationTimestampKey is the attribute Key conforming to the + // "heroku.release.creation_timestamp" semantic conventions. It represents + // the time and date the release was created + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2022-10-23T18:00:42Z' + HerokuReleaseCreationTimestampKey = attribute.Key("heroku.release.creation_timestamp") +) + +// HerokuAppID returns an attribute KeyValue conforming to the +// "heroku.app.id" semantic conventions. It represents the unique identifier +// for the application +func HerokuAppID(val string) attribute.KeyValue { + return HerokuAppIDKey.String(val) +} + +// HerokuReleaseCommit returns an attribute KeyValue conforming to the +// "heroku.release.commit" semantic conventions. It represents the commit hash +// for the current release +func HerokuReleaseCommit(val string) attribute.KeyValue { + return HerokuReleaseCommitKey.String(val) +} + +// HerokuReleaseCreationTimestamp returns an attribute KeyValue conforming +// to the "heroku.release.creation_timestamp" semantic conventions. It +// represents the time and date the release was created +func HerokuReleaseCreationTimestamp(val string) attribute.KeyValue { + return HerokuReleaseCreationTimestampKey.String(val) +} + +// The software deployment. +const ( + // DeploymentEnvironmentKey is the attribute Key conforming to the + // "deployment.environment" semantic conventions. It represents the name of + // the [deployment + // environment](https://wikipedia.org/wiki/Deployment_environment) (aka + // deployment tier). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'staging', 'production' + // Note: `deployment.environment` does not affect the uniqueness + // constraints defined through + // the `service.namespace`, `service.name` and `service.instance.id` + // resource attributes. + // This implies that resources carrying the following attribute + // combinations MUST be + // considered to be identifying the same service: + // + // * `service.name=frontend`, `deployment.environment=production` + // * `service.name=frontend`, `deployment.environment=staging`. + DeploymentEnvironmentKey = attribute.Key("deployment.environment") +) + +// DeploymentEnvironment returns an attribute KeyValue conforming to the +// "deployment.environment" semantic conventions. It represents the name of the +// [deployment environment](https://wikipedia.org/wiki/Deployment_environment) +// (aka deployment tier). +func DeploymentEnvironment(val string) attribute.KeyValue { + return DeploymentEnvironmentKey.String(val) +} + +// A serverless instance. +const ( + // FaaSInstanceKey is the attribute Key conforming to the "faas.instance" + // semantic conventions. It represents the execution environment ID as a + // string, that will be potentially reused for other invocations to the + // same function/function version. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2021/06/28/[$LATEST]2f399eb14537447da05ab2a2e39309de' + // Note: * **AWS Lambda:** Use the (full) log stream name. + FaaSInstanceKey = attribute.Key("faas.instance") + + // FaaSMaxMemoryKey is the attribute Key conforming to the + // "faas.max_memory" semantic conventions. It represents the amount of + // memory available to the serverless function converted to Bytes. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 134217728 + // Note: It's recommended to set this attribute since e.g. too little + // memory can easily stop a Java AWS Lambda function from working + // correctly. On AWS Lambda, the environment variable + // `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` provides this information (which must + // be multiplied by 1,048,576). + FaaSMaxMemoryKey = attribute.Key("faas.max_memory") + + // FaaSNameKey is the attribute Key conforming to the "faas.name" semantic + // conventions. It represents the name of the single function that this + // runtime instance executes. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'my-function', 'myazurefunctionapp/some-function-name' + // Note: This is the name of the function as configured/deployed on the + // FaaS + // platform and is usually different from the name of the callback + // function (which may be stored in the + // [`code.namespace`/`code.function`](/docs/general/attributes.md#source-code-attributes) + // span attributes). + // + // For some cloud providers, the above definition is ambiguous. The + // following + // definition of function name MUST be used for this attribute + // (and consequently the span name) for the listed cloud + // providers/products: + // + // * **Azure:** The full name `/`, i.e., function app name + // followed by a forward slash followed by the function name (this form + // can also be seen in the resource JSON for the function). + // This means that a span attribute MUST be used, as an Azure function + // app can host multiple functions that would usually share + // a TracerProvider (see also the `cloud.resource_id` attribute). + FaaSNameKey = attribute.Key("faas.name") + + // FaaSVersionKey is the attribute Key conforming to the "faas.version" + // semantic conventions. It represents the immutable version of the + // function being executed. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '26', 'pinkfroid-00002' + // Note: Depending on the cloud provider and platform, use: + // + // * **AWS Lambda:** The [function + // version](https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html) + // (an integer represented as a decimal string). + // * **Google Cloud Run (Services):** The + // [revision](https://cloud.google.com/run/docs/managing/revisions) + // (i.e., the function name plus the revision suffix). + // * **Google Cloud Functions:** The value of the + // [`K_REVISION` environment + // variable](https://cloud.google.com/functions/docs/env-var#runtime_environment_variables_set_automatically). + // * **Azure Functions:** Not applicable. Do not set this attribute. + FaaSVersionKey = attribute.Key("faas.version") +) + +// FaaSInstance returns an attribute KeyValue conforming to the +// "faas.instance" semantic conventions. It represents the execution +// environment ID as a string, that will be potentially reused for other +// invocations to the same function/function version. +func FaaSInstance(val string) attribute.KeyValue { + return FaaSInstanceKey.String(val) +} + +// FaaSMaxMemory returns an attribute KeyValue conforming to the +// "faas.max_memory" semantic conventions. It represents the amount of memory +// available to the serverless function converted to Bytes. +func FaaSMaxMemory(val int) attribute.KeyValue { + return FaaSMaxMemoryKey.Int(val) +} + +// FaaSName returns an attribute KeyValue conforming to the "faas.name" +// semantic conventions. It represents the name of the single function that +// this runtime instance executes. +func FaaSName(val string) attribute.KeyValue { + return FaaSNameKey.String(val) +} + +// FaaSVersion returns an attribute KeyValue conforming to the +// "faas.version" semantic conventions. It represents the immutable version of +// the function being executed. +func FaaSVersion(val string) attribute.KeyValue { + return FaaSVersionKey.String(val) +} + +// A service instance. +const ( + // ServiceNameKey is the attribute Key conforming to the "service.name" + // semantic conventions. It represents the logical name of the service. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'shoppingcart' + // Note: MUST be the same for all instances of horizontally scaled + // services. If the value was not specified, SDKs MUST fallback to + // `unknown_service:` concatenated with + // [`process.executable.name`](process.md#process), e.g. + // `unknown_service:bash`. If `process.executable.name` is not available, + // the value MUST be set to `unknown_service`. + ServiceNameKey = attribute.Key("service.name") + + // ServiceVersionKey is the attribute Key conforming to the + // "service.version" semantic conventions. It represents the version string + // of the service API or implementation. The format is not defined by these + // conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2.0.0', 'a01dbef8a' + ServiceVersionKey = attribute.Key("service.version") +) + +// ServiceName returns an attribute KeyValue conforming to the +// "service.name" semantic conventions. It represents the logical name of the +// service. +func ServiceName(val string) attribute.KeyValue { + return ServiceNameKey.String(val) +} + +// ServiceVersion returns an attribute KeyValue conforming to the +// "service.version" semantic conventions. It represents the version string of +// the service API or implementation. The format is not defined by these +// conventions. +func ServiceVersion(val string) attribute.KeyValue { + return ServiceVersionKey.String(val) +} + +// A service instance. +const ( + // ServiceInstanceIDKey is the attribute Key conforming to the + // "service.instance.id" semantic conventions. It represents the string ID + // of the service instance. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'my-k8s-pod-deployment-1', + // '627cc493-f310-47de-96bd-71410b7dec09' + // Note: MUST be unique for each instance of the same + // `service.namespace,service.name` pair (in other words + // `service.namespace,service.name,service.instance.id` triplet MUST be + // globally unique). The ID helps to distinguish instances of the same + // service that exist at the same time (e.g. instances of a horizontally + // scaled service). It is preferable for the ID to be persistent and stay + // the same for the lifetime of the service instance, however it is + // acceptable that the ID is ephemeral and changes during important + // lifetime events for the service (e.g. service restarts). If the service + // has no inherent unique ID that can be used as the value of this + // attribute it is recommended to generate a random Version 1 or Version 4 + // RFC 4122 UUID (services aiming for reproducible UUIDs may also use + // Version 5, see RFC 4122 for more recommendations). + ServiceInstanceIDKey = attribute.Key("service.instance.id") + + // ServiceNamespaceKey is the attribute Key conforming to the + // "service.namespace" semantic conventions. It represents a namespace for + // `service.name`. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Shop' + // Note: A string value having a meaning that helps to distinguish a group + // of services, for example the team name that owns a group of services. + // `service.name` is expected to be unique within the same namespace. If + // `service.namespace` is not specified in the Resource then `service.name` + // is expected to be unique for all services that have no explicit + // namespace defined (so the empty/unspecified namespace is simply one more + // valid namespace). Zero-length namespace string is assumed equal to + // unspecified namespace. + ServiceNamespaceKey = attribute.Key("service.namespace") +) + +// ServiceInstanceID returns an attribute KeyValue conforming to the +// "service.instance.id" semantic conventions. It represents the string ID of +// the service instance. +func ServiceInstanceID(val string) attribute.KeyValue { + return ServiceInstanceIDKey.String(val) +} + +// ServiceNamespace returns an attribute KeyValue conforming to the +// "service.namespace" semantic conventions. It represents a namespace for +// `service.name`. +func ServiceNamespace(val string) attribute.KeyValue { + return ServiceNamespaceKey.String(val) +} + +// The telemetry SDK used to capture data recorded by the instrumentation +// libraries. +const ( + // TelemetrySDKLanguageKey is the attribute Key conforming to the + // "telemetry.sdk.language" semantic conventions. It represents the + // language of the telemetry SDK. + // + // Type: Enum + // RequirementLevel: Required + // Stability: experimental + TelemetrySDKLanguageKey = attribute.Key("telemetry.sdk.language") + + // TelemetrySDKNameKey is the attribute Key conforming to the + // "telemetry.sdk.name" semantic conventions. It represents the name of the + // telemetry SDK as defined above. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'opentelemetry' + // Note: The OpenTelemetry SDK MUST set the `telemetry.sdk.name` attribute + // to `opentelemetry`. + // If another SDK, like a fork or a vendor-provided implementation, is + // used, this SDK MUST set the + // `telemetry.sdk.name` attribute to the fully-qualified class or module + // name of this SDK's main entry point + // or another suitable identifier depending on the language. + // The identifier `opentelemetry` is reserved and MUST NOT be used in this + // case. + // All custom identifiers SHOULD be stable across different versions of an + // implementation. + TelemetrySDKNameKey = attribute.Key("telemetry.sdk.name") + + // TelemetrySDKVersionKey is the attribute Key conforming to the + // "telemetry.sdk.version" semantic conventions. It represents the version + // string of the telemetry SDK. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: '1.2.3' + TelemetrySDKVersionKey = attribute.Key("telemetry.sdk.version") +) + +var ( + // cpp + TelemetrySDKLanguageCPP = TelemetrySDKLanguageKey.String("cpp") + // dotnet + TelemetrySDKLanguageDotnet = TelemetrySDKLanguageKey.String("dotnet") + // erlang + TelemetrySDKLanguageErlang = TelemetrySDKLanguageKey.String("erlang") + // go + TelemetrySDKLanguageGo = TelemetrySDKLanguageKey.String("go") + // java + TelemetrySDKLanguageJava = TelemetrySDKLanguageKey.String("java") + // nodejs + TelemetrySDKLanguageNodejs = TelemetrySDKLanguageKey.String("nodejs") + // php + TelemetrySDKLanguagePHP = TelemetrySDKLanguageKey.String("php") + // python + TelemetrySDKLanguagePython = TelemetrySDKLanguageKey.String("python") + // ruby + TelemetrySDKLanguageRuby = TelemetrySDKLanguageKey.String("ruby") + // rust + TelemetrySDKLanguageRust = TelemetrySDKLanguageKey.String("rust") + // swift + TelemetrySDKLanguageSwift = TelemetrySDKLanguageKey.String("swift") + // webjs + TelemetrySDKLanguageWebjs = TelemetrySDKLanguageKey.String("webjs") +) + +// TelemetrySDKName returns an attribute KeyValue conforming to the +// "telemetry.sdk.name" semantic conventions. It represents the name of the +// telemetry SDK as defined above. +func TelemetrySDKName(val string) attribute.KeyValue { + return TelemetrySDKNameKey.String(val) +} + +// TelemetrySDKVersion returns an attribute KeyValue conforming to the +// "telemetry.sdk.version" semantic conventions. It represents the version +// string of the telemetry SDK. +func TelemetrySDKVersion(val string) attribute.KeyValue { + return TelemetrySDKVersionKey.String(val) +} + +// The telemetry SDK used to capture data recorded by the instrumentation +// libraries. +const ( + // TelemetryDistroNameKey is the attribute Key conforming to the + // "telemetry.distro.name" semantic conventions. It represents the name of + // the auto instrumentation agent or distribution, if used. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'parts-unlimited-java' + // Note: Official auto instrumentation agents and distributions SHOULD set + // the `telemetry.distro.name` attribute to + // a string starting with `opentelemetry-`, e.g. + // `opentelemetry-java-instrumentation`. + TelemetryDistroNameKey = attribute.Key("telemetry.distro.name") + + // TelemetryDistroVersionKey is the attribute Key conforming to the + // "telemetry.distro.version" semantic conventions. It represents the + // version string of the auto instrumentation agent or distribution, if + // used. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '1.2.3' + TelemetryDistroVersionKey = attribute.Key("telemetry.distro.version") +) + +// TelemetryDistroName returns an attribute KeyValue conforming to the +// "telemetry.distro.name" semantic conventions. It represents the name of the +// auto instrumentation agent or distribution, if used. +func TelemetryDistroName(val string) attribute.KeyValue { + return TelemetryDistroNameKey.String(val) +} + +// TelemetryDistroVersion returns an attribute KeyValue conforming to the +// "telemetry.distro.version" semantic conventions. It represents the version +// string of the auto instrumentation agent or distribution, if used. +func TelemetryDistroVersion(val string) attribute.KeyValue { + return TelemetryDistroVersionKey.String(val) +} + +// Resource describing the packaged software running the application code. Web +// engines are typically executed using process.runtime. +const ( + // WebEngineDescriptionKey is the attribute Key conforming to the + // "webengine.description" semantic conventions. It represents the + // additional description of the web engine (e.g. detailed version and + // edition information). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'WildFly Full 21.0.0.Final (WildFly Core 13.0.1.Final) - + // 2.2.2.Final' + WebEngineDescriptionKey = attribute.Key("webengine.description") + + // WebEngineNameKey is the attribute Key conforming to the "webengine.name" + // semantic conventions. It represents the name of the web engine. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'WildFly' + WebEngineNameKey = attribute.Key("webengine.name") + + // WebEngineVersionKey is the attribute Key conforming to the + // "webengine.version" semantic conventions. It represents the version of + // the web engine. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '21.0.0' + WebEngineVersionKey = attribute.Key("webengine.version") +) + +// WebEngineDescription returns an attribute KeyValue conforming to the +// "webengine.description" semantic conventions. It represents the additional +// description of the web engine (e.g. detailed version and edition +// information). +func WebEngineDescription(val string) attribute.KeyValue { + return WebEngineDescriptionKey.String(val) +} + +// WebEngineName returns an attribute KeyValue conforming to the +// "webengine.name" semantic conventions. It represents the name of the web +// engine. +func WebEngineName(val string) attribute.KeyValue { + return WebEngineNameKey.String(val) +} + +// WebEngineVersion returns an attribute KeyValue conforming to the +// "webengine.version" semantic conventions. It represents the version of the +// web engine. +func WebEngineVersion(val string) attribute.KeyValue { + return WebEngineVersionKey.String(val) +} + +// Attributes used by non-OTLP exporters to represent OpenTelemetry Scope's +// concepts. +const ( + // OTelScopeNameKey is the attribute Key conforming to the + // "otel.scope.name" semantic conventions. It represents the name of the + // instrumentation scope - (`InstrumentationScope.Name` in OTLP). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'io.opentelemetry.contrib.mongodb' + OTelScopeNameKey = attribute.Key("otel.scope.name") + + // OTelScopeVersionKey is the attribute Key conforming to the + // "otel.scope.version" semantic conventions. It represents the version of + // the instrumentation scope - (`InstrumentationScope.Version` in OTLP). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '1.0.0' + OTelScopeVersionKey = attribute.Key("otel.scope.version") +) + +// OTelScopeName returns an attribute KeyValue conforming to the +// "otel.scope.name" semantic conventions. It represents the name of the +// instrumentation scope - (`InstrumentationScope.Name` in OTLP). +func OTelScopeName(val string) attribute.KeyValue { + return OTelScopeNameKey.String(val) +} + +// OTelScopeVersion returns an attribute KeyValue conforming to the +// "otel.scope.version" semantic conventions. It represents the version of the +// instrumentation scope - (`InstrumentationScope.Version` in OTLP). +func OTelScopeVersion(val string) attribute.KeyValue { + return OTelScopeVersionKey.String(val) +} + +// Span attributes used by non-OTLP exporters to represent OpenTelemetry +// Scope's concepts. +const ( + // OTelLibraryNameKey is the attribute Key conforming to the + // "otel.library.name" semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: 'io.opentelemetry.contrib.mongodb' + // Deprecated: use the `otel.scope.name` attribute. + OTelLibraryNameKey = attribute.Key("otel.library.name") + + // OTelLibraryVersionKey is the attribute Key conforming to the + // "otel.library.version" semantic conventions. + // + // Type: string + // RequirementLevel: Optional + // Stability: deprecated + // Examples: '1.0.0' + // Deprecated: use the `otel.scope.version` attribute. + OTelLibraryVersionKey = attribute.Key("otel.library.version") +) + +// OTelLibraryName returns an attribute KeyValue conforming to the +// "otel.library.name" semantic conventions. +// +// Deprecated: use the `otel.scope.name` attribute. +func OTelLibraryName(val string) attribute.KeyValue { + return OTelLibraryNameKey.String(val) +} + +// OTelLibraryVersion returns an attribute KeyValue conforming to the +// "otel.library.version" semantic conventions. +// +// Deprecated: use the `otel.scope.version` attribute. +func OTelLibraryVersion(val string) attribute.KeyValue { + return OTelLibraryVersionKey.String(val) +} diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/schema.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/schema.go new file mode 100644 index 0000000000..9733ce888a --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/schema.go @@ -0,0 +1,20 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" + +// SchemaURL is the schema URL that matches the version of the semantic conventions +// that this package defines. Semconv packages starting from v1.4.0 must declare +// non-empty schema URL in the form https://opentelemetry.io/schemas/ +const SchemaURL = "https://opentelemetry.io/schemas/1.24.0" diff --git a/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/trace.go b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/trace.go new file mode 100644 index 0000000000..397174818b --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/semconv/v1.24.0/trace.go @@ -0,0 +1,1334 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated from semantic convention specification. DO NOT EDIT. + +package semconv // import "go.opentelemetry.io/otel/semconv/v1.24.0" + +import "go.opentelemetry.io/otel/attribute" + +// Operations that access some remote service. +const ( + // PeerServiceKey is the attribute Key conforming to the "peer.service" + // semantic conventions. It represents the + // [`service.name`](/docs/resource/README.md#service) of the remote + // service. SHOULD be equal to the actual `service.name` resource attribute + // of the remote service if any. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'AuthTokenCache' + PeerServiceKey = attribute.Key("peer.service") +) + +// PeerService returns an attribute KeyValue conforming to the +// "peer.service" semantic conventions. It represents the +// [`service.name`](/docs/resource/README.md#service) of the remote service. +// SHOULD be equal to the actual `service.name` resource attribute of the +// remote service if any. +func PeerService(val string) attribute.KeyValue { + return PeerServiceKey.String(val) +} + +// These attributes may be used for any operation with an authenticated and/or +// authorized enduser. +const ( + // EnduserIDKey is the attribute Key conforming to the "enduser.id" + // semantic conventions. It represents the username or client_id extracted + // from the access token or + // [Authorization](https://tools.ietf.org/html/rfc7235#section-4.2) header + // in the inbound request from outside the system. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'username' + EnduserIDKey = attribute.Key("enduser.id") + + // EnduserRoleKey is the attribute Key conforming to the "enduser.role" + // semantic conventions. It represents the actual/assumed role the client + // is making the request under extracted from token or application security + // context. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'admin' + EnduserRoleKey = attribute.Key("enduser.role") + + // EnduserScopeKey is the attribute Key conforming to the "enduser.scope" + // semantic conventions. It represents the scopes or granted authorities + // the client currently possesses extracted from token or application + // security context. The value would come from the scope associated with an + // [OAuth 2.0 Access + // Token](https://tools.ietf.org/html/rfc6749#section-3.3) or an attribute + // value in a [SAML 2.0 + // Assertion](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'read:message, write:files' + EnduserScopeKey = attribute.Key("enduser.scope") +) + +// EnduserID returns an attribute KeyValue conforming to the "enduser.id" +// semantic conventions. It represents the username or client_id extracted from +// the access token or +// [Authorization](https://tools.ietf.org/html/rfc7235#section-4.2) header in +// the inbound request from outside the system. +func EnduserID(val string) attribute.KeyValue { + return EnduserIDKey.String(val) +} + +// EnduserRole returns an attribute KeyValue conforming to the +// "enduser.role" semantic conventions. It represents the actual/assumed role +// the client is making the request under extracted from token or application +// security context. +func EnduserRole(val string) attribute.KeyValue { + return EnduserRoleKey.String(val) +} + +// EnduserScope returns an attribute KeyValue conforming to the +// "enduser.scope" semantic conventions. It represents the scopes or granted +// authorities the client currently possesses extracted from token or +// application security context. The value would come from the scope associated +// with an [OAuth 2.0 Access +// Token](https://tools.ietf.org/html/rfc6749#section-3.3) or an attribute +// value in a [SAML 2.0 +// Assertion](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html). +func EnduserScope(val string) attribute.KeyValue { + return EnduserScopeKey.String(val) +} + +// These attributes allow to report this unit of code and therefore to provide +// more context about the span. +const ( + // CodeColumnKey is the attribute Key conforming to the "code.column" + // semantic conventions. It represents the column number in `code.filepath` + // best representing the operation. It SHOULD point within the code unit + // named in `code.function`. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 16 + CodeColumnKey = attribute.Key("code.column") + + // CodeFilepathKey is the attribute Key conforming to the "code.filepath" + // semantic conventions. It represents the source code file name that + // identifies the code unit as uniquely as possible (preferably an absolute + // file path). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '/usr/local/MyApplication/content_root/app/index.php' + CodeFilepathKey = attribute.Key("code.filepath") + + // CodeFunctionKey is the attribute Key conforming to the "code.function" + // semantic conventions. It represents the method or function name, or + // equivalent (usually rightmost part of the code unit's name). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'serveRequest' + CodeFunctionKey = attribute.Key("code.function") + + // CodeLineNumberKey is the attribute Key conforming to the "code.lineno" + // semantic conventions. It represents the line number in `code.filepath` + // best representing the operation. It SHOULD point within the code unit + // named in `code.function`. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 42 + CodeLineNumberKey = attribute.Key("code.lineno") + + // CodeNamespaceKey is the attribute Key conforming to the "code.namespace" + // semantic conventions. It represents the "namespace" within which + // `code.function` is defined. Usually the qualified class or module name, + // such that `code.namespace` + some separator + `code.function` form a + // unique identifier for the code unit. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'com.example.MyHTTPService' + CodeNamespaceKey = attribute.Key("code.namespace") + + // CodeStacktraceKey is the attribute Key conforming to the + // "code.stacktrace" semantic conventions. It represents a stacktrace as a + // string in the natural representation for the language runtime. The + // representation is to be determined and documented by each language SIG. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'at + // com.example.GenerateTrace.methodB(GenerateTrace.java:13)\\n at ' + // 'com.example.GenerateTrace.methodA(GenerateTrace.java:9)\\n at ' + // 'com.example.GenerateTrace.main(GenerateTrace.java:5)' + CodeStacktraceKey = attribute.Key("code.stacktrace") +) + +// CodeColumn returns an attribute KeyValue conforming to the "code.column" +// semantic conventions. It represents the column number in `code.filepath` +// best representing the operation. It SHOULD point within the code unit named +// in `code.function`. +func CodeColumn(val int) attribute.KeyValue { + return CodeColumnKey.Int(val) +} + +// CodeFilepath returns an attribute KeyValue conforming to the +// "code.filepath" semantic conventions. It represents the source code file +// name that identifies the code unit as uniquely as possible (preferably an +// absolute file path). +func CodeFilepath(val string) attribute.KeyValue { + return CodeFilepathKey.String(val) +} + +// CodeFunction returns an attribute KeyValue conforming to the +// "code.function" semantic conventions. It represents the method or function +// name, or equivalent (usually rightmost part of the code unit's name). +func CodeFunction(val string) attribute.KeyValue { + return CodeFunctionKey.String(val) +} + +// CodeLineNumber returns an attribute KeyValue conforming to the "code.lineno" +// semantic conventions. It represents the line number in `code.filepath` best +// representing the operation. It SHOULD point within the code unit named in +// `code.function`. +func CodeLineNumber(val int) attribute.KeyValue { + return CodeLineNumberKey.Int(val) +} + +// CodeNamespace returns an attribute KeyValue conforming to the +// "code.namespace" semantic conventions. It represents the "namespace" within +// which `code.function` is defined. Usually the qualified class or module +// name, such that `code.namespace` + some separator + `code.function` form a +// unique identifier for the code unit. +func CodeNamespace(val string) attribute.KeyValue { + return CodeNamespaceKey.String(val) +} + +// CodeStacktrace returns an attribute KeyValue conforming to the +// "code.stacktrace" semantic conventions. It represents a stacktrace as a +// string in the natural representation for the language runtime. The +// representation is to be determined and documented by each language SIG. +func CodeStacktrace(val string) attribute.KeyValue { + return CodeStacktraceKey.String(val) +} + +// These attributes may be used for any operation to store information about a +// thread that started a span. +const ( + // ThreadIDKey is the attribute Key conforming to the "thread.id" semantic + // conventions. It represents the current "managed" thread ID (as opposed + // to OS thread ID). + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 42 + ThreadIDKey = attribute.Key("thread.id") + + // ThreadNameKey is the attribute Key conforming to the "thread.name" + // semantic conventions. It represents the current thread name. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'main' + ThreadNameKey = attribute.Key("thread.name") +) + +// ThreadID returns an attribute KeyValue conforming to the "thread.id" +// semantic conventions. It represents the current "managed" thread ID (as +// opposed to OS thread ID). +func ThreadID(val int) attribute.KeyValue { + return ThreadIDKey.Int(val) +} + +// ThreadName returns an attribute KeyValue conforming to the "thread.name" +// semantic conventions. It represents the current thread name. +func ThreadName(val string) attribute.KeyValue { + return ThreadNameKey.String(val) +} + +// Span attributes used by AWS Lambda (in addition to general `faas` +// attributes). +const ( + // AWSLambdaInvokedARNKey is the attribute Key conforming to the + // "aws.lambda.invoked_arn" semantic conventions. It represents the full + // invoked ARN as provided on the `Context` passed to the function + // (`Lambda-Runtime-Invoked-Function-ARN` header on the + // `/runtime/invocation/next` applicable). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'arn:aws:lambda:us-east-1:123456:function:myfunction:myalias' + // Note: This may be different from `cloud.resource_id` if an alias is + // involved. + AWSLambdaInvokedARNKey = attribute.Key("aws.lambda.invoked_arn") +) + +// AWSLambdaInvokedARN returns an attribute KeyValue conforming to the +// "aws.lambda.invoked_arn" semantic conventions. It represents the full +// invoked ARN as provided on the `Context` passed to the function +// (`Lambda-Runtime-Invoked-Function-ARN` header on the +// `/runtime/invocation/next` applicable). +func AWSLambdaInvokedARN(val string) attribute.KeyValue { + return AWSLambdaInvokedARNKey.String(val) +} + +// Attributes for CloudEvents. CloudEvents is a specification on how to define +// event data in a standard way. These attributes can be attached to spans when +// performing operations with CloudEvents, regardless of the protocol being +// used. +const ( + // CloudeventsEventIDKey is the attribute Key conforming to the + // "cloudevents.event_id" semantic conventions. It represents the + // [event_id](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id) + // uniquely identifies the event. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: '123e4567-e89b-12d3-a456-426614174000', '0001' + CloudeventsEventIDKey = attribute.Key("cloudevents.event_id") + + // CloudeventsEventSourceKey is the attribute Key conforming to the + // "cloudevents.event_source" semantic conventions. It represents the + // [source](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1) + // identifies the context in which an event happened. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'https://github.com/cloudevents', + // '/cloudevents/spec/pull/123', 'my-service' + CloudeventsEventSourceKey = attribute.Key("cloudevents.event_source") + + // CloudeventsEventSpecVersionKey is the attribute Key conforming to the + // "cloudevents.event_spec_version" semantic conventions. It represents the + // [version of the CloudEvents + // specification](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) + // which the event uses. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '1.0' + CloudeventsEventSpecVersionKey = attribute.Key("cloudevents.event_spec_version") + + // CloudeventsEventSubjectKey is the attribute Key conforming to the + // "cloudevents.event_subject" semantic conventions. It represents the + // [subject](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject) + // of the event in the context of the event producer (identified by + // source). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'mynewfile.jpg' + CloudeventsEventSubjectKey = attribute.Key("cloudevents.event_subject") + + // CloudeventsEventTypeKey is the attribute Key conforming to the + // "cloudevents.event_type" semantic conventions. It represents the + // [event_type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) + // contains a value describing the type of event related to the originating + // occurrence. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'com.github.pull_request.opened', + // 'com.example.object.deleted.v2' + CloudeventsEventTypeKey = attribute.Key("cloudevents.event_type") +) + +// CloudeventsEventID returns an attribute KeyValue conforming to the +// "cloudevents.event_id" semantic conventions. It represents the +// [event_id](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#id) +// uniquely identifies the event. +func CloudeventsEventID(val string) attribute.KeyValue { + return CloudeventsEventIDKey.String(val) +} + +// CloudeventsEventSource returns an attribute KeyValue conforming to the +// "cloudevents.event_source" semantic conventions. It represents the +// [source](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#source-1) +// identifies the context in which an event happened. +func CloudeventsEventSource(val string) attribute.KeyValue { + return CloudeventsEventSourceKey.String(val) +} + +// CloudeventsEventSpecVersion returns an attribute KeyValue conforming to +// the "cloudevents.event_spec_version" semantic conventions. It represents the +// [version of the CloudEvents +// specification](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#specversion) +// which the event uses. +func CloudeventsEventSpecVersion(val string) attribute.KeyValue { + return CloudeventsEventSpecVersionKey.String(val) +} + +// CloudeventsEventSubject returns an attribute KeyValue conforming to the +// "cloudevents.event_subject" semantic conventions. It represents the +// [subject](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#subject) +// of the event in the context of the event producer (identified by source). +func CloudeventsEventSubject(val string) attribute.KeyValue { + return CloudeventsEventSubjectKey.String(val) +} + +// CloudeventsEventType returns an attribute KeyValue conforming to the +// "cloudevents.event_type" semantic conventions. It represents the +// [event_type](https://github.com/cloudevents/spec/blob/v1.0.2/cloudevents/spec.md#type) +// contains a value describing the type of event related to the originating +// occurrence. +func CloudeventsEventType(val string) attribute.KeyValue { + return CloudeventsEventTypeKey.String(val) +} + +// Semantic conventions for the OpenTracing Shim +const ( + // OpentracingRefTypeKey is the attribute Key conforming to the + // "opentracing.ref_type" semantic conventions. It represents the + // parent-child Reference type + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Note: The causal relationship between a child Span and a parent Span. + OpentracingRefTypeKey = attribute.Key("opentracing.ref_type") +) + +var ( + // The parent Span depends on the child Span in some capacity + OpentracingRefTypeChildOf = OpentracingRefTypeKey.String("child_of") + // The parent Span doesn't depend in any way on the result of the child Span + OpentracingRefTypeFollowsFrom = OpentracingRefTypeKey.String("follows_from") +) + +// Span attributes used by non-OTLP exporters to represent OpenTelemetry Span's +// concepts. +const ( + // OTelStatusCodeKey is the attribute Key conforming to the + // "otel.status_code" semantic conventions. It represents the name of the + // code, either "OK" or "ERROR". MUST NOT be set if the status code is + // UNSET. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + OTelStatusCodeKey = attribute.Key("otel.status_code") + + // OTelStatusDescriptionKey is the attribute Key conforming to the + // "otel.status_description" semantic conventions. It represents the + // description of the Status if it has a value, otherwise not set. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'resource not found' + OTelStatusDescriptionKey = attribute.Key("otel.status_description") +) + +var ( + // The operation has been validated by an Application developer or Operator to have completed successfully + OTelStatusCodeOk = OTelStatusCodeKey.String("OK") + // The operation contains an error + OTelStatusCodeError = OTelStatusCodeKey.String("ERROR") +) + +// OTelStatusDescription returns an attribute KeyValue conforming to the +// "otel.status_description" semantic conventions. It represents the +// description of the Status if it has a value, otherwise not set. +func OTelStatusDescription(val string) attribute.KeyValue { + return OTelStatusDescriptionKey.String(val) +} + +// This semantic convention describes an instance of a function that runs +// without provisioning or managing of servers (also known as serverless +// functions or Function as a Service (FaaS)) with spans. +const ( + // FaaSInvocationIDKey is the attribute Key conforming to the + // "faas.invocation_id" semantic conventions. It represents the invocation + // ID of the current function invocation. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'af9d5aa4-a685-4c5f-a22b-444f80b3cc28' + FaaSInvocationIDKey = attribute.Key("faas.invocation_id") +) + +// FaaSInvocationID returns an attribute KeyValue conforming to the +// "faas.invocation_id" semantic conventions. It represents the invocation ID +// of the current function invocation. +func FaaSInvocationID(val string) attribute.KeyValue { + return FaaSInvocationIDKey.String(val) +} + +// Semantic Convention for FaaS triggered as a response to some data source +// operation such as a database or filesystem read/write. +const ( + // FaaSDocumentCollectionKey is the attribute Key conforming to the + // "faas.document.collection" semantic conventions. It represents the name + // of the source on which the triggering operation was performed. For + // example, in Cloud Storage or S3 corresponds to the bucket name, and in + // Cosmos DB to the database name. + // + // Type: string + // RequirementLevel: Required + // Stability: experimental + // Examples: 'myBucketName', 'myDBName' + FaaSDocumentCollectionKey = attribute.Key("faas.document.collection") + + // FaaSDocumentNameKey is the attribute Key conforming to the + // "faas.document.name" semantic conventions. It represents the document + // name/table subjected to the operation. For example, in Cloud Storage or + // S3 is the name of the file, and in Cosmos DB the table name. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'myFile.txt', 'myTableName' + FaaSDocumentNameKey = attribute.Key("faas.document.name") + + // FaaSDocumentOperationKey is the attribute Key conforming to the + // "faas.document.operation" semantic conventions. It represents the + // describes the type of the operation that was performed on the data. + // + // Type: Enum + // RequirementLevel: Required + // Stability: experimental + FaaSDocumentOperationKey = attribute.Key("faas.document.operation") + + // FaaSDocumentTimeKey is the attribute Key conforming to the + // "faas.document.time" semantic conventions. It represents a string + // containing the time when the data was accessed in the [ISO + // 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format + // expressed in [UTC](https://www.w3.org/TR/NOTE-datetime). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2020-01-23T13:47:06Z' + FaaSDocumentTimeKey = attribute.Key("faas.document.time") +) + +var ( + // When a new object is created + FaaSDocumentOperationInsert = FaaSDocumentOperationKey.String("insert") + // When an object is modified + FaaSDocumentOperationEdit = FaaSDocumentOperationKey.String("edit") + // When an object is deleted + FaaSDocumentOperationDelete = FaaSDocumentOperationKey.String("delete") +) + +// FaaSDocumentCollection returns an attribute KeyValue conforming to the +// "faas.document.collection" semantic conventions. It represents the name of +// the source on which the triggering operation was performed. For example, in +// Cloud Storage or S3 corresponds to the bucket name, and in Cosmos DB to the +// database name. +func FaaSDocumentCollection(val string) attribute.KeyValue { + return FaaSDocumentCollectionKey.String(val) +} + +// FaaSDocumentName returns an attribute KeyValue conforming to the +// "faas.document.name" semantic conventions. It represents the document +// name/table subjected to the operation. For example, in Cloud Storage or S3 +// is the name of the file, and in Cosmos DB the table name. +func FaaSDocumentName(val string) attribute.KeyValue { + return FaaSDocumentNameKey.String(val) +} + +// FaaSDocumentTime returns an attribute KeyValue conforming to the +// "faas.document.time" semantic conventions. It represents a string containing +// the time when the data was accessed in the [ISO +// 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format +// expressed in [UTC](https://www.w3.org/TR/NOTE-datetime). +func FaaSDocumentTime(val string) attribute.KeyValue { + return FaaSDocumentTimeKey.String(val) +} + +// Semantic Convention for FaaS scheduled to be executed regularly. +const ( + // FaaSCronKey is the attribute Key conforming to the "faas.cron" semantic + // conventions. It represents a string containing the schedule period as + // [Cron + // Expression](https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '0/5 * * * ? *' + FaaSCronKey = attribute.Key("faas.cron") + + // FaaSTimeKey is the attribute Key conforming to the "faas.time" semantic + // conventions. It represents a string containing the function invocation + // time in the [ISO + // 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format + // expressed in [UTC](https://www.w3.org/TR/NOTE-datetime). + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '2020-01-23T13:47:06Z' + FaaSTimeKey = attribute.Key("faas.time") +) + +// FaaSCron returns an attribute KeyValue conforming to the "faas.cron" +// semantic conventions. It represents a string containing the schedule period +// as [Cron +// Expression](https://docs.oracle.com/cd/E12058_01/doc/doc.1014/e12030/cron_expressions.htm). +func FaaSCron(val string) attribute.KeyValue { + return FaaSCronKey.String(val) +} + +// FaaSTime returns an attribute KeyValue conforming to the "faas.time" +// semantic conventions. It represents a string containing the function +// invocation time in the [ISO +// 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format +// expressed in [UTC](https://www.w3.org/TR/NOTE-datetime). +func FaaSTime(val string) attribute.KeyValue { + return FaaSTimeKey.String(val) +} + +// Contains additional attributes for incoming FaaS spans. +const ( + // FaaSColdstartKey is the attribute Key conforming to the "faas.coldstart" + // semantic conventions. It represents a boolean that is true if the + // serverless function is executed for the first time (aka cold-start). + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + FaaSColdstartKey = attribute.Key("faas.coldstart") +) + +// FaaSColdstart returns an attribute KeyValue conforming to the +// "faas.coldstart" semantic conventions. It represents a boolean that is true +// if the serverless function is executed for the first time (aka cold-start). +func FaaSColdstart(val bool) attribute.KeyValue { + return FaaSColdstartKey.Bool(val) +} + +// The `aws` conventions apply to operations using the AWS SDK. They map +// request or response parameters in AWS SDK API calls to attributes on a Span. +// The conventions have been collected over time based on feedback from AWS +// users of tracing and will continue to evolve as new interesting conventions +// are found. +// Some descriptions are also provided for populating general OpenTelemetry +// semantic conventions based on these APIs. +const ( + // AWSRequestIDKey is the attribute Key conforming to the "aws.request_id" + // semantic conventions. It represents the AWS request ID as returned in + // the response headers `x-amz-request-id` or `x-amz-requestid`. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '79b9da39-b7ae-508a-a6bc-864b2829c622', 'C9ER4AJX75574TDJ' + AWSRequestIDKey = attribute.Key("aws.request_id") +) + +// AWSRequestID returns an attribute KeyValue conforming to the +// "aws.request_id" semantic conventions. It represents the AWS request ID as +// returned in the response headers `x-amz-request-id` or `x-amz-requestid`. +func AWSRequestID(val string) attribute.KeyValue { + return AWSRequestIDKey.String(val) +} + +// Attributes that exist for multiple DynamoDB request types. +const ( + // AWSDynamoDBAttributesToGetKey is the attribute Key conforming to the + // "aws.dynamodb.attributes_to_get" semantic conventions. It represents the + // value of the `AttributesToGet` request parameter. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'lives', 'id' + AWSDynamoDBAttributesToGetKey = attribute.Key("aws.dynamodb.attributes_to_get") + + // AWSDynamoDBConsistentReadKey is the attribute Key conforming to the + // "aws.dynamodb.consistent_read" semantic conventions. It represents the + // value of the `ConsistentRead` request parameter. + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + AWSDynamoDBConsistentReadKey = attribute.Key("aws.dynamodb.consistent_read") + + // AWSDynamoDBConsumedCapacityKey is the attribute Key conforming to the + // "aws.dynamodb.consumed_capacity" semantic conventions. It represents the + // JSON-serialized value of each item in the `ConsumedCapacity` response + // field. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: '{ "CapacityUnits": number, "GlobalSecondaryIndexes": { + // "string" : { "CapacityUnits": number, "ReadCapacityUnits": number, + // "WriteCapacityUnits": number } }, "LocalSecondaryIndexes": { "string" : + // { "CapacityUnits": number, "ReadCapacityUnits": number, + // "WriteCapacityUnits": number } }, "ReadCapacityUnits": number, "Table": + // { "CapacityUnits": number, "ReadCapacityUnits": number, + // "WriteCapacityUnits": number }, "TableName": "string", + // "WriteCapacityUnits": number }' + AWSDynamoDBConsumedCapacityKey = attribute.Key("aws.dynamodb.consumed_capacity") + + // AWSDynamoDBIndexNameKey is the attribute Key conforming to the + // "aws.dynamodb.index_name" semantic conventions. It represents the value + // of the `IndexName` request parameter. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'name_to_group' + AWSDynamoDBIndexNameKey = attribute.Key("aws.dynamodb.index_name") + + // AWSDynamoDBItemCollectionMetricsKey is the attribute Key conforming to + // the "aws.dynamodb.item_collection_metrics" semantic conventions. It + // represents the JSON-serialized value of the `ItemCollectionMetrics` + // response field. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: '{ "string" : [ { "ItemCollectionKey": { "string" : { "B": + // blob, "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { + // "string" : "AttributeValue" }, "N": "string", "NS": [ "string" ], + // "NULL": boolean, "S": "string", "SS": [ "string" ] } }, + // "SizeEstimateRangeGB": [ number ] } ] }' + AWSDynamoDBItemCollectionMetricsKey = attribute.Key("aws.dynamodb.item_collection_metrics") + + // AWSDynamoDBLimitKey is the attribute Key conforming to the + // "aws.dynamodb.limit" semantic conventions. It represents the value of + // the `Limit` request parameter. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 10 + AWSDynamoDBLimitKey = attribute.Key("aws.dynamodb.limit") + + // AWSDynamoDBProjectionKey is the attribute Key conforming to the + // "aws.dynamodb.projection" semantic conventions. It represents the value + // of the `ProjectionExpression` request parameter. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Title', 'Title, Price, Color', 'Title, Description, + // RelatedItems, ProductReviews' + AWSDynamoDBProjectionKey = attribute.Key("aws.dynamodb.projection") + + // AWSDynamoDBProvisionedReadCapacityKey is the attribute Key conforming to + // the "aws.dynamodb.provisioned_read_capacity" semantic conventions. It + // represents the value of the `ProvisionedThroughput.ReadCapacityUnits` + // request parameter. + // + // Type: double + // RequirementLevel: Optional + // Stability: experimental + // Examples: 1.0, 2.0 + AWSDynamoDBProvisionedReadCapacityKey = attribute.Key("aws.dynamodb.provisioned_read_capacity") + + // AWSDynamoDBProvisionedWriteCapacityKey is the attribute Key conforming + // to the "aws.dynamodb.provisioned_write_capacity" semantic conventions. + // It represents the value of the + // `ProvisionedThroughput.WriteCapacityUnits` request parameter. + // + // Type: double + // RequirementLevel: Optional + // Stability: experimental + // Examples: 1.0, 2.0 + AWSDynamoDBProvisionedWriteCapacityKey = attribute.Key("aws.dynamodb.provisioned_write_capacity") + + // AWSDynamoDBSelectKey is the attribute Key conforming to the + // "aws.dynamodb.select" semantic conventions. It represents the value of + // the `Select` request parameter. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'ALL_ATTRIBUTES', 'COUNT' + AWSDynamoDBSelectKey = attribute.Key("aws.dynamodb.select") + + // AWSDynamoDBTableNamesKey is the attribute Key conforming to the + // "aws.dynamodb.table_names" semantic conventions. It represents the keys + // in the `RequestItems` object field. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Users', 'Cats' + AWSDynamoDBTableNamesKey = attribute.Key("aws.dynamodb.table_names") +) + +// AWSDynamoDBAttributesToGet returns an attribute KeyValue conforming to +// the "aws.dynamodb.attributes_to_get" semantic conventions. It represents the +// value of the `AttributesToGet` request parameter. +func AWSDynamoDBAttributesToGet(val ...string) attribute.KeyValue { + return AWSDynamoDBAttributesToGetKey.StringSlice(val) +} + +// AWSDynamoDBConsistentRead returns an attribute KeyValue conforming to the +// "aws.dynamodb.consistent_read" semantic conventions. It represents the value +// of the `ConsistentRead` request parameter. +func AWSDynamoDBConsistentRead(val bool) attribute.KeyValue { + return AWSDynamoDBConsistentReadKey.Bool(val) +} + +// AWSDynamoDBConsumedCapacity returns an attribute KeyValue conforming to +// the "aws.dynamodb.consumed_capacity" semantic conventions. It represents the +// JSON-serialized value of each item in the `ConsumedCapacity` response field. +func AWSDynamoDBConsumedCapacity(val ...string) attribute.KeyValue { + return AWSDynamoDBConsumedCapacityKey.StringSlice(val) +} + +// AWSDynamoDBIndexName returns an attribute KeyValue conforming to the +// "aws.dynamodb.index_name" semantic conventions. It represents the value of +// the `IndexName` request parameter. +func AWSDynamoDBIndexName(val string) attribute.KeyValue { + return AWSDynamoDBIndexNameKey.String(val) +} + +// AWSDynamoDBItemCollectionMetrics returns an attribute KeyValue conforming +// to the "aws.dynamodb.item_collection_metrics" semantic conventions. It +// represents the JSON-serialized value of the `ItemCollectionMetrics` response +// field. +func AWSDynamoDBItemCollectionMetrics(val string) attribute.KeyValue { + return AWSDynamoDBItemCollectionMetricsKey.String(val) +} + +// AWSDynamoDBLimit returns an attribute KeyValue conforming to the +// "aws.dynamodb.limit" semantic conventions. It represents the value of the +// `Limit` request parameter. +func AWSDynamoDBLimit(val int) attribute.KeyValue { + return AWSDynamoDBLimitKey.Int(val) +} + +// AWSDynamoDBProjection returns an attribute KeyValue conforming to the +// "aws.dynamodb.projection" semantic conventions. It represents the value of +// the `ProjectionExpression` request parameter. +func AWSDynamoDBProjection(val string) attribute.KeyValue { + return AWSDynamoDBProjectionKey.String(val) +} + +// AWSDynamoDBProvisionedReadCapacity returns an attribute KeyValue +// conforming to the "aws.dynamodb.provisioned_read_capacity" semantic +// conventions. It represents the value of the +// `ProvisionedThroughput.ReadCapacityUnits` request parameter. +func AWSDynamoDBProvisionedReadCapacity(val float64) attribute.KeyValue { + return AWSDynamoDBProvisionedReadCapacityKey.Float64(val) +} + +// AWSDynamoDBProvisionedWriteCapacity returns an attribute KeyValue +// conforming to the "aws.dynamodb.provisioned_write_capacity" semantic +// conventions. It represents the value of the +// `ProvisionedThroughput.WriteCapacityUnits` request parameter. +func AWSDynamoDBProvisionedWriteCapacity(val float64) attribute.KeyValue { + return AWSDynamoDBProvisionedWriteCapacityKey.Float64(val) +} + +// AWSDynamoDBSelect returns an attribute KeyValue conforming to the +// "aws.dynamodb.select" semantic conventions. It represents the value of the +// `Select` request parameter. +func AWSDynamoDBSelect(val string) attribute.KeyValue { + return AWSDynamoDBSelectKey.String(val) +} + +// AWSDynamoDBTableNames returns an attribute KeyValue conforming to the +// "aws.dynamodb.table_names" semantic conventions. It represents the keys in +// the `RequestItems` object field. +func AWSDynamoDBTableNames(val ...string) attribute.KeyValue { + return AWSDynamoDBTableNamesKey.StringSlice(val) +} + +// DynamoDB.CreateTable +const ( + // AWSDynamoDBGlobalSecondaryIndexesKey is the attribute Key conforming to + // the "aws.dynamodb.global_secondary_indexes" semantic conventions. It + // represents the JSON-serialized value of each item of the + // `GlobalSecondaryIndexes` request field + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: '{ "IndexName": "string", "KeySchema": [ { "AttributeName": + // "string", "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ + // "string" ], "ProjectionType": "string" }, "ProvisionedThroughput": { + // "ReadCapacityUnits": number, "WriteCapacityUnits": number } }' + AWSDynamoDBGlobalSecondaryIndexesKey = attribute.Key("aws.dynamodb.global_secondary_indexes") + + // AWSDynamoDBLocalSecondaryIndexesKey is the attribute Key conforming to + // the "aws.dynamodb.local_secondary_indexes" semantic conventions. It + // represents the JSON-serialized value of each item of the + // `LocalSecondaryIndexes` request field. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: '{ "IndexARN": "string", "IndexName": "string", + // "IndexSizeBytes": number, "ItemCount": number, "KeySchema": [ { + // "AttributeName": "string", "KeyType": "string" } ], "Projection": { + // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" } }' + AWSDynamoDBLocalSecondaryIndexesKey = attribute.Key("aws.dynamodb.local_secondary_indexes") +) + +// AWSDynamoDBGlobalSecondaryIndexes returns an attribute KeyValue +// conforming to the "aws.dynamodb.global_secondary_indexes" semantic +// conventions. It represents the JSON-serialized value of each item of the +// `GlobalSecondaryIndexes` request field +func AWSDynamoDBGlobalSecondaryIndexes(val ...string) attribute.KeyValue { + return AWSDynamoDBGlobalSecondaryIndexesKey.StringSlice(val) +} + +// AWSDynamoDBLocalSecondaryIndexes returns an attribute KeyValue conforming +// to the "aws.dynamodb.local_secondary_indexes" semantic conventions. It +// represents the JSON-serialized value of each item of the +// `LocalSecondaryIndexes` request field. +func AWSDynamoDBLocalSecondaryIndexes(val ...string) attribute.KeyValue { + return AWSDynamoDBLocalSecondaryIndexesKey.StringSlice(val) +} + +// DynamoDB.ListTables +const ( + // AWSDynamoDBExclusiveStartTableKey is the attribute Key conforming to the + // "aws.dynamodb.exclusive_start_table" semantic conventions. It represents + // the value of the `ExclusiveStartTableName` request parameter. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'Users', 'CatsTable' + AWSDynamoDBExclusiveStartTableKey = attribute.Key("aws.dynamodb.exclusive_start_table") + + // AWSDynamoDBTableCountKey is the attribute Key conforming to the + // "aws.dynamodb.table_count" semantic conventions. It represents the the + // number of items in the `TableNames` response parameter. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 20 + AWSDynamoDBTableCountKey = attribute.Key("aws.dynamodb.table_count") +) + +// AWSDynamoDBExclusiveStartTable returns an attribute KeyValue conforming +// to the "aws.dynamodb.exclusive_start_table" semantic conventions. It +// represents the value of the `ExclusiveStartTableName` request parameter. +func AWSDynamoDBExclusiveStartTable(val string) attribute.KeyValue { + return AWSDynamoDBExclusiveStartTableKey.String(val) +} + +// AWSDynamoDBTableCount returns an attribute KeyValue conforming to the +// "aws.dynamodb.table_count" semantic conventions. It represents the the +// number of items in the `TableNames` response parameter. +func AWSDynamoDBTableCount(val int) attribute.KeyValue { + return AWSDynamoDBTableCountKey.Int(val) +} + +// DynamoDB.Query +const ( + // AWSDynamoDBScanForwardKey is the attribute Key conforming to the + // "aws.dynamodb.scan_forward" semantic conventions. It represents the + // value of the `ScanIndexForward` request parameter. + // + // Type: boolean + // RequirementLevel: Optional + // Stability: experimental + AWSDynamoDBScanForwardKey = attribute.Key("aws.dynamodb.scan_forward") +) + +// AWSDynamoDBScanForward returns an attribute KeyValue conforming to the +// "aws.dynamodb.scan_forward" semantic conventions. It represents the value of +// the `ScanIndexForward` request parameter. +func AWSDynamoDBScanForward(val bool) attribute.KeyValue { + return AWSDynamoDBScanForwardKey.Bool(val) +} + +// DynamoDB.Scan +const ( + // AWSDynamoDBCountKey is the attribute Key conforming to the + // "aws.dynamodb.count" semantic conventions. It represents the value of + // the `Count` response parameter. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 10 + AWSDynamoDBCountKey = attribute.Key("aws.dynamodb.count") + + // AWSDynamoDBScannedCountKey is the attribute Key conforming to the + // "aws.dynamodb.scanned_count" semantic conventions. It represents the + // value of the `ScannedCount` response parameter. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 50 + AWSDynamoDBScannedCountKey = attribute.Key("aws.dynamodb.scanned_count") + + // AWSDynamoDBSegmentKey is the attribute Key conforming to the + // "aws.dynamodb.segment" semantic conventions. It represents the value of + // the `Segment` request parameter. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 10 + AWSDynamoDBSegmentKey = attribute.Key("aws.dynamodb.segment") + + // AWSDynamoDBTotalSegmentsKey is the attribute Key conforming to the + // "aws.dynamodb.total_segments" semantic conventions. It represents the + // value of the `TotalSegments` request parameter. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 100 + AWSDynamoDBTotalSegmentsKey = attribute.Key("aws.dynamodb.total_segments") +) + +// AWSDynamoDBCount returns an attribute KeyValue conforming to the +// "aws.dynamodb.count" semantic conventions. It represents the value of the +// `Count` response parameter. +func AWSDynamoDBCount(val int) attribute.KeyValue { + return AWSDynamoDBCountKey.Int(val) +} + +// AWSDynamoDBScannedCount returns an attribute KeyValue conforming to the +// "aws.dynamodb.scanned_count" semantic conventions. It represents the value +// of the `ScannedCount` response parameter. +func AWSDynamoDBScannedCount(val int) attribute.KeyValue { + return AWSDynamoDBScannedCountKey.Int(val) +} + +// AWSDynamoDBSegment returns an attribute KeyValue conforming to the +// "aws.dynamodb.segment" semantic conventions. It represents the value of the +// `Segment` request parameter. +func AWSDynamoDBSegment(val int) attribute.KeyValue { + return AWSDynamoDBSegmentKey.Int(val) +} + +// AWSDynamoDBTotalSegments returns an attribute KeyValue conforming to the +// "aws.dynamodb.total_segments" semantic conventions. It represents the value +// of the `TotalSegments` request parameter. +func AWSDynamoDBTotalSegments(val int) attribute.KeyValue { + return AWSDynamoDBTotalSegmentsKey.Int(val) +} + +// DynamoDB.UpdateTable +const ( + // AWSDynamoDBAttributeDefinitionsKey is the attribute Key conforming to + // the "aws.dynamodb.attribute_definitions" semantic conventions. It + // represents the JSON-serialized value of each item in the + // `AttributeDefinitions` request field. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: '{ "AttributeName": "string", "AttributeType": "string" }' + AWSDynamoDBAttributeDefinitionsKey = attribute.Key("aws.dynamodb.attribute_definitions") + + // AWSDynamoDBGlobalSecondaryIndexUpdatesKey is the attribute Key + // conforming to the "aws.dynamodb.global_secondary_index_updates" semantic + // conventions. It represents the JSON-serialized value of each item in the + // the `GlobalSecondaryIndexUpdates` request field. + // + // Type: string[] + // RequirementLevel: Optional + // Stability: experimental + // Examples: '{ "Create": { "IndexName": "string", "KeySchema": [ { + // "AttributeName": "string", "KeyType": "string" } ], "Projection": { + // "NonKeyAttributes": [ "string" ], "ProjectionType": "string" }, + // "ProvisionedThroughput": { "ReadCapacityUnits": number, + // "WriteCapacityUnits": number } }' + AWSDynamoDBGlobalSecondaryIndexUpdatesKey = attribute.Key("aws.dynamodb.global_secondary_index_updates") +) + +// AWSDynamoDBAttributeDefinitions returns an attribute KeyValue conforming +// to the "aws.dynamodb.attribute_definitions" semantic conventions. It +// represents the JSON-serialized value of each item in the +// `AttributeDefinitions` request field. +func AWSDynamoDBAttributeDefinitions(val ...string) attribute.KeyValue { + return AWSDynamoDBAttributeDefinitionsKey.StringSlice(val) +} + +// AWSDynamoDBGlobalSecondaryIndexUpdates returns an attribute KeyValue +// conforming to the "aws.dynamodb.global_secondary_index_updates" semantic +// conventions. It represents the JSON-serialized value of each item in the the +// `GlobalSecondaryIndexUpdates` request field. +func AWSDynamoDBGlobalSecondaryIndexUpdates(val ...string) attribute.KeyValue { + return AWSDynamoDBGlobalSecondaryIndexUpdatesKey.StringSlice(val) +} + +// Attributes that exist for S3 request types. +const ( + // AWSS3BucketKey is the attribute Key conforming to the "aws.s3.bucket" + // semantic conventions. It represents the S3 bucket name the request + // refers to. Corresponds to the `--bucket` parameter of the [S3 + // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) + // operations. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'some-bucket-name' + // Note: The `bucket` attribute is applicable to all S3 operations that + // reference a bucket, i.e. that require the bucket name as a mandatory + // parameter. + // This applies to almost all S3 operations except `list-buckets`. + AWSS3BucketKey = attribute.Key("aws.s3.bucket") + + // AWSS3CopySourceKey is the attribute Key conforming to the + // "aws.s3.copy_source" semantic conventions. It represents the source + // object (in the form `bucket`/`key`) for the copy operation. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'someFile.yml' + // Note: The `copy_source` attribute applies to S3 copy operations and + // corresponds to the `--copy-source` parameter + // of the [copy-object operation within the S3 + // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html). + // This applies in particular to the following operations: + // + // - + // [copy-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html) + // - + // [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html) + AWSS3CopySourceKey = attribute.Key("aws.s3.copy_source") + + // AWSS3DeleteKey is the attribute Key conforming to the "aws.s3.delete" + // semantic conventions. It represents the delete request container that + // specifies the objects to be deleted. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: + // 'Objects=[{Key=string,VersionID=string},{Key=string,VersionID=string}],Quiet=boolean' + // Note: The `delete` attribute is only applicable to the + // [delete-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html) + // operation. + // The `delete` attribute corresponds to the `--delete` parameter of the + // [delete-objects operation within the S3 + // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-objects.html). + AWSS3DeleteKey = attribute.Key("aws.s3.delete") + + // AWSS3KeyKey is the attribute Key conforming to the "aws.s3.key" semantic + // conventions. It represents the S3 object key the request refers to. + // Corresponds to the `--key` parameter of the [S3 + // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) + // operations. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'someFile.yml' + // Note: The `key` attribute is applicable to all object-related S3 + // operations, i.e. that require the object key as a mandatory parameter. + // This applies in particular to the following operations: + // + // - + // [copy-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/copy-object.html) + // - + // [delete-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html) + // - + // [get-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/get-object.html) + // - + // [head-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/head-object.html) + // - + // [put-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/put-object.html) + // - + // [restore-object](https://docs.aws.amazon.com/cli/latest/reference/s3api/restore-object.html) + // - + // [select-object-content](https://docs.aws.amazon.com/cli/latest/reference/s3api/select-object-content.html) + // - + // [abort-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html) + // - + // [complete-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html) + // - + // [create-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/create-multipart-upload.html) + // - + // [list-parts](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html) + // - + // [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html) + // - + // [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html) + AWSS3KeyKey = attribute.Key("aws.s3.key") + + // AWSS3PartNumberKey is the attribute Key conforming to the + // "aws.s3.part_number" semantic conventions. It represents the part number + // of the part being uploaded in a multipart-upload operation. This is a + // positive integer between 1 and 10,000. + // + // Type: int + // RequirementLevel: Optional + // Stability: experimental + // Examples: 3456 + // Note: The `part_number` attribute is only applicable to the + // [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html) + // and + // [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html) + // operations. + // The `part_number` attribute corresponds to the `--part-number` parameter + // of the + // [upload-part operation within the S3 + // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html). + AWSS3PartNumberKey = attribute.Key("aws.s3.part_number") + + // AWSS3UploadIDKey is the attribute Key conforming to the + // "aws.s3.upload_id" semantic conventions. It represents the upload ID + // that identifies the multipart upload. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'dfRtDYWFbkRONycy.Yxwh66Yjlx.cph0gtNBtJ' + // Note: The `upload_id` attribute applies to S3 multipart-upload + // operations and corresponds to the `--upload-id` parameter + // of the [S3 + // API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) + // multipart operations. + // This applies in particular to the following operations: + // + // - + // [abort-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/abort-multipart-upload.html) + // - + // [complete-multipart-upload](https://docs.aws.amazon.com/cli/latest/reference/s3api/complete-multipart-upload.html) + // - + // [list-parts](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-parts.html) + // - + // [upload-part](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part.html) + // - + // [upload-part-copy](https://docs.aws.amazon.com/cli/latest/reference/s3api/upload-part-copy.html) + AWSS3UploadIDKey = attribute.Key("aws.s3.upload_id") +) + +// AWSS3Bucket returns an attribute KeyValue conforming to the +// "aws.s3.bucket" semantic conventions. It represents the S3 bucket name the +// request refers to. Corresponds to the `--bucket` parameter of the [S3 +// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) +// operations. +func AWSS3Bucket(val string) attribute.KeyValue { + return AWSS3BucketKey.String(val) +} + +// AWSS3CopySource returns an attribute KeyValue conforming to the +// "aws.s3.copy_source" semantic conventions. It represents the source object +// (in the form `bucket`/`key`) for the copy operation. +func AWSS3CopySource(val string) attribute.KeyValue { + return AWSS3CopySourceKey.String(val) +} + +// AWSS3Delete returns an attribute KeyValue conforming to the +// "aws.s3.delete" semantic conventions. It represents the delete request +// container that specifies the objects to be deleted. +func AWSS3Delete(val string) attribute.KeyValue { + return AWSS3DeleteKey.String(val) +} + +// AWSS3Key returns an attribute KeyValue conforming to the "aws.s3.key" +// semantic conventions. It represents the S3 object key the request refers to. +// Corresponds to the `--key` parameter of the [S3 +// API](https://docs.aws.amazon.com/cli/latest/reference/s3api/index.html) +// operations. +func AWSS3Key(val string) attribute.KeyValue { + return AWSS3KeyKey.String(val) +} + +// AWSS3PartNumber returns an attribute KeyValue conforming to the +// "aws.s3.part_number" semantic conventions. It represents the part number of +// the part being uploaded in a multipart-upload operation. This is a positive +// integer between 1 and 10,000. +func AWSS3PartNumber(val int) attribute.KeyValue { + return AWSS3PartNumberKey.Int(val) +} + +// AWSS3UploadID returns an attribute KeyValue conforming to the +// "aws.s3.upload_id" semantic conventions. It represents the upload ID that +// identifies the multipart upload. +func AWSS3UploadID(val string) attribute.KeyValue { + return AWSS3UploadIDKey.String(val) +} + +// Semantic conventions to apply when instrumenting the GraphQL implementation. +// They map GraphQL operations to attributes on a Span. +const ( + // GraphqlDocumentKey is the attribute Key conforming to the + // "graphql.document" semantic conventions. It represents the GraphQL + // document being executed. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'query findBookByID { bookByID(id: ?) { name } }' + // Note: The value may be sanitized to exclude sensitive information. + GraphqlDocumentKey = attribute.Key("graphql.document") + + // GraphqlOperationNameKey is the attribute Key conforming to the + // "graphql.operation.name" semantic conventions. It represents the name of + // the operation being executed. + // + // Type: string + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'findBookByID' + GraphqlOperationNameKey = attribute.Key("graphql.operation.name") + + // GraphqlOperationTypeKey is the attribute Key conforming to the + // "graphql.operation.type" semantic conventions. It represents the type of + // the operation being executed. + // + // Type: Enum + // RequirementLevel: Optional + // Stability: experimental + // Examples: 'query', 'mutation', 'subscription' + GraphqlOperationTypeKey = attribute.Key("graphql.operation.type") +) + +var ( + // GraphQL query + GraphqlOperationTypeQuery = GraphqlOperationTypeKey.String("query") + // GraphQL mutation + GraphqlOperationTypeMutation = GraphqlOperationTypeKey.String("mutation") + // GraphQL subscription + GraphqlOperationTypeSubscription = GraphqlOperationTypeKey.String("subscription") +) + +// GraphqlDocument returns an attribute KeyValue conforming to the +// "graphql.document" semantic conventions. It represents the GraphQL document +// being executed. +func GraphqlDocument(val string) attribute.KeyValue { + return GraphqlDocumentKey.String(val) +} + +// GraphqlOperationName returns an attribute KeyValue conforming to the +// "graphql.operation.name" semantic conventions. It represents the name of the +// operation being executed. +func GraphqlOperationName(val string) attribute.KeyValue { + return GraphqlOperationNameKey.String(val) +} diff --git a/vendor/go.opentelemetry.io/otel/trace/tracestate.go b/vendor/go.opentelemetry.io/otel/trace/tracestate.go index d1e47ca2fa..db936ba5b7 100644 --- a/vendor/go.opentelemetry.io/otel/trace/tracestate.go +++ b/vendor/go.opentelemetry.io/otel/trace/tracestate.go @@ -17,20 +17,14 @@ package trace // import "go.opentelemetry.io/otel/trace" import ( "encoding/json" "fmt" - "regexp" "strings" ) const ( maxListMembers = 32 - listDelimiter = "," - - // based on the W3C Trace Context specification, see - // https://www.w3.org/TR/trace-context-1/#tracestate-header - noTenantKeyFormat = `[a-z][_0-9a-z\-\*\/]*` - withTenantKeyFormat = `[a-z0-9][_0-9a-z\-\*\/]*@[a-z][_0-9a-z\-\*\/]*` - valueFormat = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]*[\x21-\x2b\x2d-\x3c\x3e-\x7e]` + listDelimiters = "," + memberDelimiter = "=" errInvalidKey errorConst = "invalid tracestate key" errInvalidValue errorConst = "invalid tracestate value" @@ -39,43 +33,128 @@ const ( errDuplicate errorConst = "duplicate list-member in tracestate" ) -var ( - noTenantKeyRe = regexp.MustCompile(`^` + noTenantKeyFormat + `$`) - withTenantKeyRe = regexp.MustCompile(`^` + withTenantKeyFormat + `$`) - valueRe = regexp.MustCompile(`^` + valueFormat + `$`) - memberRe = regexp.MustCompile(`^\s*((?:` + noTenantKeyFormat + `)|(?:` + withTenantKeyFormat + `))=(` + valueFormat + `)\s*$`) -) - type member struct { Key string Value string } +// according to (chr = %x20 / (nblk-char = %x21-2B / %x2D-3C / %x3E-7E) ) +// means (chr = %x20-2B / %x2D-3C / %x3E-7E) . +func checkValueChar(v byte) bool { + return v >= '\x20' && v <= '\x7e' && v != '\x2c' && v != '\x3d' +} + +// according to (nblk-chr = %x21-2B / %x2D-3C / %x3E-7E) . +func checkValueLast(v byte) bool { + return v >= '\x21' && v <= '\x7e' && v != '\x2c' && v != '\x3d' +} + +// based on the W3C Trace Context specification +// +// value = (0*255(chr)) nblk-chr +// nblk-chr = %x21-2B / %x2D-3C / %x3E-7E +// chr = %x20 / nblk-chr +// +// see https://www.w3.org/TR/trace-context-1/#value +func checkValue(val string) bool { + n := len(val) + if n == 0 || n > 256 { + return false + } + for i := 0; i < n-1; i++ { + if !checkValueChar(val[i]) { + return false + } + } + return checkValueLast(val[n-1]) +} + +func checkKeyRemain(key string) bool { + // ( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ) + for _, v := range key { + if isAlphaNum(byte(v)) { + continue + } + switch v { + case '_', '-', '*', '/': + continue + } + return false + } + return true +} + +// according to +// +// simple-key = lcalpha (0*255( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )) +// system-id = lcalpha (0*13( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )) +// +// param n is remain part length, should be 255 in simple-key or 13 in system-id. +func checkKeyPart(key string, n int) bool { + if len(key) == 0 { + return false + } + first := key[0] // key's first char + ret := len(key[1:]) <= n + ret = ret && first >= 'a' && first <= 'z' + return ret && checkKeyRemain(key[1:]) +} + +func isAlphaNum(c byte) bool { + if c >= 'a' && c <= 'z' { + return true + } + return c >= '0' && c <= '9' +} + +// according to +// +// tenant-id = ( lcalpha / DIGIT ) 0*240( lcalpha / DIGIT / "_" / "-"/ "*" / "/" ) +// +// param n is remain part length, should be 240 exactly. +func checkKeyTenant(key string, n int) bool { + if len(key) == 0 { + return false + } + return isAlphaNum(key[0]) && len(key[1:]) <= n && checkKeyRemain(key[1:]) +} + +// based on the W3C Trace Context specification +// +// key = simple-key / multi-tenant-key +// simple-key = lcalpha (0*255( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )) +// multi-tenant-key = tenant-id "@" system-id +// tenant-id = ( lcalpha / DIGIT ) (0*240( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )) +// system-id = lcalpha (0*13( lcalpha / DIGIT / "_" / "-"/ "*" / "/" )) +// lcalpha = %x61-7A ; a-z +// +// see https://www.w3.org/TR/trace-context-1/#tracestate-header. +func checkKey(key string) bool { + tenant, system, ok := strings.Cut(key, "@") + if !ok { + return checkKeyPart(key, 255) + } + return checkKeyTenant(tenant, 240) && checkKeyPart(system, 13) +} + func newMember(key, value string) (member, error) { - if len(key) > 256 { - return member{}, fmt.Errorf("%w: %s", errInvalidKey, key) + if !checkKey(key) { + return member{}, errInvalidKey } - if !noTenantKeyRe.MatchString(key) { - if !withTenantKeyRe.MatchString(key) { - return member{}, fmt.Errorf("%w: %s", errInvalidKey, key) - } - atIndex := strings.LastIndex(key, "@") - if atIndex > 241 || len(key)-1-atIndex > 14 { - return member{}, fmt.Errorf("%w: %s", errInvalidKey, key) - } - } - if len(value) > 256 || !valueRe.MatchString(value) { - return member{}, fmt.Errorf("%w: %s", errInvalidValue, value) + if !checkValue(value) { + return member{}, errInvalidValue } return member{Key: key, Value: value}, nil } func parseMember(m string) (member, error) { - matches := memberRe.FindStringSubmatch(m) - if len(matches) != 3 { + key, val, ok := strings.Cut(m, memberDelimiter) + if !ok { return member{}, fmt.Errorf("%w: %s", errInvalidMember, m) } - result, e := newMember(matches[1], matches[2]) + key = strings.TrimLeft(key, " \t") + val = strings.TrimRight(val, " \t") + result, e := newMember(key, val) if e != nil { return member{}, fmt.Errorf("%w: %s", errInvalidMember, m) } @@ -85,7 +164,7 @@ func parseMember(m string) (member, error) { // String encodes member into a string compliant with the W3C Trace Context // specification. func (m member) String() string { - return fmt.Sprintf("%s=%s", m.Key, m.Value) + return m.Key + "=" + m.Value } // TraceState provides additional vendor-specific trace identification @@ -109,8 +188,8 @@ var _ json.Marshaler = TraceState{} // ParseTraceState attempts to decode a TraceState from the passed // string. It returns an error if the input is invalid according to the W3C // Trace Context specification. -func ParseTraceState(tracestate string) (TraceState, error) { - if tracestate == "" { +func ParseTraceState(ts string) (TraceState, error) { + if ts == "" { return TraceState{}, nil } @@ -120,7 +199,9 @@ func ParseTraceState(tracestate string) (TraceState, error) { var members []member found := make(map[string]struct{}) - for _, memberStr := range strings.Split(tracestate, listDelimiter) { + for ts != "" { + var memberStr string + memberStr, ts, _ = strings.Cut(ts, listDelimiters) if len(memberStr) == 0 { continue } @@ -153,11 +234,29 @@ func (ts TraceState) MarshalJSON() ([]byte, error) { // Trace Context specification. The returned string will be invalid if the // TraceState contains any invalid members. func (ts TraceState) String() string { - members := make([]string, len(ts.list)) - for i, m := range ts.list { - members[i] = m.String() + if len(ts.list) == 0 { + return "" } - return strings.Join(members, listDelimiter) + var n int + n += len(ts.list) // member delimiters: '=' + n += len(ts.list) - 1 // list delimiters: ',' + for _, mem := range ts.list { + n += len(mem.Key) + n += len(mem.Value) + } + + var sb strings.Builder + sb.Grow(n) + _, _ = sb.WriteString(ts.list[0].Key) + _ = sb.WriteByte('=') + _, _ = sb.WriteString(ts.list[0].Value) + for i := 1; i < len(ts.list); i++ { + _ = sb.WriteByte(listDelimiters[0]) + _, _ = sb.WriteString(ts.list[i].Key) + _ = sb.WriteByte('=') + _, _ = sb.WriteString(ts.list[i].Value) + } + return sb.String() } // Get returns the value paired with key from the corresponding TraceState @@ -189,15 +288,25 @@ func (ts TraceState) Insert(key, value string) (TraceState, error) { if err != nil { return ts, err } - - cTS := ts.Delete(key) - if cTS.Len()+1 <= maxListMembers { - cTS.list = append(cTS.list, member{}) + n := len(ts.list) + found := n + for i := range ts.list { + if ts.list[i].Key == key { + found = i + } + } + cTS := TraceState{} + if found == n && n < maxListMembers { + cTS.list = make([]member, n+1) + } else { + cTS.list = make([]member, n) } - // When the number of members exceeds capacity, drop the "right-most". - copy(cTS.list[1:], cTS.list) cTS.list[0] = m - + // When the number of members exceeds capacity, drop the "right-most". + copy(cTS.list[1:], ts.list[0:found]) + if found < n { + copy(cTS.list[1+found:], ts.list[found+1:]) + } return cTS, nil } diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go index e2f743585d..c7aba1c3f4 100644 --- a/vendor/go.opentelemetry.io/otel/version.go +++ b/vendor/go.opentelemetry.io/otel/version.go @@ -16,5 +16,5 @@ package otel // import "go.opentelemetry.io/otel" // Version is the current release version of OpenTelemetry in use. func Version() string { - return "1.21.0" + return "1.22.0" } diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml index 3c153c9d6f..a9cfb80ae5 100644 --- a/vendor/go.opentelemetry.io/otel/versions.yaml +++ b/vendor/go.opentelemetry.io/otel/versions.yaml @@ -14,7 +14,7 @@ module-sets: stable-v1: - version: v1.21.0 + version: v1.22.0 modules: - go.opentelemetry.io/otel - go.opentelemetry.io/otel/bridge/opentracing @@ -34,7 +34,7 @@ module-sets: - go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/trace experimental-metrics: - version: v0.44.0 + version: v0.45.0 modules: - go.opentelemetry.io/otel/bridge/opencensus - go.opentelemetry.io/otel/bridge/opencensus/test diff --git a/vendor/modules.txt b/vendor/modules.txt index 8feed6370a..7d8481d6da 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -901,7 +901,7 @@ github.com/go-ldap/ldif # github.com/go-logfmt/logfmt v0.5.1 ## explicit; go 1.17 github.com/go-logfmt/logfmt -# github.com/go-logr/logr v1.3.0 +# github.com/go-logr/logr v1.4.1 ## explicit; go 1.18 github.com/go-logr/logr github.com/go-logr/logr/funcr @@ -1928,7 +1928,7 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvut ## explicit; go 1.20 go.opentelemetry.io/contrib/zpages go.opentelemetry.io/contrib/zpages/internal -# go.opentelemetry.io/otel v1.21.0 +# go.opentelemetry.io/otel v1.22.0 ## explicit; go 1.20 go.opentelemetry.io/otel go.opentelemetry.io/otel/attribute @@ -1944,6 +1944,7 @@ go.opentelemetry.io/otel/semconv/v1.10.0 go.opentelemetry.io/otel/semconv/v1.17.0 go.opentelemetry.io/otel/semconv/v1.20.0 go.opentelemetry.io/otel/semconv/v1.21.0 +go.opentelemetry.io/otel/semconv/v1.24.0 go.opentelemetry.io/otel/semconv/v1.4.0 # go.opentelemetry.io/otel/exporters/jaeger v1.17.0 ## explicit; go 1.19 @@ -1963,11 +1964,11 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry -# go.opentelemetry.io/otel/metric v1.21.0 +# go.opentelemetry.io/otel/metric v1.22.0 ## explicit; go 1.20 go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric/embedded -# go.opentelemetry.io/otel/sdk v1.21.0 +# go.opentelemetry.io/otel/sdk v1.22.0 ## explicit; go 1.20 go.opentelemetry.io/otel/sdk go.opentelemetry.io/otel/sdk/instrumentation @@ -1975,7 +1976,7 @@ go.opentelemetry.io/otel/sdk/internal go.opentelemetry.io/otel/sdk/internal/env go.opentelemetry.io/otel/sdk/resource go.opentelemetry.io/otel/sdk/trace -# go.opentelemetry.io/otel/trace v1.21.0 +# go.opentelemetry.io/otel/trace v1.22.0 ## explicit; go 1.20 go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace/embedded From fafe08e9b0cac58b903c939bfc4ab0bbde2934c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jan 2024 06:50:24 +0000 Subject: [PATCH 16/73] build(deps): bump github.com/onsi/gomega from 1.30.0 to 1.31.0 Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.30.0 to 1.31.0. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.30.0...v1.31.0) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- vendor/github.com/onsi/gomega/CHANGELOG.md | 14 ++++++++++++++ vendor/github.com/onsi/gomega/gomega_dsl.go | 2 +- .../onsi/gomega/internal/async_assertion.go | 7 ++++++- vendor/github.com/onsi/gomega/matchers.go | 2 +- vendor/modules.txt | 4 ++-- 7 files changed, 27 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index b571bddb4e..b210eb0a8a 100644 --- a/go.mod +++ b/go.mod @@ -66,7 +66,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo v1.16.5 github.com/onsi/ginkgo/v2 v2.14.0 - github.com/onsi/gomega v1.30.0 + github.com/onsi/gomega v1.31.0 github.com/open-policy-agent/opa v0.60.0 github.com/orcaman/concurrent-map v1.0.0 github.com/owncloud/libre-graph-api-go v1.0.5-0.20240115110609-b018a896364e diff --git a/go.sum b/go.sum index a7c1a6fcad..1258eff89c 100644 --- a/go.sum +++ b/go.sum @@ -1775,8 +1775,8 @@ github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27H github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= +github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= github.com/open-policy-agent/opa v0.60.0 h1:ZPoPt4yeNs5UXCpd/P/btpSyR8CR0wfhVoh9BOwgJNs= github.com/open-policy-agent/opa v0.60.0/go.mod h1:aD5IK6AiLNYBjNXn7E02++yC8l4Z+bRDvgM6Ss0bBzA= github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0pfj+ynAqBxo3v6u9w= diff --git a/vendor/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md index fe72a7b183..fece58b111 100644 --- a/vendor/github.com/onsi/gomega/CHANGELOG.md +++ b/vendor/github.com/onsi/gomega/CHANGELOG.md @@ -1,3 +1,17 @@ +## 1.31.0 + +### Features +- Async assertions include context cancellation cause if present [121c37f] + +### Maintenance +- Bump minimum go version [dee1e3c] +- docs: fix typo in example usage "occured" -> "occurred" [49005fe] +- Bump actions/setup-go from 4 to 5 (#714) [f1c8757] +- Bump github/codeql-action from 2 to 3 (#715) [9836e76] +- Bump github.com/onsi/ginkgo/v2 from 2.13.0 to 2.13.2 (#713) [54726f0] +- Bump golang.org/x/net from 0.17.0 to 0.19.0 (#711) [df97ecc] +- docs: fix `HaveExactElement` typo (#712) [a672c86] + ## 1.30.0 ### Features diff --git a/vendor/github.com/onsi/gomega/gomega_dsl.go b/vendor/github.com/onsi/gomega/gomega_dsl.go index c271a366ae..4f7ab2791b 100644 --- a/vendor/github.com/onsi/gomega/gomega_dsl.go +++ b/vendor/github.com/onsi/gomega/gomega_dsl.go @@ -22,7 +22,7 @@ import ( "github.com/onsi/gomega/types" ) -const GOMEGA_VERSION = "1.30.0" +const GOMEGA_VERSION = "1.31.0" const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler. If you're using Ginkgo then you probably forgot to put your assertion in an It(). diff --git a/vendor/github.com/onsi/gomega/internal/async_assertion.go b/vendor/github.com/onsi/gomega/internal/async_assertion.go index 1188b0bce3..cde9e2ec8b 100644 --- a/vendor/github.com/onsi/gomega/internal/async_assertion.go +++ b/vendor/github.com/onsi/gomega/internal/async_assertion.go @@ -553,7 +553,12 @@ func (assertion *AsyncAssertion) match(matcher types.GomegaMatcher, desiredMatch lock.Unlock() } case <-contextDone: - fail("Context was cancelled") + err := context.Cause(assertion.ctx) + if err != nil && err != context.Canceled { + fail(fmt.Sprintf("Context was cancelled (cause: %s)", err)) + } else { + fail("Context was cancelled") + } return false case <-timeout: if assertion.asyncType == AsyncAssertionTypeEventually { diff --git a/vendor/github.com/onsi/gomega/matchers.go b/vendor/github.com/onsi/gomega/matchers.go index 43f994374d..8860d677fc 100644 --- a/vendor/github.com/onsi/gomega/matchers.go +++ b/vendor/github.com/onsi/gomega/matchers.go @@ -394,7 +394,7 @@ func ConsistOf(elements ...interface{}) types.GomegaMatcher { } } -// HaveExactElemets succeeds if actual contains elements that precisely match the elemets passed into the matcher. The ordering of the elements does matter. +// HaveExactElements succeeds if actual contains elements that precisely match the elemets passed into the matcher. The ordering of the elements does matter. // By default HaveExactElements() uses Equal() to match the elements, however custom matchers can be passed in instead. Here are some examples: // // Expect([]string{"Foo", "FooBar"}).Should(HaveExactElements("Foo", "FooBar")) diff --git a/vendor/modules.txt b/vendor/modules.txt index 7d8481d6da..9b740bc36a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1478,8 +1478,8 @@ github.com/onsi/ginkgo/v2/internal/parallel_support github.com/onsi/ginkgo/v2/internal/testingtproxy github.com/onsi/ginkgo/v2/reporters github.com/onsi/ginkgo/v2/types -# github.com/onsi/gomega v1.30.0 -## explicit; go 1.18 +# github.com/onsi/gomega v1.31.0 +## explicit; go 1.20 github.com/onsi/gomega github.com/onsi/gomega/format github.com/onsi/gomega/internal From 448916a9dd3b1169a5a4308b06db56f2773012c5 Mon Sep 17 00:00:00 2001 From: nirajacharya2 <122071597+nirajacharya2@users.noreply.github.com> Date: Thu, 18 Jan 2024 15:14:10 +0545 Subject: [PATCH 17/73] [tests-only][full-ci] forward port user and group search tests (#8240) * fixing json assertion for addUserToGroup.feature * adding tests for searching groups as a normal user * adding tests for searching user as a normal user * fixing json assertion for removeUserFromGroup.feature * fixing json assertion for listPermissions.feature --- tests/TestHelpers/GraphHelper.php | 52 ++++++ ...ected-failures-localAPI-on-OCIS-storage.md | 60 +++---- .../features/apiGraph/addUserToGroup.feature | 12 +- .../features/apiGraph/getGroup.feature | 138 +++++++++++++++- .../features/apiGraph/getUser.feature | 152 +++++++++++++++--- .../apiGraph/removeUserFromGroup.feature | 6 +- .../apiSharingNg/listPermissions.feature | 47 +++--- .../features/bootstrap/GraphContext.php | 44 +++++ 8 files changed, 424 insertions(+), 87 deletions(-) diff --git a/tests/TestHelpers/GraphHelper.php b/tests/TestHelpers/GraphHelper.php index f4a2ce846d..a60586fdc0 100644 --- a/tests/TestHelpers/GraphHelper.php +++ b/tests/TestHelpers/GraphHelper.php @@ -259,6 +259,32 @@ class GraphHelper { ); } + /** + * @param string $baseUrl + * @param string $xRequestId + * @param string $adminUser + * @param string $adminPassword + * @param string $searchTerm + * + * @return ResponseInterface + */ + public static function searchUser( + string $baseUrl, + string $xRequestId, + string $adminUser, + string $adminPassword, + string $searchTerm + ): ResponseInterface { + $url = self::getFullUrl($baseUrl, "users?\$search=$searchTerm"); + return HttpRequestHelper::get( + $url, + $xRequestId, + $adminUser, + $adminPassword, + self::getRequestHeaders() + ); + } + /** * @param string $baseUrl * @param string $xRequestId @@ -554,6 +580,32 @@ class GraphHelper { ); } + /** + * @param string $baseUrl + * @param string $xRequestId + * @param string $user + * @param string $password + * @param string $searchTerm + * + * @return ResponseInterface + */ + public static function searchGroup( + string $baseUrl, + string $xRequestId, + string $user, + string $password, + string $searchTerm + ): ResponseInterface { + $url = self::getFullUrl($baseUrl, "groups?\$search=$searchTerm"); + return HttpRequestHelper::get( + $url, + $xRequestId, + $user, + $password, + self::getRequestHeaders() + ); + } + /** * @param string $baseUrl * @param string $xRequestId diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index 798ad62002..72a9ec5106 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -59,8 +59,6 @@ The expected failures in this file are from features in the owncloud/ocis repo. #### [A User can get information of another user with Graph API](https://github.com/owncloud/ocis/issues/5125) -- [apiGraph/getUser.feature:87](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L87) -- [apiGraph/getUser.feature:88](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L88) - [apiGraph/getUser.feature:89](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L89) - [apiGraph/getUser.feature:90](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L90) - [apiGraph/getUser.feature:91](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L91) @@ -71,37 +69,39 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiGraph/getUser.feature:96](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L96) - [apiGraph/getUser.feature:97](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L97) - [apiGraph/getUser.feature:98](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L98) -- [apiGraph/getUser.feature:642](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L642) -- [apiGraph/getUser.feature:643](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L643) -- [apiGraph/getUser.feature:644](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L644) -- [apiGraph/getUser.feature:645](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L645) -- [apiGraph/getUser.feature:646](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L646) -- [apiGraph/getUser.feature:647](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L647) -- [apiGraph/getUser.feature:648](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L648) -- [apiGraph/getUser.feature:649](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L649) +- [apiGraph/getUser.feature:99](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L99) +- [apiGraph/getUser.feature:100](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L100) - [apiGraph/getUser.feature:650](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L650) - [apiGraph/getUser.feature:651](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L651) - [apiGraph/getUser.feature:652](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L652) - [apiGraph/getUser.feature:653](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L653) +- [apiGraph/getUser.feature:654](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L654) +- [apiGraph/getUser.feature:655](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L655) +- [apiGraph/getUser.feature:656](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L656) +- [apiGraph/getUser.feature:657](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L657) +- [apiGraph/getUser.feature:658](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L658) +- [apiGraph/getUser.feature:659](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L659) +- [apiGraph/getUser.feature:660](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L660) +- [apiGraph/getUser.feature:661](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L661) #### [Normal user can get expanded members information of a group](https://github.com/owncloud/ocis/issues/5604) -- [apiGraph/getGroup.feature:381](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L381) -- [apiGraph/getGroup.feature:382](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L382) -- [apiGraph/getGroup.feature:383](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L383) +- [apiGraph/getGroup.feature:389](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L389) +- [apiGraph/getGroup.feature:390](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L390) +- [apiGraph/getGroup.feature:391](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L391) #### [Same users can be added in a group multiple time](https://github.com/owncloud/ocis/issues/5702) -- [apiGraph/addUserToGroup.feature:285](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L285) +- [apiGraph/addUserToGroup.feature:289](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L289) #### [API requests from an unauthorized user should return 403](https://github.com/owncloud/ocis/issues/5938) -- [apiGraph/addUserToGroup.feature:150](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L150) -- [apiGraph/addUserToGroup.feature:151](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L151) - [apiGraph/addUserToGroup.feature:152](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L152) -- [apiGraph/addUserToGroup.feature:184](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L184) -- [apiGraph/addUserToGroup.feature:185](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L185) -- [apiGraph/addUserToGroup.feature:186](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L186) +- [apiGraph/addUserToGroup.feature:153](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L153) +- [apiGraph/addUserToGroup.feature:154](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L154) +- [apiGraph/addUserToGroup.feature:188](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L188) +- [apiGraph/addUserToGroup.feature:189](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L189) +- [apiGraph/addUserToGroup.feature:190](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L190) - [apiGraph/createGroup.feature:42](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/createGroup.feature#L42) - [apiGraph/createGroup.feature:43](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/createGroup.feature#L43) - [apiGraph/createGroup.feature:44](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/createGroup.feature#L44) @@ -111,27 +111,27 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiGraph/editGroup.feature:35](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/editGroup.feature#L35) - [apiGraph/editGroup.feature:34](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/editGroup.feature#L34) - [apiGraph/editGroup.feature:36](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/editGroup.feature#L36) -- [apiGraph/getGroup.feature:103](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L103) -- [apiGraph/getGroup.feature:104](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L104) -- [apiGraph/getGroup.feature:105](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L105) -- [apiGraph/removeUserFromGroup.feature:191](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/removeUserFromGroup.feature#L191) -- [apiGraph/removeUserFromGroup.feature:192](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/removeUserFromGroup.feature#L192) +- [apiGraph/getGroup.feature:107](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L107) +- [apiGraph/getGroup.feature:108](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L108) +- [apiGraph/getGroup.feature:109](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L109) - [apiGraph/removeUserFromGroup.feature:193](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/removeUserFromGroup.feature#L193) +- [apiGraph/removeUserFromGroup.feature:194](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/removeUserFromGroup.feature#L194) +- [apiGraph/removeUserFromGroup.feature:195](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/removeUserFromGroup.feature#L195) #### [API requests for a non-existent resources should return 404](https://github.com/owncloud/ocis/issues/5939) -- [apiGraph/addUserToGroup.feature:201](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L201) -- [apiGraph/addUserToGroup.feature:202](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L202) -- [apiGraph/addUserToGroup.feature:203](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L203) +- [apiGraph/addUserToGroup.feature:205](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L205) +- [apiGraph/addUserToGroup.feature:206](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L206) +- [apiGraph/addUserToGroup.feature:207](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L207) ### [Users are added in a group with wrong host in host-part of user](https://github.com/owncloud/ocis/issues/5871) -- [apiGraph/addUserToGroup.feature:369](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L369) -- [apiGraph/addUserToGroup.feature:383](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L383) +- [apiGraph/addUserToGroup.feature:373](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L373) +- [apiGraph/addUserToGroup.feature:387](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L387) ### [Adding the same user as multiple members in a single request results in listing the same user twice in the group](https://github.com/owncloud/ocis/issues/5855) -- [apiGraph/addUserToGroup.feature:420](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L420) +- [apiGraph/addUserToGroup.feature:424](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L424) ### [Shared file locking is not possible using different path](https://github.com/owncloud/ocis/issues/7599) diff --git a/tests/acceptance/features/apiGraph/addUserToGroup.feature b/tests/acceptance/features/apiGraph/addUserToGroup.feature index 79eb55fe5e..f3c9162d73 100644 --- a/tests/acceptance/features/apiGraph/addUserToGroup.feature +++ b/tests/acceptance/features/apiGraph/addUserToGroup.feature @@ -138,8 +138,10 @@ Feature: add users to group "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["Unauthorized"] + } } } } @@ -172,8 +174,10 @@ Feature: add users to group "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message" : { + "type": "string", + "enum": ["Unauthorized"] + } } } } diff --git a/tests/acceptance/features/apiGraph/getGroup.feature b/tests/acceptance/features/apiGraph/getGroup.feature index 00f4f7c80a..5a1ccecf8d 100644 --- a/tests/acceptance/features/apiGraph/getGroup.feature +++ b/tests/acceptance/features/apiGraph/getGroup.feature @@ -42,8 +42,10 @@ Feature: get groups and their members "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["search term too short"] + } } } } @@ -91,8 +93,10 @@ Feature: get groups and their members "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["Unauthorized"] + } } } } @@ -255,8 +259,10 @@ Feature: get groups and their members "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["search term too short"] + } } } } @@ -369,8 +375,10 @@ Feature: get groups and their members "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["Unauthorized"] + } } } } @@ -444,3 +452,117 @@ Feature: get groups and their members Scenario: admin user tries to get group information of non-existing group When user "Alice" gets details of the group "non-existing" using the Graph API Then the HTTP status code should be "404" + + + Scenario Outline: non-admin user search for a group by group name + Given these users have been created with default attributes and without skeleton files: + | username | + | Brian | + And group "tea-lover" has been created + When user "Brian" searches for group "" using Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "array", + "required": [ + "displayName", + "id", + "groupTypes" + ], + "properties": { + "displayName": { + "type": "string", + "enum": ["tea-lover"] + }, + "id": { + "type": "string", + "pattern": "%group_id_pattern%" + }, + "groupTypes": { + "type": "array", + "enum": [] + } + } + } + } + } + """ + Examples: + | group | + | tea | + | %22tea-%22 | + + + Scenario: non-admin user tries to search for a group by group name with less than 3 characters + Given these users have been created with default attributes and without skeleton files: + | username | + | Brian | + And group "tea-lover" has been created + When user "Brian" tries to search for group "te" using Graph API + Then the HTTP status code should be "403" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message":{ + "type": "string", + "enum": ["search term too short"] + } + } + } + } + } + """ + + @issue-7990 + Scenario Outline: non-admin user tries to search for a group by group name with invalid characters/token + Given these users have been created with default attributes and without skeleton files: + | username | + | Brian | + And group "" has been created + When user "Brian" tries to search for group "" using Graph API + Then the HTTP status code should be "400" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string", + "enum": ["Token '' is invalid"] + } + } + } + } + } + """ + Examples: + | group | token | + | tea-lovers | -lovers | + | tea@lovers | @lovers | \ No newline at end of file diff --git a/tests/acceptance/features/apiGraph/getUser.feature b/tests/acceptance/features/apiGraph/getUser.feature index b8996f605f..9254358854 100644 --- a/tests/acceptance/features/apiGraph/getUser.feature +++ b/tests/acceptance/features/apiGraph/getUser.feature @@ -75,8 +75,10 @@ Feature: get users "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message":{ + "type": "string", + "enum": ["Unauthorized"] + } } } } @@ -269,8 +271,10 @@ Feature: get users "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["search term too short"] + } } } } @@ -359,14 +363,16 @@ Feature: get users "user" ], "properties": { - "user": "string", - "required": [ - "id" - ], - "properties": { - "id": { - "type": "string", - "enum": ["%user_id_pattern%"] + "user": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "pattern": "%user_id_pattern%" + } } } } @@ -630,8 +636,10 @@ Feature: get users "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message: { + "type": "string", + "enum": ["Unauthorized"] + } } } } @@ -905,8 +913,10 @@ Feature: get users "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["search term too short"] + } } } } @@ -1057,8 +1067,10 @@ Feature: get users "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["search term too short"] + } } } } @@ -1327,3 +1339,107 @@ Feature: get users | Space Admin | | User | | User Light | + + + Scenario: non-admin user searches other users by display name + When user "Brian" searches for user "ali" using Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "array", + "required": [ + "displayName", + "id", + "mail", + "userType" + ], + "properties": { + "displayName": { + "type": "string", + "enum": ["Alice Hansen"] + }, + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "mail": { + "type": "string", + "enum": ["alice@example.org"] + }, + "userType": { + "type": "string", + "enum": ["Member"] + } + } + } + } + } + """ + + + Scenario: non-admin user tries to search for a user by display name with less than 3 characters + When user "Brian" tries to search for user "al" using Graph API + Then the HTTP status code should be "403" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string", + "enum": ["search term too short"] + } + } + } + } + } + """ + + @issue-7990 + Scenario Outline: non-admin user tries to search for a user by display name with invalid characters/token + Given user "" has been created with default attributes and without skeleton files + When user "Brian" tries to search for user "" using Graph API + Then the HTTP status code should be "400" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "message" + ], + "properties": { + "message": { + "type": "string", + "enum": ["Token '' is invalid"] + } + } + } + } + } + """ + Examples: + | user | errorToken | + | Alice-From-Wonderland | -From-Wonderland | + | Alice@From@Wonderland | @From@Wonderland | diff --git a/tests/acceptance/features/apiGraph/removeUserFromGroup.feature b/tests/acceptance/features/apiGraph/removeUserFromGroup.feature index b79479c370..534496ddf4 100644 --- a/tests/acceptance/features/apiGraph/removeUserFromGroup.feature +++ b/tests/acceptance/features/apiGraph/removeUserFromGroup.feature @@ -178,8 +178,10 @@ Feature: remove a user from a group "message" ], "properties": { - "type": "string", - "enum": ["Unauthorized"] + "message": { + "type": "string", + "enum": ["Unauthorized"] + } } } } diff --git a/tests/acceptance/features/apiSharingNg/listPermissions.feature b/tests/acceptance/features/apiSharingNg/listPermissions.feature index a46edd99a6..e15b857205 100644 --- a/tests/acceptance/features/apiSharingNg/listPermissions.feature +++ b/tests/acceptance/features/apiSharingNg/listPermissions.feature @@ -22,31 +22,28 @@ Feature: List a sharing permissions "properties": { "@libre.graph.permissions.actions.allowedValues": { "type": "array", - "items": [ - { - "type": "string", - "required": [ - "libre.graph/driveItem/permissions/create", - "libre.graph/driveItem/children/create", - "libre.graph/driveItem/standard/delete", - "libre.graph/driveItem/path/read", - "libre.graph/driveItem/quota/read", - "libre.graph/driveItem/content/read", - "libre.graph/driveItem/upload/create", - "libre.graph/driveItem/permissions/read", - "libre.graph/driveItem/children/read", - "libre.graph/driveItem/versions/read", - "libre.graph/driveItem/deleted/read", - "libre.graph/driveItem/path/update", - "libre.graph/driveItem/permissions/delete", - "libre.graph/driveItem/deleted/delete", - "libre.graph/driveItem/versions/update", - "libre.graph/driveItem/deleted/update", - "libre.graph/driveItem/basic/read", - "libre.graph/driveItem/permissions/update", - "libre.graph/driveItem/permissions/deny" - ] - } + "enum": [ + [ + "libre.graph/driveItem/permissions/create", + "libre.graph/driveItem/children/create", + "libre.graph/driveItem/standard/delete", + "libre.graph/driveItem/path/read", + "libre.graph/driveItem/quota/read", + "libre.graph/driveItem/content/read", + "libre.graph/driveItem/upload/create", + "libre.graph/driveItem/permissions/read", + "libre.graph/driveItem/children/read", + "libre.graph/driveItem/versions/read", + "libre.graph/driveItem/deleted/read", + "libre.graph/driveItem/path/update", + "libre.graph/driveItem/permissions/delete", + "libre.graph/driveItem/deleted/delete", + "libre.graph/driveItem/versions/update", + "libre.graph/driveItem/deleted/update", + "libre.graph/driveItem/basic/read", + "libre.graph/driveItem/permissions/update", + "libre.graph/driveItem/permissions/deny" + ] ] }, "@libre.graph.permissions.roles.allowedValues": { diff --git a/tests/acceptance/features/bootstrap/GraphContext.php b/tests/acceptance/features/bootstrap/GraphContext.php index 4c0d76215c..aee5618c25 100644 --- a/tests/acceptance/features/bootstrap/GraphContext.php +++ b/tests/acceptance/features/bootstrap/GraphContext.php @@ -1252,6 +1252,28 @@ class GraphContext implements Context { $this->featureContext->setResponse($response); } + /** + * @When user :byUser tries to search for user :searchTerm using Graph API + * @When user :byUser searches for user :searchTerm using Graph API + * + * @param string $byUser + * @param string $searchTerm + * + * @return void + * @throws GuzzleException + */ + public function userSearchesForUserUsingGraphApi(string $byUser, string $searchTerm): void { + $credentials = $this->getAdminOrUserCredentials($byUser); + $response = GraphHelper::searchUser( + $this->featureContext->getBaseUrl(), + $this->featureContext->getStepLineRef(), + $credentials['username'], + $credentials['password'], + $searchTerm, + ); + $this->featureContext->setResponse($response); + } + /** * @When user :user tries to get all users using the Graph API * @When user :user gets all users using the Graph API @@ -1875,6 +1897,28 @@ class GraphContext implements Context { ); } + /** + * @When user :user tries to search for group :searchTerm using Graph API + * @When user :user searches for group :searchTerm using Graph API + * + * @param string $user + * @param string $searchTerm + * + * @return void + */ + public function userSearchesForGroupUsingGraphApi($user, $searchTerm):void { + $credentials = $this->getAdminOrUserCredentials($user); + $this->featureContext->setResponse( + GraphHelper::searchGroup( + $this->featureContext->getBaseUrl(), + $this->featureContext->getStepLineRef(), + $credentials["username"], + $credentials["password"], + $searchTerm + ) + ); + } + /** * @Then /^the JSON data of the response should (not )?contain the user "([^"]*)" in the item 'value'(?:, the user-details should match)?$/ * @Then /^the JSON data of the response should (not )?contain the group "([^"]*)" in the item 'value'(?:, the group-details should match)?$/ From fb4213e75f0c5b8e49adae621bd2f3c5c04b0f05 Mon Sep 17 00:00:00 2001 From: Willy Kloucek Date: Wed, 6 Dec 2023 09:49:13 +0100 Subject: [PATCH 18/73] remove jwt config from policies after #7672 --- services/policies/pkg/config/config.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/services/policies/pkg/config/config.go b/services/policies/pkg/config/config.go index bf502c8c44..31a10886e1 100644 --- a/services/policies/pkg/config/config.go +++ b/services/policies/pkg/config/config.go @@ -34,11 +34,6 @@ type GRPC struct { TLS *shared.GRPCServiceTLS `yaml:"tls"` } -// TokenManager is the config for using the reva token manager -type TokenManager struct { - JWTSecret string `yaml:"jwt_secret" env:"OCIS_JWT_SECRET;POLICIES_JWT_SECRET" desc:"The secret to mint and validate jwt tokens."` -} - // Engine configures the policy engine. type Engine struct { Timeout time.Duration `yaml:"timeout" env:"POLICIES_ENGINE_TIMEOUT" desc:"Sets the timeout the rego expression evaluation can take. Rules default to deny if the timeout was reached. See the Environment Variable Types description for more details."` From f7865c0ec768a771a1deea80d7b0f30b0af352f2 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 12 Dec 2023 16:18:54 +0100 Subject: [PATCH 19/73] add changelog Signed-off-by: jkoberg --- changelog/unreleased/fix-policies-jwt-config.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/unreleased/fix-policies-jwt-config.md diff --git a/changelog/unreleased/fix-policies-jwt-config.md b/changelog/unreleased/fix-policies-jwt-config.md new file mode 100644 index 0000000000..1ab77dedf8 --- /dev/null +++ b/changelog/unreleased/fix-policies-jwt-config.md @@ -0,0 +1,5 @@ +Bugfix: Fix jwt config of policies service + +Removes jwt config of policies service + +https://github.com/owncloud/ocis/pull/7893 From e1c74f338fc54e6a9b134101c532d1ae7edb5330 Mon Sep 17 00:00:00 2001 From: ownClouders Date: Fri, 19 Jan 2024 00:48:40 +0000 Subject: [PATCH 20/73] [tx] updated from transifex --- .../pkg/email/l10n/locale/de/LC_MESSAGES/notifications.po | 2 +- .../pkg/email/l10n/locale/de_DE/LC_MESSAGES/notifications.po | 2 +- .../pkg/email/l10n/locale/zh-Hans/LC_MESSAGES/notifications.po | 2 +- .../pkg/email/l10n/locale/zh_CN/LC_MESSAGES/notifications.po | 2 +- .../pkg/service/l10n/locale/en_GB/LC_MESSAGES/userlog.po | 2 +- .../userlog/pkg/service/l10n/locale/tr/LC_MESSAGES/userlog.po | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/services/notifications/pkg/email/l10n/locale/de/LC_MESSAGES/notifications.po b/services/notifications/pkg/email/l10n/locale/de/LC_MESSAGES/notifications.po index 39bd82a721..6d609dd2cc 100644 --- a/services/notifications/pkg/email/l10n/locale/de/LC_MESSAGES/notifications.po +++ b/services/notifications/pkg/email/l10n/locale/de/LC_MESSAGES/notifications.po @@ -13,7 +13,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: EMAIL\n" -"POT-Creation-Date: 2023-12-30 00:38+0000\n" +"POT-Creation-Date: 2024-01-19 00:48+0000\n" "PO-Revision-Date: 2023-04-19 11:11+0000\n" "Last-Translator: Michael Barz , 2023\n" "Language-Team: German (https://app.transifex.com/owncloud-org/teams/6149/de/)\n" diff --git a/services/notifications/pkg/email/l10n/locale/de_DE/LC_MESSAGES/notifications.po b/services/notifications/pkg/email/l10n/locale/de_DE/LC_MESSAGES/notifications.po index 65e8bebc47..baf751ee2f 100644 --- a/services/notifications/pkg/email/l10n/locale/de_DE/LC_MESSAGES/notifications.po +++ b/services/notifications/pkg/email/l10n/locale/de_DE/LC_MESSAGES/notifications.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: EMAIL\n" -"POT-Creation-Date: 2023-12-30 00:38+0000\n" +"POT-Creation-Date: 2024-01-19 00:48+0000\n" "PO-Revision-Date: 2023-04-19 11:11+0000\n" "Last-Translator: Michael Barz , 2023\n" "Language-Team: German (Germany) (https://app.transifex.com/owncloud-org/teams/6149/de_DE/)\n" diff --git a/services/notifications/pkg/email/l10n/locale/zh-Hans/LC_MESSAGES/notifications.po b/services/notifications/pkg/email/l10n/locale/zh-Hans/LC_MESSAGES/notifications.po index 9d9111633e..30b752ee38 100644 --- a/services/notifications/pkg/email/l10n/locale/zh-Hans/LC_MESSAGES/notifications.po +++ b/services/notifications/pkg/email/l10n/locale/zh-Hans/LC_MESSAGES/notifications.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: EMAIL\n" -"POT-Creation-Date: 2023-12-30 00:38+0000\n" +"POT-Creation-Date: 2024-01-19 00:48+0000\n" "PO-Revision-Date: 2023-04-19 11:11+0000\n" "Last-Translator: Shouyuan, 2023\n" "Language-Team: Chinese Simplified (https://app.transifex.com/owncloud-org/teams/6149/zh-Hans/)\n" diff --git a/services/notifications/pkg/email/l10n/locale/zh_CN/LC_MESSAGES/notifications.po b/services/notifications/pkg/email/l10n/locale/zh_CN/LC_MESSAGES/notifications.po index 1f0f7f4f1e..4bcf5c6c01 100644 --- a/services/notifications/pkg/email/l10n/locale/zh_CN/LC_MESSAGES/notifications.po +++ b/services/notifications/pkg/email/l10n/locale/zh_CN/LC_MESSAGES/notifications.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: EMAIL\n" -"POT-Creation-Date: 2023-12-30 00:38+0000\n" +"POT-Creation-Date: 2024-01-19 00:48+0000\n" "PO-Revision-Date: 2023-04-19 11:11+0000\n" "Last-Translator: Shouyuan, 2023\n" "Language-Team: Chinese (China) (https://app.transifex.com/owncloud-org/teams/6149/zh_CN/)\n" diff --git a/services/userlog/pkg/service/l10n/locale/en_GB/LC_MESSAGES/userlog.po b/services/userlog/pkg/service/l10n/locale/en_GB/LC_MESSAGES/userlog.po index a610f8506d..65bcfa993f 100644 --- a/services/userlog/pkg/service/l10n/locale/en_GB/LC_MESSAGES/userlog.po +++ b/services/userlog/pkg/service/l10n/locale/en_GB/LC_MESSAGES/userlog.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: EMAIL\n" -"POT-Creation-Date: 2023-12-30 00:38+0000\n" +"POT-Creation-Date: 2024-01-19 00:48+0000\n" "PO-Revision-Date: 2023-03-15 08:28+0000\n" "Last-Translator: Andi Chandler , 2023\n" "Language-Team: English (United Kingdom) (https://app.transifex.com/owncloud-org/teams/6149/en_GB/)\n" diff --git a/services/userlog/pkg/service/l10n/locale/tr/LC_MESSAGES/userlog.po b/services/userlog/pkg/service/l10n/locale/tr/LC_MESSAGES/userlog.po index 2a7abbb898..cbfdbc0f64 100644 --- a/services/userlog/pkg/service/l10n/locale/tr/LC_MESSAGES/userlog.po +++ b/services/userlog/pkg/service/l10n/locale/tr/LC_MESSAGES/userlog.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: EMAIL\n" -"POT-Creation-Date: 2023-12-30 00:38+0000\n" +"POT-Creation-Date: 2024-01-19 00:48+0000\n" "PO-Revision-Date: 2023-03-15 08:28+0000\n" "Last-Translator: Begüm Topyıldız , 2023\n" "Language-Team: Turkish (https://app.transifex.com/owncloud-org/teams/6149/tr/)\n" From 54a7da451f54e474e9d0da3e6b62bba986323546 Mon Sep 17 00:00:00 2001 From: Sagar Gurung <46086950+SagarGi@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:33:02 +0545 Subject: [PATCH 21/73] [tests-only][full-ci]Forward port `setpassword` and `internallink` (#8245) * [tests-only][full-ci]Added test for banned password to create public link (#8194) * Added test for banned password to create public link Signed-off-by: sagargurung1001@gmail.com * review address Signed-off-by: sagargurung1001@gmail.com --------- Signed-off-by: sagargurung1001@gmail.com * [tests-only][full-ci]Added type internal for share link (public) (#8210) * Added type internal for share link (public) Signed-off-by: sagargurung1001@gmail.com * fix Ci fail Signed-off-by: sagargurung1001@gmail.com --------- Signed-off-by: sagargurung1001@gmail.com --------- Signed-off-by: sagargurung1001@gmail.com --- ...ected-failures-localAPI-on-OCIS-storage.md | 19 ++- .../features/apiSharingNg/linkShare.feature | 108 ++++++++++++++++++ 2 files changed, 117 insertions(+), 10 deletions(-) diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index 72a9ec5106..3d8352b86c 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -260,16 +260,15 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiLocks/lockFiles.feature:457](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiLocks/lockFiles.feature#L457) ### [blocksDownload link type is not implemented yet (sharing-ng)](https://github.com/owncloud/ocis/issues/7879) - -- [apiSharingNg/linkShare.feature:78](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L78) -- [apiSharingNg/linkShare.feature:147](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L147) -- [apiSharingNg/linkShare.feature:225](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L225) -- [apiSharingNg/linkShare.feature:301](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L301) -- [apiSharingNg/linkShare.feature:372](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L372) -- [apiSharingNg/linkShare.feature:445](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L445) -- [apiSharingNg/linkShare.feature:447](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L447) -- [apiSharingNg/linkShare.feature:448](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L448) -- [apiSharingNg/linkShare.feature:449](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L449) +- [apiSharingNg/linkShare.feature:79](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L79) +- [apiSharingNg/linkShare.feature:149](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L149) +- [apiSharingNg/linkShare.feature:228](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L228) +- [apiSharingNg/linkShare.feature:305](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L305) +- [apiSharingNg/linkShare.feature:377](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L377) +- [apiSharingNg/linkShare.feature:451](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L451) +- [apiSharingNg/linkShare.feature:453](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L453) +- [apiSharingNg/linkShare.feature:455](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L455) +- [apiSharingNg/linkShare.feature:456](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L456) - [apiSharingNg/deletePermissions.feature:146](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L146) - [apiSharingNg/deletePermissions.feature:163](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L163) - [apiSharingNg/deletePermissions.feature:184](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L184) diff --git a/tests/acceptance/features/apiSharingNg/linkShare.feature b/tests/acceptance/features/apiSharingNg/linkShare.feature index 671fb0fe1f..b7259c17a9 100644 --- a/tests/acceptance/features/apiSharingNg/linkShare.feature +++ b/tests/acceptance/features/apiSharingNg/linkShare.feature @@ -73,6 +73,7 @@ Feature: Create a share link for a resource | permissionsRole | | view | | edit | + | internal | | upload | | createOnly | | blocksDownload | @@ -144,6 +145,7 @@ Feature: Create a share link for a resource | permissionsRole | | view | | edit | + | internal | | blocksDownload | @issue-7879 @@ -220,6 +222,7 @@ Feature: Create a share link for a resource | permissionsRole | | view | | edit | + | internal | | upload | | createOnly | | blocksDownload | @@ -298,6 +301,7 @@ Feature: Create a share link for a resource | permissionsRole | | view | | edit | + | internal | | blocksDownload | @env-config @issue-7879 @@ -369,6 +373,7 @@ Feature: Create a share link for a resource | permissionsRole | | view | | edit | + | internal | | blocksDownload | @issue-7879 @@ -442,11 +447,14 @@ Feature: Create a share link for a resource Examples: | previousPermissionsRole | newPermissionsRole | | view | edit | + | view | internal | | view | blocksDownload | | edit | view | | edit | blocksDownload | + | view | internal | | blocksDownload | edit | | blocksDownload | blocksDownload | + | view | internal | Scenario: update expiration date of a file's link share @@ -584,3 +592,103 @@ Feature: Create a share link for a resource """ And the public should be able to download file "textfile1.txt" from the last link share with password "%public%" and the content should be "other data" And the public download of file "textfile1.txt" from the last link share with password "$heLlo*1234*" should fail with HTTP status code "401" using shareNg + + + Scenario Outline: create a file's link share with a password that is listed in the Banned-Password-List + Given the config "OCIS_PASSWORD_POLICY_BANNED_PASSWORDS_LIST" has been set to path "config/drone/banned-password-list.txt" + And user "Alice" has uploaded file with content "other data" to "text.txt" + When user "Alice" creates the following link share using the Graph API: + | resourceType | file | + | resource | text.txt | + | space | Personal | + | permissionsRole | view | + | password | | + Then the HTTP status code should be "400" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "pattern": "invalidRequest" + }, + "message": { + "type": "string", + "enum": [ + "unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety" + ] + } + } + } + } + } + """ + Examples: + | banned-password | + | 123 | + | password | + | ownCloud | + + + Scenario Outline: update a file's link share with a password that is listed in the Banned-Password-List + Given the config "OCIS_PASSWORD_POLICY_BANNED_PASSWORDS_LIST" has been set to path "config/drone/banned-password-list.txt" + And user "Alice" has uploaded file with content "other data" to "text.txt" + And user "Alice" has created the following link share: + | resourceType | file | + | resource | text.txt | + | space | Personal | + | permissionsRole | view | + | password | %public% | + When user "Alice" sets the following password for the last link share using the Graph API: + | resourceType | file | + | resource | text.txt | + | space | Personal | + | permissionsRole | view | + | password | | + Then the HTTP status code should be "400" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "pattern": "invalidRequest" + }, + "message": { + "type": "string", + "enum": [ + "unfortunately, your password is commonly used. please pick a harder-to-guess password for your safety" + ] + } + } + } + } + } + """ + Examples: + | banned-password | + | 123 | + | password | + | ownCloud | From 0e1b5dd98971dca9b35d81af981ddec403796253 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 17 Jan 2024 15:05:24 +0100 Subject: [PATCH 22/73] graph/sharedWitMe: fix response for shares from project space Resources on project space do not have a real owner assigned. A special of the type USER_TYPE_SPACE_OWNER is returned as the owner. This type of user can't be looked up via a GetUser request. So we skip that call for this usertype. This also fixes the behavior of 'sharedWithMe' for case when the owner or creator of a share or shared resource can't be looked up in the 'users' service. Previously cause the complete request to fail with an error message. So a single share with an unresolvable owner caused 'sharedWithMe' to fail. Now we log a warning but return all shares. Those where the owner or creator couldn't be resolved will have the 'displayName' field of the user in the 'remoteItem.shared.owner' or 'remoteItem.shared.sharedBy' property left empty. Fixes: #8215 Fixes: #8027 --- .../unreleased/sharing-ng-empty-owner.md | 11 +++ services/graph/pkg/service/v0/sharedwithme.go | 67 +++++++++---------- .../graph/pkg/service/v0/sharedwithme_test.go | 30 +++++++++ 3 files changed, 73 insertions(+), 35 deletions(-) create mode 100644 changelog/unreleased/sharing-ng-empty-owner.md diff --git a/changelog/unreleased/sharing-ng-empty-owner.md b/changelog/unreleased/sharing-ng-empty-owner.md new file mode 100644 index 0000000000..51769ead4f --- /dev/null +++ b/changelog/unreleased/sharing-ng-empty-owner.md @@ -0,0 +1,11 @@ +Bugfix: graph/sharedWithMe works for shares from project spaces now + +We fixed a bug in the 'graph/v1beta1/me/drive/sharedWithMe' endpoint that +caused an error response when the user received shares from project spaces. +Additionally the endpoint now behaves more graceful in cases where the +displayname of the owner or creator of a share or shared resource couldn't be +resolved. + +https://github.com/owncloud/ocis/pull/8233 +https://github.com/owncloud/ocis/issues/8027 +https://github.com/owncloud/ocis/issues/8215 diff --git a/services/graph/pkg/service/v0/sharedwithme.go b/services/graph/pkg/service/v0/sharedwithme.go index 14c56caee2..73558f324f 100644 --- a/services/graph/pkg/service/v0/sharedwithme.go +++ b/services/graph/pkg/service/v0/sharedwithme.go @@ -6,6 +6,7 @@ import ( "reflect" "slices" + cs3User "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" storageprovider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/cs3org/reva/v2/pkg/utils" @@ -183,55 +184,36 @@ func (g Graph) listSharedWithMe(ctx context.Context) ([]libregraph.DriveItem, er } if userID := shareStat.GetInfo().GetOwner(); userID != nil { - user, err := g.identityCache.GetUser(ctx, userID.GetOpaqueId()) + identity, err := g.cs3UserIdToIdentity(ctx, userID) if err != nil { - g.logger.Error().Err(err).Msg("could not get user") - return err + // TODO: define a proper error behavior here. We don't + // want the whole request to fail just because a single + // resource owner couldn't be resolved. But, should be + // really return the affect share in the response? + // For now we just log a warning. The returned + // identitySet will just contain the userid. + g.logger.Warn().Err(err).Str("userid", userID.String()).Msg("could not get owner of shared resource") } - identitySet := libregraph.IdentitySet{ - User: &libregraph.Identity{ - DisplayName: user.GetDisplayName(), - Id: libregraph.PtrString(user.GetId()), - }, - } - - remoteItem.SetCreatedBy(identitySet) - driveItem.SetCreatedBy(identitySet) + remoteItem.SetCreatedBy(libregraph.IdentitySet{User: &identity}) + driveItem.SetCreatedBy(libregraph.IdentitySet{User: &identity}) } if userID := receivedShare.GetShare().GetOwner(); userID != nil { - user, err := g.identityCache.GetUser(ctx, userID.GetOpaqueId()) + identity, err := g.cs3UserIdToIdentity(ctx, userID) if err != nil { - g.logger.Error().Err(err).Msg("could not get user") - return err + g.logger.Warn().Err(err).Str("userid", userID.String()).Msg("could not get owner of the share") } - - identitySet := libregraph.IdentitySet{ - User: &libregraph.Identity{ - DisplayName: user.GetDisplayName(), - Id: libregraph.PtrString(user.GetId()), - }, - } - - shared.SetOwner(identitySet) + shared.SetOwner(libregraph.IdentitySet{User: &identity}) } if userID := receivedShare.GetShare().GetCreator(); userID != nil { - user, err := g.identityCache.GetUser(ctx, userID.GetOpaqueId()) + identity, err := g.cs3UserIdToIdentity(ctx, userID) if err != nil { - g.logger.Error().Err(err).Msg("could not get user") - return err + g.logger.Warn().Err(err).Str("userid", userID.String()).Msg("could not get creator of the share") } - identitySet := libregraph.IdentitySet{ - User: &libregraph.Identity{ - DisplayName: user.GetDisplayName(), - Id: libregraph.PtrString(user.GetId()), - }, - } - - shared.SetSharedBy(identitySet) + shared.SetSharedBy(libregraph.IdentitySet{User: &identity}) } @@ -344,3 +326,18 @@ func (g Graph) cs3ReceivedShareToLibreGraphPermissions(ctx context.Context, rece return permission, nil } + +func (g Graph) cs3UserIdToIdentity(ctx context.Context, cs3UserID *cs3User.UserId) (libregraph.Identity, error) { + identity := libregraph.Identity{ + Id: libregraph.PtrString(cs3UserID.GetOpaqueId()), + } + var err error + if cs3UserID.GetType() != cs3User.UserType_USER_TYPE_SPACE_OWNER { + var user libregraph.User + user, err = g.identityCache.GetUser(ctx, cs3UserID.GetOpaqueId()) + if err == nil { + identity.SetDisplayName(user.GetDisplayName()) + } + } + return identity, err +} diff --git a/services/graph/pkg/service/v0/sharedwithme_test.go b/services/graph/pkg/service/v0/sharedwithme_test.go index 00df68ac1e..3426fe93f1 100644 --- a/services/graph/pkg/service/v0/sharedwithme_test.go +++ b/services/graph/pkg/service/v0/sharedwithme_test.go @@ -393,5 +393,35 @@ var _ = Describe("SharedWithMe", func() { Expect(jsonData.Get("user.displayName").String()).To(Equal(shareCreator.DisplayName)) Expect(jsonData.Get("user.id").String()).To(Equal(shareCreator.Id.OpaqueId)) }) + + It("returns shares created on project space", func() { + shareCreator := getUserResponseDefault.User + + ownerID := &userv1beta1.UserId{ + OpaqueId: "project-space-id", + Type: userv1beta1.UserType_USER_TYPE_SPACE_OWNER, + } + share := listReceivedSharesResponse.Shares[0].Share + share.Creator = shareCreator.Id + share.Owner = ownerID + resourceInfo := statResponse.Info + resourceInfo.Owner = ownerID + + svc.ListSharedWithMe( + tape, + httptest.NewRequest(http.MethodGet, "/graph/v1beta1/me/drive/sharedWithMe", nil), + ) + + jsonData := gjson.Get(tape.Body.String(), "value.0.createdBy") + + Expect(jsonData.Get("user.displayName").String()).To(Equal("")) + Expect(jsonData.Get("user.id").String()).To(Equal(ownerID.OpaqueId)) + + jsonData = gjson.Get(tape.Body.String(), "value.0.remoteItem.shared") + Expect(jsonData.Get("sharedBy.user.displayName").String()).To(Equal(shareCreator.DisplayName)) + Expect(jsonData.Get("sharedBy.user.id").String()).To(Equal(shareCreator.Id.OpaqueId)) + Expect(jsonData.Get("owner.user.displayName").String()).To(Equal("")) + Expect(jsonData.Get("owner.user.id").String()).To(Equal(ownerID.OpaqueId)) + }) }) }) From 109881c06fe10a230e77014ae38bacf736aa7253 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Fri, 19 Jan 2024 08:02:12 +0000 Subject: [PATCH 23/73] Automated changelog update [skip ci] --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61d845d3e5..9e3e01e209 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ The following sections list the changes for unreleased. * Bugfix - Updating and reset logo failed: [#8211](https://github.com/owncloud/ocis/pull/8211) * Bugfix - Cleanup graph/pkg/service/v0/driveitems.go: [#8228](https://github.com/owncloud/ocis/pull/8228) * Bugfix - Cleanup `search/pkg/search/search.go`: [#8230](https://github.com/owncloud/ocis/pull/8230) +* Bugfix - Graph/sharedWithMe works for shares from project spaces now: [#8233](https://github.com/owncloud/ocis/pull/8233) * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) * Enhancement - Update reva to latest edge version: [#8100](https://github.com/owncloud/ocis/pull/8100) @@ -127,6 +128,18 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/pull/8230 +* Bugfix - Graph/sharedWithMe works for shares from project spaces now: [#8233](https://github.com/owncloud/ocis/pull/8233) + + We fixed a bug in the 'graph/v1beta1/me/drive/sharedWithMe' endpoint that caused + an error response when the user received shares from project spaces. + Additionally the endpoint now behaves more graceful in cases where the + displayname of the owner or creator of a share or shared resource couldn't be + resolved. + + https://github.com/owncloud/ocis/issues/8027 + https://github.com/owncloud/ocis/issues/8215 + https://github.com/owncloud/ocis/pull/8233 + * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) We add the environment variable that allow to disable the password policy. From 0c6ebfec7ccfc5ea74a2174f8add699202ab94c5 Mon Sep 17 00:00:00 2001 From: kobergj Date: Fri, 19 Jan 2024 08:04:34 +0000 Subject: [PATCH 24/73] Automated changelog update [skip ci] --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e3e01e209..b414d3e05b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ The following sections list the changes for unreleased. ## Summary * Bugfix - The race conditions in tests: [#7847](https://github.com/owncloud/ocis/pull/7847) +* Bugfix - Fix jwt config of policies service: [#7893](https://github.com/owncloud/ocis/pull/7893) * Bugfix - Fix Service Account Roles on external IDP: [#8074](https://github.com/owncloud/ocis/pull/8074) * Bugfix - Fix the upload postprocessing: [#8117](https://github.com/owncloud/ocis/pull/8117) * Bugfix - Fix wrong naming in nats-js-kv registry: [#8140](https://github.com/owncloud/ocis/pull/8140) @@ -66,6 +67,12 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/issues/7846 https://github.com/owncloud/ocis/pull/7847 +* Bugfix - Fix jwt config of policies service: [#7893](https://github.com/owncloud/ocis/pull/7893) + + Removes jwt config of policies service + + https://github.com/owncloud/ocis/pull/7893 + * Bugfix - Fix Service Account Roles on external IDP: [#8074](https://github.com/owncloud/ocis/pull/8074) Service Account Roles wouldn't work when using with external IDP From 077d0980bad7c4b6c5cab3320a2c692db4d7a6ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Duffeck?= Date: Fri, 19 Jan 2024 09:53:19 +0100 Subject: [PATCH 25/73] Bump wopiserver to fix a problem with 0-byte uploads --- .drone.star | 2 +- deployments/examples/ocis_wopi/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.drone.star b/.drone.star index d791f28ef2..153cf503ad 100644 --- a/.drone.star +++ b/.drone.star @@ -939,7 +939,7 @@ def wopiValidatorTests(ctx, storage, accounts_hash_difficulty = 4): [ { "name": "wopiserver", - "image": "cs3org/wopiserver:v10.2.2", + "image": "cs3org/wopiserver:v10.3.0", "detach": True, "commands": [ "cp %s/tests/config/drone/wopiserver.conf /etc/wopi/wopiserver.conf" % (dirs["base"]), diff --git a/deployments/examples/ocis_wopi/docker-compose.yml b/deployments/examples/ocis_wopi/docker-compose.yml index 555c04efe4..f4ebf31406 100644 --- a/deployments/examples/ocis_wopi/docker-compose.yml +++ b/deployments/examples/ocis_wopi/docker-compose.yml @@ -164,7 +164,7 @@ services: restart: always wopiserver: - image: cs3org/wopiserver:${WOPISERVER_DOCKER_TAG:-v10.2.2} + image: cs3org/wopiserver:${WOPISERVER_DOCKER_TAG:-v10.3.0} networks: ocis-net: entrypoint: From 60a67d7b0aef041e6cdd046ecdef0f8c71ca14cc Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Fri, 19 Jan 2024 10:29:33 +0100 Subject: [PATCH 26/73] Fix proxy debug env name --- services/proxy/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/proxy/README.md b/services/proxy/README.md index 0fb83d9ae0..d34424fbd9 100644 --- a/services/proxy/README.md +++ b/services/proxy/README.md @@ -182,7 +182,7 @@ The following metrics are exposed by the proxy service: | `ocis_proxy_build_info{version}` | A metric with a constant `1` value labeled by version, exposing the version of the ocis proxy service. | `version`: Build version of the proxy | ### Prometheus Configuration -The following is an example prometheus configuration for the single process mode. It assumes that the proxy service is configured to bind on all interfaces `PROXY_HTTP_ADDR=0.0.0.0:9205` and that the proxy is available via the `ocis` service name (typically in docker-compose). The prometheus service detects the `/metrics` endpoint automatically and scrapes it every 15 seconds. +The following is an example prometheus configuration for the single process mode. It assumes that the proxy debug address is configured to bind on all interfaces `PROXY_DEBUG_ADDR=0.0.0.0:9205` and that the proxy is available via the `ocis` service name (typically in docker-compose). The prometheus service detects the `/metrics` endpoint automatically and scrapes it every 15 seconds. ```yaml global: From e07f4f0cb45d9e56b2a1d1097375ab3a7be2b0a1 Mon Sep 17 00:00:00 2001 From: Sawjan Gurung Date: Fri, 19 Jan 2024 15:16:19 +0545 Subject: [PATCH 27/73] [tests-only][ci] split large API test suites (#8212) * split large API test suites * remove 30s sleep * organize core-api test suites * organize core-api test suites * divide into 9 pipelines * organize core-api test suites * organize api-search suites * organize api-search suites * fix config file --- .drone.star | 7 +- tests/acceptance/config/behat-core.yml | 60 +------ tests/acceptance/config/behat.yml | 90 ++++++++--- .../expected-failures-API-on-OCIS-storage.md | 148 +++++++++--------- ...ected-failures-localAPI-on-OCIS-storage.md | 113 ++++++------- .../addUserToGroup.feature | 0 .../changeOwnPassword.feature | 0 .../createGroup.feature | 0 .../createGroupCaseSensitive.feature | 0 .../createUser.feature | 0 .../deleteGroup.feature | 0 .../deleteUser.feature | 0 .../editGroup.feature | 0 .../editUser.feature | 0 .../getGroup.feature | 0 .../getUser.feature | 0 .../getUserOwnInformation.feature | 0 .../removeUserFromGroup.feature | 0 .../apiSpaceSearch.feature | 0 .../dateSearch.feature | 0 .../mediaTypeSearch.feature | 0 .../tagSearch.feature | 0 .../contentSearch.feature | 0 .../ocsDELETEAuth.feature | 0 .../ocsGETAuth.feature | 0 .../ocsPOSTAuth.feature | 0 .../ocsPUTAuth.feature | 0 .../webDavCOPYAuth.feature | 0 .../webDavDELETEAuth.feature | 0 .../webDavLOCKAuth.feature | 0 .../webDavMKCOLAuth.feature | 0 .../webDavMOVEAuth.feature | 0 .../webDavPOSTAuth.feature | 0 .../webDavPROPFINDAuth.feature | 0 .../webDavPROPPATCHAuth.feature | 0 .../webDavPUTAuth.feature | 0 .../webDavSpecialURLs.feature | 0 .../updatePublicLinkShare.feature | 0 .../uploadToPublicLinkShare.feature | 0 .../reShareChain.feature | 0 .../reShareDisabled.feature | 0 .../reShareUpdate.feature | 0 .../reShareWithExpiryDate.feature | 0 .../copyFile.feature | 0 .../createFileFolder.feature | 0 .../createFileFolderWhenSharesExist.feature | 0 .../getFileProperties.feature | 0 .../getQuota.feature | 0 .../setFileProperties.feature | 0 .../uploadFile.feature | 0 .../uploadFileUsingOldChunking.feature | 0 tests/acceptance/run.sh | 22 +-- 52 files changed, 221 insertions(+), 219 deletions(-) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/addUserToGroup.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/changeOwnPassword.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/createGroup.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/createGroupCaseSensitive.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/createUser.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/deleteGroup.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/deleteUser.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/editGroup.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/editUser.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/getGroup.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/getUser.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/getUserOwnInformation.feature (100%) rename tests/acceptance/features/{apiGraph => apiGraphUserGroup}/removeUserFromGroup.feature (100%) rename tests/acceptance/features/{apiSearch => apiSearch1}/apiSpaceSearch.feature (100%) rename tests/acceptance/features/{apiSearch => apiSearch1}/dateSearch.feature (100%) rename tests/acceptance/features/{apiSearch => apiSearch2}/mediaTypeSearch.feature (100%) rename tests/acceptance/features/{apiSearch => apiSearch2}/tagSearch.feature (100%) rename tests/acceptance/features/{apiSearch => apiSearchContent}/contentSearch.feature (100%) rename tests/acceptance/features/{coreApiAuthOcs => coreApiAuth}/ocsDELETEAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthOcs => coreApiAuth}/ocsGETAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthOcs => coreApiAuth}/ocsPOSTAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthOcs => coreApiAuth}/ocsPUTAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavCOPYAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavDELETEAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavLOCKAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavMKCOLAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavMOVEAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavPOSTAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavPROPFINDAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavPROPPATCHAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavPUTAuth.feature (100%) rename tests/acceptance/features/{coreApiAuthWebDav => coreApiAuth}/webDavSpecialURLs.feature (100%) rename tests/acceptance/features/{coreApiSharePublicLink3 => coreApiSharePublicLink2}/updatePublicLinkShare.feature (100%) rename tests/acceptance/features/{coreApiSharePublicLink3 => coreApiSharePublicLink2}/uploadToPublicLinkShare.feature (100%) rename tests/acceptance/features/{coreApiShareReshareToShares2 => coreApiShareReshareToShares1}/reShareChain.feature (100%) rename tests/acceptance/features/{coreApiShareReshareToShares2 => coreApiShareReshareToShares1}/reShareDisabled.feature (100%) rename tests/acceptance/features/{coreApiShareReshareToShares3 => coreApiShareReshareToShares2}/reShareUpdate.feature (100%) rename tests/acceptance/features/{coreApiShareReshareToShares3 => coreApiShareReshareToShares2}/reShareWithExpiryDate.feature (100%) rename tests/acceptance/features/{coreApiWebdavProperties1 => coreApiWebdavProperties}/copyFile.feature (100%) rename tests/acceptance/features/{coreApiWebdavProperties1 => coreApiWebdavProperties}/createFileFolder.feature (100%) rename tests/acceptance/features/{coreApiWebdavProperties1 => coreApiWebdavProperties}/createFileFolderWhenSharesExist.feature (100%) rename tests/acceptance/features/{coreApiWebdavProperties2 => coreApiWebdavProperties}/getFileProperties.feature (100%) rename tests/acceptance/features/{coreApiWebdavProperties1 => coreApiWebdavProperties}/getQuota.feature (100%) rename tests/acceptance/features/{coreApiWebdavProperties1 => coreApiWebdavProperties}/setFileProperties.feature (100%) rename tests/acceptance/features/{coreApiWebdavUpload1 => coreApiWebdavUpload}/uploadFile.feature (100%) rename tests/acceptance/features/{coreApiWebdavUpload2 => coreApiWebdavUpload}/uploadFileUsingOldChunking.feature (100%) diff --git a/.drone.star b/.drone.star index bc6e810c64..8148a0e363 100644 --- a/.drone.star +++ b/.drone.star @@ -68,6 +68,7 @@ config = { "apiArchiver", "apiContract", "apiGraph", + "apiGraphUserGroup", "apiSpaces", "apiSpacesShares", "apiCors", @@ -77,6 +78,8 @@ config = { "apiSpacesDavOperation", "apiDepthInfinity", "apiLocks", + "apiSearch1", + "apiSearch2", "apiSharingNg", ], "skip": False, @@ -118,9 +121,9 @@ config = { "OCIS_ADD_RUN_SERVICES": "antivirus", }, }, - "apiSearch": { + "apiSearchContent": { "suites": [ - "apiSearch", + "apiSearchContent", ], "skip": False, "tikaNeeded": True, diff --git a/tests/acceptance/config/behat-core.yml b/tests/acceptance/config/behat-core.yml index 90711e3a0b..9625eb63fb 100644 --- a/tests/acceptance/config/behat-core.yml +++ b/tests/acceptance/config/behat-core.yml @@ -27,22 +27,6 @@ default: paths: - "%paths.base%/../features/coreApiAuth" context: *common_ldap_suite_context - contexts: - - FeatureContext: *common_feature_context_params - - AuthContext: - - coreApiAuthOcs: - paths: - - "%paths.base%/../features/coreApiAuthOcs" - context: *common_ldap_suite_context - contexts: - - FeatureContext: *common_feature_context_params - - AuthContext: - - coreApiAuthWebDav: - paths: - - "%paths.base%/../features/coreApiAuthWebDav" - context: *common_ldap_suite_context contexts: - FeatureContext: *common_feature_context_params - SearchContext: @@ -161,16 +145,6 @@ default: - WebDavPropertiesContext: - OcisConfigContext: - coreApiSharePublicLink3: - paths: - - "%paths.base%/../features/coreApiSharePublicLink3" - context: *common_ldap_suite_context - contexts: - - FeatureContext: *common_feature_context_params - - PublicWebDavContext: - - TrashbinContext: - - WebDavPropertiesContext: - coreApiShareReshareToShares1: paths: - "%paths.base%/../features/coreApiShareReshareToShares1" @@ -191,16 +165,6 @@ default: - TrashbinContext: - WebDavPropertiesContext: - coreApiShareReshareToShares3: - paths: - - "%paths.base%/../features/coreApiShareReshareToShares3" - context: *common_ldap_suite_context - contexts: - - FeatureContext: *common_feature_context_params - - PublicWebDavContext: - - TrashbinContext: - - WebDavPropertiesContext: - coreApiShareUpdateToShares: paths: - "%paths.base%/../features/coreApiShareUpdateToShares" @@ -309,39 +273,23 @@ default: - FeatureContext: *common_feature_context_params - WebDavPropertiesContext: - coreApiWebdavProperties1: + coreApiWebdavProperties: paths: - - "%paths.base%/../features/coreApiWebdavProperties1" + - "%paths.base%/../features/coreApiWebdavProperties" context: *common_ldap_suite_context contexts: - FeatureContext: *common_feature_context_params - WebDavPropertiesContext: - coreApiWebdavProperties2: + coreApiWebdavUpload: paths: - - "%paths.base%/../features/coreApiWebdavProperties2" - context: *common_ldap_suite_context - contexts: - - FeatureContext: *common_feature_context_params - - WebDavPropertiesContext: - - coreApiWebdavUpload1: - paths: - - "%paths.base%/../features/coreApiWebdavUpload1" + - "%paths.base%/../features/coreApiWebdavUpload" context: *common_ldap_suite_context contexts: - FeatureContext: *common_feature_context_params - PublicWebDavContext: - WebDavPropertiesContext: - coreApiWebdavUpload2: - paths: - - "%paths.base%/../features/coreApiWebdavUpload2" - context: *common_ldap_suite_context - contexts: - - FeatureContext: *common_feature_context_params - - PublicWebDavContext: - coreApiWebdavUploadTUS: paths: - "%paths.base%/../features/coreApiWebdavUploadTUS" diff --git a/tests/acceptance/config/behat.yml b/tests/acceptance/config/behat.yml index 3a37d66cc0..00369a9cb5 100644 --- a/tests/acceptance/config/behat.yml +++ b/tests/acceptance/config/behat.yml @@ -1,11 +1,11 @@ default: autoload: - '': '%paths.base%/../features/bootstrap' + "": "%paths.base%/../features/bootstrap" suites: apiAccountsHashDifficulty: paths: - - '%paths.base%/../features/apiAccountsHashDifficulty' + - "%paths.base%/../features/apiAccountsHashDifficulty" context: &common_ldap_suite_context parameters: ldapAdminPassword: admin @@ -30,7 +30,7 @@ default: apiSpaces: paths: - - '%paths.base%/../features/apiSpaces' + - "%paths.base%/../features/apiSpaces" context: *common_ldap_suite_context contexts: - SettingsContext: @@ -50,7 +50,7 @@ default: apiSpacesShares: paths: - - '%paths.base%/../features/apiSpacesShares' + - "%paths.base%/../features/apiSpacesShares" context: *common_ldap_suite_context contexts: - SettingsContext: @@ -72,7 +72,7 @@ default: apiContract: paths: - - '%paths.base%/../features/apiContract' + - "%paths.base%/../features/apiContract" context: *common_ldap_suite_context contexts: - SettingsContext: @@ -89,7 +89,7 @@ default: apiArchiver: paths: - - '%paths.base%/../features/apiArchiver' + - "%paths.base%/../features/apiArchiver" context: *common_ldap_suite_context contexts: - SettingsContext: @@ -104,7 +104,25 @@ default: apiGraph: paths: - - '%paths.base%/../features/apiGraph' + - "%paths.base%/../features/apiGraph" + context: *common_ldap_suite_context + contexts: + - SettingsContext: + - GraphContext: + - SpacesContext: + - FeatureContext: *common_feature_context_params + - CapabilitiesContext: + - FilesVersionsContext: + - OCSContext: + - PublicWebDavContext: + - TUSContext: + - SpacesTUSContext: + - OcisConfigContext: + - TrashbinContext: + + apiGraphUserGroup: + paths: + - "%paths.base%/../features/apiGraphUserGroup" context: *common_ldap_suite_context contexts: - SettingsContext: @@ -122,7 +140,7 @@ default: apiCors: paths: - - '%paths.base%/../features/apiCors' + - "%paths.base%/../features/apiCors" context: *common_ldap_suite_context contexts: - SpacesContext: @@ -134,7 +152,7 @@ default: apiDepthInfinity: paths: - - '%paths.base%/../features/apiDepthInfinity' + - "%paths.base%/../features/apiDepthInfinity" context: *common_ldap_suite_context contexts: - SpacesContext: @@ -147,7 +165,7 @@ default: apiAsyncUpload: paths: - - '%paths.base%/../features/apiAsyncUpload' + - "%paths.base%/../features/apiAsyncUpload" context: *common_ldap_suite_context contexts: - SpacesContext: @@ -160,7 +178,7 @@ default: apiNotification: paths: - - '%paths.base%/../features/apiNotification' + - "%paths.base%/../features/apiNotification" context: *common_ldap_suite_context contexts: - NotificationContext: @@ -174,7 +192,7 @@ default: apiAntivirus: paths: - - '%paths.base%/../features/apiAntivirus' + - "%paths.base%/../features/apiAntivirus" context: *common_ldap_suite_context contexts: - NotificationContext: @@ -189,7 +207,7 @@ default: apiDownloads: paths: - - '%paths.base%/../features/apiDownloads' + - "%paths.base%/../features/apiDownloads" context: *common_ldap_suite_context contexts: - NotificationContext: @@ -207,9 +225,42 @@ default: - PublicWebDavContext: - ArchiverContext: - apiSearch: + apiSearch1: paths: - - '%paths.base%/../features/apiSearch' + - "%paths.base%/../features/apiSearch1" + context: *common_ldap_suite_context + contexts: + - SettingsContext: + - GraphContext: + - SpacesContext: + - PublicWebDavContext: + - FeatureContext: *common_feature_context_params + - SearchContext: + - OCSContext: + - SpacesTUSContext: + - TagContext: + - TUSContext: + + apiSearch2: + paths: + - "%paths.base%/../features/apiSearch2" + context: *common_ldap_suite_context + contexts: + - SettingsContext: + - GraphContext: + - SpacesContext: + - FeatureContext: *common_feature_context_params + - FilesVersionsContext: + - SearchContext: + - OCSContext: + - TrashbinContext: + - SpacesTUSContext: + - TagContext: + - TUSContext: + + apiSearchContent: + paths: + - "%paths.base%/../features/apiSearchContent" context: *common_ldap_suite_context contexts: - SettingsContext: @@ -229,7 +280,7 @@ default: apiReshare: paths: - - '%paths.base%/../features/apiReshare' + - "%paths.base%/../features/apiReshare" context: *common_ldap_suite_context contexts: - FeatureContext: *common_feature_context_params @@ -237,7 +288,7 @@ default: apiSpacesDavOperation: paths: - - '%paths.base%/../features/apiSpacesDavOperation' + - "%paths.base%/../features/apiSpacesDavOperation" context: *common_ldap_suite_context contexts: - FeatureContext: *common_feature_context_params @@ -246,7 +297,7 @@ default: apiLocks: paths: - - '%paths.base%/../features/apiLocks' + - "%paths.base%/../features/apiLocks" context: *common_ldap_suite_context contexts: - FeatureContext: *common_feature_context_params @@ -256,7 +307,7 @@ default: apiSharingNg: paths: - - '%paths.base%/../features/apiSharingNg' + - "%paths.base%/../features/apiSharingNg" context: *common_ldap_suite_context contexts: - FeatureContext: *common_feature_context_params @@ -265,7 +316,6 @@ default: - PublicWebDavContext: - OcisConfigContext: - extensions: rdx\behatvars\BehatVariablesExtension: ~ diff --git a/tests/acceptance/expected-failures-API-on-OCIS-storage.md b/tests/acceptance/expected-failures-API-on-OCIS-storage.md index ae683c30be..763f401dec 100644 --- a/tests/acceptance/expected-failures-API-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-API-on-OCIS-storage.md @@ -8,28 +8,28 @@ Basic file management like up and download, move, copy, properties, trash, versi #### [copy personal space file to shared folder root result share in decline state](https://github.com/owncloud/ocis/issues/6999) -- [coreApiWebdavProperties1/copyFile.feature:285](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L285) -- [coreApiWebdavProperties1/copyFile.feature:286](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L286) +- [coreApiWebdavProperties/copyFile.feature:285](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L285) +- [coreApiWebdavProperties/copyFile.feature:286](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L286) #### [Custom dav properties with namespaces are rendered incorrectly](https://github.com/owncloud/ocis/issues/2140) _ocdav: double-check the webdav property parsing when custom namespaces are used_ -- [coreApiWebdavProperties1/setFileProperties.feature:36](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/setFileProperties.feature#L36) -- [coreApiWebdavProperties1/setFileProperties.feature:37](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/setFileProperties.feature#L37) -- [coreApiWebdavProperties1/setFileProperties.feature:42](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/setFileProperties.feature#L42) -- [coreApiWebdavProperties1/setFileProperties.feature:78](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/setFileProperties.feature#L78) -- [coreApiWebdavProperties1/setFileProperties.feature:77](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/setFileProperties.feature#L77) -- [coreApiWebdavProperties1/setFileProperties.feature:83](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/setFileProperties.feature#L83) +- [coreApiWebdavProperties/setFileProperties.feature:36](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/setFileProperties.feature#L36) +- [coreApiWebdavProperties/setFileProperties.feature:37](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/setFileProperties.feature#L37) +- [coreApiWebdavProperties/setFileProperties.feature:42](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/setFileProperties.feature#L42) +- [coreApiWebdavProperties/setFileProperties.feature:78](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/setFileProperties.feature#L78) +- [coreApiWebdavProperties/setFileProperties.feature:77](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/setFileProperties.feature#L77) +- [coreApiWebdavProperties/setFileProperties.feature:83](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/setFileProperties.feature#L83) #### [Cannot set custom webDav properties](https://github.com/owncloud/product/issues/264) -- [coreApiWebdavProperties2/getFileProperties.feature:342](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties2/getFileProperties.feature#L342) -- [coreApiWebdavProperties2/getFileProperties.feature:343](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties2/getFileProperties.feature#L343) -- [coreApiWebdavProperties2/getFileProperties.feature:348](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties2/getFileProperties.feature#L348) -- [coreApiWebdavProperties2/getFileProperties.feature:378](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties2/getFileProperties.feature#L378) -- [coreApiWebdavProperties2/getFileProperties.feature:379](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties2/getFileProperties.feature#L379) -- [coreApiWebdavProperties2/getFileProperties.feature:384](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties2/getFileProperties.feature#L384) +- [coreApiWebdavProperties/getFileProperties.feature:342](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getFileProperties.feature#L342) +- [coreApiWebdavProperties/getFileProperties.feature:343](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getFileProperties.feature#L343) +- [coreApiWebdavProperties/getFileProperties.feature:348](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getFileProperties.feature#L348) +- [coreApiWebdavProperties/getFileProperties.feature:378](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getFileProperties.feature#L378) +- [coreApiWebdavProperties/getFileProperties.feature:379](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getFileProperties.feature#L379) +- [coreApiWebdavProperties/getFileProperties.feature:384](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getFileProperties.feature#L384) #### [file versions do not report the version author](https://github.com/owncloud/ocis/issues/2914) @@ -122,13 +122,13 @@ cannot share a folder with create permission #### [Upload-only shares must not overwrite but create a separate file](https://github.com/owncloud/ocis/issues/1267) -- [coreApiSharePublicLink3/uploadToPublicLinkShare.feature:13](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink3/uploadToPublicLinkShare.feature#L13) -- [coreApiSharePublicLink3/uploadToPublicLinkShare.feature:121](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink3/uploadToPublicLinkShare.feature#L121) +- [coreApiSharePublicLink2/uploadToPublicLinkShare.feature:13](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature#L13) +- [coreApiSharePublicLink2/uploadToPublicLinkShare.feature:121](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature#L121) #### [Set quota over settings](https://github.com/owncloud/ocis/issues/1290) -- [coreApiSharePublicLink3/uploadToPublicLinkShare.feature:91](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink3/uploadToPublicLinkShare.feature#L91) -- [coreApiSharePublicLink3/uploadToPublicLinkShare.feature:101](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink3/uploadToPublicLinkShare.feature#L101) +- [coreApiSharePublicLink2/uploadToPublicLinkShare.feature:91](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature#L91) +- [coreApiSharePublicLink2/uploadToPublicLinkShare.feature:101](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature#L101) #### [deleting a file inside a received shared folder is moved to the trash-bin of the sharer not the receiver](https://github.com/owncloud/ocis/issues/1124) @@ -153,13 +153,13 @@ cannot share a folder with create permission #### Expiration date of user shares -- [coreApiShareReshareToShares3/reShareWithExpiryDate.feature:33](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareReshareToShares3/reShareWithExpiryDate.feature#L33) -- [coreApiShareReshareToShares3/reShareWithExpiryDate.feature:34](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareReshareToShares3/reShareWithExpiryDate.feature#L34) +- [coreApiShareReshareToShares2/reShareWithExpiryDate.feature:33](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareReshareToShares2/reShareWithExpiryDate.feature#L33) +- [coreApiShareReshareToShares2/reShareWithExpiryDate.feature:34](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareReshareToShares2/reShareWithExpiryDate.feature#L34) #### Expiration date of group shares -- [coreApiShareReshareToShares3/reShareWithExpiryDate.feature:56](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareReshareToShares3/reShareWithExpiryDate.feature#L56) -- [coreApiShareReshareToShares3/reShareWithExpiryDate.feature:57](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareReshareToShares3/reShareWithExpiryDate.feature#L57) +- [coreApiShareReshareToShares2/reShareWithExpiryDate.feature:56](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareReshareToShares2/reShareWithExpiryDate.feature#L56) +- [coreApiShareReshareToShares2/reShareWithExpiryDate.feature:57](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareReshareToShares2/reShareWithExpiryDate.feature#L57) #### [Cannot move folder/file from one received share to another](https://github.com/owncloud/ocis/issues/2442) @@ -216,65 +216,65 @@ API, search, favorites, config, capabilities, not existing endpoints, CORS and o #### [Ability to return error messages in Webdav response bodies](https://github.com/owncloud/ocis/issues/1293) -- [coreApiAuthOcs/ocsDELETEAuth.feature:7](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsDELETEAuth.feature#L7) -- [coreApiAuthOcs/ocsGETAuth.feature:10](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsGETAuth.feature#L10) -- [coreApiAuthOcs/ocsGETAuth.feature:44](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsGETAuth.feature#L44) -- [coreApiAuthOcs/ocsGETAuth.feature:75](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsGETAuth.feature#L75) -- [coreApiAuthOcs/ocsGETAuth.feature:106](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsGETAuth.feature#L106) -- [coreApiAuthOcs/ocsGETAuth.feature:123](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsGETAuth.feature#L123) -- [coreApiAuthOcs/ocsPOSTAuth.feature:10](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsPOSTAuth.feature#L10) -- [coreApiAuthOcs/ocsPUTAuth.feature:7](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsPUTAuth.feature#L7) +- [coreApiAuth/ocsDELETEAuth.feature:7](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsDELETEAuth.feature#L7) +- [coreApiAuth/ocsGETAuth.feature:10](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsGETAuth.feature#L10) +- [coreApiAuth/ocsGETAuth.feature:44](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsGETAuth.feature#L44) +- [coreApiAuth/ocsGETAuth.feature:75](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsGETAuth.feature#L75) +- [coreApiAuth/ocsGETAuth.feature:106](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsGETAuth.feature#L106) +- [coreApiAuth/ocsGETAuth.feature:123](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsGETAuth.feature#L123) +- [coreApiAuth/ocsPOSTAuth.feature:10](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsPOSTAuth.feature#L10) +- [coreApiAuth/ocsPUTAuth.feature:7](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsPUTAuth.feature#L7) - [coreApiSharePublicLink1/createPublicLinkShare.feature:277](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink1/createPublicLinkShare.feature#L277) #### [sending MKCOL requests to another or non-existing user's webDav endpoints as normal user should return 404](https://github.com/owncloud/ocis/issues/5049) _ocdav: api compatibility, return correct status code_ -- [coreApiAuthWebDav/webDavMKCOLAuth.feature:42](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavMKCOLAuth.feature#L42) -- [coreApiAuthWebDav/webDavMKCOLAuth.feature:53](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavMKCOLAuth.feature#L53) +- [coreApiAuth/webDavMKCOLAuth.feature:42](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavMKCOLAuth.feature#L42) +- [coreApiAuth/webDavMKCOLAuth.feature:53](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavMKCOLAuth.feature#L53) #### [trying to lock file of another user gives http 200](https://github.com/owncloud/ocis/issues/2176) -- [coreApiAuthWebDav/webDavLOCKAuth.feature:46](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavLOCKAuth.feature#L46) -- [coreApiAuthWebDav/webDavLOCKAuth.feature:58](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavLOCKAuth.feature#L58) +- [coreApiAuth/webDavLOCKAuth.feature:46](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavLOCKAuth.feature#L46) +- [coreApiAuth/webDavLOCKAuth.feature:58](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavLOCKAuth.feature#L58) #### [send (MOVE,COPY) requests to another user's webDav endpoints as normal user gives 400 instead of 403](https://github.com/owncloud/ocis/issues/3882) _ocdav: api compatibility, return correct status code_ -- [coreApiAuthWebDav/webDavMOVEAuth.feature:45](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavMOVEAuth.feature#L45) -- [coreApiAuthWebDav/webDavMOVEAuth.feature:54](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavMOVEAuth.feature#L54) -- [coreApiAuthWebDav/webDavCOPYAuth.feature:45](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavCOPYAuth.feature#L45) -- [coreApiAuthWebDav/webDavCOPYAuth.feature:54](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavCOPYAuth.feature#L54) +- [coreApiAuth/webDavMOVEAuth.feature:45](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavMOVEAuth.feature#L45) +- [coreApiAuth/webDavMOVEAuth.feature:54](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavMOVEAuth.feature#L54) +- [coreApiAuth/webDavCOPYAuth.feature:45](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavCOPYAuth.feature#L45) +- [coreApiAuth/webDavCOPYAuth.feature:54](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavCOPYAuth.feature#L54) #### [send POST requests to another user's webDav endpoints as normal user](https://github.com/owncloud/ocis/issues/1287) _ocdav: api compatibility, return correct status code_ -- [coreApiAuthWebDav/webDavPOSTAuth.feature:46](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavPOSTAuth.feature#L46) -- [coreApiAuthWebDav/webDavPOSTAuth.feature:55](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavPOSTAuth.feature#L55) +- [coreApiAuth/webDavPOSTAuth.feature:46](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavPOSTAuth.feature#L46) +- [coreApiAuth/webDavPOSTAuth.feature:55](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavPOSTAuth.feature#L55) #### Another users space literally does not exist because it is not listed as a space for him, 404 seems correct, expects 403 -- [coreApiAuthWebDav/webDavPUTAuth.feature:46](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavPUTAuth.feature#L46) -- [coreApiAuthWebDav/webDavPUTAuth.feature:58](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavPUTAuth.feature#L58) +- [coreApiAuth/webDavPUTAuth.feature:46](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavPUTAuth.feature#L46) +- [coreApiAuth/webDavPUTAuth.feature:58](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavPUTAuth.feature#L58) #### [Using double slash in URL to access a folder gives 501 and other status codes](https://github.com/owncloud/ocis/issues/1667) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:15](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L15) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:26](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L26) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:78](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L78) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:90](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L90) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:102](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L102) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:113](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L113) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:123](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L123) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:134](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L134) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:144](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L144) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:155](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L155) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:165](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L165) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:176](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L176) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:186](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L186) -- [coreApiAuthWebDav/webDavSpecialURLs.feature:197](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature#L197) +- [coreApiAuth/webDavSpecialURLs.feature:15](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L15) +- [coreApiAuth/webDavSpecialURLs.feature:26](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L26) +- [coreApiAuth/webDavSpecialURLs.feature:78](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L78) +- [coreApiAuth/webDavSpecialURLs.feature:90](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L90) +- [coreApiAuth/webDavSpecialURLs.feature:102](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L102) +- [coreApiAuth/webDavSpecialURLs.feature:113](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L113) +- [coreApiAuth/webDavSpecialURLs.feature:123](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L123) +- [coreApiAuth/webDavSpecialURLs.feature:134](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L134) +- [coreApiAuth/webDavSpecialURLs.feature:144](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L144) +- [coreApiAuth/webDavSpecialURLs.feature:155](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L155) +- [coreApiAuth/webDavSpecialURLs.feature:165](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L165) +- [coreApiAuth/webDavSpecialURLs.feature:176](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L176) +- [coreApiAuth/webDavSpecialURLs.feature:186](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L186) +- [coreApiAuth/webDavSpecialURLs.feature:197](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature#L197) #### [Difference in response content of status.php and default capabilities](https://github.com/owncloud/ocis/issues/1286) @@ -316,7 +316,7 @@ And other missing implementation of favorites #### [Request to edit non-existing user by authorized admin gets unauthorized in http response](https://github.com/owncloud/core/issues/38423) -- [coreApiAuthOcs/ocsPUTAuth.feature:22](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuthOcs/ocsPUTAuth.feature#L22) +- [coreApiAuth/ocsPUTAuth.feature:22](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiAuth/ocsPUTAuth.feature#L22) #### [Sharing a same file twice to the same group](https://github.com/owncloud/ocis/issues/1710) @@ -394,14 +394,14 @@ And other missing implementation of favorites #### [copying the file inside Shares folder returns 404](https://github.com/owncloud/ocis/issues/3874) -- [coreApiWebdavProperties1/copyFile.feature:398](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L398) -- [coreApiWebdavProperties1/copyFile.feature:399](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L399) -- [coreApiWebdavProperties1/copyFile.feature:404](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L404) -- [coreApiWebdavProperties1/copyFile.feature:423](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L423) -- [coreApiWebdavProperties1/copyFile.feature:424](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L424) -- [coreApiWebdavProperties1/copyFile.feature:429](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L429) -- [coreApiWebdavProperties1/copyFile.feature:268](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L268) -- [coreApiWebdavProperties1/copyFile.feature:269](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L269) +- [coreApiWebdavProperties/copyFile.feature:398](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L398) +- [coreApiWebdavProperties/copyFile.feature:399](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L399) +- [coreApiWebdavProperties/copyFile.feature:404](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L404) +- [coreApiWebdavProperties/copyFile.feature:423](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L423) +- [coreApiWebdavProperties/copyFile.feature:424](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L424) +- [coreApiWebdavProperties/copyFile.feature:429](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L429) +- [coreApiWebdavProperties/copyFile.feature:268](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L268) +- [coreApiWebdavProperties/copyFile.feature:269](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L269) ### Won't fix @@ -412,15 +412,15 @@ Not everything needs to be implemented for ocis. While the oc10 testsuite covers #### [Blacklist files extensions](https://github.com/owncloud/ocis/issues/2177) -- [coreApiWebdavProperties1/copyFile.feature:115](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L115) -- [coreApiWebdavProperties1/copyFile.feature:116](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L116) -- [coreApiWebdavProperties1/copyFile.feature:121](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature#L121) -- [coreApiWebdavProperties1/createFileFolder.feature:97](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/createFileFolder.feature#L97) -- [coreApiWebdavProperties1/createFileFolder.feature:98](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/createFileFolder.feature#L98) -- [coreApiWebdavProperties1/createFileFolder.feature:103](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties1/createFileFolder.feature#L103) -- [coreApiWebdavUpload1/uploadFile.feature:181](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavUpload1/uploadFile.feature#L181) -- [coreApiWebdavUpload1/uploadFile.feature:180](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavUpload1/uploadFile.feature#L180) -- [coreApiWebdavUpload1/uploadFile.feature:186](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavUpload1/uploadFile.feature#L186) +- [coreApiWebdavProperties/copyFile.feature:115](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L115) +- [coreApiWebdavProperties/copyFile.feature:116](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L116) +- [coreApiWebdavProperties/copyFile.feature:121](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature#L121) +- [coreApiWebdavProperties/createFileFolder.feature:97](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/createFileFolder.feature#L97) +- [coreApiWebdavProperties/createFileFolder.feature:98](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/createFileFolder.feature#L98) +- [coreApiWebdavProperties/createFileFolder.feature:103](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/createFileFolder.feature#L103) +- [coreApiWebdavUpload/uploadFile.feature:181](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavUpload/uploadFile.feature#L181) +- [coreApiWebdavUpload/uploadFile.feature:180](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavUpload/uploadFile.feature#L180) +- [coreApiWebdavUpload/uploadFile.feature:186](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavUpload/uploadFile.feature#L186) - [coreApiWebdavMove2/moveFile.feature:196](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavMove2/moveFile.feature#L196) - [coreApiWebdavMove2/moveFile.feature:197](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavMove2/moveFile.feature#L197) - [coreApiWebdavMove2/moveFile.feature:202](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavMove2/moveFile.feature#L202) diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index 3d8352b86c..523a252c84 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -43,7 +43,7 @@ The expected failures in this file are from features in the owncloud/ocis repo. #### [Share lists deleted user as 'user'](https://github.com/owncloud/ocis/issues/903) -- [apiGraph/deleteGroup.feature:67](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/deleteGroup.feature#L67) +- [apiGraphUserGroup/deleteGroup.feature:67](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/deleteGroup.feature#L67) #### [CORS headers are not identical with oC10 headers](https://github.com/owncloud/ocis/issues/5195) @@ -59,79 +59,79 @@ The expected failures in this file are from features in the owncloud/ocis repo. #### [A User can get information of another user with Graph API](https://github.com/owncloud/ocis/issues/5125) -- [apiGraph/getUser.feature:89](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L89) -- [apiGraph/getUser.feature:90](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L90) -- [apiGraph/getUser.feature:91](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L91) -- [apiGraph/getUser.feature:92](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L92) -- [apiGraph/getUser.feature:93](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L93) -- [apiGraph/getUser.feature:94](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L94) -- [apiGraph/getUser.feature:95](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L95) -- [apiGraph/getUser.feature:96](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L96) -- [apiGraph/getUser.feature:97](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L97) -- [apiGraph/getUser.feature:98](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L98) -- [apiGraph/getUser.feature:99](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L99) -- [apiGraph/getUser.feature:100](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L100) -- [apiGraph/getUser.feature:650](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L650) -- [apiGraph/getUser.feature:651](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L651) -- [apiGraph/getUser.feature:652](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L652) -- [apiGraph/getUser.feature:653](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L653) -- [apiGraph/getUser.feature:654](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L654) -- [apiGraph/getUser.feature:655](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L655) -- [apiGraph/getUser.feature:656](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L656) -- [apiGraph/getUser.feature:657](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L657) -- [apiGraph/getUser.feature:658](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L658) -- [apiGraph/getUser.feature:659](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L659) -- [apiGraph/getUser.feature:660](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L660) -- [apiGraph/getUser.feature:661](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getUser.feature#L661) +- [apiGraphUserGroup/getUser.feature:89](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L89) +- [apiGraphUserGroup/getUser.feature:90](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L90) +- [apiGraphUserGroup/getUser.feature:91](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L91) +- [apiGraphUserGroup/getUser.feature:92](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L92) +- [apiGraphUserGroup/getUser.feature:93](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L93) +- [apiGraphUserGroup/getUser.feature:94](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L94) +- [apiGraphUserGroup/getUser.feature:95](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L95) +- [apiGraphUserGroup/getUser.feature:96](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L96) +- [apiGraphUserGroup/getUser.feature:97](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L97) +- [apiGraphUserGroup/getUser.feature:98](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L98) +- [apiGraphUserGroup/getUser.feature:99](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L99) +- [apiGraphUserGroup/getUser.feature:100](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L100) +- [apiGraphUserGroup/getUser.feature:650](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L650) +- [apiGraphUserGroup/getUser.feature:651](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L651) +- [apiGraphUserGroup/getUser.feature:652](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L652) +- [apiGraphUserGroup/getUser.feature:653](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L653) +- [apiGraphUserGroup/getUser.feature:654](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L654) +- [apiGraphUserGroup/getUser.feature:655](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L655) +- [apiGraphUserGroup/getUser.feature:656](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L656) +- [apiGraphUserGroup/getUser.feature:657](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L657) +- [apiGraphUserGroup/getUser.feature:658](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L658) +- [apiGraphUserGroup/getUser.feature:659](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L659) +- [apiGraphUserGroup/getUser.feature:660](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L660) +- [apiGraphUserGroup/getUser.feature:661](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L661) #### [Normal user can get expanded members information of a group](https://github.com/owncloud/ocis/issues/5604) -- [apiGraph/getGroup.feature:389](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L389) -- [apiGraph/getGroup.feature:390](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L390) -- [apiGraph/getGroup.feature:391](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L391) +- [apiGraphUserGroup/getGroup.feature:389](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L389) +- [apiGraphUserGroup/getGroup.feature:390](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L390) +- [apiGraphUserGroup/getGroup.feature:391](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L391) #### [Same users can be added in a group multiple time](https://github.com/owncloud/ocis/issues/5702) -- [apiGraph/addUserToGroup.feature:289](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L289) +- [apiGraphUserGroup/addUserToGroup.feature:289](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L289) #### [API requests from an unauthorized user should return 403](https://github.com/owncloud/ocis/issues/5938) -- [apiGraph/addUserToGroup.feature:152](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L152) -- [apiGraph/addUserToGroup.feature:153](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L153) -- [apiGraph/addUserToGroup.feature:154](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L154) -- [apiGraph/addUserToGroup.feature:188](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L188) -- [apiGraph/addUserToGroup.feature:189](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L189) -- [apiGraph/addUserToGroup.feature:190](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L190) -- [apiGraph/createGroup.feature:42](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/createGroup.feature#L42) -- [apiGraph/createGroup.feature:43](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/createGroup.feature#L43) -- [apiGraph/createGroup.feature:44](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/createGroup.feature#L44) -- [apiGraph/deleteGroup.feature:63](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/deleteGroup.feature#L63) -- [apiGraph/deleteGroup.feature:62](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/deleteGroup.feature#L62) -- [apiGraph/deleteGroup.feature:64](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/deleteGroup.feature#L64) -- [apiGraph/editGroup.feature:35](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/editGroup.feature#L35) -- [apiGraph/editGroup.feature:34](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/editGroup.feature#L34) -- [apiGraph/editGroup.feature:36](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/editGroup.feature#L36) -- [apiGraph/getGroup.feature:107](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L107) -- [apiGraph/getGroup.feature:108](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L108) -- [apiGraph/getGroup.feature:109](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/getGroup.feature#L109) -- [apiGraph/removeUserFromGroup.feature:193](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/removeUserFromGroup.feature#L193) -- [apiGraph/removeUserFromGroup.feature:194](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/removeUserFromGroup.feature#L194) -- [apiGraph/removeUserFromGroup.feature:195](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/removeUserFromGroup.feature#L195) +- [apiGraphUserGroup/addUserToGroup.feature:152](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L152) +- [apiGraphUserGroup/addUserToGroup.feature:153](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L153) +- [apiGraphUserGroup/addUserToGroup.feature:154](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L154) +- [apiGraphUserGroup/addUserToGroup.feature:188](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L188) +- [apiGraphUserGroup/addUserToGroup.feature:189](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L189) +- [apiGraphUserGroup/addUserToGroup.feature:190](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L190) +- [apiGraphUserGroup/createGroup.feature:42](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/createGroup.feature#L42) +- [apiGraphUserGroup/createGroup.feature:43](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/createGroup.feature#L43) +- [apiGraphUserGroup/createGroup.feature:44](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/createGroup.feature#L44) +- [apiGraphUserGroup/deleteGroup.feature:63](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/deleteGroup.feature#L63) +- [apiGraphUserGroup/deleteGroup.feature:62](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/deleteGroup.feature#L62) +- [apiGraphUserGroup/deleteGroup.feature:64](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/deleteGroup.feature#L64) +- [apiGraphUserGroup/editGroup.feature:35](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/editGroup.feature#L35) +- [apiGraphUserGroup/editGroup.feature:34](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/editGroup.feature#L34) +- [apiGraphUserGroup/editGroup.feature:36](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/editGroup.feature#L36) +- [apiGraphUserGroup/getGroup.feature:107](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L107) +- [apiGraphUserGroup/getGroup.feature:108](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L108) +- [apiGraphUserGroup/getGroup.feature:109](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getGroup.feature#L109) +- [apiGraphUserGroup/removeUserFromGroup.feature:193](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/removeUserFromGroup.feature#L193) +- [apiGraphUserGroup/removeUserFromGroup.feature:194](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/removeUserFromGroup.feature#L194) +- [apiGraphUserGroup/removeUserFromGroup.feature:195](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/removeUserFromGroup.feature#L195) #### [API requests for a non-existent resources should return 404](https://github.com/owncloud/ocis/issues/5939) -- [apiGraph/addUserToGroup.feature:205](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L205) -- [apiGraph/addUserToGroup.feature:206](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L206) -- [apiGraph/addUserToGroup.feature:207](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L207) +- [apiGraphUserGroup/addUserToGroup.feature:205](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L205) +- [apiGraphUserGroup/addUserToGroup.feature:206](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L206) +- [apiGraphUserGroup/addUserToGroup.feature:207](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L207) ### [Users are added in a group with wrong host in host-part of user](https://github.com/owncloud/ocis/issues/5871) -- [apiGraph/addUserToGroup.feature:373](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L373) -- [apiGraph/addUserToGroup.feature:387](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L387) +- [apiGraphUserGroup/addUserToGroup.feature:373](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L373) +- [apiGraphUserGroup/addUserToGroup.feature:387](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L387) ### [Adding the same user as multiple members in a single request results in listing the same user twice in the group](https://github.com/owncloud/ocis/issues/5855) -- [apiGraph/addUserToGroup.feature:424](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraph/addUserToGroup.feature#L424) +- [apiGraphUserGroup/addUserToGroup.feature:424](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature#L424) ### [Shared file locking is not possible using different path](https://github.com/owncloud/ocis/issues/7599) @@ -260,6 +260,7 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiLocks/lockFiles.feature:457](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiLocks/lockFiles.feature#L457) ### [blocksDownload link type is not implemented yet (sharing-ng)](https://github.com/owncloud/ocis/issues/7879) + - [apiSharingNg/linkShare.feature:79](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L79) - [apiSharingNg/linkShare.feature:149](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L149) - [apiSharingNg/linkShare.feature:228](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L228) diff --git a/tests/acceptance/features/apiGraph/addUserToGroup.feature b/tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature similarity index 100% rename from tests/acceptance/features/apiGraph/addUserToGroup.feature rename to tests/acceptance/features/apiGraphUserGroup/addUserToGroup.feature diff --git a/tests/acceptance/features/apiGraph/changeOwnPassword.feature b/tests/acceptance/features/apiGraphUserGroup/changeOwnPassword.feature similarity index 100% rename from tests/acceptance/features/apiGraph/changeOwnPassword.feature rename to tests/acceptance/features/apiGraphUserGroup/changeOwnPassword.feature diff --git a/tests/acceptance/features/apiGraph/createGroup.feature b/tests/acceptance/features/apiGraphUserGroup/createGroup.feature similarity index 100% rename from tests/acceptance/features/apiGraph/createGroup.feature rename to tests/acceptance/features/apiGraphUserGroup/createGroup.feature diff --git a/tests/acceptance/features/apiGraph/createGroupCaseSensitive.feature b/tests/acceptance/features/apiGraphUserGroup/createGroupCaseSensitive.feature similarity index 100% rename from tests/acceptance/features/apiGraph/createGroupCaseSensitive.feature rename to tests/acceptance/features/apiGraphUserGroup/createGroupCaseSensitive.feature diff --git a/tests/acceptance/features/apiGraph/createUser.feature b/tests/acceptance/features/apiGraphUserGroup/createUser.feature similarity index 100% rename from tests/acceptance/features/apiGraph/createUser.feature rename to tests/acceptance/features/apiGraphUserGroup/createUser.feature diff --git a/tests/acceptance/features/apiGraph/deleteGroup.feature b/tests/acceptance/features/apiGraphUserGroup/deleteGroup.feature similarity index 100% rename from tests/acceptance/features/apiGraph/deleteGroup.feature rename to tests/acceptance/features/apiGraphUserGroup/deleteGroup.feature diff --git a/tests/acceptance/features/apiGraph/deleteUser.feature b/tests/acceptance/features/apiGraphUserGroup/deleteUser.feature similarity index 100% rename from tests/acceptance/features/apiGraph/deleteUser.feature rename to tests/acceptance/features/apiGraphUserGroup/deleteUser.feature diff --git a/tests/acceptance/features/apiGraph/editGroup.feature b/tests/acceptance/features/apiGraphUserGroup/editGroup.feature similarity index 100% rename from tests/acceptance/features/apiGraph/editGroup.feature rename to tests/acceptance/features/apiGraphUserGroup/editGroup.feature diff --git a/tests/acceptance/features/apiGraph/editUser.feature b/tests/acceptance/features/apiGraphUserGroup/editUser.feature similarity index 100% rename from tests/acceptance/features/apiGraph/editUser.feature rename to tests/acceptance/features/apiGraphUserGroup/editUser.feature diff --git a/tests/acceptance/features/apiGraph/getGroup.feature b/tests/acceptance/features/apiGraphUserGroup/getGroup.feature similarity index 100% rename from tests/acceptance/features/apiGraph/getGroup.feature rename to tests/acceptance/features/apiGraphUserGroup/getGroup.feature diff --git a/tests/acceptance/features/apiGraph/getUser.feature b/tests/acceptance/features/apiGraphUserGroup/getUser.feature similarity index 100% rename from tests/acceptance/features/apiGraph/getUser.feature rename to tests/acceptance/features/apiGraphUserGroup/getUser.feature diff --git a/tests/acceptance/features/apiGraph/getUserOwnInformation.feature b/tests/acceptance/features/apiGraphUserGroup/getUserOwnInformation.feature similarity index 100% rename from tests/acceptance/features/apiGraph/getUserOwnInformation.feature rename to tests/acceptance/features/apiGraphUserGroup/getUserOwnInformation.feature diff --git a/tests/acceptance/features/apiGraph/removeUserFromGroup.feature b/tests/acceptance/features/apiGraphUserGroup/removeUserFromGroup.feature similarity index 100% rename from tests/acceptance/features/apiGraph/removeUserFromGroup.feature rename to tests/acceptance/features/apiGraphUserGroup/removeUserFromGroup.feature diff --git a/tests/acceptance/features/apiSearch/apiSpaceSearch.feature b/tests/acceptance/features/apiSearch1/apiSpaceSearch.feature similarity index 100% rename from tests/acceptance/features/apiSearch/apiSpaceSearch.feature rename to tests/acceptance/features/apiSearch1/apiSpaceSearch.feature diff --git a/tests/acceptance/features/apiSearch/dateSearch.feature b/tests/acceptance/features/apiSearch1/dateSearch.feature similarity index 100% rename from tests/acceptance/features/apiSearch/dateSearch.feature rename to tests/acceptance/features/apiSearch1/dateSearch.feature diff --git a/tests/acceptance/features/apiSearch/mediaTypeSearch.feature b/tests/acceptance/features/apiSearch2/mediaTypeSearch.feature similarity index 100% rename from tests/acceptance/features/apiSearch/mediaTypeSearch.feature rename to tests/acceptance/features/apiSearch2/mediaTypeSearch.feature diff --git a/tests/acceptance/features/apiSearch/tagSearch.feature b/tests/acceptance/features/apiSearch2/tagSearch.feature similarity index 100% rename from tests/acceptance/features/apiSearch/tagSearch.feature rename to tests/acceptance/features/apiSearch2/tagSearch.feature diff --git a/tests/acceptance/features/apiSearch/contentSearch.feature b/tests/acceptance/features/apiSearchContent/contentSearch.feature similarity index 100% rename from tests/acceptance/features/apiSearch/contentSearch.feature rename to tests/acceptance/features/apiSearchContent/contentSearch.feature diff --git a/tests/acceptance/features/coreApiAuthOcs/ocsDELETEAuth.feature b/tests/acceptance/features/coreApiAuth/ocsDELETEAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthOcs/ocsDELETEAuth.feature rename to tests/acceptance/features/coreApiAuth/ocsDELETEAuth.feature diff --git a/tests/acceptance/features/coreApiAuthOcs/ocsGETAuth.feature b/tests/acceptance/features/coreApiAuth/ocsGETAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthOcs/ocsGETAuth.feature rename to tests/acceptance/features/coreApiAuth/ocsGETAuth.feature diff --git a/tests/acceptance/features/coreApiAuthOcs/ocsPOSTAuth.feature b/tests/acceptance/features/coreApiAuth/ocsPOSTAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthOcs/ocsPOSTAuth.feature rename to tests/acceptance/features/coreApiAuth/ocsPOSTAuth.feature diff --git a/tests/acceptance/features/coreApiAuthOcs/ocsPUTAuth.feature b/tests/acceptance/features/coreApiAuth/ocsPUTAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthOcs/ocsPUTAuth.feature rename to tests/acceptance/features/coreApiAuth/ocsPUTAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavCOPYAuth.feature b/tests/acceptance/features/coreApiAuth/webDavCOPYAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavCOPYAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavCOPYAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavDELETEAuth.feature b/tests/acceptance/features/coreApiAuth/webDavDELETEAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavDELETEAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavDELETEAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavLOCKAuth.feature b/tests/acceptance/features/coreApiAuth/webDavLOCKAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavLOCKAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavLOCKAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavMKCOLAuth.feature b/tests/acceptance/features/coreApiAuth/webDavMKCOLAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavMKCOLAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavMKCOLAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavMOVEAuth.feature b/tests/acceptance/features/coreApiAuth/webDavMOVEAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavMOVEAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavMOVEAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavPOSTAuth.feature b/tests/acceptance/features/coreApiAuth/webDavPOSTAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavPOSTAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavPOSTAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavPROPFINDAuth.feature b/tests/acceptance/features/coreApiAuth/webDavPROPFINDAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavPROPFINDAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavPROPFINDAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavPROPPATCHAuth.feature b/tests/acceptance/features/coreApiAuth/webDavPROPPATCHAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavPROPPATCHAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavPROPPATCHAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavPUTAuth.feature b/tests/acceptance/features/coreApiAuth/webDavPUTAuth.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavPUTAuth.feature rename to tests/acceptance/features/coreApiAuth/webDavPUTAuth.feature diff --git a/tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature b/tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature similarity index 100% rename from tests/acceptance/features/coreApiAuthWebDav/webDavSpecialURLs.feature rename to tests/acceptance/features/coreApiAuth/webDavSpecialURLs.feature diff --git a/tests/acceptance/features/coreApiSharePublicLink3/updatePublicLinkShare.feature b/tests/acceptance/features/coreApiSharePublicLink2/updatePublicLinkShare.feature similarity index 100% rename from tests/acceptance/features/coreApiSharePublicLink3/updatePublicLinkShare.feature rename to tests/acceptance/features/coreApiSharePublicLink2/updatePublicLinkShare.feature diff --git a/tests/acceptance/features/coreApiSharePublicLink3/uploadToPublicLinkShare.feature b/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature similarity index 100% rename from tests/acceptance/features/coreApiSharePublicLink3/uploadToPublicLinkShare.feature rename to tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature diff --git a/tests/acceptance/features/coreApiShareReshareToShares2/reShareChain.feature b/tests/acceptance/features/coreApiShareReshareToShares1/reShareChain.feature similarity index 100% rename from tests/acceptance/features/coreApiShareReshareToShares2/reShareChain.feature rename to tests/acceptance/features/coreApiShareReshareToShares1/reShareChain.feature diff --git a/tests/acceptance/features/coreApiShareReshareToShares2/reShareDisabled.feature b/tests/acceptance/features/coreApiShareReshareToShares1/reShareDisabled.feature similarity index 100% rename from tests/acceptance/features/coreApiShareReshareToShares2/reShareDisabled.feature rename to tests/acceptance/features/coreApiShareReshareToShares1/reShareDisabled.feature diff --git a/tests/acceptance/features/coreApiShareReshareToShares3/reShareUpdate.feature b/tests/acceptance/features/coreApiShareReshareToShares2/reShareUpdate.feature similarity index 100% rename from tests/acceptance/features/coreApiShareReshareToShares3/reShareUpdate.feature rename to tests/acceptance/features/coreApiShareReshareToShares2/reShareUpdate.feature diff --git a/tests/acceptance/features/coreApiShareReshareToShares3/reShareWithExpiryDate.feature b/tests/acceptance/features/coreApiShareReshareToShares2/reShareWithExpiryDate.feature similarity index 100% rename from tests/acceptance/features/coreApiShareReshareToShares3/reShareWithExpiryDate.feature rename to tests/acceptance/features/coreApiShareReshareToShares2/reShareWithExpiryDate.feature diff --git a/tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature b/tests/acceptance/features/coreApiWebdavProperties/copyFile.feature similarity index 100% rename from tests/acceptance/features/coreApiWebdavProperties1/copyFile.feature rename to tests/acceptance/features/coreApiWebdavProperties/copyFile.feature diff --git a/tests/acceptance/features/coreApiWebdavProperties1/createFileFolder.feature b/tests/acceptance/features/coreApiWebdavProperties/createFileFolder.feature similarity index 100% rename from tests/acceptance/features/coreApiWebdavProperties1/createFileFolder.feature rename to tests/acceptance/features/coreApiWebdavProperties/createFileFolder.feature diff --git a/tests/acceptance/features/coreApiWebdavProperties1/createFileFolderWhenSharesExist.feature b/tests/acceptance/features/coreApiWebdavProperties/createFileFolderWhenSharesExist.feature similarity index 100% rename from tests/acceptance/features/coreApiWebdavProperties1/createFileFolderWhenSharesExist.feature rename to tests/acceptance/features/coreApiWebdavProperties/createFileFolderWhenSharesExist.feature diff --git a/tests/acceptance/features/coreApiWebdavProperties2/getFileProperties.feature b/tests/acceptance/features/coreApiWebdavProperties/getFileProperties.feature similarity index 100% rename from tests/acceptance/features/coreApiWebdavProperties2/getFileProperties.feature rename to tests/acceptance/features/coreApiWebdavProperties/getFileProperties.feature diff --git a/tests/acceptance/features/coreApiWebdavProperties1/getQuota.feature b/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature similarity index 100% rename from tests/acceptance/features/coreApiWebdavProperties1/getQuota.feature rename to tests/acceptance/features/coreApiWebdavProperties/getQuota.feature diff --git a/tests/acceptance/features/coreApiWebdavProperties1/setFileProperties.feature b/tests/acceptance/features/coreApiWebdavProperties/setFileProperties.feature similarity index 100% rename from tests/acceptance/features/coreApiWebdavProperties1/setFileProperties.feature rename to tests/acceptance/features/coreApiWebdavProperties/setFileProperties.feature diff --git a/tests/acceptance/features/coreApiWebdavUpload1/uploadFile.feature b/tests/acceptance/features/coreApiWebdavUpload/uploadFile.feature similarity index 100% rename from tests/acceptance/features/coreApiWebdavUpload1/uploadFile.feature rename to tests/acceptance/features/coreApiWebdavUpload/uploadFile.feature diff --git a/tests/acceptance/features/coreApiWebdavUpload2/uploadFileUsingOldChunking.feature b/tests/acceptance/features/coreApiWebdavUpload/uploadFileUsingOldChunking.feature similarity index 100% rename from tests/acceptance/features/coreApiWebdavUpload2/uploadFileUsingOldChunking.feature rename to tests/acceptance/features/coreApiWebdavUpload/uploadFileUsingOldChunking.feature diff --git a/tests/acceptance/run.sh b/tests/acceptance/run.sh index af5eb25598..99a86c8ddf 100755 --- a/tests/acceptance/run.sh +++ b/tests/acceptance/run.sh @@ -669,17 +669,17 @@ then ${RED_COLOR}; printf "%s\n" "${UNEXPECTED_BEHAT_EXIT_STATUSES[@]}" fi -# sync the file-system so all output will be flushed to storage. -# In drone we sometimes see that the last lines of output are missing from the -# drone log. -sync +# # sync the file-system so all output will be flushed to storage. +# # In drone we sometimes see that the last lines of output are missing from the +# # drone log. +# sync -# If we are running in drone CI, then sleep for a bit to (hopefully) let the -# drone agent send all the output to the drone server. -if [ -n "${CI_REPO}" ] -then - echo "sleeping for 30 seconds at end of test run" - sleep 30 -fi +# # If we are running in drone CI, then sleep for a bit to (hopefully) let the +# # drone agent send all the output to the drone server. +# if [ -n "${CI_REPO}" ] +# then +# echo "sleeping for 30 seconds at end of test run" +# sleep 30 +# fi exit ${FINAL_EXIT_STATUS} From 5264450c939aeb7b242bf0f9ed71b703030a642c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 06:12:02 +0000 Subject: [PATCH 28/73] build(deps): bump go.opentelemetry.io/contrib/zpages Bumps [go.opentelemetry.io/contrib/zpages](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.46.1 to 0.47.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.46.1...zpages/v0.47.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/contrib/zpages dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- vendor/go.opentelemetry.io/contrib/zpages/version.go | 2 +- vendor/modules.txt | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index b210eb0a8a..fb97d67a06 100644 --- a/go.mod +++ b/go.mod @@ -89,7 +89,7 @@ require ( go-micro.dev/v4 v4.9.0 go.etcd.io/bbolt v1.3.8 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 - go.opentelemetry.io/contrib/zpages v0.46.1 + go.opentelemetry.io/contrib/zpages v0.47.0 go.opentelemetry.io/otel v1.22.0 go.opentelemetry.io/otel/exporters/jaeger v1.17.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 diff --git a/go.sum b/go.sum index 1258eff89c..19a1393345 100644 --- a/go.sum +++ b/go.sum @@ -2091,8 +2091,8 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.4 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/contrib/zpages v0.46.1 h1:U8Hh84dc+vJTVgRnL+QKWtWD2iqTSKibrQ85EeQqsNg= -go.opentelemetry.io/contrib/zpages v0.46.1/go.mod h1:1Wq9YTzkhr3Jkyi/sVrasFSppVzJQcvFf2Vc2ExZd6c= +go.opentelemetry.io/contrib/zpages v0.47.0 h1:ekpdNa2wqOvAfwZIGDIIV02zmR+z08aWPt21KrPJnaU= +go.opentelemetry.io/contrib/zpages v0.47.0/go.mod h1:rBeFA/UxnMjRlEGpmClIqzf1mCIKtl7ahjww3wsSdGs= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= diff --git a/vendor/go.opentelemetry.io/contrib/zpages/version.go b/vendor/go.opentelemetry.io/contrib/zpages/version.go index 91b9678b43..5f3c6dd816 100644 --- a/vendor/go.opentelemetry.io/contrib/zpages/version.go +++ b/vendor/go.opentelemetry.io/contrib/zpages/version.go @@ -16,7 +16,7 @@ package zpages // import "go.opentelemetry.io/contrib/zpages" // Version is the current release version of the zpages span processor. func Version() string { - return "0.46.1" + return "0.47.0" // This string is updated by the pre_release.sh script during release } diff --git a/vendor/modules.txt b/vendor/modules.txt index 9b740bc36a..3118ad5769 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1924,7 +1924,7 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/inte ## explicit; go 1.20 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil -# go.opentelemetry.io/contrib/zpages v0.46.1 +# go.opentelemetry.io/contrib/zpages v0.47.0 ## explicit; go 1.20 go.opentelemetry.io/contrib/zpages go.opentelemetry.io/contrib/zpages/internal From 6e1f3b91632a04378ff9ca6e3a8188b81544a2be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 09:16:14 +0000 Subject: [PATCH 29/73] build(deps): bump github.com/onsi/ginkgo/v2 from 2.14.0 to 2.15.0 Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.14.0 to 2.15.0. - [Release notes](https://github.com/onsi/ginkgo/releases) - [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/ginkgo/compare/v2.14.0...v2.15.0) --- updated-dependencies: - dependency-name: github.com/onsi/ginkgo/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md | 18 ++++++++++++++++++ .../v2/ginkgo/internal/profiles_and_reports.go | 4 ++-- .../onsi/ginkgo/v2/ginkgo/outline/ginkgo.go | 3 ++- .../onsi/ginkgo/v2/ginkgo/outline/import.go | 9 +-------- .../github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go | 5 +++++ .../onsi/ginkgo/v2/internal/spec_context.go | 4 ++-- .../onsi/ginkgo/v2/internal/suite.go | 6 +++--- .../onsi/ginkgo/v2/reporters/junit_report.go | 12 ++++++++++++ .../github.com/onsi/ginkgo/v2/types/version.go | 2 +- vendor/modules.txt | 4 ++-- 12 files changed, 51 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index d1460b5689..2f9566aa0d 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,7 @@ require ( github.com/oklog/run v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo v1.16.5 - github.com/onsi/ginkgo/v2 v2.14.0 + github.com/onsi/ginkgo/v2 v2.15.0 github.com/onsi/gomega v1.31.0 github.com/open-policy-agent/opa v0.60.0 github.com/orcaman/concurrent-map v1.0.0 diff --git a/go.sum b/go.sum index e7116cd6e5..816a6ecb7b 100644 --- a/go.sum +++ b/go.sum @@ -1770,8 +1770,8 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= -github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= diff --git a/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md index fbe515639e..9a65dd10c5 100644 --- a/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md +++ b/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md @@ -1,3 +1,21 @@ +## 2.15.0 + +### Features + +- JUnit reports now interpret Label(owner:X) and set owner to X. [8f3bd70] +- include cancellation reason when cancelling spec context [96e915c] + +### Fixes + +- emit output of failed go tool cover invocation so users can try to debug things for themselves [c245d09] +- fix outline when using nodot in ginkgo v2 [dca77c8] +- Document areas where GinkgoT() behaves differently from testing.T [dbaf18f] +- bugfix(docs): use Unsetenv instead of Clearenv (#1337) [6f67a14] + +### Maintenance + +- Bump to go 1.20 [4fcd0b3] + ## 2.14.0 ### Features diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/profiles_and_reports.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/profiles_and_reports.go index bd3c6d0287..26de28b570 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/profiles_and_reports.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/internal/profiles_and_reports.go @@ -144,7 +144,7 @@ func FinalizeProfilesAndReportsForSuites(suites TestSuites, cliConfig types.CLIC return messages, nil } -//loads each profile, combines them, deletes them, stores them in destination +// loads each profile, combines them, deletes them, stores them in destination func MergeAndCleanupCoverProfiles(profiles []string, destination string) error { combined := &bytes.Buffer{} modeRegex := regexp.MustCompile(`^mode: .*\n`) @@ -184,7 +184,7 @@ func GetCoverageFromCoverProfile(profile string) (float64, error) { cmd := exec.Command("go", "tool", "cover", "-func", profile) output, err := cmd.CombinedOutput() if err != nil { - return 0, fmt.Errorf("Could not process Coverprofile %s: %s", profile, err.Error()) + return 0, fmt.Errorf("Could not process Coverprofile %s: %s - %s", profile, err.Error(), string(output)) } re := regexp.MustCompile(`total:\s*\(statements\)\s*(\d*\.\d*)\%`) matches := re.FindStringSubmatch(string(output)) diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go index 958daccbfa..5d8d00bb17 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go @@ -1,10 +1,11 @@ package outline import ( - "github.com/onsi/ginkgo/v2/types" "go/ast" "go/token" "strconv" + + "github.com/onsi/ginkgo/v2/types" ) const ( diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go index 67ec5ab757..f0a6b5d26c 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/import.go @@ -28,14 +28,7 @@ func packageNameForImport(f *ast.File, path string) *string { } name := spec.Name.String() if name == "" { - // If the package name is not explicitly specified, - // make an educated guess. This is not guaranteed to be correct. - lastSlash := strings.LastIndex(path, "/") - if lastSlash == -1 { - name = path - } else { - name = path[lastSlash+1:] - } + name = "ginkgo" } if name == "." { name = "" diff --git a/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go b/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go index 639541a16c..02c6739e5b 100644 --- a/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go +++ b/vendor/github.com/onsi/ginkgo/v2/ginkgo_t_dsl.go @@ -15,6 +15,11 @@ GinkgoT() is analogous to *testing.T and implements the majority of *testing.T's GinkgoT() takes an optional offset argument that can be used to get the correct line number associated with the failure - though you do not need to use this if you call GinkgoHelper() or GinkgoT().Helper() appropriately +GinkgoT() attempts to mimic the behavior of `testing.T` with the exception of the following: + +- Error/Errorf: failures in Ginkgo always immediately stop execution and there is no mechanism to log a failure without aborting the test. As such Error/Errorf are equivalent to Fatal/Fatalf. +- Parallel() is a no-op as Ginkgo's multi-process parallelism model is substantially different from go test's in-process model. + You can learn more here: https://onsi.github.io/ginkgo/#using-third-party-libraries */ func GinkgoT(optionalOffset ...int) FullGinkgoTInterface { diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/spec_context.go b/vendor/github.com/onsi/ginkgo/v2/internal/spec_context.go index 2515b84a14..2d2ea2fc35 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/spec_context.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/spec_context.go @@ -17,7 +17,7 @@ type specContext struct { context.Context *ProgressReporterManager - cancel context.CancelFunc + cancel context.CancelCauseFunc suite *Suite } @@ -30,7 +30,7 @@ Note that while SpecContext is used to enforce deadlines by Ginkgo it is not con This is because Ginkgo needs finer control over when the context is canceled. Specifically, Ginkgo needs to generate a ProgressReport before it cancels the context to ensure progress is captured where the spec is currently running. The only way to avoid a race here is to manually control the cancellation. */ func NewSpecContext(suite *Suite) *specContext { - ctx, cancel := context.WithCancel(context.Background()) + ctx, cancel := context.WithCancelCause(context.Background()) sc := &specContext{ cancel: cancel, suite: suite, diff --git a/vendor/github.com/onsi/ginkgo/v2/internal/suite.go b/vendor/github.com/onsi/ginkgo/v2/internal/suite.go index 6746152ec9..2b4db48af8 100644 --- a/vendor/github.com/onsi/ginkgo/v2/internal/suite.go +++ b/vendor/github.com/onsi/ginkgo/v2/internal/suite.go @@ -858,7 +858,7 @@ func (suite *Suite) runNode(node Node, specDeadline time.Time, text string) (typ } sc := NewSpecContext(suite) - defer sc.cancel() + defer sc.cancel(fmt.Errorf("spec has finished")) suite.selectiveLock.Lock() suite.currentSpecContext = sc @@ -958,7 +958,7 @@ func (suite *Suite) runNode(node Node, specDeadline time.Time, text string) (typ // tell the spec to stop. it's important we generate the progress report first to make sure we capture where // the spec is actually stuck - sc.cancel() + sc.cancel(fmt.Errorf("%s timeout occurred", timeoutInPlay)) //and now we wait for the grace period gracePeriodChannel = time.After(gracePeriod) case <-interruptStatus.Channel: @@ -985,7 +985,7 @@ func (suite *Suite) runNode(node Node, specDeadline time.Time, text string) (typ } progressReport = progressReport.WithoutOtherGoroutines() - sc.cancel() + sc.cancel(fmt.Errorf(interruptStatus.Message())) if interruptStatus.Level == interrupt_handler.InterruptLevelBailOut { if interruptStatus.ShouldIncludeProgressReport() { diff --git a/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go b/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go index 816042208c..43244a9bd5 100644 --- a/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go +++ b/vendor/github.com/onsi/ginkgo/v2/reporters/junit_report.go @@ -15,6 +15,7 @@ import ( "fmt" "os" "path" + "regexp" "strings" "github.com/onsi/ginkgo/v2/config" @@ -104,6 +105,8 @@ type JUnitProperty struct { Value string `xml:"value,attr"` } +var ownerRE = regexp.MustCompile(`(?i)^owner:(.*)$`) + type JUnitTestCase struct { // Name maps onto the full text of the spec - equivalent to "[SpecReport.LeafNodeType] SpecReport.FullText()" Name string `xml:"name,attr"` @@ -113,6 +116,8 @@ type JUnitTestCase struct { Status string `xml:"status,attr"` // Time is the time in seconds to execute the spec - maps onto SpecReport.RunTime Time float64 `xml:"time,attr"` + // Owner is the owner the spec - is set if a label matching Label("owner:X") is provided. The last matching label is used as the owner, thereby allowing specs to override owners specified in container nodes. + Owner string `xml:"owner,attr,omitempty"` //Skipped is populated with a message if the test was skipped or pending Skipped *JUnitSkipped `xml:"skipped,omitempty"` //Error is populated if the test panicked or was interrupted @@ -195,6 +200,12 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit if len(labels) > 0 && !config.OmitSpecLabels { name = name + " [" + strings.Join(labels, ", ") + "]" } + owner := "" + for _, label := range labels { + if matches := ownerRE.FindStringSubmatch(label); len(matches) == 2 { + owner = matches[1] + } + } name = strings.TrimSpace(name) test := JUnitTestCase{ @@ -202,6 +213,7 @@ func GenerateJUnitReportWithConfig(report types.Report, dst string, config Junit Classname: report.SuiteDescription, Status: spec.State.String(), Time: spec.RunTime.Seconds(), + Owner: owner, } if !spec.State.Is(config.OmitTimelinesForSpecState) { test.SystemErr = systemErrForUnstructuredReporters(spec) diff --git a/vendor/github.com/onsi/ginkgo/v2/types/version.go b/vendor/github.com/onsi/ginkgo/v2/types/version.go index 7015be1286..ed93464745 100644 --- a/vendor/github.com/onsi/ginkgo/v2/types/version.go +++ b/vendor/github.com/onsi/ginkgo/v2/types/version.go @@ -1,3 +1,3 @@ package types -const VERSION = "2.14.0" +const VERSION = "2.15.0" diff --git a/vendor/modules.txt b/vendor/modules.txt index 926827f12f..552be2a0b2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1456,8 +1456,8 @@ github.com/onsi/ginkgo/reporters/stenographer github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty github.com/onsi/ginkgo/types -# github.com/onsi/ginkgo/v2 v2.14.0 -## explicit; go 1.18 +# github.com/onsi/ginkgo/v2 v2.15.0 +## explicit; go 1.20 github.com/onsi/ginkgo/v2 github.com/onsi/ginkgo/v2/config github.com/onsi/ginkgo/v2/formatter From f3ed318d9d5dc431a7b8c9fafb9c08b8128bc195 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 17 Jan 2024 16:15:43 +0100 Subject: [PATCH 30/73] graph/drives: Fix status code for PATCH/DELETE on drives don't allow them Return a 405 Status when UpdateSpace() or DeleteSpace() are not implemented in the backend for a certain type of drive (e.g. the virtual mountpoint drives created for shares). Fixes: #7881 --- changelog/unreleased/fix-getdrives-response-code.md | 7 +++++++ services/graph/pkg/service/v0/drives.go | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 changelog/unreleased/fix-getdrives-response-code.md diff --git a/changelog/unreleased/fix-getdrives-response-code.md b/changelog/unreleased/fix-getdrives-response-code.md new file mode 100644 index 0000000000..7c427d556b --- /dev/null +++ b/changelog/unreleased/fix-getdrives-response-code.md @@ -0,0 +1,7 @@ +Bugfix: fix PATCH/DELETE status code for drives that don't support them + +Updating and Deleting the virtual drives for shares is currently not supported. Instead +of returning a generic 500 status we return a 405 response now. + +https://github.com/owncloud/ocis/pull/8235 +https://github.com/owncloud/ocis/issues/7881 diff --git a/services/graph/pkg/service/v0/drives.go b/services/graph/pkg/service/v0/drives.go index af029f0b37..311c351afe 100644 --- a/services/graph/pkg/service/v0/drives.go +++ b/services/graph/pkg/service/v0/drives.go @@ -622,6 +622,10 @@ func (g Graph) UpdateDrive(w http.ResponseWriter, r *http.Request) { logger.Debug().Interface("id", rid).Msg("could not update drive, invalid argument") errorcode.NotAllowed.Render(w, r, http.StatusBadRequest, resp.GetStatus().GetMessage()) return + case cs3rpc.Code_CODE_UNIMPLEMENTED: + logger.Debug().Interface("id", rid).Msg("could not delete drive: delete not implemented for this type of drive") + errorcode.NotAllowed.Render(w, r, http.StatusMethodNotAllowed, "drive cannot be updated") + return default: logger.Debug().Interface("id", rid).Str("grpc", resp.GetStatus().GetMessage()).Msg("could not update drive: grpc error") errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, "grpc error") @@ -1193,6 +1197,10 @@ func (g Graph) DeleteDrive(w http.ResponseWriter, r *http.Request) { logger.Debug().Interface("id", rid).Msg("could not delete drive: drive not found") errorcode.ItemNotFound.Render(w, r, http.StatusNotFound, "drive not found") return + case cs3rpc.Code_CODE_UNIMPLEMENTED: + logger.Debug().Interface("id", rid).Msg("could not delete drive: delete not implemented for this type of drive") + errorcode.NotAllowed.Render(w, r, http.StatusMethodNotAllowed, "drive cannot be deleted") + return // don't expose internal error codes to the outside world default: logger.Debug().Str("grpc", dRes.GetStatus().GetMessage()).Interface("id", rid).Msg("could not delete drive: grpc error") From 0d119325402519f25114cb02740047dc55eb74ac Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Mon, 22 Jan 2024 13:05:14 +0000 Subject: [PATCH 31/73] Automated changelog update [skip ci] --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b414d3e05b..9305d77cef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ The following sections list the changes for unreleased. * Bugfix - Cleanup graph/pkg/service/v0/driveitems.go: [#8228](https://github.com/owncloud/ocis/pull/8228) * Bugfix - Cleanup `search/pkg/search/search.go`: [#8230](https://github.com/owncloud/ocis/pull/8230) * Bugfix - Graph/sharedWithMe works for shares from project spaces now: [#8233](https://github.com/owncloud/ocis/pull/8233) +* Bugfix - Fix PATCH/DELETE status code for drives that don't support them: [#8235](https://github.com/owncloud/ocis/pull/8235) * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) * Enhancement - Update reva to latest edge version: [#8100](https://github.com/owncloud/ocis/pull/8100) @@ -147,6 +148,14 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/issues/8215 https://github.com/owncloud/ocis/pull/8233 +* Bugfix - Fix PATCH/DELETE status code for drives that don't support them: [#8235](https://github.com/owncloud/ocis/pull/8235) + + Updating and Deleting the virtual drives for shares is currently not supported. + Instead of returning a generic 500 status we return a 405 response now. + + https://github.com/owncloud/ocis/issues/7881 + https://github.com/owncloud/ocis/pull/8235 + * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) We add the environment variable that allow to disable the password policy. From cb0090e840c91c5c611e7e2f0d9eb12f9be5bc00 Mon Sep 17 00:00:00 2001 From: Sawjan Gurung Date: Mon, 22 Jan 2024 20:01:10 +0545 Subject: [PATCH 32/73] extend test coverage for replacing file with zero-byte file (tus upload) (#8105) --- .../features/apiSpaces/tusUpload.feature | 79 +++++++++++++++++++ .../features/bootstrap/TUSContext.php | 5 +- .../coreApiWebdavUploadTUS/uploadFile.feature | 36 +++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) diff --git a/tests/acceptance/features/apiSpaces/tusUpload.feature b/tests/acceptance/features/apiSpaces/tusUpload.feature index 4a1cbccd07..ce0c7bc82e 100644 --- a/tests/acceptance/features/apiSpaces/tusUpload.feature +++ b/tests/acceptance/features/apiSpaces/tusUpload.feature @@ -39,3 +39,82 @@ Feature: upload resources using TUS protocol Then for user "Alice" the space "Alice Hansen" should contain these entries: | test.txt | | upload.txt | + + + Scenario Outline: upload a zero-byte file inside a shared folder + Given using DAV path + And user "Brian" has been created with default attributes and without skeleton files + And user "Alice" has created folder "testFolder" + And user "Alice" has shared folder "testFolder" with user "Brian" with permissions "all" + When user "Brian" uploads file "filesForUpload/zerobyte.txt" to "Shares/testFolder/textfile.txt" using the TUS protocol on the WebDAV API + Then the content of file "Shares/testFolder/textfile.txt" for user "Brian" should be "" + And the content of file "testFolder/textfile.txt" for user "Alice" should be "" + Examples: + | dav-path-version | + | old | + | new | + + + Scenario: upload a zero-byte file inside a shared folder (spaces dav path) + Given using spaces DAV path + And user "Brian" has been created with default attributes and without skeleton files + And user "Alice" has created folder "testFolder" + And user "Alice" has shared folder "testFolder" with user "Brian" with permissions "all" + When user "Brian" uploads a file from "filesForUpload/zerobyte.txt" to "testFolder/textfile.txt" via TUS inside of the space "Shares" using the WebDAV API + Then for user "Brian" the content of the file "testFolder/textfile.txt" of the space "Shares" should be "" + And for user "Alice" the content of the file "testFolder/textfile.txt" of the space "Personal" should be "" + + + Scenario: upload a zero-byte file inside a project space + Given using spaces DAV path + And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API + And user "Alice" has created a space "new-space" with the default quota using the Graph API + When user "Alice" uploads a file from "filesForUpload/zerobyte.txt" to "textfile.txt" via TUS inside of the space "new-space" using the WebDAV API + Then for user "Alice" the content of the file "textfile.txt" of the space "new-space" should be "" + + @issue-8003 + Scenario Outline: replace a shared file with zero-byte file + Given using DAV path + And user "Brian" has been created with default attributes and without skeleton files + And user "Alice" has uploaded file with content "This is TUS upload" to "textfile.txt" + And user "Alice" has shared file "textfile.txt" with user "Brian" with permissions "read,update" + When user "Brian" uploads file "filesForUpload/zerobyte.txt" to "Shares/textfile.txt" using the TUS protocol on the WebDAV API + Then the content of file "Shares/textfile.txt" for user "Brian" should be "" + And the content of file "textfile.txt" for user "Alice" should be "" + Examples: + | dav-path-version | + | old | + | new | + + @issue-8003 + Scenario: replace a shared file with zero-byte file (spaces dav path) + Given using spaces DAV path + And user "Brian" has been created with default attributes and without skeleton files + And user "Alice" has uploaded file with content "This is TUS upload" to "textfile.txt" + And user "Alice" has shared file "textfile.txt" with user "Brian" with permissions "read,update" + When user "Brian" uploads a file from "filesForUpload/zerobyte.txt" to "textfile.txt" via TUS inside of the space "Shares" using the WebDAV API + Then for user "Brian" the content of the file "textfile.txt" of the space "Shares" should be "" + And for user "Alice" the content of the file "textfile.txt" of the space "Personal" should be "" + + @issue-8003 + Scenario: replace a file inside a project space with zero-byte file + Given using spaces DAV path + And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API + And user "Alice" has created a space "new-space" with the default quota using the Graph API + And user "Alice" has uploaded a file inside space "new-space" with content "This is TUS upload" to "textfile.txt" + When user "Alice" uploads a file from "filesForUpload/zerobyte.txt" to "textfile.txt" via TUS inside of the space "new-space" using the WebDAV API + Then for user "Alice" the content of the file "textfile.txt" of the space "new-space" should be "" + + @issue-8003 + Scenario: replace a file inside a shared project space with zero-byte file + Given using spaces DAV path + And user "Brian" has been created with default attributes and without skeleton files + And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API + And user "Alice" has created a space "new-space" with the default quota using the Graph API + And user "Alice" has uploaded a file inside space "new-space" with content "This is TUS upload" to "textfile.txt" + And user "Alice" has shared a space "new-space" with settings: + | shareWith | Brian | + | role | editor | + When user "Brian" uploads a file from "filesForUpload/zerobyte.txt" to "textfile.txt" via TUS inside of the space "new-space" using the WebDAV API + Then for user "Brian" the content of the file "textfile.txt" of the space "new-space" should be "" + And for user "Alice" the content of the file "textfile.txt" of the space "new-space" should be "" \ No newline at end of file diff --git a/tests/acceptance/features/bootstrap/TUSContext.php b/tests/acceptance/features/bootstrap/TUSContext.php index 57b912d3bb..7b74fd5194 100644 --- a/tests/acceptance/features/bootstrap/TUSContext.php +++ b/tests/acceptance/features/bootstrap/TUSContext.php @@ -209,7 +209,8 @@ class TUSContext implements Context { $client = new Client( $this->featureContext->getBaseUrl(), - ['verify' => false, + [ + 'verify' => false, 'headers' => $headers ] ); @@ -230,6 +231,8 @@ class TUSContext implements Context { if ($bytes !== null) { $client->file($sourceFile, $destination)->createWithUpload($client->getKey(), $bytes); + } elseif (\filesize($sourceFile) === 0) { + $client->file($sourceFile, $destination)->createWithUpload($client->getKey(), 0); } elseif ($noOfChunks === 1) { $client->file($sourceFile, $destination)->upload(); } else { diff --git a/tests/acceptance/features/coreApiWebdavUploadTUS/uploadFile.feature b/tests/acceptance/features/coreApiWebdavUploadTUS/uploadFile.feature index 894ebbc3ad..9337ad7f20 100644 --- a/tests/acceptance/features/coreApiWebdavUploadTUS/uploadFile.feature +++ b/tests/acceptance/features/coreApiWebdavUploadTUS/uploadFile.feature @@ -208,3 +208,39 @@ Feature: upload file | spaces | "filewithLF-and-CR\r\n" | ZmlsZXdpdGhMRi1hbmQtQ1INCgo= | | spaces | "folder/file" | Zm9sZGVyL2ZpbGU= | | spaces | "my\\file" | bXkMaWxl | + + + Scenario Outline: upload a zero-byte file + Given using DAV path + When user "Alice" uploads file "filesForUpload/zerobyte.txt" to "textfile.txt" using the TUS protocol on the WebDAV API + Then the content of file "textfile.txt" for user "Alice" should be "" + Examples: + | dav-path-version | + | old | + | new | + | spaces | + + @issue-8003 + Scenario Outline: replace a file with zero-byte file + Given using DAV path + And user "Alice" has uploaded file with content "This is TUS upload" to "textfile.txt" + When user "Alice" uploads file "filesForUpload/zerobyte.txt" to "textfile.txt" using the TUS protocol on the WebDAV API + Then the content of file "textfile.txt" for user "Alice" should be "" + Examples: + | dav-path-version | + | old | + | new | + | spaces | + + @issue-8003 + Scenario Outline: replace a file inside a folder with zero-byte file + Given using DAV path + And user "Alice" has created folder "testFolder" + And user "Alice" has uploaded file with content "This is TUS upload" to "testFolder/textfile.txt" + When user "Alice" uploads file "filesForUpload/zerobyte.txt" to "testFolder/textfile.txt" using the TUS protocol on the WebDAV API + Then the content of file "testFolder/textfile.txt" for user "Alice" should be "" + Examples: + | dav-path-version | + | old | + | new | + | spaces | From 6515de1a903988b797fe2bc10e7b40fbdd60cbb3 Mon Sep 17 00:00:00 2001 From: Christian Richter Date: Mon, 22 Jan 2024 15:37:13 +0100 Subject: [PATCH 33/73] bump reva Signed-off-by: Christian Richter --- go.mod | 2 +- go.sum | 6 +- .../sharesstorageprovider.go | 1 + .../usershareprovider/usershareprovider.go | 10 +- .../http/services/owncloud/ocdav/ocdav.go | 2 - .../owncloud/ocdav/propfind/propfind.go | 10 +- .../handlers/apps/sharing/shares/pending.go | 216 +++++++++--------- .../handlers/apps/sharing/shares/shares.go | 38 +-- .../ocs/handlers/apps/sharing/shares/user.go | 12 +- .../cs3org/reva/v2/pkg/conversions/main.go | 4 +- .../rhttp/datatx/utils/download/download.go | 5 +- .../pkg/storage/utils/decomposedfs/grants.go | 10 - .../utils/decomposedfs/options/options.go | 6 +- .../cs3org/reva/v2/pkg/store/store.go | 4 +- vendor/modules.txt | 2 +- 15 files changed, 151 insertions(+), 177 deletions(-) diff --git a/go.mod b/go.mod index 2f9566aa0d..3e345cc0b8 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/coreos/go-oidc v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.9.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.18.1-0.20240115094008-bde86a38bd77 + github.com/cs3org/reva/v2 v2.18.1-0.20240122171534-e8fc07f2395a github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e diff --git a/go.sum b/go.sum index 816a6ecb7b..c9ca0d89b2 100644 --- a/go.sum +++ b/go.sum @@ -1018,8 +1018,10 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c= github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.18.1-0.20240115094008-bde86a38bd77 h1:wDi6MOBGdd9zyqDSwhm2FBYqkiEVgDUevpMBKQ6zSf4= -github.com/cs3org/reva/v2 v2.18.1-0.20240115094008-bde86a38bd77/go.mod h1:plMbmaHczZbP+1rtV56YCYs5lkmpdRNpj0KZb9BWLus= +github.com/cs3org/reva/v2 v2.18.1-0.20240122154113-d79f163775db h1:0nc89DfeCGRr98Z/NZor9fRyQ0pGxq0iQnnUsWFhnek= +github.com/cs3org/reva/v2 v2.18.1-0.20240122154113-d79f163775db/go.mod h1:plMbmaHczZbP+1rtV56YCYs5lkmpdRNpj0KZb9BWLus= +github.com/cs3org/reva/v2 v2.18.1-0.20240122171534-e8fc07f2395a h1:2FLa9HFgDlvXTAdDjqcHsb8Ky2eTBXIIR/ukZeemMKI= +github.com/cs3org/reva/v2 v2.18.1-0.20240122171534-e8fc07f2395a/go.mod h1:GCN3g6uYE0Nvd31dGlhaGGyUviUfbG2NkecPRv5oSc4= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go index 012ee4bcef..432bcb15ce 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go @@ -859,6 +859,7 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer OpaqueId: share.Share.Id.OpaqueId, } info.Path = filepath.Base(share.MountPoint.Path) + info.Name = info.Path infos = append(infos, info) } diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go index 6efc53a59a..0710d00786 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go @@ -198,7 +198,7 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar Status: status.NewPermissionDenied(ctx, nil, "no permission to add grants on shared resource"), }, err } - // check if the requested share creation has sufficient permissions to do so. + // check if the share creator has sufficient permissions to do so. if shareCreationAllowed := conversions.SufficientCS3Permissions( sRes.GetInfo().GetPermissionSet(), req.GetGrant().GetPermissions().GetPermissions(), @@ -207,6 +207,14 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar Status: status.NewPermissionDenied(ctx, nil, "insufficient permissions to create that kind of share"), }, nil } + // check if the requested permission are plausible for the Resource + if sRes.GetInfo().GetType() == provider.ResourceType_RESOURCE_TYPE_FILE { + if newPermissions := req.GetGrant().GetPermissions().GetPermissions(); newPermissions.GetCreateContainer() || newPermissions.GetMove() || newPermissions.GetDelete() { + return &collaboration.CreateShareResponse{ + Status: status.NewInvalid(ctx, "cannot set the requested permissions on that type of resource"), + }, nil + } + } if !s.isPathAllowed(req.GetResourceInfo().GetPath()) { return &collaboration.CreateShareResponse{ diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/ocdav.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/ocdav.go index 0eabd525e1..509a6ea633 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/ocdav.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/ocdav.go @@ -286,8 +286,6 @@ func (s *svc) ApplyLayout(ctx context.Context, ns string, useLoggedInUserNS bool func addAccessHeaders(w http.ResponseWriter, r *http.Request) { headers := w.Header() - // the webdav api is accessible from anywhere - headers.Set("Access-Control-Allow-Origin", "*") // all resources served via the DAV endpoint should have the strictest possible as default headers.Set("Content-Security-Policy", "default-src 'none';") // disable sniffing the content type for IE diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go index f9271fbbe9..fc5764738e 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go @@ -486,12 +486,16 @@ func (p *Handler) propfindResponse(ctx context.Context, w http.ResponseWriter, r w.Header().Set(net.HeaderDav, "1, 3, extended-mkcol") w.Header().Set(net.HeaderContentType, "application/xml; charset=utf-8") if sendTusHeaders { - w.Header().Add(net.HeaderAccessControlExposeHeaders, strings.Join([]string{net.HeaderTusResumable, net.HeaderTusVersion, net.HeaderTusExtension}, ", ")) + w.Header().Add(net.HeaderAccessControlExposeHeaders, net.HeaderTusResumable) + w.Header().Add(net.HeaderAccessControlExposeHeaders, net.HeaderTusVersion) + w.Header().Add(net.HeaderAccessControlExposeHeaders, net.HeaderTusExtension) + w.Header().Set(net.HeaderAccessControlExposeHeaders, strings.Join(w.Header().Values(net.HeaderAccessControlExposeHeaders), ", ")) w.Header().Set(net.HeaderTusResumable, "1.0.0") w.Header().Set(net.HeaderTusVersion, "1.0.0") - w.Header().Set(net.HeaderTusExtension, "creation,creation-with-upload,checksum,expiration") + w.Header().Set(net.HeaderTusExtension, "creation, creation-with-upload, checksum, expiration") } - w.Header().Set(net.HeaderVary, net.HeaderPrefer) + w.Header().Add(net.HeaderVary, net.HeaderPrefer) + w.Header().Set(net.HeaderVary, strings.Join(w.Header().Values(net.HeaderVary), ", ")) if returnMinimal { w.Header().Set(net.HeaderPreferenceApplied, "return=minimal") } diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go index b53d18021b..ca6c28df5d 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go @@ -36,6 +36,7 @@ import ( "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/conversions" + "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/utils" "github.com/go-chi/chi/v5" "github.com/pkg/errors" @@ -63,62 +64,110 @@ func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) { return } - rs, ocsResponse := getReceivedShareFromID(ctx, client, shareID) + receivedShare, ocsResponse := getReceivedShareFromID(ctx, client, shareID) if ocsResponse != nil { response.WriteOCSResponse(w, r, *ocsResponse, nil) return } - sharedResource, ocsResponse := getSharedResource(ctx, client, rs.Share.Share.ResourceId) + sharedResource, ocsResponse := getSharedResource(ctx, client, receivedShare.Share.ResourceId) if ocsResponse != nil { response.WriteOCSResponse(w, r, *ocsResponse, nil) return } - lrs, ocsResponse := getSharesList(ctx, client) - if ocsResponse != nil { - response.WriteOCSResponse(w, r, *ocsResponse, nil) + mount, unmountedShares, err := GetMountpointAndUnmountedShares(ctx, client, sharedResource.Info) + if err != nil { + response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "could not determine mountpoint", err) return } + // first update the requested share + receivedShare.State = collaboration.ShareState_SHARE_STATE_ACCEPTED + // we need to add a path to the share + receivedShare.MountPoint = &provider.Reference{ + Path: mount, + } + + updateMask := &fieldmaskpb.FieldMask{Paths: []string{"state", "mount_point"}} + data, meta, err := h.updateReceivedShare(r.Context(), receivedShare, updateMask) + if err != nil { + // we log an error for affected shares, for the actual share we return an error + response.WriteOCSData(w, r, meta, data, err) + return + } + response.WriteOCSSuccess(w, r, []*conversions.ShareData{data}) + + // then update other unmounted shares to the same resource + for _, rs := range unmountedShares { + if rs.GetShare().GetId().GetOpaqueId() == shareID { + // we already updated this one + continue + } + + rs.State = collaboration.ShareState_SHARE_STATE_ACCEPTED + // set the same mountpoint as for the requested received share + rs.MountPoint = &provider.Reference{ + Path: mount, + } + + _, _, err := h.updateReceivedShare(r.Context(), rs, updateMask) + if err != nil { + // we log an error for affected shares, the actual share was successful + appctx.GetLogger(ctx).Error().Err(err).Str("received_share", shareID).Str("affected_share", rs.GetShare().GetId().GetOpaqueId()).Msg("could not update affected received share") + } + } +} + +// GetMountpointAndUnmountedShares returns a new or existing mountpoint for the given info and produces a list of unmounted received shares for the same resource +func GetMountpointAndUnmountedShares(ctx context.Context, gwc gateway.GatewayAPIClient, info *provider.ResourceInfo) (string, []*collaboration.ReceivedShare, error) { + unmountedShares := []*collaboration.ReceivedShare{} + receivedShares, err := listReceivedShares(ctx, gwc) + if err != nil { + return "", unmountedShares, err + } + // we need to sort the received shares by mount point in order to make things easier to evaluate. - base := path.Base(sharedResource.GetInfo().GetPath()) - mount := base - var mountedShares []*collaboration.ReceivedShare - sharesToAccept := map[string]bool{shareID: true} - for _, s := range lrs.Shares { - if utils.ResourceIDEqual(s.Share.ResourceId, rs.Share.Share.GetResourceId()) { + mount := filepath.Clean(info.Name) + existingMountpoint := "" + mountedShares := make([]*collaboration.ReceivedShare, 0, len(receivedShares)) + for _, s := range receivedShares { + if utils.ResourceIDEqual(s.Share.ResourceId, info.GetId()) { if s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED { - mount = s.MountPoint.Path + // a share to the resource already exists and is mounted, remember the mount point + _, err := utils.GetResourceByID(ctx, s.Share.ResourceId, gwc) + if err == nil { + existingMountpoint = s.MountPoint.Path + } } else { - sharesToAccept[s.Share.Id.OpaqueId] = true - } - } else { - if s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED { - s.Hidden = h.getReceivedShareHideFlagFromShareID(r.Context(), shareID) - mountedShares = append(mountedShares, s) + // a share to the resource already exists but is not mounted, collect the unmounted share + unmountedShares = append(unmountedShares, s) } } + + if s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED { + mountedShares = append(mountedShares, s) + } } - compareMountPoint := func(i, j int) bool { + sort.Slice(mountedShares, func(i, j int) bool { return mountedShares[i].MountPoint.Path > mountedShares[j].MountPoint.Path - } - sort.Slice(mountedShares, compareMountPoint) + }) - // now we have a list of shares, we want to iterate over all of them and check for name collisions + if existingMountpoint != "" { + // we want to reuse the same mountpoint for all unmounted shares to the same resource + return existingMountpoint, unmountedShares, nil + } + + // we have a list of shares, we want to iterate over all of them and check for name collisions for i, ms := range mountedShares { if ms.MountPoint.Path == mount { // does the shared resource still exist? - res, err := client.Stat(ctx, &provider.StatRequest{ - Ref: &provider.Reference{ - ResourceId: ms.Share.ResourceId, - }, - }) - if err == nil && res.Status.Code == rpc.Code_CODE_OK { + _, err := utils.GetResourceByID(ctx, ms.Share.ResourceId, gwc) + if err == nil { // The mount point really already exists, we need to insert a number into the filename - ext := filepath.Ext(base) - name := strings.TrimSuffix(base, ext) + ext := filepath.Ext(mount) + name := strings.TrimSuffix(mount, ext) // be smart about .tar.(gz|bz) files if strings.HasSuffix(name, ".tar") { name = strings.TrimSuffix(name, ".tar") @@ -130,26 +179,7 @@ func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) { // TODO we could delete shares here if the stat returns code NOT FOUND ... but listening for file deletes would be better } } - // we need to add a path to the share - receivedShare := &collaboration.ReceivedShare{ - Share: &collaboration.Share{ - Id: &collaboration.ShareId{OpaqueId: shareID}, - }, - State: collaboration.ShareState_SHARE_STATE_ACCEPTED, - Hidden: h.getReceivedShareHideFlagFromShareID(r.Context(), shareID), - MountPoint: &provider.Reference{ - Path: mount, - }, - } - updateMask := &fieldmaskpb.FieldMask{Paths: []string{"state", "hidden", "mount_point"}} - - for id := range sharesToAccept { - data := h.updateReceivedShare(w, r, receivedShare, updateMask) - // only render the data for the changed share - if id == shareID && data != nil { - response.WriteOCSSuccess(w, r, []*conversions.ShareData{data}) - } - } + return mount, unmountedShares, nil } // RejectReceivedShare handles DELETE Requests on /apps/files_sharing/api/v1/shares/{shareid} @@ -166,15 +196,15 @@ func (h *Handler) RejectReceivedShare(w http.ResponseWriter, r *http.Request) { Share: &collaboration.Share{ Id: &collaboration.ShareId{OpaqueId: shareID}, }, - State: collaboration.ShareState_SHARE_STATE_REJECTED, - Hidden: h.getReceivedShareHideFlagFromShareID(r.Context(), shareID), + State: collaboration.ShareState_SHARE_STATE_REJECTED, } - updateMask := &fieldmaskpb.FieldMask{Paths: []string{"state", "hidden"}} + updateMask := &fieldmaskpb.FieldMask{Paths: []string{"state"}} - data := h.updateReceivedShare(w, r, receivedShare, updateMask) - if data != nil { - response.WriteOCSSuccess(w, r, []*conversions.ShareData{data}) + data, meta, err := h.updateReceivedShare(r.Context(), receivedShare, updateMask) + if err != nil { + response.WriteOCSData(w, r, meta, nil, err) } + response.WriteOCSSuccess(w, r, []*conversions.ShareData{data}) } func (h *Handler) UpdateReceivedShare(w http.ResponseWriter, r *http.Request) { @@ -199,18 +229,17 @@ func (h *Handler) UpdateReceivedShare(w http.ResponseWriter, r *http.Request) { rs, _ := getReceivedShareFromID(r.Context(), client, shareID) if rs != nil && rs.Share != nil { - receivedShare.State = rs.Share.State + receivedShare.State = rs.State } - data := h.updateReceivedShare(w, r, receivedShare, updateMask) - if data != nil { - response.WriteOCSSuccess(w, r, []*conversions.ShareData{data}) + data, meta, err := h.updateReceivedShare(r.Context(), receivedShare, updateMask) + if err != nil { + response.WriteOCSData(w, r, meta, nil, err) } - // TODO: do we need error handling here? + response.WriteOCSSuccess(w, r, []*conversions.ShareData{data}) } -func (h *Handler) updateReceivedShare(w http.ResponseWriter, r *http.Request, receivedShare *collaboration.ReceivedShare, fieldMask *fieldmaskpb.FieldMask) *conversions.ShareData { - ctx := r.Context() +func (h *Handler) updateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *fieldmaskpb.FieldMask) (*conversions.ShareData, response.Meta, error) { logger := appctx.GetLogger(ctx) updateShareRequest := &collaboration.UpdateReceivedShareRequest{ @@ -220,23 +249,19 @@ func (h *Handler) updateReceivedShare(w http.ResponseWriter, r *http.Request, re client, err := h.getClient() if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error getting grpc gateway client", err) - return nil + return nil, response.MetaServerError, errors.Wrap(err, "error getting grpc gateway client") } shareRes, err := client.UpdateReceivedShare(ctx, updateShareRequest) if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc update received share request failed", err) - return nil + return nil, response.MetaServerError, errors.Wrap(err, "grpc update received share request failed") } if shareRes.Status.Code != rpc.Code_CODE_OK { if shareRes.Status.Code == rpc.Code_CODE_NOT_FOUND { - response.WriteOCSError(w, r, response.MetaNotFound.StatusCode, "not found", nil) - return nil + return nil, response.MetaNotFound, errors.New(shareRes.Status.Message) } - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc update received share request failed", errors.Errorf("code: %d, message: %s", shareRes.Status.Code, shareRes.Status.Message)) - return nil + return nil, response.MetaServerError, errors.Errorf("grpc update received share request failed: code: %d, message: %s", shareRes.Status.Code, shareRes.Status.Message) } rs := shareRes.GetShare() @@ -244,27 +269,23 @@ func (h *Handler) updateReceivedShare(w http.ResponseWriter, r *http.Request, re info, status, err := h.getResourceInfoByID(ctx, client, rs.Share.ResourceId) if err != nil || status.Code != rpc.Code_CODE_OK { h.logProblems(logger, status, err, "could not stat, skipping") - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "grpc get resource info failed", errors.Errorf("code: %d, message: %s", status.Code, status.Message)) - return nil + return nil, response.MetaServerError, errors.Errorf("grpc get resource info failed: code: %d, message: %s", status.Code, status.Message) } - data, err := conversions.CS3Share2ShareData(r.Context(), rs.Share) - if err != nil { - logger.Debug().Interface("share", rs.Share).Interface("shareData", data).Err(err).Msg("could not CS3Share2ShareData, skipping") - } + data := conversions.CS3Share2ShareData(ctx, rs.Share) data.State = mapState(rs.GetState()) data.Hidden = rs.GetHidden() h.addFileInfo(ctx, data, info) - h.mapUserIds(r.Context(), client, data) + h.mapUserIds(ctx, client, data) if data.State == ocsStateAccepted { // Needed because received shares can be jailed in a folder in the users home data.Path = path.Join(h.sharePrefix, path.Base(info.Path)) } - return data + return data, response.MetaOK, nil } func (h *Handler) updateReceivedFederatedShare(w http.ResponseWriter, r *http.Request, shareID string, rejectShare bool) { @@ -337,21 +358,8 @@ func (h *Handler) updateReceivedFederatedShare(w http.ResponseWriter, r *http.Re response.WriteOCSSuccess(w, r, []*conversions.ShareData{data}) } -// getReceivedShareHideFlagFromShareId returns the hide flag of a received share based on its ID. -func (h *Handler) getReceivedShareHideFlagFromShareID(ctx context.Context, shareID string) bool { - client, err := h.getClient() - if err != nil { - return false - } - rs, _ := getReceivedShareFromID(ctx, client, shareID) - if rs != nil { - return rs.GetShare().GetHidden() - } - return false -} - // getReceivedShareFromID uses a client to the gateway to fetch a share based on its ID. -func getReceivedShareFromID(ctx context.Context, client gateway.GatewayAPIClient, shareID string) (*collaboration.GetReceivedShareResponse, *response.Response) { +func getReceivedShareFromID(ctx context.Context, client gateway.GatewayAPIClient, shareID string) (*collaboration.ReceivedShare, *response.Response) { s, err := client.GetReceivedShare(ctx, &collaboration.GetReceivedShareRequest{ Ref: &collaboration.ShareReference{ Spec: &collaboration.ShareReference_Id{ @@ -376,7 +384,7 @@ func getReceivedShareFromID(ctx context.Context, client gateway.GatewayAPIClient return nil, arbitraryOcsResponse(response.MetaBadRequest.StatusCode, e.Error()) } - return s, nil + return s.Share, nil } // getSharedResource attempts to get a shared resource from the storage from the resource reference. @@ -403,23 +411,17 @@ func getSharedResource(ctx context.Context, client gateway.GatewayAPIClient, res return res, nil } -// getSharedResource gets the list of all shares for the current user. -func getSharesList(ctx context.Context, client gateway.GatewayAPIClient) (*collaboration.ListReceivedSharesResponse, *response.Response) { - shares, err := client.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{}) +// listReceivedShares list all received shares for the current user. +func listReceivedShares(ctx context.Context, client gateway.GatewayAPIClient) ([]*collaboration.ReceivedShare, error) { + res, err := client.ListReceivedShares(ctx, &collaboration.ListReceivedSharesRequest{}) if err != nil { - e := errors.Wrap(err, "error getting shares list") - return nil, arbitraryOcsResponse(response.MetaNotFound.StatusCode, e.Error()) + return nil, errtypes.InternalError("grpc list received shares request failed") } - if shares.Status.Code != rpc.Code_CODE_OK { - if shares.Status.Code == rpc.Code_CODE_NOT_FOUND { - e := fmt.Errorf("not found") - return nil, arbitraryOcsResponse(response.MetaNotFound.StatusCode, e.Error()) - } - e := fmt.Errorf(shares.GetStatus().GetMessage()) - return nil, arbitraryOcsResponse(response.MetaServerError.StatusCode, e.Error()) + if err := errtypes.NewErrtypeFromStatus(res.Status); err != nil { + return nil, err } - return shares, nil + return res.Shares, nil } // arbitraryOcsResponse abstracts the boilerplate that is creating a response.Response struct. diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index 303fc95d40..f75a30b340 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -303,11 +303,7 @@ func (h *Handler) CreateShare(w http.ResponseWriter, r *http.Request) { return } - s, err := conversions.CS3Share2ShareData(ctx, share) - if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err) - return - } + s := conversions.CS3Share2ShareData(ctx, share) h.addFileInfo(ctx, s, statRes.Info) @@ -402,12 +398,12 @@ func (h *Handler) updateExistingShareMountpoints(ctx context.Context, shareType } granteeCtx = metadata.AppendToOutgoingContext(granteeCtx, ctxpkg.TokenHeader, authRes.Token) - lrs, ocsResponse := getSharesList(granteeCtx, client) - if ocsResponse != nil { - return ocsResponse.OCS.Meta.StatusCode, ocsResponse.OCS.Meta.Message, nil + receivedShares, err := listReceivedShares(granteeCtx, client) + if err != nil { + return response.MetaServerError.StatusCode, "could not list shares", nil } - for _, s := range lrs.Shares { + for _, s := range receivedShares { if s.GetShare().GetId() != share.Id && s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED && utils.ResourceIDEqual(s.Share.ResourceId, info.GetId()) { updateRequest := &collaboration.UpdateReceivedShareRequest{ Share: &collaboration.ReceivedShare{ @@ -595,12 +591,8 @@ func (h *Handler) GetShare(w http.ResponseWriter, r *http.Request) { }) if err == nil && uRes.GetShare() != nil { resourceID = uRes.Share.Share.ResourceId - share, err = conversions.CS3Share2ShareData(ctx, uRes.Share.Share) + share = conversions.CS3Share2ShareData(ctx, uRes.Share.Share) share.Hidden = uRes.Share.Hidden - if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err) - return - } } } @@ -635,11 +627,7 @@ func (h *Handler) GetShare(w http.ResponseWriter, r *http.Request) { if err == nil && uRes.GetShare() != nil { resourceID = uRes.Share.ResourceId - share, err = conversions.CS3Share2ShareData(ctx, uRes.Share) - if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err) - return - } + share = conversions.CS3Share2ShareData(ctx, uRes.Share) } } @@ -874,11 +862,7 @@ func (h *Handler) updateShare(w http.ResponseWriter, r *http.Request, share *col h.statCache.RemoveStat(currentUser.Id, share.ResourceId) } - resultshare, err := conversions.CS3Share2ShareData(ctx, uRes.Share) - if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "error mapping share data", err) - return - } + resultshare := conversions.CS3Share2ShareData(ctx, uRes.Share) statReq := provider.StatRequest{Ref: &provider.Reference{ ResourceId: uRes.Share.ResourceId, @@ -1072,11 +1056,7 @@ func (h *Handler) listSharesWithMe(w http.ResponseWriter, r *http.Request) { } } - data, err := conversions.CS3Share2ShareData(r.Context(), rs.Share) - if err != nil { - sublog.Debug().Interface("share", rs.Share).Interface("shareData", data).Err(err).Msg("could not CS3Share2ShareData, skipping") - continue - } + data := conversions.CS3Share2ShareData(r.Context(), rs.Share) data.State = mapState(rs.GetState()) data.Hidden = rs.Hidden diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go index 04498b2205..dd940741b2 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/user.go @@ -281,11 +281,7 @@ func (h *Handler) removeUserShare(w http.ResponseWriter, r *http.Request, share }, } - data, err := conversions.CS3Share2ShareData(ctx, share) - if err != nil { - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "deleting share failed", err) - return - } + data := conversions.CS3Share2ShareData(ctx, share) // A deleted share should not have an ID. data.ID = "" @@ -337,11 +333,7 @@ func (h *Handler) listUserShares(r *http.Request, filters []*collaboration.Filte // build OCS response payload for _, s := range lsUserSharesResponse.Shares { - data, err := conversions.CS3Share2ShareData(ctx, s) - if err != nil { - log.Debug().Interface("share", s).Interface("shareData", data).Err(err).Msg("could not CS3Share2ShareData, skipping") - continue - } + data := conversions.CS3Share2ShareData(ctx, s) info, status, err := h.getResourceInfoByID(ctx, client, s.ResourceId) if err != nil || status.Code != rpc.Code_CODE_OK { diff --git a/vendor/github.com/cs3org/reva/v2/pkg/conversions/main.go b/vendor/github.com/cs3org/reva/v2/pkg/conversions/main.go index 8ef5dc395a..dbeaedd372 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/conversions/main.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/conversions/main.go @@ -232,7 +232,7 @@ type MatchValueData struct { } // CS3Share2ShareData converts a cs3api user share into shareData data model -func CS3Share2ShareData(ctx context.Context, share *collaboration.Share) (*ShareData, error) { +func CS3Share2ShareData(ctx context.Context, share *collaboration.Share) *ShareData { sd := &ShareData{ // share.permissions are mapped below // Displaynames are added later @@ -269,7 +269,7 @@ func CS3Share2ShareData(ctx context.Context, share *collaboration.Share) (*Share sd.Expiration = expiration.Format(_iso8601) } - return sd, nil + return sd } // PublicShare2ShareData converts a cs3api public share into shareData data model diff --git a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download/download.go b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download/download.go index cf0c863237..c15029bd2f 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download/download.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download/download.go @@ -159,6 +159,8 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI w.Header().Set("Accept-Ranges", "bytes") } + w.Header().Set(net.HeaderContentType, strings.Join([]string{md.MimeType, "charset=UTF-8"}, "; ")) + if len(ranges) > 0 { sublog.Debug().Int64("start", ranges[0].Start).Int64("length", ranges[0].Length).Msg("range request") if s == nil { @@ -200,7 +202,7 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI defer pr.Close() // cause writing goroutine to fail and exit if CopyN doesn't finish. go func() { for _, ra := range ranges { - part, err := mw.CreatePart(ra.MimeHeader(md.MimeType, int64(md.Size))) + part, err := mw.CreatePart(ra.MimeHeader(md.MimeType+"; charset=UTF-8", int64(md.Size))) if err != nil { _ = pw.CloseWithError(err) // CloseWithError always returns nil return @@ -224,7 +226,6 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI w.Header().Set(net.HeaderContentLength, strconv.FormatInt(sendSize, 10)) } - w.Header().Set(net.HeaderContentType, md.MimeType) w.Header().Set(net.HeaderContentDisposistion, net.ContentDispositionAttachment(path.Base(md.Path))) w.Header().Set(net.HeaderETag, md.Etag) w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*md.Id)) diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/grants.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/grants.go index ed3f7ca113..9dda19fa63 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/grants.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/grants.go @@ -197,11 +197,6 @@ func (fs *Decomposedfs) RemoveGrant(ctx context.Context, ref *provider.Reference } } - // check lock - if err := grantNode.CheckLock(ctx); err != nil { - return err - } - if err := grantNode.DeleteGrant(ctx, g, false); err != nil { return err } @@ -308,11 +303,6 @@ func (fs *Decomposedfs) loadGrant(ctx context.Context, ref *provider.Reference, } func (fs *Decomposedfs) storeGrant(ctx context.Context, n *node.Node, g *provider.Grant) error { - // check lock - if err := n.CheckLock(ctx); err != nil { - return err - } - var spaceType string spaceGrant := ctx.Value(utils.SpaceGrant) // this is not a grant on a space root we are just adding a share diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options/options.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options/options.go index 6e081fdcea..f58edff6a2 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options/options.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/options/options.go @@ -91,11 +91,7 @@ type AsyncPropagatorOptions struct { // EventOptions are the configurable options for events type EventOptions struct { - NatsAddress string `mapstructure:"natsaddress"` - NatsClusterID string `mapstructure:"natsclusterid"` - TLSInsecure bool `mapstructure:"tlsinsecure"` - TLSRootCACertificate string `mapstructure:"tlsrootcacertificate"` - NumConsumers int `mapstructure:"numconsumers"` + NumConsumers int `mapstructure:"numconsumers"` } // TokenOptions are the configurable option for tokens diff --git a/vendor/github.com/cs3org/reva/v2/pkg/store/store.go b/vendor/github.com/cs3org/reva/v2/pkg/store/store.go index f26edff2e2..0038d00580 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/store/store.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/store/store.go @@ -151,8 +151,8 @@ func Create(opts ...microstore.Option) microstore.Store { } return natsjskv.NewStore( append(opts, - natsjs.NatsOptions(natsOptions), // always pass in properly initialized default nats options - natsjs.DefaultTTL(ttl))..., + natsjskv.NatsOptions(natsOptions), // always pass in properly initialized default nats options + natsjskv.DefaultTTL(ttl))..., ) case TypeMemory, "mem", "": // allow existing short form and use as default return microstore.NewMemoryStore(opts...) diff --git a/vendor/modules.txt b/vendor/modules.txt index 552be2a0b2..1e48fa46ea 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -362,7 +362,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1 github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1 github.com/cs3org/go-cs3apis/cs3/tx/v1beta1 github.com/cs3org/go-cs3apis/cs3/types/v1beta1 -# github.com/cs3org/reva/v2 v2.18.1-0.20240115094008-bde86a38bd77 +# github.com/cs3org/reva/v2 v2.18.1-0.20240122171534-e8fc07f2395a ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime From c2f0ac41df375116c76c5bbec9803ecbf02c5605 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Mon, 22 Jan 2024 21:37:28 +0100 Subject: [PATCH 34/73] tests: fix test expectation --- changelog/unreleased/bump-reva.md | 1 + .../expected-failures-localAPI-on-OCIS-storage.md | 12 ++++++++---- .../features/apiSharingNg/deletePermissions.feature | 8 -------- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/changelog/unreleased/bump-reva.md b/changelog/unreleased/bump-reva.md index 81e2d51d5e..b08ffe6c43 100644 --- a/changelog/unreleased/bump-reva.md +++ b/changelog/unreleased/bump-reva.md @@ -2,4 +2,5 @@ Enhancement: Update reva to latest edge version We update reva to the latest edge version to get the latest fixes and features. +https://github.com/owncloud/ocis/pull/8264 https://github.com/owncloud/ocis/pull/8100 diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index 523a252c84..acd221bf22 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -270,10 +270,10 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiSharingNg/linkShare.feature:453](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L453) - [apiSharingNg/linkShare.feature:455](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L455) - [apiSharingNg/linkShare.feature:456](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L456) -- [apiSharingNg/deletePermissions.feature:146](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L146) -- [apiSharingNg/deletePermissions.feature:163](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L163) -- [apiSharingNg/deletePermissions.feature:184](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L184) -- [apiSharingNg/deletePermissions.feature:203](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L203) +- [apiSharingNg/deletePermissions.feature:138](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L138) +- [apiSharingNg/deletePermissions.feature:155](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L155) +- [apiSharingNg/deletePermissions.feature:176](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L176) +- [apiSharingNg/deletePermissions.feature:195](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L195) ### [sharee (editor role) MOVE a file by file-id into same shared folder returns 403](https://github.com/owncloud/ocis/issues/7617) @@ -359,5 +359,9 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiSpacesDavOperation/moveByFileId.feature:464](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L464) - [apiSpacesDavOperation/moveByFileId.feature:465](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L465) +### [CORS headers are only set when origin is sent by the client](https://github.com/owncloud/ocis/issues/5195) + +- [apiContract/copy.feature:16](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiContract/copy.feature#L16) + - Note: always have an empty line at the end of this file. The bash script that processes this file requires that the last line has a newline on the end. diff --git a/tests/acceptance/features/apiSharingNg/deletePermissions.feature b/tests/acceptance/features/apiSharingNg/deletePermissions.feature index 8319982966..83053a6718 100644 --- a/tests/acceptance/features/apiSharingNg/deletePermissions.feature +++ b/tests/acceptance/features/apiSharingNg/deletePermissions.feature @@ -27,8 +27,6 @@ Feature: Remove access to a drive item | permissionsRole | resource-type | path | | Viewer | file | textfile.txt | | File Editor | file | textfile.txt | - | Co Owner | file | textfile.txt | - | Manager | file | textfile.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -56,8 +54,6 @@ Feature: Remove access to a drive item | permissionsRole | resource-type | path | | Viewer | file | textfile.txt | | File Editor | file | textfile.txt | - | Co Owner | file | textfile.txt | - | Manager | file | textfile.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -86,8 +82,6 @@ Feature: Remove access to a drive item | permissionsRole | resource-type | path | | Viewer | file | textfile.txt | | File Editor | file | textfile.txt | - | Co Owner | file | textfile.txt | - | Manager | file | textfile.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -118,8 +112,6 @@ Feature: Remove access to a drive item | permissionsRole | resource-type | path | | Viewer | file | textfile.txt | | File Editor | file | textfile.txt | - | Co Owner | file | textfile.txt | - | Manager | file | textfile.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | From f08a9ae0d915fd42f496b254c0ca48685174db50 Mon Sep 17 00:00:00 2001 From: Prarup Gurung Date: Wed, 17 Jan 2024 15:59:55 +0545 Subject: [PATCH 35/73] Added test for sending share invitation to normal user --- tests/TestHelpers/GraphHelper.php | 25 +++++++++++++++ .../apiSharingNg/shareInvitations.feature | 26 ++++++++++++++++ .../features/bootstrap/SharingNgContext.php | 31 +++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/tests/TestHelpers/GraphHelper.php b/tests/TestHelpers/GraphHelper.php index a60586fdc0..a8cbd2e419 100644 --- a/tests/TestHelpers/GraphHelper.php +++ b/tests/TestHelpers/GraphHelper.php @@ -1822,4 +1822,29 @@ class GraphHelper { self::getRequestHeaders() ); } + + /** + * @param string $baseUrl + * @param string $xRequestId + * @param string $user + * @param string $password + * + * @return ResponseInterface + * @throws GuzzleException + */ + public static function getSharesSharedWithMe( + string $baseUrl, + string $xRequestId, + string $user, + string $password + ): ResponseInterface { + $url = self::getBetaFullUrl($baseUrl, "me/drive/sharedWithMe"); + return HttpRequestHelper::get( + $url, + $xRequestId, + $user, + $password, + self::getRequestHeaders() + ); + } } diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index 331668114f..c5a7ae1809 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -1111,3 +1111,29 @@ Feature: Send a sharing invitations | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | | Manager | folder | FolderToShare | + + + Scenario Outline: send share invitation to normal user + And user "Alice" has created folder "FolderToShare" + And user "Alice" has uploaded file "filesForUpload/textfile.txt" to "textfile.txt" + When user "Alice" sends the following share invitation using the Graph API: + | resourceType | | + | resource | | + | space | Personal | + | sharee | Brian | + | shareType | user | + | permissionsRole | | + Then the HTTP status code should be "200" + And for user "Brian" the space Shares should contain these entries: + | | + Examples: + | permissions-role | resource-type | path | + | Viewer | file | textfile.txt | + | File Editor | file | textfile.txt | + | Co Owner | file | textfile.txt | + | Manager | file | textfile.txt | + | Viewer | folder | FolderToShare | + | Editor | folder | FolderToShare | + | Co Owner | folder | FolderToShare | + | Uploader | folder | FolderToShare | + | Manager | folder | FolderToShare | diff --git a/tests/acceptance/features/bootstrap/SharingNgContext.php b/tests/acceptance/features/bootstrap/SharingNgContext.php index 73dd1e531d..8ae528bf9d 100644 --- a/tests/acceptance/features/bootstrap/SharingNgContext.php +++ b/tests/acceptance/features/bootstrap/SharingNgContext.php @@ -24,6 +24,7 @@ use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Psr\Http\Message\ResponseInterface; use TestHelpers\GraphHelper; use Behat\Gherkin\Node\TableNode; +use PHPUnit\Framework\Assert; require_once 'bootstrap.php'; @@ -424,4 +425,34 @@ class SharingNgContext implements Context { $this->removeSharePermission($sharer, 'link', $resourceType, $resource, $space) ); } + + /** + * @Then /^for user "([^"]*)" the space Shares should (not|)\s?contain these (files|entries):$/ + * + * @param string $user + * @param string $shouldOrNot + * @param TableNode $table + * + * @return void + * @throws Exception + */ + public function forUserTheSpaceSharesShouldContainTheseEntries(string $user, string $shouldOrNot, TableNode $table): void { + $should = $shouldOrNot !== 'not'; + $rows = $table->getRows(); + $response = GraphHelper::getSharesSharedWithMe( + $this->featureContext->getBaseUrl(), + $this->featureContext->getStepLineRef(), + $user, + $this->featureContext->getPasswordForUser($user) + ); + $contents = \json_decode($response->getBody()->getContents(), true); + + $fileFound = !empty(array_intersect(array_column($rows, 0), array_column($contents['value'], 'name'))); + + $assertMessage = $should + ? "Response does not contain the entry." + : "Response does contain the entry but should not."; + + Assert::assertSame($should, $fileFound, $assertMessage); + } } From 0312e72bd2c2050f337669e58184215edb62e7c1 Mon Sep 17 00:00:00 2001 From: Prarup Gurung Date: Fri, 19 Jan 2024 10:15:20 +0545 Subject: [PATCH 36/73] Addressed reviews --- .../apiSharingNg/shareInvitations.feature | 28 ++----------------- .../features/bootstrap/SharingNgContext.php | 2 +- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index c5a7ae1809..130f21c175 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -23,6 +23,8 @@ Feature: Send a sharing invitations | shareType | user | | permissionsRole | | Then the HTTP status code should be "200" + And for user "Brian" the space Shares should contain these entries: + | | And the JSON data of the response should match """ { @@ -1111,29 +1113,3 @@ Feature: Send a sharing invitations | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | | Manager | folder | FolderToShare | - - - Scenario Outline: send share invitation to normal user - And user "Alice" has created folder "FolderToShare" - And user "Alice" has uploaded file "filesForUpload/textfile.txt" to "textfile.txt" - When user "Alice" sends the following share invitation using the Graph API: - | resourceType | | - | resource | | - | space | Personal | - | sharee | Brian | - | shareType | user | - | permissionsRole | | - Then the HTTP status code should be "200" - And for user "Brian" the space Shares should contain these entries: - | | - Examples: - | permissions-role | resource-type | path | - | Viewer | file | textfile.txt | - | File Editor | file | textfile.txt | - | Co Owner | file | textfile.txt | - | Manager | file | textfile.txt | - | Viewer | folder | FolderToShare | - | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | - | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | diff --git a/tests/acceptance/features/bootstrap/SharingNgContext.php b/tests/acceptance/features/bootstrap/SharingNgContext.php index 8ae528bf9d..7f18bd793c 100644 --- a/tests/acceptance/features/bootstrap/SharingNgContext.php +++ b/tests/acceptance/features/bootstrap/SharingNgContext.php @@ -447,7 +447,7 @@ class SharingNgContext implements Context { ); $contents = \json_decode($response->getBody()->getContents(), true); - $fileFound = !empty(array_intersect(array_column($rows, 0), array_column($contents['value'], 'name'))); + $fileFound = empty(array_diff(array_map(fn ($row) => trim($row[0], '/'), $rows), array_column($contents['value'], 'name'))); $assertMessage = $should ? "Response does not contain the entry." From f7599b3fc86102e6a26978f17d262f3f091d7669 Mon Sep 17 00:00:00 2001 From: Prarup Gurung Date: Tue, 23 Jan 2024 11:13:44 +0545 Subject: [PATCH 37/73] Added step to check as sharee for share invitation to group --- .../acceptance/features/apiSharingNg/shareInvitations.feature | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index 130f21c175..cab96f4632 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -117,6 +117,10 @@ Feature: Send a sharing invitations | shareType | group | | permissionsRole | | Then the HTTP status code should be "200" + And for user "Brian" the space Shares should contain these entries: + | | + And for user "Carol" the space Shares should contain these entries: + | | And the JSON data of the response should match """ { From 9cb81073c1fd61dd959f02de68c391a81d4e376d Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Tue, 23 Jan 2024 12:18:19 +0545 Subject: [PATCH 38/73] fix test expectations --- .../apiSharingNg/shareInvitations.feature | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index 331668114f..931e0160e8 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -89,8 +89,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -181,8 +179,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -265,7 +261,7 @@ Feature: Send a sharing invitations Examples: | permissionsAction | | permissions/create | - | children/create | + # | children/create | | upload/create | | path/read | | quota/read | @@ -275,11 +271,11 @@ Feature: Send a sharing invitations | versions/read | | deleted/read | | basic/read | - | path/update | + # | path/update | | versions/update | | deleted/update | | permissions/update | - | standard/delete | + # | standard/delete | | permissions/delete | | deleted/delete | | permissions/deny | @@ -461,7 +457,7 @@ Feature: Send a sharing invitations Examples: | permissionsAction | | permissions/create | - | children/create | + # | children/create | | upload/create | | path/read | | quota/read | @@ -471,11 +467,11 @@ Feature: Send a sharing invitations | versions/read | | deleted/read | | basic/read | - | path/update | + # | path/update | | versions/update | | deleted/update | | permissions/update | - | standard/delete | + # | standard/delete | | permissions/delete | | deleted/delete | | permissions/deny | @@ -667,8 +663,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -767,8 +761,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -854,8 +846,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -917,8 +907,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -972,8 +960,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -1039,8 +1025,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | @@ -1104,8 +1088,6 @@ Feature: Send a sharing invitations | permissions-role | resource-type | path | | Viewer | file | /textfile1.txt | | File Editor | file | /textfile1.txt | - | Co Owner | file | /textfile1.txt | - | Manager | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Co Owner | folder | FolderToShare | From ca2b5744a1ab93d9a96e981e5cd8914841a0de64 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Tue, 23 Jan 2024 12:19:31 +0545 Subject: [PATCH 39/73] fix test expectations --- .../features/apiSharingNg/shareInvitations.feature | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index 931e0160e8..8737dd2a6f 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -261,7 +261,6 @@ Feature: Send a sharing invitations Examples: | permissionsAction | | permissions/create | - # | children/create | | upload/create | | path/read | | quota/read | @@ -271,11 +270,9 @@ Feature: Send a sharing invitations | versions/read | | deleted/read | | basic/read | - # | path/update | | versions/update | | deleted/update | | permissions/update | - # | standard/delete | | permissions/delete | | deleted/delete | | permissions/deny | @@ -457,7 +454,6 @@ Feature: Send a sharing invitations Examples: | permissionsAction | | permissions/create | - # | children/create | | upload/create | | path/read | | quota/read | @@ -467,11 +463,9 @@ Feature: Send a sharing invitations | versions/read | | deleted/read | | basic/read | - # | path/update | | versions/update | | deleted/update | | permissions/update | - # | standard/delete | | permissions/delete | | deleted/delete | | permissions/deny | From e1101940dcb211d6a720a8f0933cc7feaccece83 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Tue, 23 Jan 2024 12:40:13 +0545 Subject: [PATCH 40/73] fix cors tests --- ...xpected-failures-localAPI-on-OCIS-storage.md | 4 ---- .../features/apiContract/copy.feature | 4 +++- .../features/bootstrap/SpacesContext.php | 17 ++++++++++++++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index acd221bf22..d9b6da351e 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -359,9 +359,5 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiSpacesDavOperation/moveByFileId.feature:464](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L464) - [apiSpacesDavOperation/moveByFileId.feature:465](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSpacesDavOperation/moveByFileId.feature#L465) -### [CORS headers are only set when origin is sent by the client](https://github.com/owncloud/ocis/issues/5195) - -- [apiContract/copy.feature:16](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiContract/copy.feature#L16) - - Note: always have an empty line at the end of this file. The bash script that processes this file requires that the last line has a newline on the end. diff --git a/tests/acceptance/features/apiContract/copy.feature b/tests/acceptance/features/apiContract/copy.feature index 5bf61391e8..08a1fc195a 100644 --- a/tests/acceptance/features/apiContract/copy.feature +++ b/tests/acceptance/features/apiContract/copy.feature @@ -16,7 +16,9 @@ Feature: Copy test Scenario: check the COPY response headers Given user "Alice" has uploaded a file inside space "new-space" with content "some content" to "testfile.txt" And user "Alice" has created a folder "new" in space "new-space" - When user "Alice" copies file "testfile.txt" from space "new-space" to "/new/testfile.txt" inside space "new-space" using the WebDAV API + When user "Alice" copies file "testfile.txt" from space "new-space" to "/new/testfile.txt" inside space "new-space" with following headers using the WebDAV API + | header | value | + | Origin | %base_url% | Then the HTTP status code should be "201" And the following headers should match these regular expressions | Oc-Fileid | /^[a-f0-9!\$\-]{110}$/ | diff --git a/tests/acceptance/features/bootstrap/SpacesContext.php b/tests/acceptance/features/bootstrap/SpacesContext.php index f4672f1878..acc293c080 100644 --- a/tests/acceptance/features/bootstrap/SpacesContext.php +++ b/tests/acceptance/features/bootstrap/SpacesContext.php @@ -1807,12 +1807,15 @@ class SpacesContext implements Context { /** * @When /^user "([^"]*)" copies (?:file|folder) "([^"]*)" from space "([^"]*)" to "([^"]*)" inside space "([^"]*)" using the WebDAV API$/ + * @When /^user "([^"]*)" copies (?:file|folder) "([^"]*)" from space "([^"]*)" to "([^"]*)" inside space "([^"]*)"(?: with following headers) using the WebDAV API$/ * * @param string $user * @param string $fileSource * @param string $fromSpaceName * @param string $fileDestination * @param string $toSpaceName + * @param string $toSpaceName + * @param TableNode|null $table * * @return void * @throws GuzzleException @@ -1822,10 +1825,22 @@ class SpacesContext implements Context { string $fileSource, string $fromSpaceName, string $fileDestination, - string $toSpaceName + string $toSpaceName, + TableNode $table = null ):void { $space = $this->getSpaceByName($user, $fromSpaceName); $headers['Destination'] = $this->destinationHeaderValueWithSpaceName($user, $fileDestination, $toSpaceName); + + if ($table !== null) { + $this->featureContext->verifyTableNodeColumns( + $table, + ['header', 'value'] + ); + foreach ($table as $row) { + $headers[$row['header']] = $this->featureContext->substituteInLineCodes($row['value']); + } + } + $fullUrl = $space["root"]["webDavUrl"] . '/' . ltrim($fileSource, "/"); $this->featureContext->setResponse($this->copyFilesAndFoldersRequest($user, $fullUrl, $headers)); } From a7ab682f172bd1a4ac0499ba46e853a839c64e72 Mon Sep 17 00:00:00 2001 From: Saw-jan Date: Tue, 23 Jan 2024 12:42:47 +0545 Subject: [PATCH 41/73] fix php code --- tests/acceptance/features/bootstrap/SpacesContext.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/acceptance/features/bootstrap/SpacesContext.php b/tests/acceptance/features/bootstrap/SpacesContext.php index acc293c080..1fd4615bab 100644 --- a/tests/acceptance/features/bootstrap/SpacesContext.php +++ b/tests/acceptance/features/bootstrap/SpacesContext.php @@ -1814,7 +1814,6 @@ class SpacesContext implements Context { * @param string $fromSpaceName * @param string $fileDestination * @param string $toSpaceName - * @param string $toSpaceName * @param TableNode|null $table * * @return void From c9a77eb43f1f2d4591c9b8920396437b758ad624 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Tue, 23 Jan 2024 08:59:16 +0000 Subject: [PATCH 42/73] Automated changelog update [skip ci] --- CHANGELOG.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9305d77cef..05ca5b72b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,9 +55,9 @@ The following sections list the changes for unreleased. * Bugfix - Fix PATCH/DELETE status code for drives that don't support them: [#8235](https://github.com/owncloud/ocis/pull/8235) * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) -* Enhancement - Update reva to latest edge version: [#8100](https://github.com/owncloud/ocis/pull/8100) * Enhancement - Remove deprecated environment variables: [#8149](https://github.com/owncloud/ocis/pull/8149) * Enhancement - Disable the password policy: [#8152](https://github.com/owncloud/ocis/pull/8152) +* Enhancement - Update reva to latest edge version: [#8264](https://github.com/owncloud/ocis/pull/8264) ## Details @@ -176,12 +176,6 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/issues/6764 https://github.com/owncloud/ocis/pull/8062 -* Enhancement - Update reva to latest edge version: [#8100](https://github.com/owncloud/ocis/pull/8100) - - We update reva to the latest edge version to get the latest fixes and features. - - https://github.com/owncloud/ocis/pull/8100 - * Enhancement - Remove deprecated environment variables: [#8149](https://github.com/owncloud/ocis/pull/8149) We have removed all deprecated environment variables that have been marked for @@ -199,6 +193,13 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/pull/8152 https://github.com/cs3org/reva/pull/4453 +* Enhancement - Update reva to latest edge version: [#8264](https://github.com/owncloud/ocis/pull/8264) + + We update reva to the latest edge version to get the latest fixes and features. + + https://github.com/owncloud/ocis/pull/8264 + https://github.com/owncloud/ocis/pull/8100 + # Changelog for [5.0.0-rc.1] (2023-12-27) The following sections list the changes for 5.0.0-rc.1. From 8dc7420b044007e4ca1018fe8b8f4a07fc71d3c3 Mon Sep 17 00:00:00 2001 From: Roman Perekhod Date: Tue, 23 Jan 2024 12:44:09 +0100 Subject: [PATCH 43/73] [full-ci][bump reva] fix race in a publicshare manager --- .../fix-concurrent-access-to-map.md | 7 +++ go.mod | 2 +- go.sum | 6 +-- .../v2/pkg/publicshare/manager/json/json.go | 47 ++++++++++--------- vendor/modules.txt | 2 +- 5 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 changelog/unreleased/fix-concurrent-access-to-map.md diff --git a/changelog/unreleased/fix-concurrent-access-to-map.md b/changelog/unreleased/fix-concurrent-access-to-map.md new file mode 100644 index 0000000000..0e4ca0f759 --- /dev/null +++ b/changelog/unreleased/fix-concurrent-access-to-map.md @@ -0,0 +1,7 @@ +Bugfix: Fix concurrent access to a map + +We fixed the race condition that led to concurrent map access in a publicshare manager. + +https://github.com/owncloud/ocis/pull/8269 +https://github.com/cs3org/reva/pull/4472 +https://github.com/owncloud/ocis/issues/8255 diff --git a/go.mod b/go.mod index 3e345cc0b8..b4c3913826 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/coreos/go-oidc v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.9.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.18.1-0.20240122171534-e8fc07f2395a + github.com/cs3org/reva/v2 v2.18.1-0.20240123151850-049234cc31e0 github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e diff --git a/go.sum b/go.sum index c9ca0d89b2..97bd36a7a6 100644 --- a/go.sum +++ b/go.sum @@ -1018,10 +1018,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c= github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.18.1-0.20240122154113-d79f163775db h1:0nc89DfeCGRr98Z/NZor9fRyQ0pGxq0iQnnUsWFhnek= -github.com/cs3org/reva/v2 v2.18.1-0.20240122154113-d79f163775db/go.mod h1:plMbmaHczZbP+1rtV56YCYs5lkmpdRNpj0KZb9BWLus= -github.com/cs3org/reva/v2 v2.18.1-0.20240122171534-e8fc07f2395a h1:2FLa9HFgDlvXTAdDjqcHsb8Ky2eTBXIIR/ukZeemMKI= -github.com/cs3org/reva/v2 v2.18.1-0.20240122171534-e8fc07f2395a/go.mod h1:GCN3g6uYE0Nvd31dGlhaGGyUviUfbG2NkecPRv5oSc4= +github.com/cs3org/reva/v2 v2.18.1-0.20240123151850-049234cc31e0 h1:btY1QRE5X4bvp7V+PUkQptFFBkB9QoJTObDNrX9G3EU= +github.com/cs3org/reva/v2 v2.18.1-0.20240123151850-049234cc31e0/go.mod h1:GCN3g6uYE0Nvd31dGlhaGGyUviUfbG2NkecPRv5oSc4= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= diff --git a/vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/json/json.go b/vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/json/json.go index 960a2eea6e..7e809f5528 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/json/json.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/json/json.go @@ -219,6 +219,9 @@ func (m *manager) Dump(ctx context.Context, shareChan chan<- *publicshare.WithPa // Load imports public shares and received shares from channels (e.g. during migration) func (m *manager) Load(ctx context.Context, shareChan <-chan *publicshare.WithPassword) error { + m.mutex.Lock() + defer m.mutex.Unlock() + db, err := m.persistence.Read(ctx) if err != nil { return err @@ -414,6 +417,9 @@ func (m *manager) UpdatePublicShare(ctx context.Context, u *user.User, req *link // GetPublicShare gets a public share either by ID or Token. func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference, sign bool) (*link.PublicShare, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + if ref.GetToken() != "" { ps, pw, err := m.getByToken(ctx, ref.GetToken()) if err != nil { @@ -428,9 +434,6 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu return ps, nil } - m.mutex.Lock() - defer m.mutex.Unlock() - db, err := m.persistence.Read(ctx) if err != nil { return nil, err @@ -447,7 +450,7 @@ func (m *manager) GetPublicShare(ctx context.Context, u *user.User, ref *link.Pu if ref.GetId().GetOpaqueId() == ps.Id.OpaqueId { if publicshare.IsExpired(ps) { - if err := m.revokeExpiredPublicShare(ctx, &ps, u); err != nil { + if err := m.revokeExpiredPublicShare(ctx, &ps); err != nil { return nil, err } return nil, errtypes.NotFound("no shares found by id:" + ref.GetId().String()) @@ -491,7 +494,7 @@ func (m *manager) ListPublicShares(ctx context.Context, u *user.User, filters [] } if publicshare.IsExpired(local.PublicShare) { - if err := m.revokeExpiredPublicShare(ctx, &local.PublicShare, u); err != nil { + if err := m.revokeExpiredPublicShare(ctx, &local.PublicShare); err != nil { log.Error().Err(err). Str("share_token", local.Token). Msg("failed to revoke expired public share") @@ -561,20 +564,18 @@ func (m *manager) cleanupExpiredShares() { _ = utils.UnmarshalJSONToProtoV1([]byte(d.(string)), &ps) if publicshare.IsExpired(ps) { - _ = m.revokeExpiredPublicShare(context.Background(), &ps, nil) + _ = m.revokeExpiredPublicShare(context.Background(), &ps) } } } -func (m *manager) revokeExpiredPublicShare(ctx context.Context, s *link.PublicShare, u *user.User) error { +// revokeExpiredPublicShare doesn't have a lock inside, ensure a lock before call +func (m *manager) revokeExpiredPublicShare(ctx context.Context, s *link.PublicShare) error { if !m.enableExpiredSharesCleanup { return nil } - m.mutex.Unlock() - defer m.mutex.Lock() - - err := m.RevokePublicShare(ctx, u, &link.PublicShareReference{ + err := m.revokePublicShare(ctx, &link.PublicShareReference{ Spec: &link.PublicShareReference_Id{ Id: &link.PublicShareId{ OpaqueId: s.Id.OpaqueId, @@ -590,13 +591,18 @@ func (m *manager) revokeExpiredPublicShare(ctx context.Context, s *link.PublicSh } // RevokePublicShare undocumented. -func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, ref *link.PublicShareReference) error { +func (m *manager) RevokePublicShare(ctx context.Context, _ *user.User, ref *link.PublicShareReference) error { m.mutex.Lock() + defer m.mutex.Unlock() + return m.revokePublicShare(ctx, ref) +} + +// revokePublicShare doesn't have a lock inside, ensure a lock before call +func (m *manager) revokePublicShare(ctx context.Context, ref *link.PublicShareReference) error { db, err := m.persistence.Read(ctx) if err != nil { return err } - m.mutex.Unlock() switch { case ref.GetId() != nil && ref.GetId().OpaqueId != "": @@ -615,20 +621,16 @@ func (m *manager) RevokePublicShare(ctx context.Context, u *user.User, ref *link return errors.New("reference does not exist") } - m.mutex.Lock() - defer m.mutex.Unlock() return m.persistence.Write(ctx, db) } +// getByToken doesn't have a lock inside, ensure a lock before call func (m *manager) getByToken(ctx context.Context, token string) (*link.PublicShare, string, error) { db, err := m.persistence.Read(ctx) if err != nil { return nil, "", err } - m.mutex.Lock() - defer m.mutex.Unlock() - for _, v := range db { var local link.PublicShare if err := utils.UnmarshalJSONToProtoV1([]byte(v.(map[string]interface{})["share"].(string)), &local); err != nil { @@ -646,14 +648,14 @@ func (m *manager) getByToken(ctx context.Context, token string) (*link.PublicSha // GetPublicShareByToken gets a public share by its opaque token. func (m *manager) GetPublicShareByToken(ctx context.Context, token string, auth *link.PublicShareAuthentication, sign bool) (*link.PublicShare, error) { + m.mutex.Lock() + defer m.mutex.Unlock() + db, err := m.persistence.Read(ctx) if err != nil { return nil, err } - m.mutex.Lock() - defer m.mutex.Unlock() - for _, v := range db { passDB := v.(map[string]interface{})["password"].(string) var local link.PublicShare @@ -663,8 +665,7 @@ func (m *manager) GetPublicShareByToken(ctx context.Context, token string, auth if local.Token == token { if publicshare.IsExpired(local) { - // TODO user is not needed at all in this API. - if err := m.revokeExpiredPublicShare(ctx, &local, nil); err != nil { + if err := m.revokeExpiredPublicShare(ctx, &local); err != nil { return nil, err } break diff --git a/vendor/modules.txt b/vendor/modules.txt index 1e48fa46ea..c8d9daa6a0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -362,7 +362,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1 github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1 github.com/cs3org/go-cs3apis/cs3/tx/v1beta1 github.com/cs3org/go-cs3apis/cs3/types/v1beta1 -# github.com/cs3org/reva/v2 v2.18.1-0.20240122171534-e8fc07f2395a +# github.com/cs3org/reva/v2 v2.18.1-0.20240123151850-049234cc31e0 ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime From e5d910acebce45a1038107c1deb7fed1e05a0183 Mon Sep 17 00:00:00 2001 From: ownClouders Date: Wed, 24 Jan 2024 00:44:59 +0000 Subject: [PATCH 44/73] [tx] updated from transifex --- .../userlog/pkg/service/l10n/locale/es/LC_MESSAGES/userlog.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/userlog/pkg/service/l10n/locale/es/LC_MESSAGES/userlog.po b/services/userlog/pkg/service/l10n/locale/es/LC_MESSAGES/userlog.po index e65b51976c..3d8574bee2 100644 --- a/services/userlog/pkg/service/l10n/locale/es/LC_MESSAGES/userlog.po +++ b/services/userlog/pkg/service/l10n/locale/es/LC_MESSAGES/userlog.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: EMAIL\n" -"POT-Creation-Date: 2024-01-03 04:25+0000\n" +"POT-Creation-Date: 2024-01-24 00:44+0000\n" "PO-Revision-Date: 2023-03-15 08:28+0000\n" "Last-Translator: Juan Carlos Garrote, 2023\n" "Language-Team: Spanish (https://app.transifex.com/owncloud-org/teams/6149/es/)\n" From 4592d06c2bce6af572ecaf9aaa8e741b972d6123 Mon Sep 17 00:00:00 2001 From: nirajacharya2 <122071597+nirajacharya2@users.noreply.github.com> Date: Wed, 24 Jan 2024 09:57:19 +0545 Subject: [PATCH 45/73] fixing incorrect json format for json assertion steps (#8265) --- .../features/apiSpaces/changeSpaces.feature | 24 ++++--- .../features/apiSpaces/createSpace.feature | 66 +++++++++--------- .../features/apiSpaces/listSpaces.feature | 68 +++++++++++-------- .../apiSpaces/spaceManagement.feature | 8 +-- 4 files changed, 91 insertions(+), 75 deletions(-) diff --git a/tests/acceptance/features/apiSpaces/changeSpaces.feature b/tests/acceptance/features/apiSpaces/changeSpaces.feature index cc34268dec..4c34faceef 100644 --- a/tests/acceptance/features/apiSpaces/changeSpaces.feature +++ b/tests/acceptance/features/apiSpaces/changeSpaces.feature @@ -205,8 +205,10 @@ Feature: Change data of space "mimeType" ], "properties": { - "type": "string", - "enum": ["text/markdown"] + "mimeType": { + "type": "string", + "enum": ["text/markdown"] + } } }, "id": { @@ -298,8 +300,10 @@ Feature: Change data of space "mimeType" ], "properties": { - "type": "string", - "enum": [""] + "mimeType": { + "type": "string", + "enum": [""] + } } }, "id": { @@ -393,8 +397,10 @@ Feature: Change data of space "mimeType" ], "properties": { - "type": "string", - "enum": ["text/markdown"] + "mimeType": { + "type": "string", + "enum": ["text/markdown"] + } } }, "id": { @@ -479,8 +485,10 @@ Feature: Change data of space "mimeType" ], "properties": { - "type": "string", - "enum": ["image/png"] + "mimeType": { + "type": "string", + "enum": ["image/png"] + } } }, "id": { diff --git a/tests/acceptance/features/apiSpaces/createSpace.feature b/tests/acceptance/features/apiSpaces/createSpace.feature index f3f2b6b3b4..e4ea59c103 100644 --- a/tests/acceptance/features/apiSpaces/createSpace.feature +++ b/tests/acceptance/features/apiSpaces/createSpace.feature @@ -41,28 +41,28 @@ Feature: create space "enum": ["Project Mars"] }, "driveType": { - "type": "string", + "type": "string", "enum": ["project"] }, "driveAlias": { - "type": "string", + "type": "string", "enum": ["project/project-mars"] }, "id": { - "type": "string", + "type": "string", "enum": ["%space_id%"] }, "quota": { - "type": "object", - "required": [ + "type": "object", + "required": [ "total" - ], - "properties": { - "state": { - "type": "number", - "enum": [1000000000] - } - } + ], + "properties": { + "total": { + "type": "number", + "enum": [1000000000] + } + } }, "root": { "type": "object", @@ -70,11 +70,11 @@ Feature: create space "webDavUrl" ], "properties": { - "webDavUrl": { - "type": "string", - "enum": ["%base_url%/dav/spaces/%space_id%"] - } - } + "webDavUrl": { + "type": "string", + "enum": ["%base_url%/dav/spaces/%space_id%"] + } + } }, "webUrl": { "type": "string", @@ -111,24 +111,24 @@ Feature: create space "enum": ["Project Venus"] }, "driveType": { - "type": "string", + "type": "string", "enum": ["project"] }, "id": { - "type": "string", + "type": "string", "enum": ["%space_id%"] }, "quota": { - "type": "object", - "required": [ + "type": "object", + "required": [ "total" - ], - "properties": { - "state": { - "type": "number", - "enum": [2000] - } - } + ], + "properties": { + "total": { + "type": "number", + "enum": [2000] + } + } }, "root": { "type": "object", @@ -136,11 +136,11 @@ Feature: create space "webDavUrl" ], "properties": { - "webDavUrl": { - "type": "string", - "enum": ["%base_url%/dav/spaces/%space_id%"] - } - } + "webDavUrl": { + "type": "string", + "enum": ["%base_url%/dav/spaces/%space_id%"] + } + } }, "webUrl": { "type": "string", diff --git a/tests/acceptance/features/apiSpaces/listSpaces.feature b/tests/acceptance/features/apiSpaces/listSpaces.feature index 81559075b4..4676e3dd7f 100644 --- a/tests/acceptance/features/apiSpaces/listSpaces.feature +++ b/tests/acceptance/features/apiSpaces/listSpaces.feature @@ -167,11 +167,11 @@ Feature: List and create spaces "enum": ["my project"] }, "driveType": { - "type": "string", + "type": "string", "enum": ["project"] }, "id": { - "type": "string", + "type": "string", "enum": ["%space_id%"] } } @@ -227,13 +227,17 @@ Feature: List and create spaces "user" ], "properties": { - "type": "object", - "required": [ - "id" - ], - "properties": { - "type": "string", - "enum": ["%user_id%"] + "user": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "enum": ["%user_id%"] + } + } } } }, @@ -343,6 +347,10 @@ Feature: List and create spaces "enum": ["%base_url%/dav/spaces/%space_id%"] } } + }, + "webUrl": { + "type": "string", + "enum": ["%base_url%/f/%space_id%"] } } } @@ -454,28 +462,28 @@ Feature: List and create spaces "enum": ["Shares"] }, "driveType": { - "type": "string", + "type": "string", "enum": ["virtual"] }, "driveAlias": { - "type": "string", + "type": "string", "enum": ["virtual/shares"] }, "id": { - "type": "string", + "type": "string", "enum": ["%space_id%"] }, "quota": { - "type": "object", - "required": [ + "type": "object", + "required": [ "state" - ], - "properties": { - "state": { - "type": "string", - "enum": ["normal"] - } - } + ], + "properties": { + "state": { + "type": "string", + "enum": ["normal"] + } + } }, "root": { "type": "object", @@ -484,15 +492,15 @@ Feature: List and create spaces "webDavUrl" ], "properties": { - "eTag": { - "type": "string", - "enum": ["%space_etag%"] - }, - "webDavUrl": { - "type": "string", - "enum": ["%base_url%/dav/spaces/%space_id%"] - } - } + "eTag": { + "type": "string", + "enum": ["%space_etag%"] + }, + "webDavUrl": { + "type": "string", + "enum": ["%base_url%/dav/spaces/%space_id%"] + } + } }, "webUrl": { "type": "string", diff --git a/tests/acceptance/features/apiSpaces/spaceManagement.feature b/tests/acceptance/features/apiSpaces/spaceManagement.feature index f904c6dd7f..926bb407b9 100644 --- a/tests/acceptance/features/apiSpaces/spaceManagement.feature +++ b/tests/acceptance/features/apiSpaces/spaceManagement.feature @@ -39,11 +39,11 @@ Feature: Space management "enum": ["Project"] }, "driveType": { - "type": "string", + "type": "string", "enum": ["project"] }, "id": { - "type": "string", + "type": "string", "enum": ["%space_id%"] } } @@ -70,11 +70,11 @@ Feature: Space management "enum": ["Alice Hansen"] }, "driveType": { - "type": "string", + "type": "string", "enum": ["personal"] }, "id": { - "type": "string", + "type": "string", "enum": ["%space_id%"] } } From 7d6cdd649effde60da5f8922ce5efa81ccea65b6 Mon Sep 17 00:00:00 2001 From: nirajacharya2 <122071597+nirajacharya2@users.noreply.github.com> Date: Wed, 24 Jan 2024 09:57:38 +0545 Subject: [PATCH 46/73] added tests for searching users by normal user (#8241) --- .../apiGraphUserGroup/getUser.feature | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/tests/acceptance/features/apiGraphUserGroup/getUser.feature b/tests/acceptance/features/apiGraphUserGroup/getUser.feature index 9254358854..dced646708 100644 --- a/tests/acceptance/features/apiGraphUserGroup/getUser.feature +++ b/tests/acceptance/features/apiGraphUserGroup/getUser.feature @@ -1443,3 +1443,171 @@ Feature: get users | user | errorToken | | Alice-From-Wonderland | -From-Wonderland | | Alice@From@Wonderland | @From@Wonderland | + + @issue-7990 + Scenario: non-admin user searches other users by e-mail + When user "Brian" searches for user "%22alice@example.org%22" using Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "array", + "required": [ + "displayName", + "id", + "mail", + "userType" + ], + "properties": { + "displayName": { + "type": "string", + "enum": ["Alice Hansen"] + }, + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "mail": { + "type": "string", + "enum": ["alice@example.org"] + }, + "userType": { + "type": "string", + "enum": ["Member"] + } + } + } + } + } + """ + + + Scenario: non-admin user searches for a disabled users + Given the user "Admin" has disabled user "Alice" + When user "Brian" searches for user "alice" using Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "array", + "required": [ + "displayName", + "id", + "mail", + "userType" + ], + "properties": { + "displayName": { + "type": "string", + "enum": ["Alice Hansen"] + }, + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "mail": { + "type": "string", + "enum": ["alice@example.org"] + }, + "userType": { + "type": "string", + "enum": ["Member"] + } + } + } + } + } + """ + + + Scenario: non-admin user searches for multiple users having same displayname + Given the user "Admin" has created a new user with the following attributes: + | userName | another-alice | + | displayName | Alice Hansen | + | email | another-alice@example.org | + | password | containsCharacters(*:!;_+-&) | + + When user "Brian" searches for user "alice" using Graph API + Then the HTTP status code should be "200" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "value": { + "type": "array", + "items": [ + { + "type": "object", + "required": [ + "displayName", + "id", + "mail", + "userType" + ], + "properties": { + "displayName": { + "type": "string", + "enum": ["Alice Hansen"] + }, + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "mail": { + "type": "string", + "enum": ["alice@example.org"] + }, + "userType": { + "type": "string", + "enum": ["Member"] + } + } + }, + { + "type": "object", + "required": [ + "displayName", + "id", + "mail", + "userType" + ], + "properties": { + "displayName": { + "type": "string", + "enum": ["Alice Hansen"] + }, + "id": { + "type": "string", + "pattern": "^%user_id_pattern%$" + }, + "mail": { + "type": "string", + "enum": ["another-alice@example.org"] + }, + "userType": { + "type": "string", + "enum": ["Member"] + } + } + } + ] + } + } + } + """ From be8973def1604ee9979c88a64ab891be4e2b630d Mon Sep 17 00:00:00 2001 From: Sabin Panta <64484313+S-Panta@users.noreply.github.com> Date: Wed, 24 Jan 2024 10:12:42 +0545 Subject: [PATCH 47/73] [tests-only][full-ci] adding user quota using graph api instead of Provisioning api (#7000) * refactored getQuota scenario * deleted quota step inside provisioning file * updating feature file of quota as per graphapi * updated expected failures file * updated expected failures file * removed issue tag --- .../expected-failures-API-on-OCIS-storage.md | 15 +- .../features/bootstrap/Provisioning.php | 178 ------------------ .../uploadToShare.feature | 20 +- .../changingPublicLinkShare.feature | 2 +- .../uploadToPublicLinkShare.feature | 8 +- .../coreApiWebdavProperties/getQuota.feature | 49 ++--- 6 files changed, 47 insertions(+), 225 deletions(-) diff --git a/tests/acceptance/expected-failures-API-on-OCIS-storage.md b/tests/acceptance/expected-failures-API-on-OCIS-storage.md index 763f401dec..a91c9f7ef1 100644 --- a/tests/acceptance/expected-failures-API-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-API-on-OCIS-storage.md @@ -125,10 +125,14 @@ cannot share a folder with create permission - [coreApiSharePublicLink2/uploadToPublicLinkShare.feature:13](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature#L13) - [coreApiSharePublicLink2/uploadToPublicLinkShare.feature:121](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature#L121) -#### [Set quota over settings](https://github.com/owncloud/ocis/issues/1290) +#### [d:quota-available-bytes in dprop of PROPFIND give wrong response value](https://github.com/owncloud/ocis/issues/8197) -- [coreApiSharePublicLink2/uploadToPublicLinkShare.feature:91](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature#L91) -- [coreApiSharePublicLink2/uploadToPublicLinkShare.feature:101](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature#L101) +- [coreApiWebdavProperties/getQuota.feature:55](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature#L55) +- [coreApiWebdavProperties/getQuota.feature:56](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature#L56) +- [coreApiWebdavProperties/getQuota.feature:57](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature#L57) +- [coreApiWebdavProperties/getQuota.feature:71](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature#L71) +- [coreApiWebdavProperties/getQuota.feature:72](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature#L72) +- [coreApiWebdavProperties/getQuota.feature:73](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature#L73) #### [deleting a file inside a received shared folder is moved to the trash-bin of the sharer not the receiver](https://github.com/owncloud/ocis/issues/1124) @@ -144,11 +148,6 @@ cannot share a folder with create permission - [coreApiTrashbin/trashbinSharingToShares.feature:201](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiTrashbin/trashbinSharingToShares.feature#L201) - [coreApiTrashbin/trashbinSharingToShares.feature:224](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiTrashbin/trashbinSharingToShares.feature#L224) -#### [changing user quota gives ocs status 103 / Cannot set quota](https://github.com/owncloud/product/issues/247) - -- [coreApiShareOperationsToShares2/uploadToShare.feature:202](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareOperationsToShares2/uploadToShare.feature#L202) -- [coreApiShareOperationsToShares2/uploadToShare.feature:203](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/coreApiShareOperationsToShares2/uploadToShare.feature#L203) - #### [Expiration date for shares is not implemented](https://github.com/owncloud/ocis/issues/1250) #### Expiration date of user shares diff --git a/tests/acceptance/features/bootstrap/Provisioning.php b/tests/acceptance/features/bootstrap/Provisioning.php index 1ef51bd4bf..0f28e7c190 100644 --- a/tests/acceptance/features/bootstrap/Provisioning.php +++ b/tests/acceptance/features/bootstrap/Provisioning.php @@ -1937,122 +1937,6 @@ trait Provisioning { ); } - /** - * @When /^the administrator changes the quota of user "([^"]*)" to "([^"]*)" using the provisioning API$/ - * - * @param string $user - * @param string $quota - * - * @return void - */ - public function adminChangesTheQuotaOfUserUsingTheProvisioningApi( - string $user, - string $quota - ):void { - $result = UserHelper::editUser( - $this->getBaseUrl(), - $this->getActualUsername($user), - 'quota', - $quota, - $this->getAdminUsername(), - $this->getAdminPassword(), - $this->getStepLineRef(), - $this->ocsApiVersion - ); - $this->response = $result; - } - - /** - * @Given /^the administrator has (?:changed|set) the quota of user "([^"]*)" to "([^"]*)"$/ - * - * @param string $user - * @param string $quota - * - * @return void - */ - public function adminHasChangedTheQuotaOfUserTo( - string $user, - string $quota - ):void { - $user = $this->getActualUsername($user); - $this->adminChangesTheQuotaOfUserUsingTheProvisioningApi( - $user, - $quota - ); - $this->theHTTPStatusCodeShouldBe( - 200, - "could not change quota of user $user" - ); - } - - /** - * @param string $requestingUser - * @param string $targetUser - * @param string $quota - * - * @return ResponseInterface - */ - public function userChangeQuotaOfUserUsingProvisioningApi( - string $requestingUser, - string $targetUser, - string $quota - ):ResponseInterface { - return UserHelper::editUser( - $this->getBaseUrl(), - $this->getActualUsername($targetUser), - 'quota', - $quota, - $this->getActualUsername($requestingUser), - $this->getPasswordForUser($requestingUser), - $this->getStepLineRef(), - $this->ocsApiVersion - ); - } - - /** - * @When /^user "([^"]*)" changes the quota of user "([^"]*)" to "([^"]*)" using the provisioning API$/ - * - * @param string $requestingUser - * @param string $targetUser - * @param string $quota - * - * @return void - */ - public function userChangesTheQuotaOfUserUsingTheProvisioningApi( - string $requestingUser, - string $targetUser, - string $quota - ):void { - $this->response = $this->userChangeQuotaOfUserUsingProvisioningApi( - $requestingUser, - $targetUser, - $quota - ); - $this->pushToLastStatusCodesArrays(); - } - - /** - * @Given /^user "([^"]*)" has changed the quota of user "([^"]*)" to "([^"]*)"$/ - * - * @param string $requestingUser - * @param string $targetUser - * @param string $quota - * - * @return void - */ - public function userHasChangedTheQuotaOfUserUsingTheProvisioningApi( - string $requestingUser, - string $targetUser, - string $quota - ):void { - $response = $this->userChangeQuotaOfUserUsingProvisioningApi( - $requestingUser, - $targetUser, - $quota - ); - $this->theHTTPStatusCodeShouldBeBetween(200, 299, $response); - } - /** * @param string $user * @@ -4450,68 +4334,6 @@ trait Provisioning { } } - /** - * @When the administrator sets the quota of user :user to :quota using the provisioning API - * - * @param string $user - * @param string $quota - * - * @return void - */ - public function adminSetsUserQuotaToUsingTheProvisioningApi(string $user, string $quota):void { - $user = $this->getActualUsername($user); - $body - = [ - 'key' => 'quota', - 'value' => $quota, - ]; - - $this->response = OcsApiHelper::sendRequest( - $this->getBaseUrl(), - $this->getAdminUsername(), - $this->getAdminPassword(), - "PUT", - "/cloud/users/$user", - $this->getStepLineRef(), - $body - ); - } - - /** - * @Given the quota of user :user has been set to :quota - * - * @param string $user - * @param string $quota - * - * @return void - */ - public function theQuotaOfUserHasBeenSetTo(string $user, string $quota):void { - $this->adminSetsUserQuotaToUsingTheProvisioningApi($user, $quota); - $this->theHTTPStatusCodeShouldBe(200); - } - - /** - * @When the administrator gives unlimited quota to user :user using the provisioning API - * - * @param string $user - * - * @return void - */ - public function adminGivesUnlimitedQuotaToUserUsingTheProvisioningApi(string $user):void { - $this->adminSetsUserQuotaToUsingTheProvisioningApi($user, 'none'); - } - - /** - * @Given user :user has been given unlimited quota - * - * @param string $user - * - * @return void - */ - public function userHasBeenGivenUnlimitedQuota(string $user):void { - $this->theQuotaOfUserHasBeenSetTo($user, 'none'); - } - /** * @Then /^the user attributes returned by the API should include$/ * diff --git a/tests/acceptance/features/coreApiShareOperationsToShares2/uploadToShare.feature b/tests/acceptance/features/coreApiShareOperationsToShares2/uploadToShare.feature index 0661926f96..8e3e43e001 100644 --- a/tests/acceptance/features/coreApiShareOperationsToShares2/uploadToShare.feature +++ b/tests/acceptance/features/coreApiShareOperationsToShares2/uploadToShare.feature @@ -140,11 +140,11 @@ Feature: sharing | old | | new | - @smokeTest @skipOnGraph + @smokeTest Scenario Outline: check quota of owners parent directory of a shared file Given using DAV path And user "Brian" has been created with default attributes and without skeleton files - And the quota of user "Brian" has been set to "0" + And user "Admin" has changed the quota of the personal space of "Brian Murphy" space to "0" And user "Alice" has uploaded file "filesForUpload/lorem.txt" to "/myfile.txt" And user "Alice" has shared file "myfile.txt" with user "Brian" When user "Brian" uploads file "filesForUpload/textfile.txt" to "/Shares/myfile.txt" using the WebDAV API @@ -162,17 +162,17 @@ Feature: sharing | old | | new | - @skipOnGraph + Scenario Outline: uploading to a user shared folder with read/write permission when the sharer has insufficient quota does not work Given using DAV path - And user "Brian" has been created with default attributes and small skeleton files + And user "Brian" has been created with default attributes and without skeleton files And user "Alice" has created folder "FOLDER" And user "Alice" has created a share with settings | path | FOLDER | | shareType | user | | permissions | change | | shareWith | Brian | - And the quota of user "Alice" has been set to "0" + And user "Admin" has changed the quota of the personal space of "Alice Hansen" space to "1" When user "Brian" uploads file "filesForUpload/textfile.txt" to "/Shares/FOLDER/myfile.txt" using the WebDAV API Then the HTTP status code should be "507" And as "Alice" file "/FOLDER/myfile.txt" should not exist @@ -193,7 +193,7 @@ Feature: sharing | shareType | group | | permissions | change | | shareWith | grp1 | - And the quota of user "Alice" has been set to "0" + And user "Admin" has changed the quota of the personal space of "Alice Hansen" space to "1" When user "Brian" uploads file "filesForUpload/textfile.txt" to "/Shares/FOLDER/myfile.txt" using the WebDAV API Then the HTTP status code should be "507" And as "Alice" file "/FOLDER/myfile.txt" should not exist @@ -202,7 +202,7 @@ Feature: sharing | old | | new | - @skipOnGraph + Scenario Outline: uploading to a user shared folder with upload-only permission when the sharer has insufficient quota does not work Given using DAV path And user "Brian" has been created with default attributes and without skeleton files @@ -212,7 +212,7 @@ Feature: sharing | shareType | user | | permissions | create | | shareWith | Brian | - And the quota of user "Alice" has been set to "0" + And user "Admin" has changed the quota of the personal space of "Alice Hansen" space to "1" When user "Brian" uploads file "filesForUpload/textfile.txt" to "/Shares/FOLDER/myfile.txt" using the WebDAV API Then the HTTP status code should be "507" And as "Alice" file "/FOLDER/myfile.txt" should not exist @@ -221,7 +221,7 @@ Feature: sharing | old | | new | - @skipOnGraph + Scenario Outline: uploading to a group shared folder with upload-only permission when the sharer has insufficient quota does not work Given using DAV path And user "Brian" has been created with default attributes and without skeleton files @@ -233,7 +233,7 @@ Feature: sharing | shareType | group | | permissions | create | | shareWith | grp1 | - And the quota of user "Alice" has been set to "0" + And user "Admin" has changed the quota of the personal space of "Alice Hansen" space to "1" When user "Brian" uploads file "filesForUpload/textfile.txt" to "/Shares/FOLDER/myfile.txt" using the WebDAV API Then the HTTP status code should be "507" And as "Alice" file "/FOLDER/myfile.txt" should not exist diff --git a/tests/acceptance/features/coreApiSharePublicLink1/changingPublicLinkShare.feature b/tests/acceptance/features/coreApiSharePublicLink1/changingPublicLinkShare.feature index a06d0eb26b..14ea10de4d 100644 --- a/tests/acceptance/features/coreApiSharePublicLink1/changingPublicLinkShare.feature +++ b/tests/acceptance/features/coreApiSharePublicLink1/changingPublicLinkShare.feature @@ -1,4 +1,4 @@ -@issue-1276 @issue-1277 @issue-1269 +@issue-1276 @issue-1269 Feature: changing a public link share As a user diff --git a/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature b/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature index 6ce3826377..c8ba39ab75 100644 --- a/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature +++ b/tests/acceptance/features/coreApiSharePublicLink2/uploadToPublicLinkShare.feature @@ -1,4 +1,4 @@ -@issue-1276 @issue-1277 +@issue-1276 Feature: upload to a public link share As a user @@ -93,17 +93,17 @@ Feature: upload to a public link share | path | FOLDER | | permissions | change | | password | %public% | - And the quota of user "Alice" has been set to "0" + And user "Admin" has changed the quota of the personal space of "Alice Hansen" space to "1" When the public uploads file "test.txt" with password "%public%" and content "test2" using the new public WebDAV API Then the HTTP status code should be "507" - @issue-1290 + Scenario: uploading file to a public shared folder with upload-only permission when the sharer has insufficient quota does not work with public API Given user "Alice" has created a public link share with settings | path | FOLDER | | permissions | create | | password | %public% | - And the quota of user "Alice" has been set to "0" + And user "Admin" has changed the quota of the personal space of "Alice Hansen" space to "1" When the public uploads file "test.txt" with password "%public%" and content "test2" using the new public WebDAV API Then the HTTP status code should be "507" diff --git a/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature b/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature index 631b7d9d27..6811716660 100644 --- a/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature +++ b/tests/acceptance/features/coreApiWebdavProperties/getQuota.feature @@ -1,4 +1,4 @@ -@issue-1313 @skipOnGraph +@issue-1313 @skipOnReva Feature: get quota As a user I want to be able to find out my available storage quota @@ -11,9 +11,9 @@ Feature: get quota Scenario Outline: retrieving folder quota when no quota is set Given using DAV path - When the administrator gives unlimited quota to user "Alice" using the provisioning API + When user "Admin" changes the quota of the "Alice Hansen" space to "0" Then the HTTP status code should be "200" - And as user "Alice" folder "/" should contain a property "d:quota-available-bytes" with value "-3" + And as user "Alice" folder "/" should contain a property "d:quota-available-bytes" with value "0" Examples: | dav-path-version | | old | @@ -23,66 +23,67 @@ Feature: get quota @smokeTest Scenario Outline: retrieving folder quota when quota is set Given using DAV path - When the administrator sets the quota of user "Alice" to "10 MB" using the provisioning API + When user "Admin" changes the quota of the "Alice Hansen" space to "10000" Then the HTTP status code should be "200" - And as user "Alice" folder "/" should contain a property "d:quota-available-bytes" with value "10485406" + And as user "Alice" folder "/" should contain a property "d:quota-available-bytes" with value "10000" Examples: | dav-path-version | | old | | new | | spaces | - + @issue-8197 Scenario Outline: retrieving folder quota of shared folder with quota when no quota is set for recipient Given using DAV path And user "Brian" has been created with default attributes and without skeleton files - And user "Alice" has been given unlimited quota - And the quota of user "Brian" has been set to "10 MB" + And user "Admin" has changed the quota of the personal space of "Alice Hansen" space to "0" + And user "Admin" has changed the quota of the personal space of "Brian Murphy" space to "10000" And user "Brian" has created folder "/testquota" + And user "Brian" has uploaded file "/testquota/Brian.txt" of size 1000 bytes And user "Brian" has created a share with settings | path | testquota | | shareType | user | | permissions | all | | shareWith | Alice | - When user "Alice" gets the following properties of folder "/testquota" using the WebDAV API + When user "Alice" gets the following properties of folder "" inside space "Shares" using the WebDAV API | propertyName | | d:quota-available-bytes | - Then the HTTP status code should be "200" - And the single response should contain a property "d:quota-available-bytes" with value "10485406" + Then the HTTP status code should be "207" + And the single response should contain a property "d:quota-available-bytes" with value "9000" Examples: - | dav-path-version | - | old | - | new | - | spaces | - + | dav-path-version | folder-path | + | old | /Shares/testquota | + | new | /Shares/testquota | + | spaces | /testquota | + @issue-8197 Scenario Outline: retrieving folder quota when quota is set and a file was uploaded Given using DAV path - And the quota of user "Alice" has been set to "1 KB" - And user "Alice" has uploaded file "/prueba.txt" of size 93 bytes + And user "Admin" has changed the quota of the personal space of "Alice Hansen" space to "10000" + And user "Alice" has uploaded file "/prueba.txt" of size 1000 bytes When user "Alice" gets the following properties of folder "/" using the WebDAV API | propertyName | | d:quota-available-bytes | - Then the HTTP status code should be "201" - And the single response should contain a property "d:quota-available-bytes" with value "577" + Then the HTTP status code should be "207" + And the single response should contain a property "d:quota-available-bytes" with value "9000" Examples: | dav-path-version | | old | | new | | spaces | - @skipOnReva + Scenario Outline: retrieving folder quota when quota is set and a file was received Given using DAV path And user "Brian" has been created with default attributes and without skeleton files - And the quota of user "Brian" has been set to "1 KB" + And user "Admin" has changed the quota of the personal space of "Brian Murphy" space to "10000" And user "Alice" has uploaded file "/Alice.txt" of size 93 bytes And user "Alice" has shared file "Alice.txt" with user "Brian" When user "Brian" gets the following properties of folder "/" using the WebDAV API | propertyName | | d:quota-available-bytes | - Then the HTTP status code should be "200" - And the single response should contain a property "d:quota-available-bytes" with value "670" + Then the HTTP status code should be "207" + And the single response should contain a property "d:quota-available-bytes" with value "10000" Examples: | dav-path-version | | old | From 2d203775a912237988f622b428ee06acf9298ed8 Mon Sep 17 00:00:00 2001 From: Prajwol Amatya <83579989+PrajwolAmatya@users.noreply.github.com> Date: Wed, 24 Jan 2024 12:13:54 +0545 Subject: [PATCH 48/73] added test to send share invitation to unknown group (#8175) --- .../apiSharingNg/shareInvitations.feature | 52 +++++++++++++++++++ .../features/bootstrap/SharingNgContext.php | 6 ++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index dd2bb5629b..1c8fe943e3 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -1093,3 +1093,55 @@ Feature: Send a sharing invitations | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | | Manager | folder | FolderToShare | + + + Scenario Outline: send sharing invitation to non-existing group + Given user "Alice" has uploaded file with content "to share" to "/textfile1.txt" + And user "Alice" has created folder "FolderToShare" + When user "Alice" sends the following share invitation using the Graph API: + | resourceType | | + | resource | | + | space | Personal | + | sharee | nonExistentGroup | + | shareType | group | + | permissionsRole | | + Then the HTTP status code should be "400" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "enum": [ + "generalException" + ] + }, + "message": { + "type": "string", + "enum": [ + "itemNotFound: not found" + ] + } + } + } + } + } + """ + Examples: + | permissions-role | resource-type | path | + | Viewer | file | /textfile1.txt | + | File Editor | file | /textfile1.txt | + | Viewer | folder | FolderToShare | + | Editor | folder | FolderToShare | + | Uploader | folder | FolderToShare | diff --git a/tests/acceptance/features/bootstrap/SharingNgContext.php b/tests/acceptance/features/bootstrap/SharingNgContext.php index 7f18bd793c..bb4492301f 100644 --- a/tests/acceptance/features/bootstrap/SharingNgContext.php +++ b/tests/acceptance/features/bootstrap/SharingNgContext.php @@ -23,6 +23,7 @@ use Behat\Behat\Context\Context; use Behat\Behat\Hook\Scope\BeforeScenarioScope; use Psr\Http\Message\ResponseInterface; use TestHelpers\GraphHelper; +use TestHelpers\WebDavHelper; use Behat\Gherkin\Node\TableNode; use PHPUnit\Framework\Assert; @@ -150,9 +151,10 @@ class SharingNgContext implements Context { $shareeIds = []; foreach ($sharees as $index => $sharee) { $shareType = $shareTypes[$index]; - $shareeIds[] = ($shareType === 'user') + // for non-exiting group or user, generate random id + $shareeIds[] = (($shareType === 'user') ? $this->featureContext->getAttributeOfCreatedUser($sharee, 'id') - : $this->featureContext->getAttributeOfCreatedGroup($sharee, 'id'); + : $this->featureContext->getAttributeOfCreatedGroup($sharee, 'id')) ?: WebDavHelper::generateUUIDv4(); } $permissionsRole = $rows['permissionsRole'] ?? null; From 6d4cb092a2283c9472ebe8f914a382581b9c85fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 06:33:09 +0000 Subject: [PATCH 49/73] build(deps): bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc Bumps [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc](https://github.com/open-telemetry/opentelemetry-go) from 1.21.0 to 1.22.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.21.0...v1.22.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- .../otel/exporters/otlp/otlptrace/version.go | 2 +- vendor/modules.txt | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 3e345cc0b8..427367caec 100644 --- a/go.mod +++ b/go.mod @@ -92,7 +92,7 @@ require ( go.opentelemetry.io/contrib/zpages v0.47.0 go.opentelemetry.io/otel v1.22.0 go.opentelemetry.io/otel/exporters/jaeger v1.17.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 go.opentelemetry.io/otel/sdk v1.22.0 go.opentelemetry.io/otel/trace v1.22.0 golang.org/x/crypto v0.18.0 @@ -327,7 +327,7 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib v1.0.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect go.opentelemetry.io/otel/metric v1.22.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.uber.org/atomic v1.10.0 // indirect diff --git a/go.sum b/go.sum index c9ca0d89b2..2b2b99c6a2 100644 --- a/go.sum +++ b/go.sum @@ -2100,10 +2100,10 @@ go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs= diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go index 8ee285b8d5..3b3bc35911 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go @@ -16,5 +16,5 @@ package otlptrace // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace" // Version is the current release version of the OpenTelemetry OTLP trace exporter in use. func Version() string { - return "1.21.0" + return "1.22.0" } diff --git a/vendor/modules.txt b/vendor/modules.txt index 1e48fa46ea..9aad267f1d 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1953,11 +1953,11 @@ go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/agent go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/jaeger go.opentelemetry.io/otel/exporters/jaeger/internal/gen-go/zipkincore go.opentelemetry.io/otel/exporters/jaeger/internal/third_party/thrift/lib/go/thrift -# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 +# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 ## explicit; go 1.20 go.opentelemetry.io/otel/exporters/otlp/otlptrace go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform -# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 +# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 ## explicit; go 1.20 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal From d703a8ef1d306067fe70732464fc4aae841aaf31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 06:33:57 +0000 Subject: [PATCH 50/73] build(deps): bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.46.1 to 0.47.0. - [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases) - [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md) - [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.46.1...zpages/v0.47.0) --- updated-dependencies: - dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 +- .../net/http/otelhttp/handler.go | 28 ++- .../otelhttp/internal/semconvutil/httpconv.go | 178 +++++++++++------- .../otelhttp/internal/semconvutil/netconv.go | 12 +- .../net/http/otelhttp/version.go | 2 +- vendor/modules.txt | 2 +- 7 files changed, 142 insertions(+), 86 deletions(-) diff --git a/go.mod b/go.mod index 427367caec..d7ef6f3261 100644 --- a/go.mod +++ b/go.mod @@ -88,7 +88,7 @@ require ( github.com/xhit/go-simple-mail/v2 v2.16.0 go-micro.dev/v4 v4.9.0 go.etcd.io/bbolt v1.3.8 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 go.opentelemetry.io/contrib/zpages v0.47.0 go.opentelemetry.io/otel v1.22.0 go.opentelemetry.io/otel/exporters/jaeger v1.17.0 diff --git a/go.sum b/go.sum index 2b2b99c6a2..bd4fd228b7 100644 --- a/go.sum +++ b/go.sum @@ -2091,8 +2091,8 @@ go.opentelemetry.io/contrib v1.0.0 h1:khwDCxdSspjOLmFnvMuSHd/5rPzbTx0+l6aURwtQdf go.opentelemetry.io/contrib v1.0.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 h1:PzIubN4/sjByhDRHLviCjJuweBXWFZWhghjg7cS28+M= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0/go.mod h1:Ct6zzQEuGK3WpJs2n4dn+wfJYzd/+hNnxMRTWjGn30M= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= go.opentelemetry.io/contrib/zpages v0.47.0 h1:ekpdNa2wqOvAfwZIGDIIV02zmR+z08aWPt21KrPJnaU= go.opentelemetry.io/contrib/zpages v0.47.0/go.mod h1:rBeFA/UxnMjRlEGpmClIqzf1mCIKtl7ahjww3wsSdGs= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs= diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go index 9a8260059d..af84f0e4bb 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/handler.go @@ -26,7 +26,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/propagation" - semconv "go.opentelemetry.io/otel/semconv/v1.17.0" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" "go.opentelemetry.io/otel/trace" ) @@ -43,10 +43,12 @@ type middleware struct { writeEvent bool filters []Filter spanNameFormatter func(string, *http.Request) string - counters map[string]metric.Int64Counter - valueRecorders map[string]metric.Float64Histogram publicEndpoint bool publicEndpointFn func(*http.Request) bool + + requestBytesCounter metric.Int64Counter + responseBytesCounter metric.Int64Counter + serverLatencyMeasure metric.Float64Histogram } func defaultHandlerFormatter(operation string, _ *http.Request) string { @@ -104,33 +106,27 @@ func handleErr(err error) { } func (h *middleware) createMeasures() { - h.counters = make(map[string]metric.Int64Counter) - h.valueRecorders = make(map[string]metric.Float64Histogram) - - requestBytesCounter, err := h.meter.Int64Counter( + var err error + h.requestBytesCounter, err = h.meter.Int64Counter( RequestContentLength, metric.WithUnit("By"), metric.WithDescription("Measures the size of HTTP request content length (uncompressed)"), ) handleErr(err) - responseBytesCounter, err := h.meter.Int64Counter( + h.responseBytesCounter, err = h.meter.Int64Counter( ResponseContentLength, metric.WithUnit("By"), metric.WithDescription("Measures the size of HTTP response content length (uncompressed)"), ) handleErr(err) - serverLatencyMeasure, err := h.meter.Float64Histogram( + h.serverLatencyMeasure, err = h.meter.Float64Histogram( ServerLatency, metric.WithUnit("ms"), metric.WithDescription("Measures the duration of HTTP request handling"), ) handleErr(err) - - h.counters[RequestContentLength] = requestBytesCounter - h.counters[ResponseContentLength] = responseBytesCounter - h.valueRecorders[ServerLatency] = serverLatencyMeasure } // serveHTTP sets up tracing and calls the given next http.Handler with the span @@ -236,13 +232,13 @@ func (h *middleware) serveHTTP(w http.ResponseWriter, r *http.Request, next http attributes = append(attributes, semconv.HTTPStatusCode(rww.statusCode)) } o := metric.WithAttributes(attributes...) - h.counters[RequestContentLength].Add(ctx, bw.read, o) - h.counters[ResponseContentLength].Add(ctx, rww.written, o) + h.requestBytesCounter.Add(ctx, bw.read, o) + h.responseBytesCounter.Add(ctx, rww.written, o) // Use floating point division here for higher precision (instead of Millisecond method). elapsedTime := float64(time.Since(requestStartTime)) / float64(time.Millisecond) - h.valueRecorders[ServerLatency].Record(ctx, elapsedTime, o) + h.serverLatencyMeasure.Record(ctx, elapsedTime, o) } func setAfterServeAttributes(span trace.Span, read, wrote int64, statusCode int, rerr, werr error) { diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go index d3dede9ebb..794d4c26a4 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/httpconv.go @@ -24,7 +24,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" - semconv "go.opentelemetry.io/otel/semconv/v1.17.0" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" ) // HTTPClientResponse returns trace attributes for an HTTP response received by a @@ -149,9 +149,7 @@ func HTTPResponseHeader(h http.Header) []attribute.KeyValue { type httpConv struct { NetConv *netConv - EnduserIDKey attribute.Key HTTPClientIPKey attribute.Key - HTTPFlavorKey attribute.Key HTTPMethodKey attribute.Key HTTPRequestContentLengthKey attribute.Key HTTPResponseContentLengthKey attribute.Key @@ -161,15 +159,13 @@ type httpConv struct { HTTPStatusCodeKey attribute.Key HTTPTargetKey attribute.Key HTTPURLKey attribute.Key - HTTPUserAgentKey attribute.Key + UserAgentOriginalKey attribute.Key } var hc = &httpConv{ NetConv: nc, - EnduserIDKey: semconv.EnduserIDKey, HTTPClientIPKey: semconv.HTTPClientIPKey, - HTTPFlavorKey: semconv.HTTPFlavorKey, HTTPMethodKey: semconv.HTTPMethodKey, HTTPRequestContentLengthKey: semconv.HTTPRequestContentLengthKey, HTTPResponseContentLengthKey: semconv.HTTPResponseContentLengthKey, @@ -179,7 +175,7 @@ var hc = &httpConv{ HTTPStatusCodeKey: semconv.HTTPStatusCodeKey, HTTPTargetKey: semconv.HTTPTargetKey, HTTPURLKey: semconv.HTTPURLKey, - HTTPUserAgentKey: semconv.HTTPUserAgentKey, + UserAgentOriginalKey: semconv.UserAgentOriginalKey, } // ClientResponse returns attributes for an HTTP response received by a client @@ -193,6 +189,10 @@ var hc = &httpConv{ // // append(ClientResponse(resp), ClientRequest(resp.Request)...) func (c *httpConv) ClientResponse(resp *http.Response) []attribute.KeyValue { + /* The following semantic conventions are returned if present: + http.status_code int + http.response_content_length int + */ var n int if resp.StatusCode > 0 { n++ @@ -212,11 +212,31 @@ func (c *httpConv) ClientResponse(resp *http.Response) []attribute.KeyValue { } // ClientRequest returns attributes for an HTTP request made by a client. The -// following attributes are always returned: "http.url", "http.flavor", -// "http.method", "net.peer.name". The following attributes are returned if the -// related values are defined in req: "net.peer.port", "http.user_agent", -// "http.request_content_length", "enduser.id". +// following attributes are always returned: "http.url", "http.method", +// "net.peer.name". The following attributes are returned if the related values +// are defined in req: "net.peer.port", "http.user_agent", +// "http.request_content_length", "user_agent.original". func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue { + /* The following semantic conventions are returned if present: + http.method string + user_agent.original string + http.url string + net.peer.name string + net.peer.port int + http.request_content_length int + */ + + /* The following semantic conventions are not returned: + http.status_code This requires the response. See ClientResponse. + http.response_content_length This requires the response. See ClientResponse. + net.sock.family This requires the socket used. + net.sock.peer.addr This requires the socket used. + net.sock.peer.name This requires the socket used. + net.sock.peer.port This requires the socket used. + http.resend_count This is something outside of a single request. + net.protocol.name The value is the Request is ignored, and the go client will always use "http". + net.protocol.version The value in the Request is ignored, and the go client will always use 1.1 or 2.0. + */ n := 3 // URL, peer name, proto, and method. var h string if req.URL != nil { @@ -234,14 +254,10 @@ func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue { if req.ContentLength > 0 { n++ } - userID, _, hasUserID := req.BasicAuth() - if hasUserID { - n++ - } + attrs := make([]attribute.KeyValue, 0, n) attrs = append(attrs, c.method(req.Method)) - attrs = append(attrs, c.flavor(req.Proto)) var u string if req.URL != nil { @@ -260,17 +276,13 @@ func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue { } if useragent != "" { - attrs = append(attrs, c.HTTPUserAgentKey.String(useragent)) + attrs = append(attrs, c.UserAgentOriginalKey.String(useragent)) } if l := req.ContentLength; l > 0 { attrs = append(attrs, c.HTTPRequestContentLengthKey.Int64(l)) } - if hasUserID { - attrs = append(attrs, c.EnduserIDKey.String(userID)) - } - return attrs } @@ -291,18 +303,35 @@ func (c *httpConv) ClientRequest(req *http.Request) []attribute.KeyValue { // The req Host will be used to determine the server instead. // // The following attributes are always returned: "http.method", "http.scheme", -// "http.flavor", "http.target", "net.host.name". The following attributes are -// returned if they related values are defined in req: "net.host.port", -// "net.sock.peer.addr", "net.sock.peer.port", "http.user_agent", "enduser.id", -// "http.client_ip". +// "http.target", "net.host.name". The following attributes are returned if they +// related values are defined in req: "net.host.port", "net.sock.peer.addr", +// "net.sock.peer.port", "user_agent.original", "http.client_ip", +// "net.protocol.name", "net.protocol.version". func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.KeyValue { - // TODO: This currently does not add the specification required - // `http.target` attribute. It has too high of a cardinality to safely be - // added. An alternate should be added, or this comment removed, when it is - // addressed by the specification. If it is ultimately decided to continue - // not including the attribute, the HTTPTargetKey field of the httpConv - // should be removed as well. + /* The following semantic conventions are returned if present: + http.method string + http.scheme string + net.host.name string + net.host.port int + net.sock.peer.addr string + net.sock.peer.port int + user_agent.original string + http.client_ip string + net.protocol.name string Note: not set if the value is "http". + net.protocol.version string + http.target string Note: doesn't include the query parameter. + */ + /* The following semantic conventions are not returned: + http.status_code This requires the response. + http.request_content_length This requires the len() of body, which can mutate it. + http.response_content_length This requires the response. + http.route This is not available. + net.sock.peer.name This would require a DNS lookup. + net.sock.host.addr The request doesn't have access to the underlying socket. + net.sock.host.port The request doesn't have access to the underlying socket. + + */ n := 4 // Method, scheme, proto, and host name. var host string var p int @@ -330,19 +359,31 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K if useragent != "" { n++ } - userID, _, hasUserID := req.BasicAuth() - if hasUserID { - n++ - } + clientIP := serverClientIP(req.Header.Get("X-Forwarded-For")) if clientIP != "" { n++ } + + var target string + if req.URL != nil { + target = req.URL.Path + if target != "" { + n++ + } + } + protoName, protoVersion := netProtocol(req.Proto) + if protoName != "" && protoName != "http" { + n++ + } + if protoVersion != "" { + n++ + } + attrs := make([]attribute.KeyValue, 0, n) attrs = append(attrs, c.method(req.Method)) attrs = append(attrs, c.scheme(req.TLS != nil)) - attrs = append(attrs, c.flavor(req.Proto)) attrs = append(attrs, c.NetConv.HostName(host)) if hostPort > 0 { @@ -359,17 +400,24 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K } if useragent != "" { - attrs = append(attrs, c.HTTPUserAgentKey.String(useragent)) - } - - if hasUserID { - attrs = append(attrs, c.EnduserIDKey.String(userID)) + attrs = append(attrs, c.UserAgentOriginalKey.String(useragent)) } if clientIP != "" { attrs = append(attrs, c.HTTPClientIPKey.String(clientIP)) } + if target != "" { + attrs = append(attrs, c.HTTPTargetKey.String(target)) + } + + if protoName != "" && protoName != "http" { + attrs = append(attrs, c.NetConv.NetProtocolName.String(protoName)) + } + if protoVersion != "" { + attrs = append(attrs, c.NetConv.NetProtocolVersion.String(protoVersion)) + } + return attrs } @@ -394,14 +442,18 @@ func (c *httpConv) ServerRequest(server string, req *http.Request) []attribute.K // "http.flavor", "net.host.name". The following attributes are // returned if they related values are defined in req: "net.host.port". func (c *httpConv) ServerRequestMetrics(server string, req *http.Request) []attribute.KeyValue { - // TODO: This currently does not add the specification required - // `http.target` attribute. It has too high of a cardinality to safely be - // added. An alternate should be added, or this comment removed, when it is - // addressed by the specification. If it is ultimately decided to continue - // not including the attribute, the HTTPTargetKey field of the httpConv - // should be removed as well. + /* The following semantic conventions are returned if present: + http.scheme string + http.route string + http.method string + http.status_code int + net.host.name string + net.host.port int + net.protocol.name string Note: not set if the value is "http". + net.protocol.version string + */ - n := 4 // Method, scheme, proto, and host name. + n := 3 // Method, scheme, and host name. var host string var p int if server == "" { @@ -417,16 +469,29 @@ func (c *httpConv) ServerRequestMetrics(server string, req *http.Request) []attr if hostPort > 0 { n++ } + protoName, protoVersion := netProtocol(req.Proto) + if protoName != "" { + n++ + } + if protoVersion != "" { + n++ + } + attrs := make([]attribute.KeyValue, 0, n) attrs = append(attrs, c.methodMetric(req.Method)) attrs = append(attrs, c.scheme(req.TLS != nil)) - attrs = append(attrs, c.flavor(req.Proto)) attrs = append(attrs, c.NetConv.HostName(host)) if hostPort > 0 { attrs = append(attrs, c.NetConv.HostPort(hostPort)) } + if protoName != "" { + attrs = append(attrs, c.NetConv.NetProtocolName.String(protoName)) + } + if protoVersion != "" { + attrs = append(attrs, c.NetConv.NetProtocolVersion.String(protoVersion)) + } return attrs } @@ -455,21 +520,6 @@ func (c *httpConv) scheme(https bool) attribute.KeyValue { // nolint:revive return c.HTTPSchemeHTTP } -func (c *httpConv) flavor(proto string) attribute.KeyValue { - switch proto { - case "HTTP/1.0": - return c.HTTPFlavorKey.String("1.0") - case "HTTP/1.1": - return c.HTTPFlavorKey.String("1.1") - case "HTTP/2": - return c.HTTPFlavorKey.String("2.0") - case "HTTP/3": - return c.HTTPFlavorKey.String("3.0") - default: - return c.HTTPFlavorKey.String(proto) - } -} - func serverClientIP(xForwardedFor string) string { if idx := strings.Index(xForwardedFor, ","); idx >= 0 { xForwardedFor = xForwardedFor[:idx] diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go index bde8893437..cb4cb9355d 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil/netconv.go @@ -22,7 +22,7 @@ import ( "strings" "go.opentelemetry.io/otel/attribute" - semconv "go.opentelemetry.io/otel/semconv/v1.17.0" + semconv "go.opentelemetry.io/otel/semconv/v1.20.0" ) // NetTransport returns a trace attribute describing the transport protocol of the @@ -57,6 +57,8 @@ type netConv struct { NetHostPortKey attribute.Key NetPeerNameKey attribute.Key NetPeerPortKey attribute.Key + NetProtocolName attribute.Key + NetProtocolVersion attribute.Key NetSockFamilyKey attribute.Key NetSockPeerAddrKey attribute.Key NetSockPeerPortKey attribute.Key @@ -73,6 +75,8 @@ var nc = &netConv{ NetHostPortKey: semconv.NetHostPortKey, NetPeerNameKey: semconv.NetPeerNameKey, NetPeerPortKey: semconv.NetPeerPortKey, + NetProtocolName: semconv.NetProtocolNameKey, + NetProtocolVersion: semconv.NetProtocolVersionKey, NetSockFamilyKey: semconv.NetSockFamilyKey, NetSockPeerAddrKey: semconv.NetSockPeerAddrKey, NetSockPeerPortKey: semconv.NetSockPeerPortKey, @@ -366,3 +370,9 @@ func splitHostPort(hostport string) (host string, port int) { } return host, int(p) } + +func netProtocol(proto string) (name string, version string) { + name, version, _ = strings.Cut(proto, "/") + name = strings.ToLower(name) + return name, version +} diff --git a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go index bd41c18042..9a4a02143d 100644 --- a/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go +++ b/vendor/go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/version.go @@ -16,7 +16,7 @@ package otelhttp // import "go.opentelemetry.io/contrib/instrumentation/net/http // Version is the current release version of the otelhttp instrumentation. func Version() string { - return "0.46.1" + return "0.47.0" // This string is updated by the pre_release.sh script during release } diff --git a/vendor/modules.txt b/vendor/modules.txt index 9aad267f1d..04ded24a64 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1920,7 +1920,7 @@ go.opentelemetry.io/contrib ## explicit; go 1.20 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc/internal -# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 +# go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 ## explicit; go 1.20 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp/internal/semconvutil From 4447ead4d020faea95a41fc806964ebea9a7a0d5 Mon Sep 17 00:00:00 2001 From: Prajwol Amatya <83579989+PrajwolAmatya@users.noreply.github.com> Date: Wed, 24 Jan 2024 14:17:38 +0545 Subject: [PATCH 51/73] added test to share resource to an already shared group (#8181) --- .../apiSharingNg/shareInvitations.feature | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index 1c8fe943e3..c670ced7eb 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -1145,3 +1145,66 @@ Feature: Send a sharing invitations | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | | Uploader | folder | FolderToShare | + + + Scenario Outline: send sharing invitation to already shared group + Given user "Carol" has been created with default attributes and without skeleton files + And group "grp1" has been created + And the following users have been added to the following groups + | username | groupname | + | Brian | grp1 | + | Carol | grp1 | + And user "Alice" has uploaded file with content "to share" to "/textfile1.txt" + And user "Alice" has created folder "FolderToShare" + And user "Alice" has sent the following share invitation: + | resourceType | | + | resource | | + | space | Personal | + | sharee | grp1 | + | shareType | group | + | permissionsRole | | + When user "Alice" sends the following share invitation using the Graph API: + | resourceType | | + | resource | | + | space | Personal | + | sharee | grp1 | + | shareType | group | + | permissionsRole | | + Then the HTTP status code should be "409" + And the JSON data of the response should match + """ + { + "type": "object", + "required": [ + "error" + ], + "properties": { + "error": { + "type": "object", + "required": [ + "code", + "message" + ], + "properties": { + "code": { + "type": "string", + "enum": [ + "nameAlreadyExists" + ] + }, + "message": { + "type": "string", + "pattern": "^error creating share: error: already exists:.*$" + } + } + } + } + } + """ + Examples: + | permissions-role | resource-type | path | + | Viewer | file | /textfile1.txt | + | File Editor | file | /textfile1.txt | + | Viewer | folder | FolderToShare | + | Editor | folder | FolderToShare | + | Uploader | folder | FolderToShare | From 7f5aa6b4a8842129942954eba799d8faa63b6a6b Mon Sep 17 00:00:00 2001 From: Viktor Scharf Date: Wed, 24 Jan 2024 09:43:39 +0100 Subject: [PATCH 52/73] [test-only] Add grafana link to CI (#8268) * add grafana link to CI * Update .drone.star * Update .drone.star --- .drone.star | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.drone.star b/.drone.star index 1eafc70a47..5eec27e395 100644 --- a/.drone.star +++ b/.drone.star @@ -2884,6 +2884,13 @@ def k6LoadTests(ctx): "sh %s/run_k6_tests.sh --ocis-log" % (dirs["base"]), ], }, + { + "name": "open-grafana-dashboard", + "image": OC_CI_ALPINE, + "commands": [ + "echo 'Grafana Dashboard: https://grafana.k6.infra.owncloud.works/d/P4D1D31A5B69203FF'", + ], + }, ], "depends_on": [], "trigger": { From 9b87682f4e22b11bf9e975375706d2407b54f0f6 Mon Sep 17 00:00:00 2001 From: Roman Perekhod <2403905@gmail.com> Date: Wed, 24 Jan 2024 09:17:44 +0000 Subject: [PATCH 53/73] Automated changelog update [skip ci] --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05ca5b72b9..31b5f18cf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ The following sections list the changes for unreleased. * Bugfix - Cleanup `search/pkg/search/search.go`: [#8230](https://github.com/owncloud/ocis/pull/8230) * Bugfix - Graph/sharedWithMe works for shares from project spaces now: [#8233](https://github.com/owncloud/ocis/pull/8233) * Bugfix - Fix PATCH/DELETE status code for drives that don't support them: [#8235](https://github.com/owncloud/ocis/pull/8235) +* Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269) * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) * Enhancement - Remove deprecated environment variables: [#8149](https://github.com/owncloud/ocis/pull/8149) @@ -156,6 +157,15 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/issues/7881 https://github.com/owncloud/ocis/pull/8235 +* Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269) + + We fixed the race condition that led to concurrent map access in a publicshare + manager. + + https://github.com/owncloud/ocis/issues/8255 + https://github.com/owncloud/ocis/pull/8269 + https://github.com/cs3org/reva/pull/4472 + * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) We add the environment variable that allow to disable the password policy. From 10628f399d6229215f9f2ad206d75291280fdd66 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 17 Jan 2024 16:48:40 +0100 Subject: [PATCH 54/73] fix events authentication Signed-off-by: jkoberg --- changelog/unreleased/fix-nats-authentication.md | 5 +++++ services/sharing/pkg/config/config.go | 2 ++ services/sharing/pkg/revaconfig/config.go | 4 ++++ services/storage-users/pkg/revaconfig/config.go | 4 ++++ services/storage-users/pkg/revaconfig/drivers.go | 12 ++---------- 5 files changed, 17 insertions(+), 10 deletions(-) create mode 100644 changelog/unreleased/fix-nats-authentication.md diff --git a/changelog/unreleased/fix-nats-authentication.md b/changelog/unreleased/fix-nats-authentication.md new file mode 100644 index 0000000000..2ab13db9d8 --- /dev/null +++ b/changelog/unreleased/fix-nats-authentication.md @@ -0,0 +1,5 @@ +Bugfix: Fix nats authentication + +Fixes nats authentication for registry/events/stores + +https://github.com/owncloud/ocis/pull/8236 diff --git a/services/sharing/pkg/config/config.go b/services/sharing/pkg/config/config.go index 24c8834d2e..7d51d0b830 100644 --- a/services/sharing/pkg/config/config.go +++ b/services/sharing/pkg/config/config.go @@ -153,6 +153,8 @@ type Events struct { TLSInsecure bool `yaml:"tls_insecure" env:"OCIS_INSECURE;SHARING_EVENTS_TLS_INSECURE" desc:"Whether to verify the server TLS certificates."` TLSRootCaCertPath string `yaml:"tls_root_ca_cert_path" env:"OCIS_EVENTS_TLS_ROOT_CA_CERTIFICATE;SHARING_EVENTS_TLS_ROOT_CA_CERTIFICATE" desc:"The root CA certificate used to validate the server's TLS certificate. If provided SHARING_EVENTS_TLS_INSECURE will be seen as false."` EnableTLS bool `yaml:"enable_tls" env:"OCIS_EVENTS_ENABLE_TLS;SHARING_EVENTS_ENABLE_TLS" desc:"Enable TLS for the connection to the events broker. The events broker is the ocis service which receives and delivers events between the services.."` + AuthUsername string `yaml:"auth_username" env:"OCIS_EVENTS_AUTH_USERNAME;SHARING_EVENTS_AUTH_USERNAME" desc:"Username for the events broker."` + AuthPassword string `yaml:"auth_password" env:"OCIS_EVENTS_AUTH_PASSWORD;SHARING_EVENTS_AUTH_PASSWORD" desc:"Password for the events broker."` } // PasswordPolicy configures reva password policy diff --git a/services/sharing/pkg/revaconfig/config.go b/services/sharing/pkg/revaconfig/config.go index b1f7e0d46a..8f02b796de 100644 --- a/services/sharing/pkg/revaconfig/config.go +++ b/services/sharing/pkg/revaconfig/config.go @@ -81,6 +81,8 @@ func SharingConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string] "natsclusterid": cfg.Events.ClusterID, "tlsinsecure": cfg.Events.TLSInsecure, "tlsrootcacertificate": cfg.Events.TLSRootCaCertPath, + "authusername": cfg.Events.AuthUsername, + "authpassword": cfg.Events.AuthPassword, }, }, }, @@ -134,6 +136,8 @@ func SharingConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string] "tls-root-ca-cert": cfg.Events.TLSRootCaCertPath, "enable-tls": cfg.Events.EnableTLS, "name": "sharing-eventsmiddleware", + "username": cfg.Events.AuthUsername, + "password": cfg.Events.AuthPassword, }, "prometheus": map[string]interface{}{ "namespace": "ocis", diff --git a/services/storage-users/pkg/revaconfig/config.go b/services/storage-users/pkg/revaconfig/config.go index 3966d86c56..8997130924 100644 --- a/services/storage-users/pkg/revaconfig/config.go +++ b/services/storage-users/pkg/revaconfig/config.go @@ -46,6 +46,8 @@ func StorageUsersConfigFromStruct(cfg *config.Config) map[string]interface{} { "tls-root-ca-cert": cfg.Events.TLSRootCaCertPath, "enable-tls": cfg.Events.EnableTLS, "name": "storage-users-eventsmiddleware", + "username": cfg.Events.AuthUsername, + "password": cfg.Events.AuthPassword, }, "prometheus": map[string]interface{}{ "namespace": "ocis", @@ -70,6 +72,8 @@ func StorageUsersConfigFromStruct(cfg *config.Config) map[string]interface{} { "nats_tls_insecure": cfg.Events.TLSInsecure, "nats_root_ca_cert_path": cfg.Events.TLSRootCaCertPath, "nats_enable_tls": cfg.Events.EnableTLS, + "nats_username": cfg.Events.AuthUsername, + "nats_password": cfg.Events.AuthPassword, "data_txs": map[string]interface{}{ "simple": map[string]interface{}{ "cache_store": cfg.StatCache.Store, diff --git a/services/storage-users/pkg/revaconfig/drivers.go b/services/storage-users/pkg/revaconfig/drivers.go index a26bf8de47..db98a352d8 100644 --- a/services/storage-users/pkg/revaconfig/drivers.go +++ b/services/storage-users/pkg/revaconfig/drivers.go @@ -157,11 +157,7 @@ func Ocis(cfg *config.Config) map[string]interface{} { "cache_disable_persistence": cfg.IDCache.DisablePersistence, }, "events": map[string]interface{}{ - "natsaddress": cfg.Events.Addr, - "natsclusterid": cfg.Events.ClusterID, - "tlsinsecure": cfg.Events.TLSInsecure, - "tlsrootcacertificate": cfg.Events.TLSRootCaCertPath, - "numconsumers": cfg.Events.NumConsumers, + "numconsumers": cfg.Events.NumConsumers, }, "tokens": map[string]interface{}{ "transfer_shared_secret": cfg.Commons.TransferSecret, @@ -284,11 +280,7 @@ func S3NG(cfg *config.Config) map[string]interface{} { "cache_disable_persistence": cfg.IDCache.DisablePersistence, }, "events": map[string]interface{}{ - "natsaddress": cfg.Events.Addr, - "natsclusterid": cfg.Events.ClusterID, - "tlsinsecure": cfg.Events.TLSInsecure, - "tlsrootcacertificate": cfg.Events.TLSRootCaCertPath, - "numconsumers": cfg.Events.NumConsumers, + "numconsumers": cfg.Events.NumConsumers, }, "tokens": map[string]interface{}{ "transfer_shared_secret": cfg.Commons.TransferSecret, From 13bb2785d4e19e52973a7218c1d81ac1f836e767 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Fri, 19 Jan 2024 15:12:04 +0100 Subject: [PATCH 55/73] fix cache authentication Signed-off-by: jkoberg --- ocis-pkg/shared/shared_types.go | 2 ++ services/frontend/pkg/config/config.go | 2 ++ services/frontend/pkg/revaconfig/config.go | 2 ++ services/gateway/pkg/config/config.go | 6 +++++ services/gateway/pkg/revaconfig/config.go | 6 +++++ services/storage-system/pkg/config/config.go | 2 ++ .../storage-system/pkg/revaconfig/config.go | 2 ++ services/storage-users/pkg/config/config.go | 6 +++++ .../storage-users/pkg/revaconfig/config.go | 6 +++++ .../storage-users/pkg/revaconfig/drivers.go | 24 +++++++++++++++++++ 10 files changed, 58 insertions(+) diff --git a/ocis-pkg/shared/shared_types.go b/ocis-pkg/shared/shared_types.go index 9775daec31..a5c5aa336a 100644 --- a/ocis-pkg/shared/shared_types.go +++ b/ocis-pkg/shared/shared_types.go @@ -63,6 +63,8 @@ type Cache struct { TTL time.Duration `yaml:"ttl" env:"OCIS_CACHE_TTL" desc:"Time to live for events in the store. The duration can be set as number followed by a unit identifier like s, m or h."` Size int `yaml:"size" env:"OCIS_CACHE_SIZE" desc:"The maximum quantity of items in the store. Only applies when store type 'ocmem' is configured."` DisablePersistence bool `yaml:"disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` + AuthUsername string `yaml:"auth_username" env:"OCIS_CACHE_AUTH_USERNAME" desc:"The username to use for authentication. Only applies when store type 'nats-js-kv' is configured."` + AuthPassword string `yaml:"auth_password" env:"OCIS_CACHE_AUTH_PASSWORD" desc:"The password to use for authentication. Only applies when store type 'nats-js-kv' is configured."` } // Commons holds configuration that are common to all extensions. Each extension can then decide whether diff --git a/services/frontend/pkg/config/config.go b/services/frontend/pkg/config/config.go index 897627ad84..fa8c7b2fc1 100644 --- a/services/frontend/pkg/config/config.go +++ b/services/frontend/pkg/config/config.go @@ -137,6 +137,8 @@ type OCS struct { StatCacheTTL time.Duration `yaml:"stat_cache_ttl" env:"OCIS_CACHE_TTL;FRONTEND_OCS_STAT_CACHE_TTL" desc:"Default time to live for user info in the cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` StatCacheSize int `yaml:"stat_cache_size" env:"OCIS_CACHE_SIZE;FRONTEND_OCS_STAT_CACHE_SIZE" desc:"Max number of entries to hold in the cache."` StatCacheDisablePersistence bool `yaml:"stat_cache_disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;FRONTEND_OCS_STAT_CACHE_DISABLE_PERSISTENCE" desc:"Disable persistence of the cache. Only applies when using the 'nats-js-kv' store type. Defaults to false."` + StatCacheAuthUsername string `yaml:"stat_cache_auth_username" env:"OCIS_CACHE_AUTH_USERNAME;FRONTEND_OCS_STAT_CACHE_AUTH_USERNAME" desc:"The username to use for authentication. Only applies when using the 'nats-js-kv' store type."` + StatCacheAuthPassword string `yaml:"stat_cache_auth_password" env:"OCIS_CACHE_AUTH_PASSWORD;FRONTEND_OCS_STAT_CACHE_AUTH_PASSWORD" desc:"The password to use for authentication. Only applies when using the 'nats-js-kv' store type."` CacheWarmupDriver string `yaml:"cache_warmup_driver,omitempty"` // not supported by the oCIS product, therefore not part of docs CacheWarmupDrivers CacheWarmupDrivers `yaml:"cache_warmup_drivers,omitempty"` // not supported by the oCIS product, therefore not part of docs diff --git a/services/frontend/pkg/revaconfig/config.go b/services/frontend/pkg/revaconfig/config.go index 51c4138560..1ee8a26864 100644 --- a/services/frontend/pkg/revaconfig/config.go +++ b/services/frontend/pkg/revaconfig/config.go @@ -163,6 +163,8 @@ func FrontendConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string "cache_ttl": cfg.OCS.StatCacheTTL / time.Second, "cache_size": cfg.OCS.StatCacheSize, "cache_disable_persistence": cfg.OCS.StatCacheDisablePersistence, + "cache_auth_username": cfg.OCS.StatCacheAuthUsername, + "cache_auth_password": cfg.OCS.StatCacheAuthPassword, }, "prefix": cfg.OCS.Prefix, "additional_info_attribute": cfg.OCS.AdditionalInfoAttribute, diff --git a/services/gateway/pkg/config/config.go b/services/gateway/pkg/config/config.go index e676f59ec4..4e0717bf32 100644 --- a/services/gateway/pkg/config/config.go +++ b/services/gateway/pkg/config/config.go @@ -91,16 +91,22 @@ type Cache struct { StatCacheTTL time.Duration `yaml:"stat_cache_ttl" env:"OCIS_CACHE_TTL;GATEWAY_STAT_CACHE_TTL" desc:"Default time to live for user info in the cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` StatCacheSize int `yaml:"stat_cache_size" env:"OCIS_CACHE_SIZE;GATEWAY_STAT_CACHE_SIZE" desc:"The maximum quantity of items in the cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` StatCacheDisablePersistence bool `yaml:"stat_cache_disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;GATEWAY_STAT_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the stat cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` + StatCacheAuthUsername string `yaml:"stat_cache_auth_username" env:"OCIS_CACHE_AUTH_USERNAME;GATEWAY_STAT_CACHE_AUTH_USERNAME" desc:"The username to use for authentication. Only applies when store type 'nats-js-kv' is configured."` + StatCacheAuthPassword string `yaml:"stat_cache_auth_password" env:"OCIS_CACHE_AUTH_PASSWORD;GATEWAY_STAT_CACHE_AUTH_PASSWORD" desc:"The password to use for authentication. Only applies when store type 'nats-js-kv' is configured."` ProviderCacheStore string `yaml:"provider_cache_store" env:"OCIS_CACHE_STORE;GATEWAY_PROVIDER_CACHE_STORE" desc:"The type of the cache store. Supported values are: 'memory', 'redis-sentinel', 'nats-js-kv', 'noop'. See the text description for details."` ProviderCacheNodes []string `yaml:"provider_cache_nodes" env:"OCIS_CACHE_STORE_NODES;GATEWAY_PROVIDER_CACHE_STORE_NODES" desc:"A list of nodes to access the configured store. This has no effect when 'memory' or 'ocmem' stores are configured. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details."` ProviderCacheDatabase string `yaml:"provider_cache_database" env:"OCIS_CACHE_DATABASE" desc:"The database name the configured store should use."` ProviderCacheTTL time.Duration `yaml:"provider_cache_ttl" env:"OCIS_CACHE_TTL;GATEWAY_PROVIDER_CACHE_TTL" desc:"Default time to live for user info in the cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` ProviderCacheSize int `yaml:"provider_cache_size" env:"OCIS_CACHE_SIZE;GATEWAY_PROVIDER_CACHE_SIZE" desc:"The maximum quantity of items in the cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` ProviderCacheDisablePersistence bool `yaml:"provider_cache_disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;GATEWAY_PROVIDER_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the provider cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` + ProviderCacheAuthUsername string `yaml:"provider_cache_auth_username" env:"OCIS_CACHE_AUTH_USERNAME;GATEWAY_PROVIDER_CACHE_AUTH_USERNAME" desc:"The username to use for authentication. Only applies when store type 'nats-js-kv' is configured."` + ProviderCacheAuthPassword string `yaml:"provider_cache_auth_password" env:"OCIS_CACHE_AUTH_PASSWORD;GATEWAY_PROVIDER_CACHE_AUTH_PASSWORD" desc:"The password to use for authentication. Only applies when store type 'nats-js-kv' is configured."` CreateHomeCacheStore string `yaml:"create_home_cache_store" env:"OCIS_CACHE_STORE;GATEWAY_CREATE_HOME_CACHE_STORE" desc:"The type of the cache store. Supported values are: 'memory', 'redis-sentinel', 'nats-js-kv', 'noop'. See the text description for details."` CreateHomeCacheNodes []string `yaml:"create_home_cache_nodes" env:"OCIS_CACHE_STORE_NODES;GATEWAY_CREATE_HOME_CACHE_STORE_NODES" desc:"A list of nodes to access the configured store. This has no effect when 'memory' or 'ocmem' stores are configured. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details."` CreateHomeCacheDatabase string `yaml:"create_home_cache_database" env:"OCIS_CACHE_DATABASE" desc:"The database name the configured store should use."` CreateHomeCacheTTL time.Duration `yaml:"create_home_cache_ttl" env:"OCIS_CACHE_TTL;GATEWAY_CREATE_HOME_CACHE_TTL" desc:"Default time to live for user info in the cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` CreateHomeCacheSize int `yaml:"create_home_cache_size" env:"OCIS_CACHE_SIZE;GATEWAY_CREATE_HOME_CACHE_SIZE" desc:"The maximum quantity of items in the cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` CreateHomeCacheDisablePersistence bool `yaml:"create_home_cache_disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;GATEWAY_CREATE_HOME_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the create home cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` + CreateHomeCacheAuthUsername string `yaml:"create_home_cache_auth_username" env:"OCIS_CACHE_AUTH_USERNAME;GATEWAY_CREATE_HOME_CACHE_AUTH_USERNAME" desc:"The username to use for authentication. Only applies when store type 'nats-js-kv' is configured."` + CreateHomeCacheAuthPassword string `yaml:"create_home_cache_auth_password" env:"OCIS_CACHE_AUTH_PASSWORD;GATEWAY_CREATE_HOME_CACHE_AUTH_PASSWORD" desc:"The password to use for authentication. Only applies when store type 'nats-js-kv' is configured."` } diff --git a/services/gateway/pkg/revaconfig/config.go b/services/gateway/pkg/revaconfig/config.go index d1affa7a92..ecd2333806 100644 --- a/services/gateway/pkg/revaconfig/config.go +++ b/services/gateway/pkg/revaconfig/config.go @@ -69,6 +69,8 @@ func GatewayConfigFromStruct(cfg *config.Config, logger log.Logger) map[string]i "cache_ttl": cfg.Cache.StatCacheTTL, "cache_size": cfg.Cache.StatCacheSize, "cache_disable_persistenc": cfg.Cache.StatCacheDisablePersistence, + "cache_auth_username": cfg.Cache.StatCacheAuthUsername, + "cache_auth_password": cfg.Cache.StatCacheAuthPassword, }, "provider_cache_config": map[string]interface{}{ "cache_store": cfg.Cache.ProviderCacheStore, @@ -78,6 +80,8 @@ func GatewayConfigFromStruct(cfg *config.Config, logger log.Logger) map[string]i "cache_ttl": cfg.Cache.ProviderCacheTTL, "cache_size": cfg.Cache.ProviderCacheSize, "disable_persistence": cfg.Cache.ProviderCacheDisablePersistence, + "cache_auth_username": cfg.Cache.ProviderCacheAuthUsername, + "cache_auth_password": cfg.Cache.ProviderCacheAuthPassword, }, "create_home_cache_config": map[string]interface{}{ "cache_store": cfg.Cache.CreateHomeCacheStore, @@ -87,6 +91,8 @@ func GatewayConfigFromStruct(cfg *config.Config, logger log.Logger) map[string]i "cache_ttl": cfg.Cache.CreateHomeCacheTTL, "cache_size": cfg.Cache.CreateHomeCacheSize, "cache_disable_persistence": cfg.Cache.CreateHomeCacheDisablePersistence, + "cache_auth_username": cfg.Cache.CreateHomeCacheAuthUsername, + "cache_auth_password": cfg.Cache.CreateHomeCacheAuthPassword, }, }, "authregistry": map[string]interface{}{ diff --git a/services/storage-system/pkg/config/config.go b/services/storage-system/pkg/config/config.go index e05a524519..6ebe5b7187 100644 --- a/services/storage-system/pkg/config/config.go +++ b/services/storage-system/pkg/config/config.go @@ -93,4 +93,6 @@ type Cache struct { TTL time.Duration `yaml:"ttl" env:"OCIS_CACHE_TTL;STORAGE_SYSTEM_CACHE_TTL" desc:"Default time to live for user info in the user info cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` Size int `yaml:"size" env:"OCIS_CACHE_SIZE;STORAGE_SYSTEM_CACHE_SIZE" desc:"The maximum quantity of items in the user info cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` DisablePersistence bool `yaml:"disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;STORAGE_SYSTEM_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` + AuthUsername string `yaml:"auth_username" env:"OCIS_CACHE_AUTH_USERNAME;STORAGE_SYSTEM_CACHE_AUTH_USERNAME" desc:"Username for the configured store. Only applies when store type 'nats-js-kv' is configured."` + AuthPassword string `yaml:"auth_password" env:"OCIS_CACHE_AUTH_PASSWORD;STORAGE_SYSTEM_CACHE_AUTH_PASSWORD" desc:"Password for the configured store. Only applies when store type 'nats-js-kv' is configured."` } diff --git a/services/storage-system/pkg/revaconfig/config.go b/services/storage-system/pkg/revaconfig/config.go index 16c1c3a09d..2a43337126 100644 --- a/services/storage-system/pkg/revaconfig/config.go +++ b/services/storage-system/pkg/revaconfig/config.go @@ -168,6 +168,8 @@ func metadataDrivers(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.FileMetadataCache.TTL / time.Second, "cache_size": cfg.FileMetadataCache.Size, "cache_disable_persistence": cfg.FileMetadataCache.DisablePersistence, + "cache_auth_username": cfg.FileMetadataCache.AuthUsername, + "cache_auth_password": cfg.FileMetadataCache.AuthPassword, }, }, } diff --git a/services/storage-users/pkg/config/config.go b/services/storage-users/pkg/config/config.go index 77616b35d3..3d75b52ab7 100644 --- a/services/storage-users/pkg/config/config.go +++ b/services/storage-users/pkg/config/config.go @@ -190,6 +190,8 @@ type StatCache struct { TTL time.Duration `yaml:"ttl" env:"OCIS_CACHE_TTL;STORAGE_USERS_STAT_CACHE_TTL" desc:"Default time to live for user info in the user info cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` Size int `yaml:"size" env:"OCIS_CACHE_SIZE;STORAGE_USERS_STAT_CACHE_SIZE" desc:"The maximum quantity of items in the user info cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` DisablePersistence bool `yaml:"disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;STORAGE_USERS_STAT_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` + AuthUsername string `yaml:"username" env:"OCIS_CACHE_AUTH_USERNAME;STORAGE_USERS_STAT_CACHE_AUTH_USERNAME" desc:"The username to authenticate with the cache store. Only applies when store type 'nats-js-kv' is configured."` + AuthPassword string `yaml:"password" env:"OCIS_CACHE_AUTH_PASSWORD;STORAGE_USERS_STAT_CACHE_AUTH_PASSWORD" desc:"The password to authenticate with the cache store. Only applies when store type 'nats-js-kv' is configured."` } // FilemetadataCache holds cache config @@ -200,6 +202,8 @@ type FilemetadataCache struct { TTL time.Duration `yaml:"ttl" env:"OCIS_CACHE_TTL;STORAGE_USERS_FILEMETADATA_CACHE_TTL" desc:"Default time to live for user info in the user info cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` Size int `yaml:"size" env:"OCIS_CACHE_SIZE;STORAGE_USERS_FILEMETADATA_CACHE_SIZE" desc:"The maximum quantity of items in the user info cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` DisablePersistence bool `yaml:"disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;STORAGE_USERS_FILEMETADATA_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` + AuthUsername string `yaml:"username" env:"OCIS_CACHE_AUTH_USERNAME;STORAGE_USERS_FILEMETADATA_CACHE_AUTH_USERNAME" desc:"The username to authenticate with the cache store. Only applies when store type 'nats-js-kv' is configured."` + AuthPassword string `yaml:"password" env:"OCIS_CACHE_AUTH_PASSWORD;STORAGE_USERS_FILEMETADATA_CACHE_AUTH_PASSWORD" desc:"The password to authenticate with the cache store. Only applies when store type 'nats-js-kv' is configured."` } // IDCache holds cache config @@ -210,6 +214,8 @@ type IDCache struct { TTL time.Duration `yaml:"ttl" env:"OCIS_CACHE_TTL;STORAGE_USERS_ID_CACHE_TTL" desc:"Default time to live for user info in the user info cache. Only applied when access tokens have no expiration. Defaults to 300s which is derived from the underlaying package though not explicitly set as default. See the Environment Variable Types description for more details."` Size int `yaml:"size" env:"OCIS_CACHE_SIZE;STORAGE_USERS_ID_CACHE_SIZE" desc:"The maximum quantity of items in the user info cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` DisablePersistence bool `yaml:"disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;STORAGE_USERS_ID_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` + AuthUsername string `yaml:"username" env:"OCIS_CACHE_AUTH_USERNAME;STORAGE_USERS_ID_CACHE_AUTH_USERNAME" desc:"The username to authenticate with the cache store. Only applies when store type 'nats-js-kv' is configured."` + AuthPassword string `yaml:"password" env:"OCIS_CACHE_AUTH_PASSWORD;STORAGE_USERS_ID_CACHE_AUTH_PASSWORD" desc:"The password to authenticate with the cache store. Only applies when store type 'nats-js-kv' is configured."` } // S3Driver is the storage driver configuration when using 's3' storage driver diff --git a/services/storage-users/pkg/revaconfig/config.go b/services/storage-users/pkg/revaconfig/config.go index 8997130924..4169106d07 100644 --- a/services/storage-users/pkg/revaconfig/config.go +++ b/services/storage-users/pkg/revaconfig/config.go @@ -83,6 +83,8 @@ func StorageUsersConfigFromStruct(cfg *config.Config) map[string]interface{} { "cache_size": cfg.StatCache.Size, "cache_table": "stat", "cache_disable_persistence": cfg.StatCache.DisablePersistence, + "cache_auth_username": cfg.StatCache.AuthUsername, + "cache_auth_password": cfg.StatCache.AuthPassword, }, "spaces": map[string]interface{}{ "cache_store": cfg.StatCache.Store, @@ -92,6 +94,8 @@ func StorageUsersConfigFromStruct(cfg *config.Config) map[string]interface{} { "cache_size": cfg.StatCache.Size, "cache_table": "stat", "cache_disable_persistence": cfg.StatCache.DisablePersistence, + "cache_auth_username": cfg.StatCache.AuthUsername, + "cache_auth_password": cfg.StatCache.AuthPassword, }, "tus": map[string]interface{}{ "cache_store": cfg.StatCache.Store, @@ -101,6 +105,8 @@ func StorageUsersConfigFromStruct(cfg *config.Config) map[string]interface{} { "cache_size": cfg.StatCache.Size, "cache_table": "stat", "cache_disable_persistence": cfg.StatCache.DisablePersistence, + "cache_auth_username": cfg.StatCache.AuthUsername, + "cache_auth_password": cfg.StatCache.AuthPassword, }, }, }, diff --git a/services/storage-users/pkg/revaconfig/drivers.go b/services/storage-users/pkg/revaconfig/drivers.go index db98a352d8..fc5b1e5951 100644 --- a/services/storage-users/pkg/revaconfig/drivers.go +++ b/services/storage-users/pkg/revaconfig/drivers.go @@ -139,6 +139,8 @@ func Ocis(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.StatCache.TTL, "cache_size": cfg.StatCache.Size, "cache_disable_persistence": cfg.StatCache.DisablePersistence, + "cache_auth_username": cfg.StatCache.AuthUsername, + "cache_auth_password": cfg.StatCache.AuthPassword, }, "filemetadatacache": map[string]interface{}{ "cache_store": cfg.FilemetadataCache.Store, @@ -147,6 +149,8 @@ func Ocis(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.FilemetadataCache.TTL, "cache_size": cfg.FilemetadataCache.Size, "cache_disable_persistence": cfg.FilemetadataCache.DisablePersistence, + "cache_auth_username": cfg.FilemetadataCache.AuthUsername, + "cache_auth_password": cfg.FilemetadataCache.AuthPassword, }, "idcache": map[string]interface{}{ "cache_store": cfg.IDCache.Store, @@ -155,6 +159,8 @@ func Ocis(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.IDCache.TTL, "cache_size": cfg.IDCache.Size, "cache_disable_persistence": cfg.IDCache.DisablePersistence, + "cache_auth_username": cfg.IDCache.AuthUsername, + "cache_auth_password": cfg.IDCache.AuthPassword, }, "events": map[string]interface{}{ "numconsumers": cfg.Events.NumConsumers, @@ -196,6 +202,8 @@ func OcisNoEvents(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.StatCache.TTL, "cache_size": cfg.StatCache.Size, "cache_disable_persistence": cfg.StatCache.DisablePersistence, + "cache_auth_username": cfg.StatCache.AuthUsername, + "cache_auth_password": cfg.StatCache.AuthPassword, }, "filemetadatacache": map[string]interface{}{ "cache_store": cfg.FilemetadataCache.Store, @@ -204,6 +212,8 @@ func OcisNoEvents(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.FilemetadataCache.TTL, "cache_size": cfg.FilemetadataCache.Size, "cache_disable_persistence": cfg.FilemetadataCache.DisablePersistence, + "cache_auth_username": cfg.FilemetadataCache.AuthUsername, + "cache_auth_password": cfg.FilemetadataCache.AuthPassword, }, "idcache": map[string]interface{}{ "cache_store": cfg.IDCache.Store, @@ -212,6 +222,8 @@ func OcisNoEvents(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.IDCache.TTL, "cache_size": cfg.IDCache.Size, "cache_disable_persistence": cfg.IDCache.DisablePersistence, + "cache_auth_username": cfg.IDCache.AuthUsername, + "cache_auth_password": cfg.IDCache.AuthPassword, }, } } @@ -262,6 +274,8 @@ func S3NG(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.StatCache.TTL, "cache_size": cfg.StatCache.Size, "cache_disable_persistence": cfg.StatCache.DisablePersistence, + "cache_auth_username": cfg.StatCache.AuthUsername, + "cache_auth_password": cfg.StatCache.AuthPassword, }, "filemetadatacache": map[string]interface{}{ "cache_store": cfg.FilemetadataCache.Store, @@ -270,6 +284,8 @@ func S3NG(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.FilemetadataCache.TTL, "cache_size": cfg.FilemetadataCache.Size, "cache_disable_persistence": cfg.FilemetadataCache.DisablePersistence, + "cache_auth_username": cfg.FilemetadataCache.AuthUsername, + "cache_auth_password": cfg.FilemetadataCache.AuthPassword, }, "idcache": map[string]interface{}{ "cache_store": cfg.IDCache.Store, @@ -278,6 +294,8 @@ func S3NG(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.IDCache.TTL, "cache_size": cfg.IDCache.Size, "cache_disable_persistence": cfg.IDCache.DisablePersistence, + "cache_auth_username": cfg.IDCache.AuthUsername, + "cache_auth_password": cfg.IDCache.AuthPassword, }, "events": map[string]interface{}{ "numconsumers": cfg.Events.NumConsumers, @@ -323,6 +341,8 @@ func S3NGNoEvents(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.StatCache.TTL, "cache_size": cfg.StatCache.Size, "cache_disable_persistence": cfg.StatCache.DisablePersistence, + "cache_auth_username": cfg.StatCache.AuthUsername, + "cache_auth_password": cfg.StatCache.AuthPassword, }, "filemetadatacache": map[string]interface{}{ "cache_store": cfg.FilemetadataCache.Store, @@ -331,6 +351,8 @@ func S3NGNoEvents(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.FilemetadataCache.TTL, "cache_size": cfg.FilemetadataCache.Size, "cache_disable_persistence": cfg.FilemetadataCache.DisablePersistence, + "cache_auth_username": cfg.FilemetadataCache.AuthUsername, + "cache_auth_password": cfg.FilemetadataCache.AuthPassword, }, "idcache": map[string]interface{}{ "cache_store": cfg.IDCache.Store, @@ -339,6 +361,8 @@ func S3NGNoEvents(cfg *config.Config) map[string]interface{} { "cache_ttl": cfg.IDCache.TTL, "cache_size": cfg.IDCache.Size, "cache_disable_persistence": cfg.IDCache.DisablePersistence, + "cache_auth_username": cfg.IDCache.AuthUsername, + "cache_auth_password": cfg.IDCache.AuthPassword, }, } } From 8e613bbe7a2d5fe652d6dc5a88364d65b3be44b3 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 23 Jan 2024 12:39:34 +0100 Subject: [PATCH 56/73] fix store ttl Signed-off-by: jkoberg --- services/frontend/pkg/revaconfig/config.go | 3 +-- services/storage-system/pkg/revaconfig/config.go | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/services/frontend/pkg/revaconfig/config.go b/services/frontend/pkg/revaconfig/config.go index 1ee8a26864..93ab7833ae 100644 --- a/services/frontend/pkg/revaconfig/config.go +++ b/services/frontend/pkg/revaconfig/config.go @@ -8,7 +8,6 @@ import ( "path" "path/filepath" "strconv" - "time" "github.com/owncloud/ocis/v2/ocis-pkg/config/defaults" "github.com/owncloud/ocis/v2/ocis-pkg/log" @@ -160,7 +159,7 @@ func FrontendConfigFromStruct(cfg *config.Config, logger log.Logger) (map[string "cache_nodes": cfg.OCS.StatCacheNodes, "cache_database": cfg.OCS.StatCacheDatabase, "cache_table": cfg.OCS.StatCacheTable, - "cache_ttl": cfg.OCS.StatCacheTTL / time.Second, + "cache_ttl": cfg.OCS.StatCacheTTL, "cache_size": cfg.OCS.StatCacheSize, "cache_disable_persistence": cfg.OCS.StatCacheDisablePersistence, "cache_auth_username": cfg.OCS.StatCacheAuthUsername, diff --git a/services/storage-system/pkg/revaconfig/config.go b/services/storage-system/pkg/revaconfig/config.go index 2a43337126..5557552097 100644 --- a/services/storage-system/pkg/revaconfig/config.go +++ b/services/storage-system/pkg/revaconfig/config.go @@ -1,8 +1,6 @@ package revaconfig import ( - "time" - userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" "github.com/owncloud/ocis/v2/services/storage-system/pkg/config" ) @@ -165,7 +163,7 @@ func metadataDrivers(cfg *config.Config) map[string]interface{} { "cache_store": cfg.FileMetadataCache.Store, "cache_nodes": cfg.FileMetadataCache.Nodes, "cache_database": cfg.FileMetadataCache.Database, - "cache_ttl": cfg.FileMetadataCache.TTL / time.Second, + "cache_ttl": cfg.FileMetadataCache.TTL, "cache_size": cfg.FileMetadataCache.Size, "cache_disable_persistence": cfg.FileMetadataCache.DisablePersistence, "cache_auth_username": cfg.FileMetadataCache.AuthUsername, From cec6ea50eb086b9d3f09823cc2abc4490e2f447e Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 23 Jan 2024 12:48:44 +0100 Subject: [PATCH 57/73] remove unused stat cache Signed-off-by: jkoberg --- services/gateway/pkg/config/config.go | 8 ---- .../pkg/config/defaults/defaultconfig.go | 4 -- services/gateway/pkg/revaconfig/config.go | 11 ----- services/storage-users/pkg/config/config.go | 13 ------ .../pkg/config/defaults/defaultconfig.go | 6 --- .../storage-users/pkg/revaconfig/config.go | 35 ---------------- .../storage-users/pkg/revaconfig/drivers.go | 40 ------------------- 7 files changed, 117 deletions(-) diff --git a/services/gateway/pkg/config/config.go b/services/gateway/pkg/config/config.go index 4e0717bf32..a3242706b8 100644 --- a/services/gateway/pkg/config/config.go +++ b/services/gateway/pkg/config/config.go @@ -85,14 +85,6 @@ type StorageRegistry struct { // Cache holds cache config type Cache struct { - StatCacheStore string // NOTE: The stat cache is not working atm. Hence we block configuring it - StatCacheNodes []string `yaml:"stat_cache_nodes" env:"OCIS_CACHE_STORE_NODES;GATEWAY_STAT_CACHE_STORE_NODES" desc:"A list of nodes to access the configured store. This has no effect when 'memory' or 'ocmem' stores are configured. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details."` - StatCacheDatabase string `yaml:"stat_cache_database" env:"OCIS_CACHE_DATABASE" desc:"The database name the configured store should use."` - StatCacheTTL time.Duration `yaml:"stat_cache_ttl" env:"OCIS_CACHE_TTL;GATEWAY_STAT_CACHE_TTL" desc:"Default time to live for user info in the cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` - StatCacheSize int `yaml:"stat_cache_size" env:"OCIS_CACHE_SIZE;GATEWAY_STAT_CACHE_SIZE" desc:"The maximum quantity of items in the cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` - StatCacheDisablePersistence bool `yaml:"stat_cache_disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;GATEWAY_STAT_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the stat cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` - StatCacheAuthUsername string `yaml:"stat_cache_auth_username" env:"OCIS_CACHE_AUTH_USERNAME;GATEWAY_STAT_CACHE_AUTH_USERNAME" desc:"The username to use for authentication. Only applies when store type 'nats-js-kv' is configured."` - StatCacheAuthPassword string `yaml:"stat_cache_auth_password" env:"OCIS_CACHE_AUTH_PASSWORD;GATEWAY_STAT_CACHE_AUTH_PASSWORD" desc:"The password to use for authentication. Only applies when store type 'nats-js-kv' is configured."` ProviderCacheStore string `yaml:"provider_cache_store" env:"OCIS_CACHE_STORE;GATEWAY_PROVIDER_CACHE_STORE" desc:"The type of the cache store. Supported values are: 'memory', 'redis-sentinel', 'nats-js-kv', 'noop'. See the text description for details."` ProviderCacheNodes []string `yaml:"provider_cache_nodes" env:"OCIS_CACHE_STORE_NODES;GATEWAY_PROVIDER_CACHE_STORE_NODES" desc:"A list of nodes to access the configured store. This has no effect when 'memory' or 'ocmem' stores are configured. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details."` ProviderCacheDatabase string `yaml:"provider_cache_database" env:"OCIS_CACHE_DATABASE" desc:"The database name the configured store should use."` diff --git a/services/gateway/pkg/config/defaults/defaultconfig.go b/services/gateway/pkg/config/defaults/defaultconfig.go index f1ae850042..b8bea1a4bc 100644 --- a/services/gateway/pkg/config/defaults/defaultconfig.go +++ b/services/gateway/pkg/config/defaults/defaultconfig.go @@ -39,10 +39,6 @@ func DefaultConfig() *config.Config { DisableHomeCreationOnLogin: true, TransferExpires: 24 * 60 * 60, Cache: config.Cache{ - StatCacheStore: "noop", // NOTE: stat cache not working - StatCacheDatabase: "ocis", - StatCacheNodes: []string{"127.0.0.1:9233"}, - StatCacheTTL: 300 * time.Second, ProviderCacheStore: "noop", ProviderCacheNodes: []string{"127.0.0.1:9233"}, ProviderCacheDatabase: "cache-providers", diff --git a/services/gateway/pkg/revaconfig/config.go b/services/gateway/pkg/revaconfig/config.go index ecd2333806..c13688aee9 100644 --- a/services/gateway/pkg/revaconfig/config.go +++ b/services/gateway/pkg/revaconfig/config.go @@ -61,17 +61,6 @@ func GatewayConfigFromStruct(cfg *config.Config, logger log.Logger) map[string]i "transfer_shared_secret": cfg.TransferSecret, "transfer_expires": cfg.TransferExpires, // cache and TTLs - "stat_cache_config": map[string]interface{}{ - "cache_store": cfg.Cache.StatCacheStore, - "cache_nodes": cfg.Cache.StatCacheNodes, - "cache_database": cfg.Cache.StatCacheDatabase, - "cache_table": "stat", - "cache_ttl": cfg.Cache.StatCacheTTL, - "cache_size": cfg.Cache.StatCacheSize, - "cache_disable_persistenc": cfg.Cache.StatCacheDisablePersistence, - "cache_auth_username": cfg.Cache.StatCacheAuthUsername, - "cache_auth_password": cfg.Cache.StatCacheAuthPassword, - }, "provider_cache_config": map[string]interface{}{ "cache_store": cfg.Cache.ProviderCacheStore, "cache_nodes": cfg.Cache.ProviderCacheNodes, diff --git a/services/storage-users/pkg/config/config.go b/services/storage-users/pkg/config/config.go index 3d75b52ab7..8fd16c74b8 100644 --- a/services/storage-users/pkg/config/config.go +++ b/services/storage-users/pkg/config/config.go @@ -31,7 +31,6 @@ type Config struct { TransferExpires int64 `yaml:"transfer_expires" env:"STORAGE_USERS_TRANSFER_EXPIRES" desc:"the time after which the token for upload postprocessing expires"` Events Events `yaml:"events"` - StatCache StatCache `yaml:"stat_cache"` FilemetadataCache FilemetadataCache `yaml:"filemetadata_cache"` IDCache IDCache `yaml:"id_cache"` MountID string `yaml:"mount_id" env:"STORAGE_USERS_MOUNT_ID" desc:"Mount ID of this storage."` @@ -182,18 +181,6 @@ type Events struct { AuthPassword string `yaml:"password" env:"OCIS_EVENTS_AUTH_PASSWORD;STORAGE_USERS_EVENTS_AUTH_PASSWORD" desc:"The password to authenticate with the events broker. The events broker is the ocis service which receives and delivers events between the services.."` } -// StatCache holds cache config -type StatCache struct { - Store string `yaml:"store" env:"OCIS_CACHE_STORE;STORAGE_USERS_STAT_CACHE_STORE" desc:"The type of the cache store. Supported values are: 'memory', 'redis-sentinel', 'nats-js-kv', 'noop'. See the text description for details."` - Nodes []string `yaml:"nodes" env:"OCIS_CACHE_STORE_NODES;STORAGE_USERS_STAT_CACHE_STORE_NODES" desc:"A list of nodes to access the configured store. This has no effect when 'memory' or 'ocmem' stores are configured. Note that the behaviour how nodes are used is dependent on the library of the configured store. See the Environment Variable Types description for more details."` - Database string `yaml:"database" env:"OCIS_CACHE_DATABASE" desc:"The database name the configured store should use."` - TTL time.Duration `yaml:"ttl" env:"OCIS_CACHE_TTL;STORAGE_USERS_STAT_CACHE_TTL" desc:"Default time to live for user info in the user info cache. Only applied when access tokens has no expiration. See the Environment Variable Types description for more details."` - Size int `yaml:"size" env:"OCIS_CACHE_SIZE;STORAGE_USERS_STAT_CACHE_SIZE" desc:"The maximum quantity of items in the user info cache. Only applies when store type 'ocmem' is configured. Defaults to 512 which is derived from the ocmem package though not exclicitely set as default."` - DisablePersistence bool `yaml:"disable_persistence" env:"OCIS_CACHE_DISABLE_PERSISTENCE;STORAGE_USERS_STAT_CACHE_DISABLE_PERSISTENCE" desc:"Disables persistence of the cache. Only applies when store type 'nats-js-kv' is configured. Defaults to false."` - AuthUsername string `yaml:"username" env:"OCIS_CACHE_AUTH_USERNAME;STORAGE_USERS_STAT_CACHE_AUTH_USERNAME" desc:"The username to authenticate with the cache store. Only applies when store type 'nats-js-kv' is configured."` - AuthPassword string `yaml:"password" env:"OCIS_CACHE_AUTH_PASSWORD;STORAGE_USERS_STAT_CACHE_AUTH_PASSWORD" desc:"The password to authenticate with the cache store. Only applies when store type 'nats-js-kv' is configured."` -} - // FilemetadataCache holds cache config type FilemetadataCache struct { Store string `yaml:"store" env:"OCIS_CACHE_STORE;STORAGE_USERS_FILEMETADATA_CACHE_STORE" desc:"The type of the cache store. Supported values are: 'memory', 'redis-sentinel', 'nats-js-kv', 'noop'. See the text description for details."` diff --git a/services/storage-users/pkg/config/defaults/defaultconfig.go b/services/storage-users/pkg/config/defaults/defaultconfig.go index 8bc070c6af..82a65ff790 100644 --- a/services/storage-users/pkg/config/defaults/defaultconfig.go +++ b/services/storage-users/pkg/config/defaults/defaultconfig.go @@ -94,12 +94,6 @@ func DefaultConfig() *config.Config { ClusterID: "ocis-cluster", EnableTLS: false, }, - StatCache: config.StatCache{ - Store: "memory", - Nodes: []string{"127.0.0.1:9233"}, - Database: "ocis", - TTL: 300 * time.Second, - }, FilemetadataCache: config.FilemetadataCache{ Store: "memory", Nodes: []string{"127.0.0.1:9233"}, diff --git a/services/storage-users/pkg/revaconfig/config.go b/services/storage-users/pkg/revaconfig/config.go index 4169106d07..f8ecffd9b7 100644 --- a/services/storage-users/pkg/revaconfig/config.go +++ b/services/storage-users/pkg/revaconfig/config.go @@ -74,41 +74,6 @@ func StorageUsersConfigFromStruct(cfg *config.Config) map[string]interface{} { "nats_enable_tls": cfg.Events.EnableTLS, "nats_username": cfg.Events.AuthUsername, "nats_password": cfg.Events.AuthPassword, - "data_txs": map[string]interface{}{ - "simple": map[string]interface{}{ - "cache_store": cfg.StatCache.Store, - "cache_nodes": cfg.StatCache.Nodes, - "cache_database": cfg.StatCache.Database, - "cache_ttl": cfg.StatCache.TTL, - "cache_size": cfg.StatCache.Size, - "cache_table": "stat", - "cache_disable_persistence": cfg.StatCache.DisablePersistence, - "cache_auth_username": cfg.StatCache.AuthUsername, - "cache_auth_password": cfg.StatCache.AuthPassword, - }, - "spaces": map[string]interface{}{ - "cache_store": cfg.StatCache.Store, - "cache_nodes": cfg.StatCache.Nodes, - "cache_database": cfg.StatCache.Database, - "cache_ttl": cfg.StatCache.TTL, - "cache_size": cfg.StatCache.Size, - "cache_table": "stat", - "cache_disable_persistence": cfg.StatCache.DisablePersistence, - "cache_auth_username": cfg.StatCache.AuthUsername, - "cache_auth_password": cfg.StatCache.AuthPassword, - }, - "tus": map[string]interface{}{ - "cache_store": cfg.StatCache.Store, - "cache_nodes": cfg.StatCache.Nodes, - "cache_database": cfg.StatCache.Database, - "cache_ttl": cfg.StatCache.TTL, - "cache_size": cfg.StatCache.Size, - "cache_table": "stat", - "cache_disable_persistence": cfg.StatCache.DisablePersistence, - "cache_auth_username": cfg.StatCache.AuthUsername, - "cache_auth_password": cfg.StatCache.AuthPassword, - }, - }, }, }, }, diff --git a/services/storage-users/pkg/revaconfig/drivers.go b/services/storage-users/pkg/revaconfig/drivers.go index fc5b1e5951..0a44caf74c 100644 --- a/services/storage-users/pkg/revaconfig/drivers.go +++ b/services/storage-users/pkg/revaconfig/drivers.go @@ -132,16 +132,6 @@ func Ocis(cfg *config.Config) map[string]interface{} { "max_concurrency": cfg.Drivers.OCIS.MaxConcurrency, "asyncfileuploads": cfg.Drivers.OCIS.AsyncUploads, "max_quota": cfg.Drivers.OCIS.MaxQuota, - "statcache": map[string]interface{}{ - "cache_store": cfg.StatCache.Store, - "cache_nodes": cfg.StatCache.Nodes, - "cache_database": cfg.StatCache.Database, - "cache_ttl": cfg.StatCache.TTL, - "cache_size": cfg.StatCache.Size, - "cache_disable_persistence": cfg.StatCache.DisablePersistence, - "cache_auth_username": cfg.StatCache.AuthUsername, - "cache_auth_password": cfg.StatCache.AuthPassword, - }, "filemetadatacache": map[string]interface{}{ "cache_store": cfg.FilemetadataCache.Store, "cache_nodes": cfg.FilemetadataCache.Nodes, @@ -195,16 +185,6 @@ func OcisNoEvents(cfg *config.Config) map[string]interface{} { "lock_cycle_duration_factor": cfg.Drivers.OCIS.LockCycleDurationFactor, "max_concurrency": cfg.Drivers.OCIS.MaxConcurrency, "max_quota": cfg.Drivers.OCIS.MaxQuota, - "statcache": map[string]interface{}{ - "cache_store": cfg.StatCache.Store, - "cache_nodes": cfg.StatCache.Nodes, - "cache_database": cfg.StatCache.Database, - "cache_ttl": cfg.StatCache.TTL, - "cache_size": cfg.StatCache.Size, - "cache_disable_persistence": cfg.StatCache.DisablePersistence, - "cache_auth_username": cfg.StatCache.AuthUsername, - "cache_auth_password": cfg.StatCache.AuthPassword, - }, "filemetadatacache": map[string]interface{}{ "cache_store": cfg.FilemetadataCache.Store, "cache_nodes": cfg.FilemetadataCache.Nodes, @@ -267,16 +247,6 @@ func S3NG(cfg *config.Config) map[string]interface{} { "lock_cycle_duration_factor": cfg.Drivers.S3NG.LockCycleDurationFactor, "max_concurrency": cfg.Drivers.S3NG.MaxConcurrency, "asyncfileuploads": cfg.Drivers.OCIS.AsyncUploads, - "statcache": map[string]interface{}{ - "cache_store": cfg.StatCache.Store, - "cache_nodes": cfg.StatCache.Nodes, - "cache_database": cfg.StatCache.Database, - "cache_ttl": cfg.StatCache.TTL, - "cache_size": cfg.StatCache.Size, - "cache_disable_persistence": cfg.StatCache.DisablePersistence, - "cache_auth_username": cfg.StatCache.AuthUsername, - "cache_auth_password": cfg.StatCache.AuthPassword, - }, "filemetadatacache": map[string]interface{}{ "cache_store": cfg.FilemetadataCache.Store, "cache_nodes": cfg.FilemetadataCache.Nodes, @@ -334,16 +304,6 @@ func S3NGNoEvents(cfg *config.Config) map[string]interface{} { "max_acquire_lock_cycles": cfg.Drivers.S3NG.MaxAcquireLockCycles, "max_concurrency": cfg.Drivers.S3NG.MaxConcurrency, "lock_cycle_duration_factor": cfg.Drivers.S3NG.LockCycleDurationFactor, - "statcache": map[string]interface{}{ - "cache_store": cfg.StatCache.Store, - "cache_nodes": cfg.StatCache.Nodes, - "cache_database": cfg.StatCache.Database, - "cache_ttl": cfg.StatCache.TTL, - "cache_size": cfg.StatCache.Size, - "cache_disable_persistence": cfg.StatCache.DisablePersistence, - "cache_auth_username": cfg.StatCache.AuthUsername, - "cache_auth_password": cfg.StatCache.AuthPassword, - }, "filemetadatacache": map[string]interface{}{ "cache_store": cfg.FilemetadataCache.Store, "cache_nodes": cfg.FilemetadataCache.Nodes, From 82ee1a6305a1e26f44d524ea2c4e4264deeaa886 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Tue, 23 Jan 2024 13:48:23 +0100 Subject: [PATCH 58/73] use inmemory natsjskv registry Signed-off-by: jkoberg --- ocis-pkg/natsjsregistry/registry.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ocis-pkg/natsjsregistry/registry.go b/ocis-pkg/natsjsregistry/registry.go index 8be5d02d82..857b4e5198 100644 --- a/ocis-pkg/natsjsregistry/registry.go +++ b/ocis-pkg/natsjsregistry/registry.go @@ -31,7 +31,7 @@ func NewRegistry(opts ...registry.Option) registry.Registry { exp, _ := options.Context.Value(expiryKey{}).(time.Duration) return &storeregistry{ opts: options, - store: natsjskv.NewStore(storeOptions(options)...), + store: natsjskv.NewStore(append(storeOptions(options), natsjskv.DefaultMemory())...), typ: _registryName, expiry: exp, } From b5ed06dad6f2fd6e6b2a4327996212aa0f47da37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Duffeck?= Date: Wed, 24 Jan 2024 10:49:45 +0100 Subject: [PATCH 59/73] Bump reva --- changelog/unreleased/bump-reva.md | 1 + go.mod | 2 +- go.sum | 4 ++-- .../sharesstorageprovider.go | 2 +- .../http/services/owncloud/ocdav/copy.go | 2 ++ .../http/services/owncloud/ocdav/put.go | 1 + .../pkg/storage/utils/decomposedfs/upload.go | 18 +++++++++++++----- .../storage/utils/decomposedfs/upload/store.go | 3 ++- vendor/modules.txt | 2 +- 9 files changed, 24 insertions(+), 11 deletions(-) diff --git a/changelog/unreleased/bump-reva.md b/changelog/unreleased/bump-reva.md index b08ffe6c43..1e32339c10 100644 --- a/changelog/unreleased/bump-reva.md +++ b/changelog/unreleased/bump-reva.md @@ -2,5 +2,6 @@ Enhancement: Update reva to latest edge version We update reva to the latest edge version to get the latest fixes and features. +https://github.com/owncloud/ocis/pull/8278 https://github.com/owncloud/ocis/pull/8264 https://github.com/owncloud/ocis/pull/8100 diff --git a/go.mod b/go.mod index 21f9ec0b55..b51fe0cff9 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/coreos/go-oidc v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.9.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.18.1-0.20240123151850-049234cc31e0 + github.com/cs3org/reva/v2 v2.18.1-0.20240124094635-6eec406c0be7 github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e diff --git a/go.sum b/go.sum index 524e8b8e9b..d36cd3ab02 100644 --- a/go.sum +++ b/go.sum @@ -1018,8 +1018,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c= github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.18.1-0.20240123151850-049234cc31e0 h1:btY1QRE5X4bvp7V+PUkQptFFBkB9QoJTObDNrX9G3EU= -github.com/cs3org/reva/v2 v2.18.1-0.20240123151850-049234cc31e0/go.mod h1:GCN3g6uYE0Nvd31dGlhaGGyUviUfbG2NkecPRv5oSc4= +github.com/cs3org/reva/v2 v2.18.1-0.20240124094635-6eec406c0be7 h1:g7vQAbo64ziFqqhKcim3JCjDW1zqHy9imAm2HZmmK8w= +github.com/cs3org/reva/v2 v2.18.1-0.20240124094635-6eec406c0be7/go.mod h1:GCN3g6uYE0Nvd31dGlhaGGyUviUfbG2NkecPRv5oSc4= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go index 432bcb15ce..1d678d06bc 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go @@ -321,7 +321,7 @@ func (s *service) GetPath(ctx context.Context, req *provider.GetPathRequest) (*p return &provider.GetPathResponse{ Status: status.NewOK(ctx), - Path: receivedShare.MountPoint.Path, + Path: filepath.Clean("/" + receivedShare.MountPoint.Path), }, nil } diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/copy.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/copy.go index 7379cff0bf..166c110f3f 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/copy.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/copy.go @@ -303,6 +303,7 @@ func (s *svc) executePathCopy(ctx context.Context, selector pool.Selectable[gate return err } httpUploadReq.Header.Set(datagateway.TokenTransportHeader, uploadToken) + httpUploadReq.ContentLength = int64(cp.sourceInfo.GetSize()) httpUploadRes, err := s.client.Do(httpUploadReq) if err != nil { @@ -521,6 +522,7 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, sele return err } httpUploadReq.Header.Set(datagateway.TokenTransportHeader, uploadToken) + httpUploadReq.ContentLength = int64(cp.sourceInfo.GetSize()) httpUploadRes, err := s.client.Do(httpUploadReq) if err != nil { diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/put.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/put.go index 7a6324ce38..485629a3f4 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/put.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/put.go @@ -307,6 +307,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ } Propagator.Inject(ctx, propagation.HeaderCarrier(httpReq.Header)) httpReq.Header.Set(datagateway.TokenTransportHeader, token) + httpReq.ContentLength = length httpRes, err := s.client.Do(httpReq) if err != nil { diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go index d3af49b90a..06d1583da6 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go @@ -72,13 +72,21 @@ func (fs *Decomposedfs) Upload(ctx context.Context, req storage.UploadRequest, u defer fd.Close() defer os.RemoveAll(assembledFile) req.Body = fd - } - size, err := session.WriteChunk(ctx, 0, req.Body) - if err != nil { - return provider.ResourceInfo{}, errors.Wrap(err, "Decomposedfs: error writing to binary file") + size, err := session.WriteChunk(ctx, 0, req.Body) + if err != nil { + return provider.ResourceInfo{}, errors.Wrap(err, "Decomposedfs: error writing to binary file") + } + session.SetSize(size) + } else { + size, err := session.WriteChunk(ctx, 0, req.Body) + if err != nil { + return provider.ResourceInfo{}, errors.Wrap(err, "Decomposedfs: error writing to binary file") + } + if size != req.Length { + return provider.ResourceInfo{}, errtypes.PartialContent("Decomposedfs: unexpected end of stream") + } } - session.SetSize(size) if err := session.FinishUpload(ctx); err != nil { return provider.ResourceInfo{}, err diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go index ce47905642..def5e545f8 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go @@ -96,7 +96,8 @@ func (store OcisStore) List(ctx context.Context) ([]*OcisSession, error) { } for _, info := range infoFiles { - progress, err := store.Get(ctx, info) + id := strings.TrimSuffix(filepath.Base(info), filepath.Ext(info)) + progress, err := store.Get(ctx, id) if err != nil { appctx.GetLogger(ctx).Error().Interface("path", info).Msg("Decomposedfs: could not getUploadSession") continue diff --git a/vendor/modules.txt b/vendor/modules.txt index d59bf27708..2aa98156d2 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -362,7 +362,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1 github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1 github.com/cs3org/go-cs3apis/cs3/tx/v1beta1 github.com/cs3org/go-cs3apis/cs3/types/v1beta1 -# github.com/cs3org/reva/v2 v2.18.1-0.20240123151850-049234cc31e0 +# github.com/cs3org/reva/v2 v2.18.1-0.20240124094635-6eec406c0be7 ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime From 3b75b5b722a976aa5c9122c1131cd098f465b323 Mon Sep 17 00:00:00 2001 From: Prajwol Amatya <83579989+PrajwolAmatya@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:45:35 +0545 Subject: [PATCH 60/73] added test to reshare resources to other users SharingNg (#8275) --- .../features/apiSharingNg/reshare.feature | 125 ++++++++++++++++++ .../features/bootstrap/SharingNgContext.php | 17 ++- 2 files changed, 139 insertions(+), 3 deletions(-) create mode 100644 tests/acceptance/features/apiSharingNg/reshare.feature diff --git a/tests/acceptance/features/apiSharingNg/reshare.feature b/tests/acceptance/features/apiSharingNg/reshare.feature new file mode 100644 index 0000000000..74a2e74127 --- /dev/null +++ b/tests/acceptance/features/apiSharingNg/reshare.feature @@ -0,0 +1,125 @@ +Feature: Reshare a share invitation + As a user + I want to be able to reshare the share invitations to other users + So that they can have access to it + + https://owncloud.dev/libre-graph-api/#/drives.permissions/Invite + + Background: + Given these users have been created with default attributes and without skeleton files: + | username | + | Alice | + | Brian | + | Carol | + + + Scenario Outline: reshare a file to a user with different roles + Given user "Alice" has uploaded file with content "to share" to "/textfile1.txt" + And user "Alice" has sent the following share invitation: + | resourceType | file | + | resource | textfile1.txt | + | space | Personal | + | sharee | Brian | + | shareType | user | + | permissionsRole | | + When user "Brian" sends the following share invitation using the Graph API: + | resourceType | file | + | resource | textfile1.txt | + | space | Shares | + | sharee | Carol | + | shareType | user | + | permissionsRole | | + Then the HTTP status code should be "200" + And for user "Carol" the space Shares should contain these entries: + | textfile1.txt | + Examples: + | permissions-role | reshare-permissions-role | + | Viewer | Viewer | + | File Editor | Viewer | + | File Editor | File Editor | + + + Scenario Outline: reshare a folder to a user with different roles + Given user "Alice" has created folder "FolderToShare" + And user "Alice" has sent the following share invitation: + | resourceType | folder | + | resource | FolderToShare | + | space | Personal | + | sharee | Brian | + | shareType | user | + | permissionsRole | | + When user "Brian" sends the following share invitation using the Graph API: + | resourceType | folder | + | resource | FolderToShare | + | space | Shares | + | sharee | Carol | + | shareType | user | + | permissionsRole | | + Then the HTTP status code should be "200" + And for user "Carol" the space Shares should contain these entries: + | FolderToShare | + Examples: + | permissions-role | reshare-permissions-role | + | Viewer | Viewer | + | Editor | Viewer | + | Editor | Editor | + | Editor | Uploader | + + + Scenario Outline: reshare a file inside project space to a user with different roles + Given using spaces DAV path + And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API + And user "Alice" has created a space "NewSpace" with the default quota using the Graph API + And user "Alice" has uploaded a file inside space "NewSpace" with content "to share" to "textfile1.txt" + And user "Alice" has sent the following share invitation: + | resourceType | file | + | resource | textfile1.txt | + | space | NewSpace | + | sharee | Brian | + | shareType | user | + | permissionsRole | | + When user "Brian" sends the following share invitation using the Graph API: + | resourceType | file | + | resource | textfile1.txt | + | space | Shares | + | sharee | Carol | + | shareType | user | + | permissionsRole | | + Then the HTTP status code should be "200" + And for user "Carol" the space Shares should contain these entries: + | textfile1.txt | + Examples: + | permissions-role | reshare-permissions-role | + | Viewer | Viewer | + | File Editor | Viewer | + | File Editor | File Editor | + + + Scenario Outline: reshare a folder inside project space to a user with different roles + Given using spaces DAV path + And the administrator has assigned the role "Space Admin" to user "Alice" using the Graph API + And user "Alice" has created a space "NewSpace" with the default quota using the Graph API + And user "Alice" has created a folder "FolderToShare" in space "NewSpace" + And user "Alice" has sent the following share invitation: + | resourceType | folder | + | resource | FolderToShare | + | space | NewSpace | + | sharee | Brian | + | shareType | user | + | permissionsRole | | + When user "Brian" sends the following share invitation using the Graph API: + | resourceType | folder | + | resource | FolderToShare | + | space | Shares | + | sharee | Carol | + | shareType | user | + | permissionsRole | | + Then the HTTP status code should be "200" + And for user "Carol" the space Shares should contain these entries: + | FolderToShare | + Examples: + | permissions-role | reshare-permissions-role | + | Viewer | Viewer | + | Editor | Viewer | + | Editor | Editor | + | Editor | Uploader | diff --git a/tests/acceptance/features/bootstrap/SharingNgContext.php b/tests/acceptance/features/bootstrap/SharingNgContext.php index bb4492301f..7e16a7356f 100644 --- a/tests/acceptance/features/bootstrap/SharingNgContext.php +++ b/tests/acceptance/features/bootstrap/SharingNgContext.php @@ -141,9 +141,20 @@ class SharingNgContext implements Context { $rows = $table->getRowsHash(); $spaceId = ($this->spacesContext->getSpaceByName($user, $rows['space']))["id"]; - $itemId = ($rows['resourceType'] === 'folder') - ? $this->spacesContext->getResourceId($user, $rows['space'], $rows['resource']) - : $this->spacesContext->getFileId($user, $rows['space'], $rows['resource']); + // for resharing a resource, "item-id" in API endpoint takes shareMountId + if ($rows['space'] === 'Shares') { + $itemId = GraphHelper::getShareMountId( + $this->featureContext->getBaseUrl(), + $this->featureContext->getStepLineRef(), + $user, + $this->featureContext->getPasswordForUser($user), + $rows['resource'] + ); + } else { + $itemId = ($rows['resourceType'] === 'folder') + ? $this->spacesContext->getResourceId($user, $rows['space'], $rows['resource']) + : $this->spacesContext->getFileId($user, $rows['space'], $rows['resource']); + } $sharees = array_map('trim', explode(',', $rows['sharee'])); $shareTypes = array_map('trim', explode(',', $rows['shareType'])); From cf53146f8bd136d3640a7a338919e5921eeed993 Mon Sep 17 00:00:00 2001 From: kobergj Date: Wed, 24 Jan 2024 10:17:53 +0000 Subject: [PATCH 61/73] Automated changelog update [skip ci] --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31b5f18cf7..594bb15274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,7 @@ The following sections list the changes for unreleased. * Bugfix - Cleanup `search/pkg/search/search.go`: [#8230](https://github.com/owncloud/ocis/pull/8230) * Bugfix - Graph/sharedWithMe works for shares from project spaces now: [#8233](https://github.com/owncloud/ocis/pull/8233) * Bugfix - Fix PATCH/DELETE status code for drives that don't support them: [#8235](https://github.com/owncloud/ocis/pull/8235) +* Bugfix - Fix nats authentication: [#8236](https://github.com/owncloud/ocis/pull/8236) * Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269) * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) @@ -157,6 +158,12 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/issues/7881 https://github.com/owncloud/ocis/pull/8235 +* Bugfix - Fix nats authentication: [#8236](https://github.com/owncloud/ocis/pull/8236) + + Fixes nats authentication for registry/events/stores + + https://github.com/owncloud/ocis/pull/8236 + * Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269) We fixed the race condition that led to concurrent map access in a publicshare From c8818f5dd5b7588cb67cbf30ec26dded929668bd Mon Sep 17 00:00:00 2001 From: Sawjan Gurung Date: Wed, 24 Jan 2024 17:09:54 +0545 Subject: [PATCH 62/73] add test coverage for checking file versions after multiple restores (#8188) --- .../coreApiVersions/fileVersions.feature | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/acceptance/features/coreApiVersions/fileVersions.feature b/tests/acceptance/features/coreApiVersions/fileVersions.feature index 3d89be133f..9658d6f611 100644 --- a/tests/acceptance/features/coreApiVersions/fileVersions.feature +++ b/tests/acceptance/features/coreApiVersions/fileVersions.feature @@ -418,3 +418,31 @@ Feature: dav-versions When user "Brian" tries to get versions of file "textfile0.txt" from "Alice" Then the HTTP status code should be "403" And the value of the item "//s:exception" in the response about user "Alice" should be "Sabre\DAV\Exception\Forbidden" + + @issue-enterprise-6249 + Scenario: upload empty content file and check versions after multiple restores + Given user "Alice" has uploaded file with content "" to "textfile.txt" + And user "Alice" has uploaded file with content "test content" to "textfile.txt" + And the version folder of file "textfile.txt" for user "Alice" should contain "1" element + When user "Alice" restores version index "1" of file "textfile.txt" using the WebDAV API + Then the HTTP status code should be "204" + And the content of file "textfile.txt" for user "Alice" should be "" + And the version folder of file "textfile.txt" for user "Alice" should contain "1" elements + When user "Alice" restores version index "1" of file "textfile.txt" using the WebDAV API + Then the HTTP status code should be "204" + And the content of file "textfile.txt" for user "Alice" should be "test content" + And the version folder of file "textfile.txt" for user "Alice" should contain "1" elements + + + Scenario: update with empty content and check versions after multiple restores + Given user "Alice" has uploaded file with content "test content" to "textfile.txt" + And user "Alice" has uploaded file with content "" to "textfile.txt" + And the version folder of file "textfile.txt" for user "Alice" should contain "1" element + When user "Alice" restores version index "1" of file "textfile.txt" using the WebDAV API + Then the HTTP status code should be "204" + And the content of file "textfile.txt" for user "Alice" should be "test content" + And the version folder of file "textfile.txt" for user "Alice" should contain "1" elements + When user "Alice" restores version index "1" of file "textfile.txt" using the WebDAV API + Then the HTTP status code should be "204" + And the content of file "textfile.txt" for user "Alice" should be "" + And the version folder of file "textfile.txt" for user "Alice" should contain "1" elements From b950fcecb13b4e83a54b60d3490e901f5ef3212a Mon Sep 17 00:00:00 2001 From: Andre Duffeck Date: Wed, 24 Jan 2024 14:48:04 +0000 Subject: [PATCH 63/73] Automated changelog update [skip ci] --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 594bb15274..3c749f8486 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,7 +59,7 @@ The following sections list the changes for unreleased. * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) * Enhancement - Remove deprecated environment variables: [#8149](https://github.com/owncloud/ocis/pull/8149) * Enhancement - Disable the password policy: [#8152](https://github.com/owncloud/ocis/pull/8152) -* Enhancement - Update reva to latest edge version: [#8264](https://github.com/owncloud/ocis/pull/8264) +* Enhancement - Update reva to latest edge version: [#8278](https://github.com/owncloud/ocis/pull/8278) ## Details @@ -210,10 +210,11 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/pull/8152 https://github.com/cs3org/reva/pull/4453 -* Enhancement - Update reva to latest edge version: [#8264](https://github.com/owncloud/ocis/pull/8264) +* Enhancement - Update reva to latest edge version: [#8278](https://github.com/owncloud/ocis/pull/8278) We update reva to the latest edge version to get the latest fixes and features. + https://github.com/owncloud/ocis/pull/8278 https://github.com/owncloud/ocis/pull/8264 https://github.com/owncloud/ocis/pull/8100 From ccfb9101de2b0b15c141effa311fda282f0fed73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn=20Friedrich=20Dreyer?= Date: Wed, 24 Jan 2024 16:34:58 +0100 Subject: [PATCH 64/73] it is called traceProvider (#8280) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jörn Friedrich Dreyer --- services/app-provider/pkg/command/server.go | 4 +-- services/app-registry/pkg/command/server.go | 4 +-- services/auth-service/pkg/command/server.go | 11 +++++--- services/auth-service/pkg/config/config.go | 6 ----- services/auth-service/pkg/config/tracing.go | 21 ++++++++++++++++ services/auth-service/pkg/tracing/tracing.go | 25 ------------------- services/frontend/pkg/command/server.go | 4 +-- services/groups/pkg/command/server.go | 4 +-- services/ocdav/pkg/command/server.go | 4 +-- services/settings/pkg/command/server.go | 8 +++--- services/sharing/pkg/command/server.go | 4 +-- .../storage-publiclink/pkg/command/server.go | 4 +-- 12 files changed, 47 insertions(+), 52 deletions(-) create mode 100644 services/auth-service/pkg/config/tracing.go delete mode 100644 services/auth-service/pkg/tracing/tracing.go diff --git a/services/app-provider/pkg/command/server.go b/services/app-provider/pkg/command/server.go index 8234b4391d..6259e7b849 100644 --- a/services/app-provider/pkg/command/server.go +++ b/services/app-provider/pkg/command/server.go @@ -33,7 +33,7 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - tracingProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } @@ -50,7 +50,7 @@ func Server(cfg *config.Config) *cli.Command { runtime.RunWithOptions(rCfg, pidFile, runtime.WithLogger(&logger.Logger), runtime.WithRegistry(reg), - runtime.WithTraceProvider(tracingProvider), + runtime.WithTraceProvider(traceProvider), ) return nil diff --git a/services/app-registry/pkg/command/server.go b/services/app-registry/pkg/command/server.go index 543eb3f833..54bf524103 100644 --- a/services/app-registry/pkg/command/server.go +++ b/services/app-registry/pkg/command/server.go @@ -32,7 +32,7 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - tracingProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } @@ -49,7 +49,7 @@ func Server(cfg *config.Config) *cli.Command { runtime.RunWithOptions(rCfg, pidFile, runtime.WithLogger(&logger.Logger), runtime.WithRegistry(reg), - runtime.WithTraceProvider(tracingProvider), + runtime.WithTraceProvider(traceProvider), ) return nil diff --git a/services/auth-service/pkg/command/server.go b/services/auth-service/pkg/command/server.go index d656ef42a9..565f675747 100644 --- a/services/auth-service/pkg/command/server.go +++ b/services/auth-service/pkg/command/server.go @@ -12,13 +12,13 @@ import ( "github.com/owncloud/ocis/v2/ocis-pkg/config/configlog" "github.com/owncloud/ocis/v2/ocis-pkg/registry" "github.com/owncloud/ocis/v2/ocis-pkg/sync" + "github.com/owncloud/ocis/v2/ocis-pkg/tracing" "github.com/owncloud/ocis/v2/ocis-pkg/version" "github.com/owncloud/ocis/v2/services/auth-service/pkg/config" "github.com/owncloud/ocis/v2/services/auth-service/pkg/config/parser" "github.com/owncloud/ocis/v2/services/auth-service/pkg/logging" "github.com/owncloud/ocis/v2/services/auth-service/pkg/revaconfig" "github.com/owncloud/ocis/v2/services/auth-service/pkg/server/debug" - "github.com/owncloud/ocis/v2/services/auth-service/pkg/tracing" "github.com/urfave/cli/v2" ) @@ -33,7 +33,7 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - err := tracing.Configure(cfg, logger) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } @@ -43,11 +43,16 @@ func Server(cfg *config.Config) *cli.Command { defer cancel() pidFile := path.Join(os.TempDir(), "revad-"+cfg.Service.Name+"-"+uuid.Must(uuid.NewV4()).String()+".pid") + reg := registry.GetRegistry() rcfg := revaconfig.AuthMachineConfigFromStruct(cfg) gr.Add(func() error { - runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger)) + runtime.RunWithOptions(rcfg, pidFile, + runtime.WithLogger(&logger.Logger), + runtime.WithRegistry(reg), + runtime.WithTraceProvider(traceProvider), + ) return nil }, func(err error) { logger.Error(). diff --git a/services/auth-service/pkg/config/config.go b/services/auth-service/pkg/config/config.go index 0314497006..36ad90df57 100644 --- a/services/auth-service/pkg/config/config.go +++ b/services/auth-service/pkg/config/config.go @@ -24,12 +24,6 @@ type Config struct { Supervised bool `yaml:"-"` Context context.Context `yaml:"-"` } -type Tracing struct { - Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;AUTH_SERVICE_TRACING_ENABLED" desc:"Activates tracing."` - Type string `yaml:"type" env:"OCIS_TRACING_TYPE;AUTH_SERVICE_TRACING_TYPE" desc:"The type of tracing. Defaults to '', which is the same as 'jaeger'. Allowed tracing types are 'jaeger' and '' as of now."` - Endpoint string `yaml:"endpoint" env:"OCIS_TRACING_ENDPOINT;AUTH_SERVICE_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent."` - Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR;AUTH_SERVICE_TRACING_COLLECTOR" desc:"The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces. Only used if the tracing endpoint is unset."` -} type Log struct { Level string `yaml:"level" env:"OCIS_LOG_LEVEL;AUTH_SERVICE_LOG_LEVEL" desc:"The log level. Valid values are: 'panic', 'fatal', 'error', 'warn', 'info', 'debug', 'trace'."` diff --git a/services/auth-service/pkg/config/tracing.go b/services/auth-service/pkg/config/tracing.go new file mode 100644 index 0000000000..135de64c32 --- /dev/null +++ b/services/auth-service/pkg/config/tracing.go @@ -0,0 +1,21 @@ +package config + +import "github.com/owncloud/ocis/v2/ocis-pkg/tracing" + +// Tracing is the config for tracing parameters +type Tracing struct { + Enabled bool `yaml:"enabled" env:"OCIS_TRACING_ENABLED;AUTH_SERVICE_TRACING_ENABLED" desc:"Activates tracing."` + Type string `yaml:"type" env:"OCIS_TRACING_TYPE;AUTH_SERVICE_TRACING_TYPE" desc:"The type of tracing. Defaults to '', which is the same as 'jaeger'. Allowed tracing types are 'jaeger' and '' as of now."` + Endpoint string `yaml:"endpoint" env:"OCIS_TRACING_ENDPOINT;AUTH_SERVICE_TRACING_ENDPOINT" desc:"The endpoint of the tracing agent."` + Collector string `yaml:"collector" env:"OCIS_TRACING_COLLECTOR;AUTH_SERVICE_TRACING_COLLECTOR" desc:"The HTTP endpoint for sending spans directly to a collector, i.e. http://jaeger-collector:14268/api/traces. Only used if the tracing endpoint is unset."` +} + +// Convert Tracing to the tracing package's Config struct. +func (t Tracing) Convert() tracing.Config { + return tracing.Config{ + Enabled: t.Enabled, + Type: t.Type, + Endpoint: t.Endpoint, + Collector: t.Collector, + } +} diff --git a/services/auth-service/pkg/tracing/tracing.go b/services/auth-service/pkg/tracing/tracing.go deleted file mode 100644 index 357ca4ebb6..0000000000 --- a/services/auth-service/pkg/tracing/tracing.go +++ /dev/null @@ -1,25 +0,0 @@ -package tracing - -import ( - "github.com/owncloud/ocis/v2/ocis-pkg/log" - "github.com/owncloud/ocis/v2/services/auth-service/pkg/config" - "go.opentelemetry.io/otel/trace" - - pkgtrace "github.com/owncloud/ocis/v2/ocis-pkg/tracing" -) - -var ( - // TraceProvider is the global trace provider for the service. - TraceProvider = trace.NewNoopTracerProvider() -) - -func Configure(cfg *config.Config, logger log.Logger) error { - var err error - if cfg.Tracing.Enabled { - if TraceProvider, err = pkgtrace.GetTraceProvider(cfg.Tracing.Endpoint, cfg.Tracing.Collector, cfg.Service.Name, cfg.Tracing.Type); err != nil { - return err - } - } - - return nil -} diff --git a/services/frontend/pkg/command/server.go b/services/frontend/pkg/command/server.go index 6fdc3a8ecd..a60e81153d 100644 --- a/services/frontend/pkg/command/server.go +++ b/services/frontend/pkg/command/server.go @@ -33,7 +33,7 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - tracingProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } @@ -54,7 +54,7 @@ func Server(cfg *config.Config) *cli.Command { runtime.RunWithOptions(rCfg, pidFile, runtime.WithLogger(&logger.Logger), runtime.WithRegistry(reg), - runtime.WithTraceProvider(tracingProvider), + runtime.WithTraceProvider(traceProvider), ) return nil diff --git a/services/groups/pkg/command/server.go b/services/groups/pkg/command/server.go index c1b43bc945..6690ebbb11 100644 --- a/services/groups/pkg/command/server.go +++ b/services/groups/pkg/command/server.go @@ -34,7 +34,7 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - tracingProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } @@ -63,7 +63,7 @@ func Server(cfg *config.Config) *cli.Command { runtime.RunWithOptions(rCfg, pidFile, runtime.WithLogger(&logger.Logger), runtime.WithRegistry(reg), - runtime.WithTraceProvider(tracingProvider), + runtime.WithTraceProvider(traceProvider), ) return nil diff --git a/services/ocdav/pkg/command/server.go b/services/ocdav/pkg/command/server.go index 10f7033458..447e72d8c7 100644 --- a/services/ocdav/pkg/command/server.go +++ b/services/ocdav/pkg/command/server.go @@ -30,7 +30,7 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - tracingProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } @@ -86,7 +86,7 @@ func Server(cfg *config.Config) *cli.Command { ocdav.MetricsEnabled(true), ocdav.MetricsNamespace("ocis"), ocdav.Tracing("Adding these strings is a workaround for ->", "https://github.com/cs3org/reva/issues/4131"), - ocdav.WithTraceProvider(tracingProvider), + ocdav.WithTraceProvider(traceProvider), } s, err := ocdav.Service(opts...) diff --git a/services/settings/pkg/command/server.go b/services/settings/pkg/command/server.go index ca87133fb0..b06302188d 100644 --- a/services/settings/pkg/command/server.go +++ b/services/settings/pkg/command/server.go @@ -32,12 +32,12 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - tracingProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } cfg.GrpcClient, err = ogrpc.NewClient( - append(ogrpc.GetClientOptions(cfg.GRPCClientTLS), ogrpc.WithTraceProvider(tracingProvider))..., + append(ogrpc.GetClientOptions(cfg.GRPCClientTLS), ogrpc.WithTraceProvider(traceProvider))..., ) if err != nil { return err @@ -65,7 +65,7 @@ func Server(cfg *config.Config) *cli.Command { http.Config(cfg), http.Metrics(mtrcs), http.ServiceHandler(handle), - http.TraceProvider(tracingProvider), + http.TraceProvider(traceProvider), ) if err != nil { logger.Error(). @@ -87,7 +87,7 @@ func Server(cfg *config.Config) *cli.Command { grpc.Config(cfg), grpc.Metrics(mtrcs), grpc.ServiceHandler(handle), - grpc.TraceProvider(tracingProvider), + grpc.TraceProvider(traceProvider), ) servers.Add(grpcServer.Run, func(_ error) { logger.Info().Str("server", "grpc").Msg("Shutting down server") diff --git a/services/sharing/pkg/command/server.go b/services/sharing/pkg/command/server.go index 8d18a3adcb..61f72d65c5 100644 --- a/services/sharing/pkg/command/server.go +++ b/services/sharing/pkg/command/server.go @@ -34,7 +34,7 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - tracingProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } @@ -66,7 +66,7 @@ func Server(cfg *config.Config) *cli.Command { runtime.RunWithOptions(rCfg, pidFile, runtime.WithLogger(&logger.Logger), runtime.WithRegistry(reg), - runtime.WithTraceProvider(tracingProvider), + runtime.WithTraceProvider(traceProvider), ) return nil diff --git a/services/storage-publiclink/pkg/command/server.go b/services/storage-publiclink/pkg/command/server.go index 6512252b75..18da72cee5 100644 --- a/services/storage-publiclink/pkg/command/server.go +++ b/services/storage-publiclink/pkg/command/server.go @@ -33,7 +33,7 @@ func Server(cfg *config.Config) *cli.Command { }, Action: func(c *cli.Context) error { logger := logging.Configure(cfg.Service.Name, cfg.Log) - tracingProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) + traceProvider, err := tracing.GetServiceTraceProvider(cfg.Tracing, cfg.Service.Name) if err != nil { return err } @@ -50,7 +50,7 @@ func Server(cfg *config.Config) *cli.Command { runtime.RunWithOptions(rCfg, pidFile, runtime.WithLogger(&logger.Logger), runtime.WithRegistry(reg), - runtime.WithTraceProvider(tracingProvider), + runtime.WithTraceProvider(traceProvider), ) return nil From 0cb731aef1d0bf7d27b81a1af823a6b4c7afacfa Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Wed, 24 Jan 2024 16:52:38 +0100 Subject: [PATCH 65/73] tests: fix test expectations for cors (#8279) --- ...ected-failures-localAPI-on-OCIS-storage.md | 12 ------ .../acceptance/features/apiCors/cors.feature | 39 ++++++++++--------- 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index d9b6da351e..83703bdc47 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -45,18 +45,6 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiGraphUserGroup/deleteGroup.feature:67](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/deleteGroup.feature#L67) -#### [CORS headers are not identical with oC10 headers](https://github.com/owncloud/ocis/issues/5195) - -- [apiCors/cors.feature:28](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L28) -- [apiCors/cors.feature:29](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L29) -- [apiCors/cors.feature:30](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L30) -- [apiCors/cors.feature:31](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L31) - -#### [Requests with invalid credentials do not return CORS headers](https://github.com/owncloud/ocis/issues/5194) - -- [apiCors/cors.feature:70](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L70) -- [apiCors/cors.feature:71](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiCors/cors.feature#L71) - #### [A User can get information of another user with Graph API](https://github.com/owncloud/ocis/issues/5125) - [apiGraphUserGroup/getUser.feature:89](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiGraphUserGroup/getUser.feature#L89) diff --git a/tests/acceptance/features/apiCors/cors.feature b/tests/acceptance/features/apiCors/cors.feature index a0a8da4cde..28131c8a08 100644 --- a/tests/acceptance/features/apiCors/cors.feature +++ b/tests/acceptance/features/apiCors/cors.feature @@ -18,11 +18,10 @@ Feature: CORS headers Then the OCS status code should be "" And the HTTP status code should be "" And the following headers should be set - | header | value | - | Access-Control-Allow-Headers | OC-Checksum,OC-Total-Length,OCS-APIREQUEST,X-OC-Mtime,OC-RequestAppPassword,Accept,Authorization,Brief,Content-Length,Content-Range,Content-Type,Date,Depth,Destination,Host,If,If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,Location,Lock-Token,Overwrite,Prefer,Range,Schedule-Reply,Timeout,User-Agent,X-Expected-Entity-Length,Accept-Language,Access-Control-Request-Method,Access-Control-Allow-Origin,Cache-Control,ETag,OC-Autorename,OC-CalDav-Import,OC-Chunked,OC-Etag,OC-FileId,OC-LazyOps,OC-Total-File-Length,Origin,X-Request-ID,X-Requested-With | - | Access-Control-Expose-Headers | Content-Location,DAV,ETag,Link,Lock-Token,OC-ETag,OC-Checksum,OC-FileId,OC-JobStatus-Location,OC-RequestAppPassword,Vary,Webdav-Location,X-Sabre-Status | - | Access-Control-Allow-Origin | https://aphno.badal | - | Access-Control-Allow-Methods | GET,OPTIONS,POST,PUT,DELETE,MKCOL,PROPFIND,PATCH,PROPPATCH,REPORT | + | header | value | + | Access-Control-Expose-Headers | Location | + | Access-Control-Allow-Origin | https://aphno.badal | + | Access-Control-Allow-Credentials | true | Examples: | ocs_api_version | endpoint | ocs-code | http-code | | 1 | /config | 100 | 200 | @@ -52,20 +51,22 @@ Feature: CORS headers | 2 | /apps/files_sharing/api/v1/shares | 200 | 200 | @issue-5194 - Scenario Outline: CORS headers should be returned when an invalid password is used + Scenario Outline: CORS headers should be returned when an preflight request is sent Given using OCS API version "" - When user "Alice" sends HTTP method "GET" to OCS API endpoint "" with headers using password "invalid" - | header | value | - | Origin | https://aphno.badal | - Then the OCS status code should be "997" - And the HTTP status code should be "401" + When user "Alice" sends HTTP method "OPTIONS" to OCS API endpoint "" with headers + | header | value | + | Origin | https://aphno.badal | + | Access-Control-Request-Headers | Origin, Accept, Content-Type, Depth, Authorization, Ocs-Apirequest, If-None-Match, If-Match, Destination, Overwrite, X-Request-Id, X-Requested-With, Tus-Resumable, Tus-Checksum-Algorithm, Upload-Concat, Upload-Length, Upload-Metadata, Upload-Defer-Length, Upload-Expires, Upload-Checksum, Upload-Offset, X-Http-Method-Override, Cache-Control | + | Access-Control-Request-Method | | + And the HTTP status code should be "204" And the following headers should be set - | header | value | - | Access-Control-Allow-Headers | OC-Checksum,OC-Total-Length,OCS-APIREQUEST,X-OC-Mtime,OC-RequestAppPassword,Accept,Authorization,Brief,Content-Length,Content-Range,Content-Type,Date,Depth,Destination,Host,If,If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,Location,Lock-Token,Overwrite,Prefer,Range,Schedule-Reply,Timeout,User-Agent,X-Expected-Entity-Length,Accept-Language,Access-Control-Request-Method,Access-Control-Allow-Origin,Cache-Control,ETag,OC-Autorename,OC-CalDav-Import,OC-Chunked,OC-Etag,OC-FileId,OC-LazyOps,OC-Total-File-Length,Origin,X-Request-ID,X-Requested-With | - | Access-Control-Expose-Headers | Content-Location,DAV,ETag,Link,Lock-Token,OC-ETag,OC-Checksum,OC-FileId,OC-JobStatus-Location,OC-RequestAppPassword,Vary,Webdav-Location,X-Sabre-Status | - | Access-Control-Allow-Origin | https://aphno.badal | - | Access-Control-Allow-Methods | GET,OPTIONS,POST,PUT,DELETE,MKCOL,PROPFIND,PATCH,PROPPATCH,REPORT | + | header | value | + | Access-Control-Allow-Headers | Origin, Accept, Content-Type, Depth, Authorization, Ocs-Apirequest, If-None-Match, If-Match, Destination, Overwrite, X-Request-Id, X-Requested-With, Tus-Resumable, Tus-Checksum-Algorithm, Upload-Concat, Upload-Length, Upload-Metadata, Upload-Defer-Length, Upload-Expires, Upload-Checksum, Upload-Offset, X-Http-Method-Override, Cache-Control | + | Access-Control-Allow-Origin | https://aphno.badal | + | Access-Control-Allow-Methods | | Examples: - | ocs_api_version | endpoint | - | 1 | /apps/files_sharing/api/v1/shares | - | 2 | /apps/files_sharing/api/v1/shares | + | ocs_api_version | | endpoint | request_method | + | 1 | | /apps/files_sharing/api/v1/shares | GET | + | 2 | | /apps/files_sharing/api/v1/shares | PUT | + | 1 | | /apps/files_sharing/api/v1/shares | DELETE | + | 2 | | /apps/files_sharing/api/v1/shares | POST | From f38f940d22fc5d8cead6d7dca0069d1a8da3bf09 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Thu, 18 Jan 2024 14:09:52 +0100 Subject: [PATCH 66/73] graph/sharing: Fix role conditions for Space specific sharing roles Co-Owner and Manager are space specific roles. They need the UnifiedRoleConditionOwner. --- services/graph/pkg/unifiedrole/unifiedrole.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/services/graph/pkg/unifiedrole/unifiedrole.go b/services/graph/pkg/unifiedrole/unifiedrole.go index 58890f8e81..fce338767c 100644 --- a/services/graph/pkg/unifiedrole/unifiedrole.go +++ b/services/graph/pkg/unifiedrole/unifiedrole.go @@ -153,7 +153,7 @@ func NewCoownerUnifiedRole() *libregraph.UnifiedRoleDefinition { RolePermissions: []libregraph.UnifiedRolePermission{ { AllowedResourceActions: convert(r), - Condition: proto.String(UnifiedRoleConditionGrantee), + Condition: proto.String(UnifiedRoleConditionOwner), }, }, LibreGraphWeight: proto.Int32(0), @@ -185,10 +185,6 @@ func NewManagerUnifiedRole() *libregraph.UnifiedRoleDefinition { Description: proto.String("Grants manager permissions on a resource. Semantically equivalent to co-owner"), DisplayName: displayName(r), RolePermissions: []libregraph.UnifiedRolePermission{ - { - AllowedResourceActions: convert(r), - Condition: proto.String(UnifiedRoleConditionGrantee), - }, { AllowedResourceActions: convert(r), Condition: proto.String(UnifiedRoleConditionOwner), From d9fc4af5757324a3ea409cc5355d940954e943f9 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Thu, 18 Jan 2024 14:11:58 +0100 Subject: [PATCH 67/73] graph/sharing: Add check for role conditions Use the condition from the unifiedrole to check if the requested role is actually applicable to the selected resource. Fixes: #8131 --- services/graph/pkg/service/v0/driveitems.go | 6 ++++ .../graph/pkg/service/v0/driveitems_test.go | 30 +++++++++++++++++++ .../graph/pkg/unifiedrole/unifiedrole_test.go | 16 +++++++--- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go index da010478b4..6c40de2a80 100644 --- a/services/graph/pkg/service/v0/driveitems.go +++ b/services/graph/pkg/service/v0/driveitems.go @@ -460,6 +460,12 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) return } + // FIXME: When setting permissions on a space, we need to use UnifiedRoleConditionOwner here + allowedResourceActions := unifiedrole.GetAllowedResourceActions(role, unifiedrole.UnifiedRoleConditionGrantee) + if len(allowedResourceActions) == 0 { + errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "role not applicable to this resource") + return + } unifiedRolePermissions = append(unifiedRolePermissions, conversions.ToPointerSlice(role.GetRolePermissions())...) } diff --git a/services/graph/pkg/service/v0/driveitems_test.go b/services/graph/pkg/service/v0/driveitems_test.go index 7513ec290c..69cacd7e90 100644 --- a/services/graph/pkg/service/v0/driveitems_test.go +++ b/services/graph/pkg/service/v0/driveitems_test.go @@ -685,6 +685,25 @@ var _ = Describe("Driveitems", func() { _, ok := res.GetRolesOk() Expect(ok).To(BeTrue()) }) + It("fails to update the share permissions for a file share when setting a space specific role", func() { + updateShareMock := gatewayClient.On("UpdateShare", + mock.Anything, + mock.MatchedBy(func(req *collaboration.UpdateShareRequest) bool { + return req.GetShare().GetId().GetOpaqueId() == "permissionid" + }), + ) + updateShareMock.Return(updateShareMockResponse, nil) + + driveItemPermission.SetRoles([]string{unifiedrole.NewSpaceViewerUnifiedRole().GetId()}) + body, err := driveItemPermission.MarshalJSON() + Expect(err).To(BeNil()) + svc.UpdatePermission( + rr, + httptest.NewRequest(http.MethodPatch, "/", strings.NewReader(string(body))). + WithContext(ctx), + ) + Expect(rr.Code).To(Equal(http.StatusBadRequest)) + }) It("updates the share permissions when changing the resource permission actions", func() { updateShareMock := gatewayClient.On("UpdateShare", mock.Anything, @@ -1007,6 +1026,17 @@ var _ = Describe("Driveitems", func() { Expect(jsonData.Get("0.roles.0").String()).To(Equal(unifiedrole.NewViewerUnifiedRole(true).GetId())) }) + It("fails with wrong role", func() { + driveItemInvite.Roles = []string{unifiedrole.NewCoownerUnifiedRole().GetId()} + svc.Invite( + rr, + httptest.NewRequest(http.MethodPost, "/", toJSONReader(driveItemInvite)). + WithContext(ctx), + ) + + Expect(rr.Code).To(Equal(http.StatusBadRequest)) + }) + It("with actions (happy path)", func() { driveItemInvite.Roles = nil driveItemInvite.LibreGraphPermissionsActions = []string{unifiedrole.DriveItemContentRead} diff --git a/services/graph/pkg/unifiedrole/unifiedrole_test.go b/services/graph/pkg/unifiedrole/unifiedrole_test.go index f11225a5a5..12248a375b 100644 --- a/services/graph/pkg/unifiedrole/unifiedrole_test.go +++ b/services/graph/pkg/unifiedrole/unifiedrole_test.go @@ -27,8 +27,7 @@ var _ = Describe("unifiedroles", func() { Entry(rConversions.RoleViewer, rConversions.NewViewerRole(true), unifiedrole.NewViewerUnifiedRole(true), unifiedrole.UnifiedRoleConditionGrantee), Entry(rConversions.RoleEditor, rConversions.NewEditorRole(true), unifiedrole.NewEditorUnifiedRole(true), unifiedrole.UnifiedRoleConditionGrantee), Entry(rConversions.RoleFileEditor, rConversions.NewFileEditorRole(true), unifiedrole.NewFileEditorUnifiedRole(true), unifiedrole.UnifiedRoleConditionGrantee), - Entry(rConversions.RoleCoowner, rConversions.NewCoownerRole(), unifiedrole.NewCoownerUnifiedRole(), unifiedrole.UnifiedRoleConditionGrantee), - Entry(rConversions.RoleManager, rConversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole(), unifiedrole.UnifiedRoleConditionGrantee), + Entry(rConversions.RoleCoowner, rConversions.NewCoownerRole(), unifiedrole.NewCoownerUnifiedRole(), unifiedrole.UnifiedRoleConditionOwner), Entry(rConversions.RoleManager, rConversions.NewManagerRole(), unifiedrole.NewManagerUnifiedRole(), unifiedrole.UnifiedRoleConditionOwner), Entry(rConversions.RoleSpaceViewer, rConversions.NewSpaceViewerRole(), unifiedrole.NewSpaceViewerUnifiedRole(), unifiedrole.UnifiedRoleConditionOwner), Entry(rConversions.RoleSpaceEditor, rConversions.NewSpaceEditorRole(), unifiedrole.NewSpaceEditorUnifiedRole(), unifiedrole.UnifiedRoleConditionOwner), @@ -208,6 +207,17 @@ var _ = Describe("unifiedroles", func() { unifiedrole.NewViewerUnifiedRole(false), unifiedrole.NewFileEditorUnifiedRole(false), unifiedrole.NewEditorUnifiedRole(false), + }, + ), + + Entry( + "GetBuiltinRoleDefinitionList", + rolesToAction(unifiedrole.GetBuiltinRoleDefinitionList(false)...), + unifiedrole.UnifiedRoleConditionOwner, + false, + []*libregraph.UnifiedRoleDefinition{ + unifiedrole.NewSpaceViewerUnifiedRole(), + unifiedrole.NewSpaceEditorUnifiedRole(), unifiedrole.NewCoownerUnifiedRole(), unifiedrole.NewManagerUnifiedRole(), }, @@ -223,8 +233,6 @@ var _ = Describe("unifiedroles", func() { unifiedrole.NewViewerUnifiedRole(true), unifiedrole.NewFileEditorUnifiedRole(true), unifiedrole.NewEditorUnifiedRole(true), - unifiedrole.NewCoownerUnifiedRole(), - unifiedrole.NewManagerUnifiedRole(), }, ), From c7943f014b485de889812a9a967d31ab4c1c3cb5 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Mon, 22 Jan 2024 17:20:40 +0100 Subject: [PATCH 68/73] graph/sharing: Adjust acceptance tests for latest changes Don't try to assign space specific roles to file or directory shares in positive tests. The API now forbids those correctly. We might want to add negative tests for that. --- ...expected-failures-localAPI-on-OCIS-storage.md | 8 ++++---- .../apiSharingNg/deletePermissions.feature | 8 -------- .../apiSharingNg/shareInvitations.feature | 16 ---------------- 3 files changed, 4 insertions(+), 28 deletions(-) diff --git a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md index 83703bdc47..e4ecfd7021 100644 --- a/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-localAPI-on-OCIS-storage.md @@ -258,10 +258,10 @@ The expected failures in this file are from features in the owncloud/ocis repo. - [apiSharingNg/linkShare.feature:453](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L453) - [apiSharingNg/linkShare.feature:455](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L455) - [apiSharingNg/linkShare.feature:456](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/linkShare.feature#L456) -- [apiSharingNg/deletePermissions.feature:138](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L138) -- [apiSharingNg/deletePermissions.feature:155](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L155) -- [apiSharingNg/deletePermissions.feature:176](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L176) -- [apiSharingNg/deletePermissions.feature:195](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L195) +- [apiSharingNg/deletePermissions.feature:130](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L130) +- [apiSharingNg/deletePermissions.feature:147](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L147) +- [apiSharingNg/deletePermissions.feature:168](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L168) +- [apiSharingNg/deletePermissions.feature:187](https://github.com/owncloud/ocis/blob/master/tests/acceptance/features/apiSharingNg/deletePermissions.feature#L187) ### [sharee (editor role) MOVE a file by file-id into same shared folder returns 403](https://github.com/owncloud/ocis/issues/7617) diff --git a/tests/acceptance/features/apiSharingNg/deletePermissions.feature b/tests/acceptance/features/apiSharingNg/deletePermissions.feature index 83053a6718..222514e4c4 100644 --- a/tests/acceptance/features/apiSharingNg/deletePermissions.feature +++ b/tests/acceptance/features/apiSharingNg/deletePermissions.feature @@ -29,9 +29,7 @@ Feature: Remove access to a drive item | File Editor | file | textfile.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: user removes access to resource inside of a project space in the user share @@ -56,9 +54,7 @@ Feature: Remove access to a drive item | File Editor | file | textfile.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: user removes access to a resource in a group share @@ -84,9 +80,7 @@ Feature: Remove access to a drive item | File Editor | file | textfile.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: user removes access to a resource inside of a project space in group share @@ -114,9 +108,7 @@ Feature: Remove access to a drive item | File Editor | file | textfile.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: user removes access to a folder in link share diff --git a/tests/acceptance/features/apiSharingNg/shareInvitations.feature b/tests/acceptance/features/apiSharingNg/shareInvitations.feature index c670ced7eb..368e34dd9f 100644 --- a/tests/acceptance/features/apiSharingNg/shareInvitations.feature +++ b/tests/acceptance/features/apiSharingNg/shareInvitations.feature @@ -93,9 +93,7 @@ Feature: Send a sharing invitations | File Editor | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: send share invitation to group with different roles @@ -187,9 +185,7 @@ Feature: Send a sharing invitations | File Editor | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: send share invitation for a file to user with different permissions @@ -665,9 +661,7 @@ Feature: Send a sharing invitations | File Editor | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: send share invitation with expiration date to group with different roles @@ -763,9 +757,7 @@ Feature: Send a sharing invitations | File Editor | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | @issue-7962 Scenario Outline: send share invitation to disabled user @@ -848,9 +840,7 @@ Feature: Send a sharing invitations | File Editor | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: send sharing invitation to a deleted group with different roles @@ -909,9 +899,7 @@ Feature: Send a sharing invitations | File Editor | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: send share invitation to deleted user @@ -962,9 +950,7 @@ Feature: Send a sharing invitations | File Editor | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: try to send sharing invitation to multiple groups @@ -1090,9 +1076,7 @@ Feature: Send a sharing invitations | File Editor | file | /textfile1.txt | | Viewer | folder | FolderToShare | | Editor | folder | FolderToShare | - | Co Owner | folder | FolderToShare | | Uploader | folder | FolderToShare | - | Manager | folder | FolderToShare | Scenario Outline: send sharing invitation to non-existing group From da495fd3060d25c4dc851706d4b02e67478ac7e7 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Tue, 23 Jan 2024 17:49:25 +0100 Subject: [PATCH 69/73] graph/sharing: Fix role condition for space roots When computing the allowed roles for a spaceroot use the correct conditions. Spaceroots require '@Subject.objectId Any_of @Resource.owners'. Note: Updating or deleting the permissions on a spaceroot via 'v1beta1/drives/{driveid}/items/{itemid}/permissions/{permissionid}' does still not work. --- .../unreleased/sharing-ng-roleconditions.md | 8 +++++ services/graph/pkg/service/v0/driveitems.go | 32 ++++++++++++------- 2 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 changelog/unreleased/sharing-ng-roleconditions.md diff --git a/changelog/unreleased/sharing-ng-roleconditions.md b/changelog/unreleased/sharing-ng-roleconditions.md new file mode 100644 index 0000000000..efad06c104 --- /dev/null +++ b/changelog/unreleased/sharing-ng-roleconditions.md @@ -0,0 +1,8 @@ +Bugfix: apply role constraints when creating shares via the graph API + +We fixed a bug in the graph API for creating and updating shares so that +Spaceroot specific roles like 'Manager' and 'Co-owner' can no longer be +assigned for shares on files or directories. + +https://github.com/owncloud/ocis/pull/8247 +https://github.com/owncloud/ocis/issues/8131 diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go index 6c40de2a80..ea6fc0ad75 100644 --- a/services/graph/pkg/service/v0/driveitems.go +++ b/services/graph/pkg/service/v0/driveitems.go @@ -378,6 +378,11 @@ func (g Graph) ListPermissions(w http.ResponseWriter, r *http.Request) { return } + condition := unifiedrole.UnifiedRoleConditionGrantee + if IsSpaceRoot(statResponse.GetInfo().GetId()) { + condition = unifiedrole.UnifiedRoleConditionOwner + } + permissionSet := *statResponse.GetInfo().GetPermissionSet() allowedActions := unifiedrole.CS3ResourcePermissionsToLibregraphActions(permissionSet) @@ -386,7 +391,7 @@ func (g Graph) ListPermissions(w http.ResponseWriter, r *http.Request) { LibreGraphPermissionsRolesAllowedValues: conversions.ToValueSlice( unifiedrole.GetApplicableRoleDefinitionsForActions( allowedActions, - unifiedrole.UnifiedRoleConditionGrantee, + condition, g.config.FilesSharing.EnableResharing, false, ), @@ -452,6 +457,18 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { return } + statResponse, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: &itemID}}) + if errCode := errorcode.FromStat(statResponse, err); errCode != nil { + g.logger.Warn().Err(errCode).Interface("stat.res", statResponse).Msg("stat failed") + errCode.Render(w, r) + return + } + + condition := unifiedrole.UnifiedRoleConditionGrantee + if IsSpaceRoot(statResponse.GetInfo().GetId()) { + condition = unifiedrole.UnifiedRoleConditionOwner + } + unifiedRolePermissions := []*libregraph.UnifiedRolePermission{{AllowedResourceActions: driveItemInvite.LibreGraphPermissionsActions}} for _, roleID := range driveItemInvite.GetRoles() { role, err := unifiedrole.NewUnifiedRoleFromID(roleID, g.config.FilesSharing.EnableResharing) @@ -460,8 +477,8 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { errorcode.GeneralException.Render(w, r, http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) return } - // FIXME: When setting permissions on a space, we need to use UnifiedRoleConditionOwner here - allowedResourceActions := unifiedrole.GetAllowedResourceActions(role, unifiedrole.UnifiedRoleConditionGrantee) + + allowedResourceActions := unifiedrole.GetAllowedResourceActions(role, condition) if len(allowedResourceActions) == 0 { errorcode.InvalidRequest.Render(w, r, http.StatusBadRequest, "role not applicable to this resource") return @@ -470,13 +487,6 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { unifiedRolePermissions = append(unifiedRolePermissions, conversions.ToPointerSlice(role.GetRolePermissions())...) } - statResponse, err := gatewayClient.Stat(ctx, &storageprovider.StatRequest{Ref: &storageprovider.Reference{ResourceId: &itemID}}) - if errCode := errorcode.FromStat(statResponse, err); errCode != nil { - g.logger.Warn().Err(errCode).Interface("stat.res", statResponse).Msg("stat failed") - errCode.Render(w, r) - return - } - driveRecipient := driveItemInvite.GetRecipients()[0] objectID := driveRecipient.GetObjectId() @@ -492,7 +502,7 @@ func (g Graph) Invite(w http.ResponseWriter, r *http.Request) { } permission := &libregraph.Permission{} - if role := unifiedrole.CS3ResourcePermissionsToUnifiedRole(*cs3ResourcePermissions, unifiedrole.UnifiedRoleConditionGrantee, g.config.FilesSharing.EnableResharing); role != nil { + if role := unifiedrole.CS3ResourcePermissionsToUnifiedRole(*cs3ResourcePermissions, condition, g.config.FilesSharing.EnableResharing); role != nil { permission.Roles = []string{role.GetId()} } From 19991677be903d82082072aff36e59da790732a5 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 24 Jan 2024 16:03:40 +0000 Subject: [PATCH 70/73] Automated changelog update [skip ci] --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c749f8486..57a761f61b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,7 @@ The following sections list the changes for unreleased. * Bugfix - Graph/sharedWithMe works for shares from project spaces now: [#8233](https://github.com/owncloud/ocis/pull/8233) * Bugfix - Fix PATCH/DELETE status code for drives that don't support them: [#8235](https://github.com/owncloud/ocis/pull/8235) * Bugfix - Fix nats authentication: [#8236](https://github.com/owncloud/ocis/pull/8236) +* Bugfix - Apply role constraints when creating shares via the graph API: [#8247](https://github.com/owncloud/ocis/pull/8247) * Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269) * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) @@ -164,6 +165,15 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/pull/8236 +* Bugfix - Apply role constraints when creating shares via the graph API: [#8247](https://github.com/owncloud/ocis/pull/8247) + + We fixed a bug in the graph API for creating and updating shares so that + Spaceroot specific roles like 'Manager' and 'Co-owner' can no longer be assigned + for shares on files or directories. + + https://github.com/owncloud/ocis/issues/8131 + https://github.com/owncloud/ocis/pull/8247 + * Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269) We fixed the race condition that led to concurrent map access in a publicshare From 46af9cce4096c053a2835300dfc728b2fc9c2c30 Mon Sep 17 00:00:00 2001 From: kobergj Date: Wed, 24 Jan 2024 17:14:19 +0100 Subject: [PATCH 71/73] move nats authentication to natsjsregistry package (#8281) Signed-off-by: jkoberg --- changelog/unreleased/fix-nats-registry.md | 6 ++++ ocis-pkg/natsjsregistry/options.go | 11 ------- ocis-pkg/natsjsregistry/registry.go | 40 +++++++++++++++++------ ocis-pkg/registry/registry.go | 13 +++----- 4 files changed, 40 insertions(+), 30 deletions(-) create mode 100644 changelog/unreleased/fix-nats-registry.md diff --git a/changelog/unreleased/fix-nats-registry.md b/changelog/unreleased/fix-nats-registry.md new file mode 100644 index 0000000000..ba5b29d0e3 --- /dev/null +++ b/changelog/unreleased/fix-nats-registry.md @@ -0,0 +1,6 @@ +Bugfix: Fix nats registry + +The nats registry would behave badly when configuring `nats-js-kv` via envvar. Reason is the way go-micro initializes. +It took 5 developers to find the issue and the fix so the details cannot be shared here. Just accept that it is working now + +https://github.com/owncloud/ocis/pull/8281 diff --git a/ocis-pkg/natsjsregistry/options.go b/ocis-pkg/natsjsregistry/options.go index a6e862a62a..dfcda616a5 100644 --- a/ocis-pkg/natsjsregistry/options.go +++ b/ocis-pkg/natsjsregistry/options.go @@ -10,7 +10,6 @@ import ( type storeOptionsKey struct{} type expiryKey struct{} -type authKey struct{} // StoreOptions sets the options for the underlying store func StoreOptions(opts []store.Option) registry.Option { @@ -31,13 +30,3 @@ func ServiceExpiry(t time.Duration) registry.Option { o.Context = context.WithValue(o.Context, expiryKey{}, t) } } - -// Authenticate sets the username/password for the nats connection -func Authenticate(username, password string) registry.Option { - return func(o *registry.Options) { - if o.Context == nil { - o.Context = context.Background() - } - o.Context = context.WithValue(o.Context, authKey{}, []string{username, password}) - } -} diff --git a/ocis-pkg/natsjsregistry/registry.go b/ocis-pkg/natsjsregistry/registry.go index 857b4e5198..feeac744b9 100644 --- a/ocis-pkg/natsjsregistry/registry.go +++ b/ocis-pkg/natsjsregistry/registry.go @@ -5,6 +5,8 @@ import ( "context" "encoding/json" "errors" + "os" + "strings" "time" natsjskv "github.com/go-micro/plugins/v4/store/nats-js-kv" @@ -14,7 +16,12 @@ import ( "go-micro.dev/v4/util/cmd" ) -var _registryName = "nats-js-kv" +var ( + _registryName = "nats-js-kv" + _registryAddressEnv = "MICRO_REGISTRY_ADDRESS" + _registryUsernameEnv = "MICRO_REGISTRY_AUTH_USERNAME" + _registryPasswordEnv = "MICRO_REGISTRY_AUTH_PASSWORD" +) func init() { cmd.DefaultRegistries[_registryName] = NewRegistry @@ -31,7 +38,7 @@ func NewRegistry(opts ...registry.Option) registry.Registry { exp, _ := options.Context.Value(expiryKey{}).(time.Duration) return &storeregistry{ opts: options, - store: natsjskv.NewStore(append(storeOptions(options), natsjskv.DefaultMemory())...), + store: natsjskv.NewStore(storeOptions(options)...), typ: _registryName, expiry: exp, } @@ -127,18 +134,31 @@ func (n *storeregistry) String() string { func storeOptions(opts registry.Options) []store.Option { storeoptions := []store.Option{ - store.Nodes(opts.Addrs...), store.Database("service-registry"), store.Table("service-registry"), + natsjskv.DefaultMemory(), } + + addr := []string{"127.0.0.1:9233"} + if len(opts.Addrs) > 0 { + addr = opts.Addrs + } else if a := strings.Split(os.Getenv(_registryAddressEnv), ","); len(a) > 0 && a[0] != "" { + addr = a + } + storeoptions = append(storeoptions, store.Nodes(addr...)) + + natsOptions := nats.GetDefaultOptions() + natsOptions.Name = "nats-js-kv-registry" + natsOptions.User, natsOptions.Password = getAuth() + storeoptions = append(storeoptions, natsjskv.NatsOptions(natsOptions)) + if so, ok := opts.Context.Value(storeOptionsKey{}).([]store.Option); ok { storeoptions = append(storeoptions, so...) } - natsOptions := nats.GetDefaultOptions() - natsOptions.Name = "nats-js-kv-registry" - if auth, ok := opts.Context.Value(authKey{}).([]string); ok { - natsOptions.User = auth[0] - natsOptions.Password = auth[1] - } - return append(storeoptions, natsjskv.NatsOptions(natsOptions)) + + return storeoptions +} + +func getAuth() (string, string) { + return os.Getenv(_registryUsernameEnv), os.Getenv(_registryPasswordEnv) } diff --git a/ocis-pkg/registry/registry.go b/ocis-pkg/registry/registry.go index 0b6b3e71f0..1672a1a8e1 100644 --- a/ocis-pkg/registry/registry.go +++ b/ocis-pkg/registry/registry.go @@ -20,10 +20,8 @@ import ( ) const ( - registryEnv = "MICRO_REGISTRY" - registryAddressEnv = "MICRO_REGISTRY_ADDRESS" - registryUsernameEnv = "MICRO_REGISTRY_AUTH_USERNAME" - registryPasswordEnv = "MICRO_REGISTRY_AUTH_PASSWORD" + _registryEnv = "MICRO_REGISTRY" + _registryAddressEnv = "MICRO_REGISTRY_ADDRESS" ) var ( @@ -64,7 +62,6 @@ func GetRegistry(opts ...Option) mRegistry.Registry { case "natsjs", "nats-js", "nats-js-kv": // for backwards compatibility - we will stick with one of those _reg = natsjsregistry.NewRegistry( mRegistry.Addrs(cfg.Addresses...), - natsjsregistry.Authenticate(cfg.Username, cfg.Password), ) case "memory": _reg = memr.NewRegistry() @@ -112,15 +109,13 @@ func getEnvs(opts ...Option) *Config { cfg := &Config{ Type: "nats-js-kv", Addresses: []string{"127.0.0.1:9233"}, - Username: os.Getenv(registryUsernameEnv), - Password: os.Getenv(registryPasswordEnv), } - if s := os.Getenv(registryEnv); s != "" { + if s := os.Getenv(_registryEnv); s != "" { cfg.Type = s } - if s := strings.Split(os.Getenv(registryAddressEnv), ","); len(s) > 0 && s[0] != "" { + if s := strings.Split(os.Getenv(_registryAddressEnv), ","); len(s) > 0 && s[0] != "" { cfg.Addresses = s } From 8c966a81cb0e4177b125117b55cc8da9c1c85933 Mon Sep 17 00:00:00 2001 From: kobergj Date: Wed, 24 Jan 2024 16:15:05 +0000 Subject: [PATCH 72/73] Automated changelog update [skip ci] --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57a761f61b..77349dfafe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ The following sections list the changes for unreleased. * Bugfix - Fix nats authentication: [#8236](https://github.com/owncloud/ocis/pull/8236) * Bugfix - Apply role constraints when creating shares via the graph API: [#8247](https://github.com/owncloud/ocis/pull/8247) * Bugfix - Fix concurrent access to a map: [#8269](https://github.com/owncloud/ocis/pull/8269) +* Bugfix - Fix nats registry: [#8281](https://github.com/owncloud/ocis/pull/8281) * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) * Enhancement - Update antivirus service: [#8062](https://github.com/owncloud/ocis/pull/8062) * Enhancement - Remove deprecated environment variables: [#8149](https://github.com/owncloud/ocis/pull/8149) @@ -183,6 +184,15 @@ The following sections list the changes for unreleased. https://github.com/owncloud/ocis/pull/8269 https://github.com/cs3org/reva/pull/4472 +* Bugfix - Fix nats registry: [#8281](https://github.com/owncloud/ocis/pull/8281) + + The nats registry would behave badly when configuring `nats-js-kv` via envvar. + Reason is the way go-micro initializes. It took 5 developers to find the issue + and the fix so the details cannot be shared here. Just accept that it is working + now + + https://github.com/owncloud/ocis/pull/8281 + * Enhancement - Disable the password policy: [#7985](https://github.com/owncloud/ocis/pull/7985) We add the environment variable that allow to disable the password policy. From ee6f155e1c2700ddbfb4552145ee5db0e3faf893 Mon Sep 17 00:00:00 2001 From: Viktor Scharf Date: Wed, 24 Jan 2024 19:25:20 +0100 Subject: [PATCH 73/73] add more CORS tests (#8254) --- tests/TestHelpers/WebDavHelper.php | 4 +- .../acceptance/features/apiCors/cors.feature | 24 ++++++- .../features/bootstrap/SpacesContext.php | 62 +++++++++++++++++-- 3 files changed, 83 insertions(+), 7 deletions(-) diff --git a/tests/TestHelpers/WebDavHelper.php b/tests/TestHelpers/WebDavHelper.php index 651ac67537..728416f893 100644 --- a/tests/TestHelpers/WebDavHelper.php +++ b/tests/TestHelpers/WebDavHelper.php @@ -179,6 +179,7 @@ class WebDavHelper { * @param string|null $type * @param int|null $davPathVersionToUse * @param string|null $doDavRequestAsUser + * @param array|null $headers * * @return ResponseInterface * @throws Exception @@ -194,7 +195,8 @@ class WebDavHelper { ?string $folderDepth = '1', ?string $type = "files", ?int $davPathVersionToUse = self::DAV_VERSION_NEW, - ?string $doDavRequestAsUser = null + ?string $doDavRequestAsUser = null, + ?array $headers = [] ):ResponseInterface { $body = self::getBodyForPropfind($properties); $folderDepth = (string) $folderDepth; diff --git a/tests/acceptance/features/apiCors/cors.feature b/tests/acceptance/features/apiCors/cors.feature index 28131c8a08..6b59cd45f7 100644 --- a/tests/acceptance/features/apiCors/cors.feature +++ b/tests/acceptance/features/apiCors/cors.feature @@ -33,8 +33,8 @@ Feature: CORS headers Scenario Outline: CORS headers should not be returned when CORS domain does not match origin header Given using OCS API version "" When user "Alice" sends HTTP method "GET" to OCS API endpoint "" with headers - | header | value | - | Origin | https://mero.badal | + | header | value | + | Origin | https://mero.badal | Then the OCS status code should be "" And the HTTP status code should be "" And the following headers should not be set @@ -70,3 +70,23 @@ Feature: CORS headers | 2 | | /apps/files_sharing/api/v1/shares | PUT | | 1 | | /apps/files_sharing/api/v1/shares | DELETE | | 2 | | /apps/files_sharing/api/v1/shares | POST | + + + Scenario: CORS headers should be returned when setting CORS domain sending origin header in the Graph api + When user "Alice" lists all available spaces with headers using the Graph API + | header | value | + | Origin | https://aphno.badal | + Then the HTTP status code should be "200" + And the following headers should be set + | header | value | + | Access-Control-Allow-Origin | https://aphno.badal | + + @issue-8231 + Scenario: CORS headers should be returned when setting CORS domain sending origin header in the Webdav api + When user "Alice" sends PROPFIND request to space "Alice Hansen" with headers using the WebDAV API + | header | value | + | Origin | https://aphno.badal | + Then the HTTP status code should be "207" + And the following headers should be set + | header | value | + | Access-Control-Allow-Origin | https://aphno.badal | diff --git a/tests/acceptance/features/bootstrap/SpacesContext.php b/tests/acceptance/features/bootstrap/SpacesContext.php index 1fd4615bab..23107d7fe8 100644 --- a/tests/acceptance/features/bootstrap/SpacesContext.php +++ b/tests/acceptance/features/bootstrap/SpacesContext.php @@ -544,19 +544,22 @@ class SpacesContext implements Context { /** * @param string $user * @param string $query + * @param array $headers * * @return ResponseInterface * * @throws GuzzleException * @throws Exception */ - public function listAllAvailableSpacesOfUser(string $user, string $query = ''): ResponseInterface { + public function listAllAvailableSpacesOfUser(string $user, string $query = '', array $headers = []): ResponseInterface { $response = GraphHelper::getMySpaces( $this->featureContext->getBaseUrl(), $user, $this->featureContext->getPasswordForUser($user), "?" . $query, - $this->featureContext->getStepLineRef() + $this->featureContext->getStepLineRef(), + [], + $headers ); $this->rememberTheAvailableSpaces($response); return $response; @@ -578,6 +581,28 @@ class SpacesContext implements Context { $this->featureContext->setResponse($this->listAllAvailableSpacesOfUser($user, $query)); } + /** + * @When /^user "([^"]*)" lists all available spaces with headers using the Graph API$/ + * + * @param string $user + * @param TableNode $headersTable + * + * @return void + * + * @throws GuzzleException + * @throws Exception + */ + public function theUserListsAllHisAvailableSpacesWithHeadersUsingTheGraphApi(string $user, TableNode $headersTable): void { + $this->featureContext->verifyTableNodeColumns( + $headersTable, + ['header', 'value'] + ); + foreach ($headersTable as $row) { + $headers[$row['header']] = $row ['value']; + } + $this->featureContext->setResponse($this->listAllAvailableSpacesOfUser($user, '', $headers)); + } + /** * The method is used on the administration setting tab, which only the Admin user and the Space admin user have access to * @@ -3528,17 +3553,44 @@ class SpacesContext implements Context { ); } + /** + * @When /^user "([^"]*)" sends PROPFIND request to space "([^"]*)" with headers using the WebDAV API$/ + * + * @param string $user + * @param string $spaceName + * @param TableNode $headersTable + * + * @return void + * + * @throws JsonException + * + * @throws GuzzleException + */ + public function userSendsPropfindRequestToSpaceWithHeaders(string $user, string $spaceName, $headersTable): void { + $this->featureContext->verifyTableNodeColumns( + $headersTable, + ['header', 'value'] + ); + foreach ($headersTable as $row) { + $headers[$row['header']] = $row ['value']; + } + $this->featureContext->setResponse( + $this->sendPropfindRequestToSpace($user, $spaceName, '', $headers) + ); + } + /** * @param string $user * @param string $spaceName * @param string|null $resource + * @param array|null $headers * * @return ResponseInterface * @throws GuzzleException * * @throws JsonException */ - public function sendPropfindRequestToSpace(string $user, string $spaceName, ?string $resource = ""): ResponseInterface { + public function sendPropfindRequestToSpace(string $user, string $spaceName, ?string $resource = "", ?array $headers = []): ResponseInterface { $this->setSpaceIDByName($user, $spaceName); $properties = ['oc:permissions','oc:file-parent','oc:fileid','oc:share-types','oc:privatelink','d:resourcetype','oc:size','oc:name','d:getcontenttype','oc:tags','d:lockdiscovery','d:activelock']; return WebDavHelper::propfind( @@ -3550,7 +3602,9 @@ class SpacesContext implements Context { $this->featureContext->getStepLineRef(), "0", "files", - WebDavHelper::DAV_VERSION_SPACES + WebDavHelper::DAV_VERSION_SPACES, + "", + $headers ); }