diff --git a/README.md b/README.md index 77fa32bf..804898f7 100644 --- a/README.md +++ b/README.md @@ -342,6 +342,7 @@ $ falcoctl registry push --type=plugin ghcr.io/falcosecurity/plugins/plugin/clou ``` The type denotes the **artifact** type in this case *plugins*. The `ghcr.io/falcosecurity/plugins/plugin/cloudtrail:0.3.0` is the unique reference that points to the **artifact**. Currently, *falcoctl* supports only two types of artifacts: **plugin** and **rulesfile**. Based on **artifact type** the commands accepts different flags: +* `--add-floating-tags`: add the floating tags for the major and minor versions * `--annotation-source`: set annotation source for the artifact; * `--depends-on`: set an artifact dependency (can be specified multiple times). Example: `--depends-on my-plugin:1.2.3` * `--tag`: additional artifact tag. Can be repeated multiple time diff --git a/cmd/registry/push/push.go b/cmd/registry/push/push.go index 01b56ee2..fa97cf98 100644 --- a/cmd/registry/push/push.go +++ b/cmd/registry/push/push.go @@ -52,6 +52,10 @@ Example - Push artifact "myplugin.tar.gz" of type "plugin" for multiple platform Example - Push artifact "myrulesfile.tar.gz" of type "rulesfile": falcoctl registry push --type rulesfile --version "0.1.2" localhost:5000/myrulesfile:latest myrulesfile.tar.gz +Example - Push artifact "myrulesfile.tar.gz" of type "rulesfile" with floating tags for the major and minor versions (0 and 0.1): + falcoctl registry push --type rulesfile --version "0.1.2" localhost:5000/myrulesfile:latest myrulesfile.tar.gz \ + --add-floating-tags + Example - Push artifact "myrulesfile.tar.gz" of type "rulesfile" to an insecure registry: falcoctl registry push --type rulesfile --version "0.1.2" --plain-http localhost:5000/myrulesfile:latest myrulesfile.tar.gz @@ -192,6 +196,14 @@ func (o *pushOptions) runPush(ctx context.Context, args []string) error { return err } + if o.AutoFloatingTags { + v, err := semver.Parse(o.Version) + if err != nil { + return fmt.Errorf("expected semver for the flag \"--version\": %w", err) + } + o.Tags = append(o.Tags, o.Version, fmt.Sprintf("%v", v.Major), fmt.Sprintf("%v.%v", v.Major, v.Minor)) + } + opts := ocipusher.Options{ ocipusher.WithTags(o.Tags...), ocipusher.WithAnnotationSource(o.AnnotationSource), diff --git a/cmd/registry/push/push_rulesfiles_test.go b/cmd/registry/push/push_rulesfiles_test.go index c7546fe1..a393b55f 100644 --- a/cmd/registry/push/push_rulesfiles_test.go +++ b/cmd/registry/push/push_rulesfiles_test.go @@ -350,6 +350,21 @@ var _ = Describe("pushing rulesfiles", func() { map[string]string{}) }) + When("with add-floating-tags and the required flags", func() { + BeforeEach(func() { + rulesfile = rulesfileyaml + args = []string{registryCmd, pushCmd, fullRepoName, rulesfile, "--config", configFile, "--type", "rulesfile", "--version", version, + "--add-floating-tags", "--plain-http"} + // Set name to the expected one. + artifactNameInConfigLayer = repoName + // The semver tags are expected to be set. + pushedTags = []string{"1.1.1", "1.1", "1"} + }) + AssertSuccesBehaviour([]oci.ArtifactDependency{}, + []oci.ArtifactRequirement{}, + map[string]string{}) + }) + When("with full flags and args but in tar.gz format", func() { BeforeEach(func() { rulesfile = rulesfiletgz diff --git a/cmd/registry/push/push_test.go b/cmd/registry/push/push_test.go index c09d6a84..26f0ff96 100644 --- a/cmd/registry/push/push_test.go +++ b/cmd/registry/push/push_test.go @@ -31,6 +31,7 @@ var registryPushUsage = `Usage: falcoctl registry push hostname/repo[:tag|@digest] file [flags] Flags: + --add-floating-tags add the floating tags for the major and minor versions --annotation-source string set annotation source for the artifact -d, --depends-on stringArray set an artifact dependency (can be specified multiple times). Example: "--depends-on my-plugin:1.2.3" -h, --help help for push @@ -65,6 +66,10 @@ Example - Push artifact "myplugin.tar.gz" of type "plugin" for multiple platform Example - Push artifact "myrulesfile.tar.gz" of type "rulesfile": falcoctl registry push --type rulesfile --version "0.1.2" localhost:5000/myrulesfile:latest myrulesfile.tar.gz +Example - Push artifact "myrulesfile.tar.gz" of type "rulesfile" with floating tags for the major and minor versions (0 and 0.1): + falcoctl registry push --type rulesfile --version "0.1.2" localhost:5000/myrulesfile:latest myrulesfile.tar.gz \ + --add-floating-tags + Example - Push artifact "myrulesfile.tar.gz" of type "rulesfile" to an insecure registry: falcoctl registry push --type rulesfile --version "0.1.2" --plain-http localhost:5000/myrulesfile:latest myrulesfile.tar.gz @@ -85,6 +90,7 @@ Usage: falcoctl registry push hostname/repo[:tag|@digest] file [flags] Flags: + --add-floating-tags add the floating tags for the major and minor versions --annotation-source string set annotation source for the artifact -d, --depends-on stringArray set an artifact dependency (can be specified multiple times). Example: "--depends-on my-plugin:1.2.3" -h, --help help for push @@ -190,6 +196,22 @@ var _ = Describe("push", func() { "registry \"noregistry\": Get \"http://noregistry/v2/\": dial tcp: lookup noregistry") }) + When("wrong semver for --version flag with --add-floating-tags", func() { + BeforeEach(func() { + args = []string{registryCmd, pushCmd, rulesRepo, rulesfiletgz, "--config", configFile, "--type", "rulesfile", + "--version", "notSemVer", "--add-floating-tags", "--plain-http"} + }) + pushAssertFailedBehavior(registryPushUsage, "ERROR expected semver for the flag \"--version\": No Major.Minor.Patch elements found") + }) + + When("invalid character in semver for --version flag with --add-floating-tags", func() { + BeforeEach(func() { + args = []string{registryCmd, pushCmd, rulesRepo, rulesfiletgz, "--config", configFile, "--type", "rulesfile", + "--version", "1.1.a", "--add-floating-tags", "--plain-http"} + }) + pushAssertFailedBehavior(registryPushUsage, "ERROR expected semver for the flag \"--version\": Invalid character(s) found in patch number \"a\"") + }) + When("missing repository", func() { BeforeEach(func() { args = []string{registryCmd, pushCmd, registry, rulesfiletgz, "--config", configFile, "--type", "rulesfile", "--version", "1.1.1", "--plain-http"} diff --git a/pkg/options/artifact.go b/pkg/options/artifact.go index 7ff5a431..e3e4daec 100644 --- a/pkg/options/artifact.go +++ b/pkg/options/artifact.go @@ -35,6 +35,7 @@ type Artifact struct { Dependencies []string Requirements []string Tags []string + AutoFloatingTags bool AnnotationSource string } @@ -64,6 +65,9 @@ func (art *Artifact) AddFlags(cmd *cobra.Command) error { cmd.Flags().StringArrayVarP(&art.Tags, "tag", "t", nil, "additional artifact tag. Can be repeated multiple times") + cmd.Flags().BoolVar(&art.AutoFloatingTags, "add-floating-tags", false, + "add the floating tags for the major and minor versions") + cmd.Flags().Var(&art.ArtifactType, "type", `type of artifact to be pushed. Allowed values: "rulesfile", "plugin", "asset"`) if err := cmd.MarkFlagRequired("type"); err != nil {