@@ -2,6 +2,7 @@ package container
22
33import (
44 "encoding/json"
5+ "fmt"
56 "os"
67 "path"
78 "strings"
@@ -91,7 +92,7 @@ func (builder *buildInfoBuilder) getSearchableRepo() string {
9192}
9293
9394// Set build properties on image layers in Artifactory.
94- func setBuildProperties (buildName , buildNumber , project string , imageLayers []utils.ResultItem , serviceManager artifactory.ArtifactoryServicesManager ) (err error ) {
95+ func setBuildProperties (buildName , buildNumber , project string , imageLayers []utils.ResultItem , serviceManager artifactory.ArtifactoryServicesManager , originalRepo string ) (err error ) {
9596 // Skip if no build info is provided
9697 if buildName == "" || buildNumber == "" {
9798 log .Debug ("Skipping setting properties - build name and build number are required" )
@@ -109,7 +110,14 @@ func setBuildProperties(buildName, buildNumber, project string, imageLayers []ut
109110 return nil
110111 }
111112
112- pathToFile , err := writeLayersToFile (imageLayers )
113+ // Filter image layers for virtual repositories to only include layers from default deployment repository
114+ filteredLayers , err := filterLayersForVirtualRepository (imageLayers , serviceManager , originalRepo )
115+ if err != nil {
116+ log .Debug ("Failed to filter layers for virtual repository, proceeding with all layers:" , err .Error ())
117+ filteredLayers = imageLayers
118+ }
119+
120+ pathToFile , err := writeLayersToFile (filteredLayers )
113121 if err != nil {
114122 return
115123 }
@@ -119,6 +127,88 @@ func setBuildProperties(buildName, buildNumber, project string, imageLayers []ut
119127 return
120128}
121129
130+ // filterLayersForVirtualRepository filters image layers to only include those from the default deployment repository
131+ // when dealing with virtual repositories. For non-virtual repositories, it returns all layers unchanged.
132+ func filterLayersForVirtualRepository (imageLayers []utils.ResultItem , serviceManager artifactory.ArtifactoryServicesManager , originalRepo string ) ([]utils.ResultItem , error ) {
133+ if len (imageLayers ) == 0 {
134+ return imageLayers , nil
135+ }
136+
137+ // Check if the original repository is a virtual repository by getting its configuration
138+ repoConfig , err := getRepositoryConfiguration (originalRepo , serviceManager )
139+ if err != nil {
140+ log .Debug ("Failed to get repository configuration for" , originalRepo , ":" , err .Error ())
141+ return imageLayers , err
142+ }
143+
144+ // If it's not a virtual repository, return all layers unchanged
145+ if repoConfig == nil || repoConfig .Rclass != "virtual" {
146+ log .Debug ("Repository" , originalRepo , "is not virtual, proceeding with all layers" )
147+ return imageLayers , nil
148+ }
149+
150+ // If it's a virtual repository but has no default deployment repo, return all layers
151+ if repoConfig .DefaultDeploymentRepo == "" {
152+ log .Debug ("Virtual repository" , originalRepo , "has no default deployment repository, proceeding with all layers" )
153+ return imageLayers , nil
154+ }
155+
156+ // Filter layers to only include those from the default deployment repository
157+ var filteredLayers []utils.ResultItem
158+ for _ , layer := range imageLayers {
159+ if layer .Repo == repoConfig .DefaultDeploymentRepo {
160+ filteredLayers = append (filteredLayers , layer )
161+ }
162+ }
163+
164+ if len (filteredLayers ) > 0 {
165+ log .Debug ("Filtered" , len (imageLayers ), "layers to" , len (filteredLayers ), "layers from default deployment repository:" , repoConfig .DefaultDeploymentRepo )
166+ } else {
167+ log .Debug ("No layers found in default deployment repository" , repoConfig .DefaultDeploymentRepo , ", proceeding with all layers" )
168+ return imageLayers , nil
169+ }
170+
171+ return filteredLayers , nil
172+ }
173+
174+ // repositoryConfig represents the virtual repository configuration
175+ type
176+ struct {
177+ Key string `json :"key "`
178+ Rclass string ` json:"rclass" `
179+ DefaultDeploymentRepo string ` json:"defaultDeploymentRepo" `
180+ }
181+
182+ // getRepositoryConfiguration fetches the repository configuration from Artifactory
183+ func getRepositoryConfiguration(repoKey string, serviceManager artifactory.ArtifactoryServicesManager) (*repositoryConfig, error) {
184+ // Create HTTP client details for the request
185+ httpClientDetails := serviceManager.GetConfig().GetServiceDetails().CreateHttpClientDetails()
186+
187+ // Construct the API endpoint URL
188+ baseUrl := serviceManager.GetConfig().GetServiceDetails().GetUrl()
189+ endpoint := "api/repositories/" + repoKey
190+ url := baseUrl + endpoint
191+
192+ // Make the HTTP GET request
193+ resp, body, _, err := serviceManager.Client().SendGet(url, true, &httpClientDetails)
194+ if err != nil {
195+ return nil, err
196+ }
197+
198+ // Check for successful response
199+ if resp.StatusCode != 200 {
200+ return nil, fmt.Errorf("failed to get repository configuration: HTTP %d", resp.StatusCode)
201+ }
202+
203+ // Parse the JSON response
204+ var config repositoryConfig
205+ if err := json.Unmarshal(body, &config); err != nil {
206+ return nil, fmt.Errorf("failed to parse repository configuration: %v", err)
207+ }
208+
209+ return &config, nil
210+ }
211+
122212// Download the content of layer search result.
123213func downloadLayer(searchResult utils.ResultItem, result interface{}, serviceManager artifactory.ArtifactoryServicesManager, repo string) error {
124214 // Search results may include artifacts from the remote-cache repository.
@@ -340,7 +430,7 @@ func (builder *buildInfoBuilder) createBuildInfo(commandType CommandType, manife
340430 return nil , err
341431 }
342432 if ! builder .skipTaggingLayers {
343- if err := setBuildProperties (builder .buildName , builder .buildNumber , builder .project , builder .imageLayers , builder .serviceManager ); err != nil {
433+ if err := setBuildProperties (builder .buildName , builder .buildNumber , builder .project , builder .imageLayers , builder .serviceManager , builder . repositoryDetails . key ); err != nil {
344434 return nil , err
345435 }
346436 }
@@ -399,7 +489,7 @@ func (builder *buildInfoBuilder) createMultiPlatformBuildInfo(fatManifest *FatMa
399489 Parent : imageLongNameWithoutRepo ,
400490 })
401491 }
402- return buildInfo , setBuildProperties (builder .buildName , builder .buildNumber , builder .project , builder .imageLayers , builder .serviceManager )
492+ return buildInfo , setBuildProperties (builder .buildName , builder .buildNumber , builder .project , builder .imageLayers , builder .serviceManager , builder . repositoryDetails . key )
403493}
404494
405495// Construct the manifest's module ID by its type (attestation) or its platform.
0 commit comments