-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create package evidence using cli #21
Changes from 19 commits
b67f47b
d9c3eed
bf36c53
d903e1d
fb52301
dcfacf1
709f5be
6b71910
3249c71
afe2025
938356e
e347df1
e3e5049
0fe644d
b83432d
7ada34a
9f56419
cc0320b
00e589c
fe110b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package cli | ||
|
||
import ( | ||
"github.com/jfrog/jfrog-cli-artifactory/evidence" | ||
"github.com/jfrog/jfrog-cli-core/v2/plugins/components" | ||
coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" | ||
"github.com/jfrog/jfrog-client-go/utils/errorutils" | ||
) | ||
|
||
type evidencePackageCommand struct { | ||
ctx *components.Context | ||
execute execCommandFunc | ||
} | ||
|
||
func NewEvidencePackageCommand(ctx *components.Context, execute execCommandFunc) EvidenceCommands { | ||
return &evidencePackageCommand{ | ||
ctx: ctx, | ||
execute: execute, | ||
} | ||
} | ||
|
||
func (epc *evidencePackageCommand) CreateEvidence(ctx *components.Context, serverDetails *coreConfig.ServerDetails) error { | ||
err := epc.validateEvidencePackageContext(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
createCmd := evidence.NewCreateEvidencePackage( | ||
serverDetails, | ||
epc.ctx.GetStringFlagValue(predicate), | ||
epc.ctx.GetStringFlagValue(predicateType), | ||
epc.ctx.GetStringFlagValue(key), | ||
epc.ctx.GetStringFlagValue(KeyAlias), | ||
epc.ctx.GetStringFlagValue(packageName), | ||
epc.ctx.GetStringFlagValue(packageVersion), | ||
epc.ctx.GetStringFlagValue(packageRepoName)) | ||
return epc.execute(createCmd) | ||
} | ||
|
||
func (epc *evidencePackageCommand) validateEvidencePackageContext(ctx *components.Context) error { | ||
if !ctx.IsFlagSet(packageVersion) || assertValueProvided(ctx, packageVersion) != nil { | ||
return errorutils.CheckErrorf("'packageVersion' is a mandatory field for creating a Package evidence: --%s", packageVersion) | ||
} | ||
if !ctx.IsFlagSet(packageRepoName) || assertValueProvided(ctx, packageRepoName) != nil { | ||
return errorutils.CheckErrorf("'packageRepoName' is a mandatory field for creating a Package evidence: --%s", packageRepoName) | ||
} | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,14 +24,17 @@ const ( | |
releaseBundleVersion = "release-bundle-version" | ||
buildName = "build-name" | ||
buildNumber = "build-number" | ||
packageName = "package-name" | ||
packageVersion = "package-version" | ||
packageRepoName = "package-repo-name" | ||
|
||
// Unique evidence flags | ||
predicate = "predicate" | ||
predicateType = "predicate-type" | ||
subjectRepoPath = "subject-repo-path" | ||
subjectSha256 = "subject-sha256" | ||
key = "key" | ||
keyId = "key-name" | ||
KeyAlias = "key-alias" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need to export this constant, can be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
) | ||
|
||
// Flag keys mapped to their corresponding components.Flag definition. | ||
|
@@ -48,13 +51,16 @@ var flagsMap = map[string]components.Flag{ | |
releaseBundleVersion: components.NewStringFlag(releaseBundleVersion, "Release Bundle version.", func(f *components.StringFlag) { f.Mandatory = false }), | ||
buildName: components.NewStringFlag(buildName, "Build name.", func(f *components.StringFlag) { f.Mandatory = false }), | ||
buildNumber: components.NewStringFlag(buildNumber, "Build number.", func(f *components.StringFlag) { f.Mandatory = false }), | ||
packageName: components.NewStringFlag(packageName, "Package name.", func(f *components.StringFlag) { f.Mandatory = false }), | ||
packageVersion: components.NewStringFlag(packageVersion, "Package version.", func(f *components.StringFlag) { f.Mandatory = false }), | ||
packageRepoName: components.NewStringFlag(packageRepoName, "Package repository Name.", func(f *components.StringFlag) { f.Mandatory = false }), | ||
|
||
predicate: components.NewStringFlag(predicate, "Path to the predicate, arbitrary JSON.", func(f *components.StringFlag) { f.Mandatory = true }), | ||
predicateType: components.NewStringFlag(predicateType, "Type of the predicate.", func(f *components.StringFlag) { f.Mandatory = true }), | ||
subjectRepoPath: components.NewStringFlag(subjectRepoPath, "Full path to some subject' location.", func(f *components.StringFlag) { f.Mandatory = false }), | ||
subjectSha256: components.NewStringFlag(subjectSha256, "Subject checksum sha256.", func(f *components.StringFlag) { f.Mandatory = false }), | ||
key: components.NewStringFlag(key, "Path to a private key that will sign the DSSE. Supported keys: 'ecdsa','rsa' and 'ed25519'.", func(f *components.StringFlag) { f.Mandatory = true }), | ||
keyId: components.NewStringFlag(keyId, "KeyId", func(f *components.StringFlag) { f.Mandatory = false }), | ||
KeyAlias: components.NewStringFlag(KeyAlias, "Key alias", func(f *components.StringFlag) { f.Mandatory = false }), | ||
} | ||
|
||
var commandFlags = map[string][]string{ | ||
|
@@ -69,12 +75,15 @@ var commandFlags = map[string][]string{ | |
releaseBundleVersion, | ||
buildName, | ||
buildNumber, | ||
packageName, | ||
packageVersion, | ||
packageRepoName, | ||
predicate, | ||
predicateType, | ||
subjectRepoPath, | ||
subjectSha256, | ||
key, | ||
keyId, | ||
KeyAlias, | ||
}, | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,4 +12,5 @@ var subjectTypes = []string{ | |
subjectRepoPath, | ||
releaseBundle, | ||
buildName, | ||
packageName, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package evidence | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"github.com/jfrog/jfrog-cli-artifactory/evidence/model" | ||
"github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" | ||
"github.com/jfrog/jfrog-cli-core/v2/utils/config" | ||
coreConfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" | ||
"github.com/jfrog/jfrog-client-go/artifactory" | ||
"github.com/jfrog/jfrog-client-go/artifactory/services" | ||
"github.com/jfrog/jfrog-client-go/metadata" | ||
"github.com/jfrog/jfrog-client-go/utils/errorutils" | ||
"github.com/jfrog/jfrog-client-go/utils/log" | ||
) | ||
|
||
const leadArtifactQueryTemplate = `{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why putting a const if you dont use it as const? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i tried to change it, but i think also is not bad to have it private const here since its too long and a bit confusing to have it directly inside the small method. |
||
"query": "{versions(filter: {packageId: \"%s\", name: \"%s\", repositoriesIn: [{name: \"%s\"}]}) { edges { node { repos { name leadFilePath } } } } }" | ||
}` | ||
|
||
type createEvidencePackage struct { | ||
createEvidenceBase | ||
packageName string | ||
packageVersion string | ||
packageRepoName string | ||
} | ||
|
||
func NewCreateEvidencePackage(serverDetails *coreConfig.ServerDetails, predicateFilePath, predicateType, key, keyId, packageName, | ||
packageVersion, packageRepoName string) Command { | ||
return &createEvidencePackage{ | ||
createEvidenceBase: createEvidenceBase{ | ||
serverDetails: serverDetails, | ||
predicateFilePath: predicateFilePath, | ||
predicateType: predicateType, | ||
key: key, | ||
keyId: keyId, | ||
}, | ||
packageName: packageName, | ||
packageVersion: packageVersion, | ||
packageRepoName: packageRepoName, | ||
} | ||
} | ||
|
||
func (c *createEvidencePackage) CommandName() string { | ||
return "create-package-evidence" | ||
} | ||
|
||
func (c *createEvidencePackage) ServerDetails() (*config.ServerDetails, error) { | ||
return c.serverDetails, nil | ||
} | ||
|
||
func (c *createEvidencePackage) Run() error { | ||
artifactoryClient, err := c.createArtifactoryClient() | ||
if err != nil { | ||
log.Error("failed to create Artifactory client", err) | ||
return err | ||
} | ||
metadataClient, err := utils.CreateMetadataServiceManager(c.serverDetails, false) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
packageType, err := c.getPackageType(artifactoryClient) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
leadArtifact, err := c.getPackageVersionLeadArtifact(packageType, metadataClient) | ||
if err != nil { | ||
return err | ||
} | ||
leadArtifactPath := c.buildLeadArtifactPath(leadArtifact) | ||
leadArtifactChecksum, err := c.getFileChecksum(leadArtifactPath, artifactoryClient) | ||
if err != nil { | ||
return err | ||
} | ||
envelope, err := c.createEnvelope(leadArtifactPath, leadArtifactChecksum) | ||
if err != nil { | ||
return err | ||
} | ||
err = c.uploadEvidence(envelope, leadArtifactPath) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (c *createEvidencePackage) getPackageType(artifactoryClient artifactory.ArtifactoryServicesManager) (string, error) { | ||
var request services.RepositoryDetails | ||
err := artifactoryClient.GetRepository(c.packageRepoName, &request) | ||
if err != nil { | ||
return "", errorutils.CheckErrorf("No such package: %s/%s", c.packageRepoName, c.packageVersion) | ||
} | ||
return request.PackageType, nil | ||
} | ||
|
||
func (c *createEvidencePackage) getPackageVersionLeadArtifact(packageType string, metadataClient metadata.Manager) (string, error) { | ||
body, err := metadataClient.GraphqlQuery(c.createQuery(packageType)) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
res := &model.GraphqlResponse{} | ||
err = json.Unmarshal(body, res) | ||
if err != nil { | ||
return "", err | ||
} | ||
if len(res.Data.Versions.Edges) == 0 { | ||
return "", errorutils.CheckErrorf("No such package: %s/%s", c.packageRepoName, c.packageVersion) | ||
} | ||
|
||
// Fetch the leadFilePath based on repoName | ||
for _, repo := range res.Data.Versions.Edges[0].Node.Repos { | ||
if repo.Name == c.packageRepoName { | ||
return repo.LeadFilePath, nil | ||
} | ||
} | ||
return "", errorutils.CheckErrorf("Can't find lead artifact of pacakge: %s/%s", c.packageRepoName, c.packageVersion) | ||
} | ||
|
||
func (c *createEvidencePackage) createQuery(packageType string) []byte { | ||
packageId := packageType + "://" + c.packageName | ||
return []byte(fmt.Sprintf(leadArtifactQueryTemplate, packageId, c.packageVersion, c.packageRepoName)) | ||
} | ||
|
||
func (c *createEvidencePackage) buildLeadArtifactPath(leadArtifact string) string { | ||
return fmt.Sprintf("%s/%s", c.packageRepoName, leadArtifact) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this command, and also in the existing build/release-bundle commands: we should not log the internal names of the variables - having
packageVersion
orpackageRepoName
in the logs is confusing.Instead, we should mention only those names, which a client is supposed to use, for example:
--%s is a mandatory parameter for creating a Package evidence
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done