drone/registry/app/api/controller/metadata/base.go
Manjunatha EN a73113f8e6 fix: [AH-771]: gitness unit test refactoring (#3589)
* fix merge conflicts
* fix merge conflicts
* fix review comment
* fix review comment
* fix review comment
* fix: [AH-771]: gitness unit test refactoring
* fix: [AH-771]: resolved review comments
* fix: [AH-771]: resolved review comments
* fix: [AH-771] Registry test refactoring and improvements

- Refactored registry metadata test implementations
- Improved code organization and readability
- Fixed line length issues in test files
- Removed unused fields from request.go
- Added proper license headers
- Fixed linting issues in mock files
- Simplified test setup and assertions
- Updated wire generation for cmd package
- Added nolint:exhaustive directive for package type switch

fix: [AH-771] Registry test refactoring and improvements

- Refactored registry metadata test implementations
- Improved code organization and readability
- Fixed line length issues in test files
- Removed unused fields from request.go
- Added proper license headers
- Fixed linting issues in mock files
- Simplifi
2025-04-22 14:49:24 +00:00

412 lines
12 KiB
Go

// Copyright 2023 Harness, Inc.
//
// 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 metadata
import (
"context"
"encoding/json"
"fmt"
"math"
"strconv"
"strings"
api "github.com/harness/gitness/registry/app/api/openapi/contracts/artifact"
storagedriver "github.com/harness/gitness/registry/app/driver"
"github.com/harness/gitness/registry/app/pkg/commons"
"github.com/harness/gitness/registry/app/storage"
"github.com/harness/gitness/registry/types"
gitnessenum "github.com/harness/gitness/types/enum"
digest "github.com/opencontainers/go-digest"
"github.com/rs/zerolog/log"
)
const MediaTypeImageConfig = "application/vnd.docker.container.image.v1+json"
var _ api.StrictServerInterface = (*APIController)(nil)
type RegistryRequestInfo struct {
*types.RegistryRequestBaseInfo
packageTypes []string
sortByField string
sortByOrder string
offset int
limit int
pageNumber int64
searchTerm string
labels []string
registryIDs []string
recursive bool
}
type RegistryRequestParams struct {
packageTypesParam *api.PackageTypeParam
page *api.PageNumber
size *api.PageSize
search *api.SearchTerm
Resource string
ParentRef string
RegRef string
labelsParam *api.LabelsParam
sortOrder *api.SortOrder
sortField *api.SortField
registryIDsParam *api.RegistryIdentifierParam
recursive bool
}
type ArtifactFilesRequestInfo struct {
*types.RegistryRequestBaseInfo
sortByField string
sortByOrder string
offset int
limit int
pageNumber int64
searchTerm string
}
func (c *APIController) GetRegistryRequestInfo(
ctx context.Context,
registryRequestParams RegistryRequestParams,
) (*RegistryRequestInfo, error) {
packageTypes := []string{}
if registryRequestParams.packageTypesParam != nil {
packageTypes = *registryRequestParams.packageTypesParam
}
registryIDs := []string{}
if registryRequestParams.registryIDsParam != nil {
registryIDs = *registryRequestParams.registryIDsParam
}
sortByField := ""
sortByOrder := ""
if registryRequestParams.sortOrder != nil {
sortByOrder = string(*registryRequestParams.sortOrder)
}
if registryRequestParams.sortField != nil {
sortByField = string(*registryRequestParams.sortField)
}
labels := []string{}
if registryRequestParams.labelsParam != nil {
labels = *registryRequestParams.labelsParam
}
sortByField = GetSortByField(sortByField, registryRequestParams.Resource)
sortByOrder = GetSortByOrder(sortByOrder)
offset := GetOffset(registryRequestParams.size, registryRequestParams.page)
limit := GetPageLimit(registryRequestParams.size)
pageNumber := GetPageNumber(registryRequestParams.page)
searchTerm := ""
if registryRequestParams.search != nil {
searchTerm = string(*registryRequestParams.search)
}
baseInfo, err := c.RegistryMetadataHelper.GetRegistryRequestBaseInfo(ctx, registryRequestParams.ParentRef,
registryRequestParams.RegRef)
if err != nil {
return nil, err
}
return &RegistryRequestInfo{
RegistryRequestBaseInfo: baseInfo,
packageTypes: packageTypes,
sortByField: sortByField,
sortByOrder: sortByOrder,
offset: offset,
limit: limit,
pageNumber: pageNumber,
searchTerm: searchTerm,
labels: labels,
registryIDs: registryIDs,
recursive: registryRequestParams.recursive,
}, nil
}
func getManifestConfig(
ctx context.Context,
digest digest.Digest,
rootRef string,
driver storagedriver.StorageDriver,
) (*manifestConfig, error) {
var config manifestConfig
path, err := storage.PathFn(strings.ToLower(rootRef), digest)
if err != nil {
return nil, fmt.Errorf("failed to get path: %w", err)
}
content, err := driver.GetContent(ctx, path)
if err != nil {
return nil, fmt.Errorf("failed to get content for image config: %w", err)
}
if err := json.Unmarshal(content, &config); err != nil {
return nil, fmt.Errorf("failed to unmarshal manifest config: %w", err)
}
return &config, nil
}
func (c *APIController) setUpstreamProxyIDs(
ctx context.Context,
registry *types.Registry,
dto api.RegistryRequest,
parentID int64,
) error {
if dto.Config.Type != api.RegistryTypeVIRTUAL {
return fmt.Errorf("invalid call to set upstream proxy ids for parentID: %d", parentID)
}
virtualConfig, err := dto.Config.AsVirtualConfig()
if err != nil {
return fmt.Errorf("failed to get virtualConfig: %w", err)
}
if nil == virtualConfig.UpstreamProxies || commons.IsEmpty(*(virtualConfig.UpstreamProxies)) {
log.Ctx(ctx).Debug().Msgf("Nothing to do for registryRequest: %s", dto.Identifier)
return nil
}
repos, err := c.RegistryRepository.GetAll(
ctx,
parentID,
[]string{string(registry.PackageType)},
"id",
"",
math.MaxInt,
0,
"",
string(api.RegistryTypeUPSTREAM),
true,
)
if repos == nil || err != nil {
err := fmt.Errorf("no repositories found for parentID: %d", parentID)
log.Ctx(ctx).Debug().Err(err).Msg("Failed to fetch repositories")
return err
}
var upstreamProxies []int64
for _, proxy := range *virtualConfig.UpstreamProxies {
for _, repo := range *repos {
if repo.RegIdentifier == proxy {
regID, err := strconv.ParseInt(repo.RegID, 10, 64)
if err != nil {
continue
}
upstreamProxies = append(upstreamProxies, regID)
}
}
}
registry.UpstreamProxies = upstreamProxies
return nil
}
func (c *APIController) getUpstreamProxyKeys(ctx context.Context, ids []int64) []string {
repoKeys, _ := c.RegistryRepository.FetchUpstreamProxyKeys(ctx, ids)
return repoKeys
}
type manifestConfig struct {
CreatedAt *string `json:"created,omitempty"`
Digest string `json:"digest,omitempty"`
History []historyEntry `json:"history"`
ModifiedAt *string `json:"modified,omitempty"`
Os string `json:"os"`
Arch string `json:"architecture,omitempty"`
RootFS rootFS `json:"rootfs,omitempty"`
}
type historyEntry struct {
Created string `json:"created"`
CreatedBy string `json:"created_by"`
EmptyLayer bool `json:"empty_layer"`
Comment string `json:"comment,omitempty"`
}
type rootFS struct {
RootFsType string `json:"type"`
DiffIDs []string `json:"diff_ids"`
}
func getRepoEntityFields(dto api.RegistryRequest) ([]string, []string, string, []string) {
allowedPattern := []string{}
if dto.AllowedPattern != nil {
allowedPattern = *dto.AllowedPattern
}
blockedPattern := []string{}
if dto.BlockedPattern != nil {
blockedPattern = *dto.BlockedPattern
}
description := ""
if dto.Description != nil {
description = *dto.Description
}
labels := []string{}
if dto.Labels != nil {
labels = *dto.Labels
}
return allowedPattern, blockedPattern, description, labels
}
func CreateVirtualRepositoryResponse(
registry *types.Registry,
upstreamProxyKeys []string,
cleanupPolicies *[]types.CleanupPolicy,
registryURL string,
) *api.RegistryResponseJSONResponse {
createdAt := GetTimeInMs(registry.CreatedAt)
modifiedAt := GetTimeInMs(registry.UpdatedAt)
allowedPattern := registry.AllowedPattern
blockedPattern := registry.BlockedPattern
labels := registry.Labels
config := api.RegistryConfig{}
_ = config.FromVirtualConfig(api.VirtualConfig{UpstreamProxies: &upstreamProxyKeys})
response := &api.RegistryResponseJSONResponse{
Data: api.Registry{
Identifier: registry.Name,
Description: &registry.Description,
Url: registryURL,
PackageType: registry.PackageType,
AllowedPattern: &allowedPattern,
BlockedPattern: &blockedPattern,
CreatedAt: &createdAt,
ModifiedAt: &modifiedAt,
CleanupPolicy: CreateCleanupPolicyResponse(cleanupPolicies),
Config: &config,
Labels: &labels,
},
Status: api.StatusSUCCESS,
}
return response
}
func CreateUpstreamProxyResponseJSONResponse(upstreamproxy *types.UpstreamProxy) *api.RegistryResponseJSONResponse {
createdAt := GetTimeInMs(upstreamproxy.CreatedAt)
modifiedAt := GetTimeInMs(upstreamproxy.UpdatedAt)
allowedPattern := upstreamproxy.AllowedPattern
blockedPattern := upstreamproxy.BlockedPattern
configAuth := &api.UpstreamConfig_Auth{}
if api.AuthType(upstreamproxy.RepoAuthType) == api.AuthTypeUserPassword {
auth := api.UserPassword{}
auth.UserName = upstreamproxy.UserName
auth.SecretIdentifier = &upstreamproxy.SecretIdentifier
auth.SecretSpacePath = &upstreamproxy.SecretSpacePath
_ = configAuth.FromUserPassword(auth)
} else if api.AuthType(upstreamproxy.RepoAuthType) == api.AuthTypeAccessKeySecretKey {
auth := api.AccessKeySecretKey{}
auth.AccessKey = &upstreamproxy.UserName
auth.AccessKeySecretIdentifier = &upstreamproxy.UserNameSecretIdentifier
auth.AccessKeySecretSpacePath = &upstreamproxy.UserNameSecretSpacePath
auth.SecretKeyIdentifier = upstreamproxy.SecretIdentifier
auth.SecretKeySpacePath = &upstreamproxy.SecretSpacePath
err := configAuth.FromAccessKeySecretKey(auth)
if err != nil {
log.Warn().Msgf("error in converting auth config to access and secret key: %v", err)
return &api.RegistryResponseJSONResponse{}
}
}
source := api.UpstreamConfigSource(upstreamproxy.Source)
config := api.UpstreamConfig{
AuthType: api.AuthType(upstreamproxy.RepoAuthType),
Auth: configAuth,
Source: &source,
Url: &upstreamproxy.RepoURL,
}
registryConfig := &api.RegistryConfig{}
_ = registryConfig.FromUpstreamConfig(config)
response := &api.RegistryResponseJSONResponse{
Data: api.Registry{
Identifier: upstreamproxy.RepoKey,
PackageType: upstreamproxy.PackageType,
Url: upstreamproxy.RepoURL,
AllowedPattern: &allowedPattern,
BlockedPattern: &blockedPattern,
CreatedAt: &createdAt,
ModifiedAt: &modifiedAt,
Config: registryConfig,
},
Status: api.StatusSUCCESS,
}
return response
}
// deduplicateTriggers de-duplicates the triggers provided by the user.
func deduplicateTriggers(in []gitnessenum.WebhookTrigger) []gitnessenum.WebhookTrigger {
if len(in) == 0 {
return []gitnessenum.WebhookTrigger{}
}
triggerSet := make(map[gitnessenum.WebhookTrigger]bool, len(in))
out := make([]gitnessenum.WebhookTrigger, 0, len(in))
for _, trigger := range in {
if triggerSet[trigger] {
continue
}
triggerSet[trigger] = true
out = append(out, trigger)
}
return out
}
func (c *APIController) GetArtifactFilesRequestInfo(
ctx context.Context,
r api.GetArtifactFilesRequestObject,
) (*ArtifactFilesRequestInfo, error) {
sortByField := ""
sortByOrder := ""
if r.Params.SortOrder != nil {
sortByOrder = string(*r.Params.SortOrder)
}
if r.Params.SortField != nil {
sortByField = string(*r.Params.SortField)
}
sortByField = GetSortByField(sortByField, ArtifactFilesResource)
sortByOrder = GetSortByOrder(sortByOrder)
offset := GetOffset(r.Params.Size, r.Params.Page)
limit := GetPageLimit(r.Params.Size)
pageNumber := GetPageNumber(r.Params.Page)
searchTerm := ""
if r.Params.SearchTerm != nil {
searchTerm = string(*r.Params.SearchTerm)
}
baseInfo, err := c.RegistryMetadataHelper.GetRegistryRequestBaseInfo(ctx, "", string(r.RegistryRef))
if err != nil {
return nil, err
}
return &ArtifactFilesRequestInfo{
RegistryRequestBaseInfo: baseInfo,
sortByField: sortByField,
sortByOrder: sortByOrder,
offset: offset,
limit: limit,
pageNumber: pageNumber,
searchTerm: searchTerm,
}, nil
}