Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions artifactory/commands/container/dockerfileutils/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func newDockerfileParser() *dockerfileParser {
// - FROM --platform=linux/amd64 ubuntu:20.04
// - FROM --platform=linux/amd64 ubuntu:20.04 AS builder
// - FROM builder (skipped - references previous stage)
func ParseDockerfileBaseImages(dockerfilePath string) ([]ocicontainer.BaseImage, error) {
func ParseDockerfileBaseImages(dockerfilePath string) ([]ocicontainer.DockerImage, error) {
file, err := os.Open(dockerfilePath)
if err != nil {
return nil, err
Expand Down Expand Up @@ -103,8 +103,8 @@ func readDockerfileLines(file *os.File) ([]string, error) {
}

// extractBaseImages processes all lines and extracts base images from FROM instructions
func (p *dockerfileParser) extractBaseImages(lines []string) []ocicontainer.BaseImage {
var baseImages []ocicontainer.BaseImage
func (p *dockerfileParser) extractBaseImages(lines []string) []ocicontainer.DockerImage {
var baseImages []ocicontainer.DockerImage

for _, line := range lines {
if !isFromInstruction(line) {
Expand All @@ -130,7 +130,7 @@ func (p *dockerfileParser) extractBaseImages(lines []string) []ocicontainer.Base
}

p.seenImages[fromInfo.image] = true
baseImages = append(baseImages, ocicontainer.BaseImage{
baseImages = append(baseImages, ocicontainer.DockerImage{
Image: fromInfo.image,
OS: fromInfo.os,
Architecture: fromInfo.arch,
Expand Down
8 changes: 7 additions & 1 deletion artifactory/commands/container/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/jfrog/jfrog-cli-core/v2/common/build"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"github.com/jfrog/jfrog-client-go/utils/log"
)

type PullCommand struct {
Expand Down Expand Up @@ -76,7 +77,12 @@ func (pc *PullCommand) Run() error {
if err != nil || buildInfoModule == nil {
return err
}
return build.SaveBuildInfo(buildName, buildNumber, project, buildInfoModule)
err = build.SaveBuildInfo(buildName, buildNumber, project, buildInfoModule)
if err != nil {
return err
}
log.Info("Successfully Saved build info for " + buildName + "/" + buildNumber)
return nil
}

func (pc *PullCommand) CommandName() string {
Expand Down
88 changes: 88 additions & 0 deletions artifactory/commands/ocicontainer/docker_artifacts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package ocicontainer

import (
"fmt"
"github.com/jfrog/jfrog-client-go/artifactory"

buildinfo "github.com/jfrog/build-info-go/entities"
"github.com/jfrog/jfrog-client-go/artifactory/services/utils"
"github.com/jfrog/jfrog-client-go/utils/log"
)

type DockerArtifactsBuilder struct {
serviceManager artifactory.ArtifactoryServicesManager
isImagePushed bool
imageTag string
repositoryDetails *DockerRepositoryDetails
}

// NewDockerArtifactsBuilder creates a new builder for docker build command
func NewDockerArtifactsBuilder(serviceManager artifactory.ArtifactoryServicesManager, imageTag string, isImagePushed bool) *DockerArtifactsBuilder {
return &DockerArtifactsBuilder{
serviceManager: serviceManager,
isImagePushed: isImagePushed,
imageTag: imageTag,
}
}

// getArtifacts collects artifacts for the pushed image
func (dab *DockerArtifactsBuilder) getArtifacts() (artifacts []buildinfo.Artifact, leadSha string, resultsToApplyProps []utils.ResultItem, err error) {
var resultItems []utils.ResultItem
if dab.isImagePushed {
leadSha, resultItems, resultsToApplyProps, err = dab.collectDetailsForPushedImage(dab.imageTag)
if err != nil {
return artifacts, leadSha, resultsToApplyProps, err
}
artifacts = dab.createArtifactsFromResults(resultItems)
}
return artifacts, leadSha, resultsToApplyProps, err
}

// collectDetailsForPushedImage collects layer details for a pushed image
func (dab *DockerArtifactsBuilder) collectDetailsForPushedImage(imageRef string) (string, []utils.ResultItem, []utils.ResultItem, error) {
log.Debug(fmt.Sprintf("Building artifacts for the pushed image %s", dab.imageTag))
remoteRepo, dockerManifestType, leadSha, err := GetRemoteRepoAndManifestTypeWithLeadSha(imageRef, dab.serviceManager)
if err != nil {
return "", []utils.ResultItem{}, []utils.ResultItem{}, err
}
searchableRepository, repositoryDetails, err := GetSearchableRepositoryAndDetails(remoteRepo, dab.serviceManager)
if err != nil {
return "", []utils.ResultItem{}, []utils.ResultItem{}, err
}
dab.repositoryDetails = repositoryDetails
layers, resultsToApplyProps, err := NewDockerManifestHandler(dab.serviceManager).FetchLayersOfPushedImage(imageRef, searchableRepository, dockerManifestType)
log.Debug(fmt.Sprintf("Collected %d layers, %d folders for props", len(layers), len(resultsToApplyProps)))
return leadSha, layers, resultsToApplyProps, err
}

// createArtifactsFromResults converts search results to artifacts
func (dab *DockerArtifactsBuilder) createArtifactsFromResults(results []utils.ResultItem) []buildinfo.Artifact {
deduplicated := deduplicateResultsBySha256(results)
artifacts := make([]buildinfo.Artifact, 0, len(deduplicated))
for _, result := range deduplicated {
artifacts = append(artifacts, result.ToArtifact())
}
return artifacts
}

// GetPushedRepo returns the repository where the image was pushed
func (dab *DockerArtifactsBuilder) GetPushedRepo() string {
if dab.repositoryDetails == nil {
return ""
}
if dab.repositoryDetails.RepoType == "virtual" {
return dab.repositoryDetails.DefaultDeploymentRepo
}
return dab.repositoryDetails.Key
}

// filterLayersFromVirtualRepo filters layers to only include those from the pushed repository
func filterLayersFromVirtualRepo(items []utils.ResultItem, pushedRepo string) []utils.ResultItem {
filteredLayers := make([]utils.ResultItem, 0, len(items))
for _, item := range items {
if item.Repo == pushedRepo {
filteredLayers = append(filteredLayers, item)
}
}
return filteredLayers
}
53 changes: 26 additions & 27 deletions artifactory/commands/ocicontainer/docker_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,34 @@

// DockerBuildInfoBuilder is a simplified builder for docker build command
type DockerBuildInfoBuilder struct {
buildName string
buildNumber string
project string
module string
serviceManager artifactory.ArtifactoryServicesManager
imageTag string
baseImages []BaseImage
isImagePushed bool
cmdArgs []string
repositoryDetails dockerRepositoryDetails
searchableLayerForApplyingProps []utils.ResultItem
buildName string
buildNumber string
project string
module string
serviceManager artifactory.ArtifactoryServicesManager
imageTag string
baseImages []DockerImage
isImagePushed bool
cmdArgs []string
repositoryDetails DockerRepositoryDetails

Check failure on line 29 in artifactory/commands/ocicontainer/docker_build.go

View workflow job for this annotation

GitHub Actions / Static Check ubuntu-latest

field repositoryDetails is unused (unused)
}

type dockerRepositoryDetails struct {
type DockerRepositoryDetails struct {
Key string `json:"key"`
RepoType string `json:"rclass"`
DefaultDeploymentRepo string `json:"defaultDeploymentRepo"`
}

type BaseImage struct {
Image string
OS string
Architecture string
}

type manifestType string
type ManifestType string

const (
ManifestList manifestType = "list.manifest.json"
Manifest manifestType = "manifest.json"
ManifestList ManifestType = "list.manifest.json"
Manifest ManifestType = "manifest.json"
)

// NewDockerBuildInfoBuilder creates a new builder for docker build command
func NewDockerBuildInfoBuilder(buildName, buildNumber, project string, module string, serviceManager artifactory.ArtifactoryServicesManager,
imageTag string, baseImages []BaseImage, isImagePushed bool, cmdArgs []string) *DockerBuildInfoBuilder {
imageTag string, baseImages []DockerImage, isImagePushed bool, cmdArgs []string) *DockerBuildInfoBuilder {

biImage := NewImage(imageTag)

Expand Down Expand Up @@ -79,21 +72,23 @@

// Build orchestrates the collection of dependencies and artifacts for the docker build
func (dbib *DockerBuildInfoBuilder) Build() error {
log.Debug(fmt.Sprintf("Starting docker build-info collection for %s/%s", dbib.buildName, dbib.buildNumber))
if err := build.SaveBuildGeneralDetails(dbib.buildName, dbib.buildNumber, dbib.project); err != nil {
return err
}

dependencies, err := dbib.getDependencies()
dependencies, err := NewDockerDependenciesBuilder(dbib.baseImages, dbib.serviceManager).getDependencies()
if err != nil {
log.Warn(fmt.Sprintf("Failed to get dependencies for '%s'. Error: %v", dbib.buildName, err))
}

artifacts, leadSha, err := dbib.getArtifacts()
artifactBuilder := NewDockerArtifactsBuilder(dbib.serviceManager, dbib.imageTag, dbib.isImagePushed)
artifacts, leadSha, resultsToApplyProps, err := artifactBuilder.getArtifacts()
if err != nil {
log.Warn(fmt.Sprintf("Failed to get artifacts for '%s'. Error: %v", dbib.buildName, err))
}

err = dbib.applyBuildProps(dbib.searchableLayerForApplyingProps)
err = dbib.applyBuildProps(resultsToApplyProps, artifactBuilder.GetPushedRepo())
if err != nil {
log.Warn(fmt.Sprintf("Failed to apply build prop. Error: %v", err))
}
Expand All @@ -108,6 +103,7 @@
Artifacts: artifacts,
}}}

log.Debug(fmt.Sprintf("Saving build info for %s/%s", dbib.buildName, dbib.buildNumber))
if err = build.SaveBuildInfo(dbib.buildName, dbib.buildNumber, dbib.project, buildInfo); err != nil {
return errorutils.CheckErrorf("failed to save build info for '%s/%s': %s", dbib.buildName, dbib.buildNumber, err.Error())
}
Expand All @@ -116,12 +112,15 @@
}

// applyBuildProps applies build properties to the artifacts
func (dbib *DockerBuildInfoBuilder) applyBuildProps(items []utils.ResultItem) (err error) {
func (dbib *DockerBuildInfoBuilder) applyBuildProps(items []utils.ResultItem, pushedRepo string) (err error) {
props, err := build.CreateBuildProperties(dbib.buildName, dbib.buildNumber, dbib.project)
if err != nil {
return
}
pushedRepo := dbib.getPushedRepo()
if pushedRepo == "" {
log.Warn("Pushed repository is empty, skipping applying build properties.")
return nil
}
filteredLayers := filterLayersFromVirtualRepo(items, pushedRepo)
if len(filteredLayers) == 0 {
log.Debug(fmt.Sprintf("Filtered layers length is 0 after filtering with pushedRepo: %s, All layers: %v", pushedRepo, items))
Expand Down
66 changes: 0 additions & 66 deletions artifactory/commands/ocicontainer/docker_build_artifacts.go

This file was deleted.

Loading
Loading