Use single OCI layer selector flag
Signed-off-by: Dan Meier <me.daniel.meier@gmail.com> Assisted-by: Codex/gpt-5
This commit is contained in:
committed by
Matheus Pimenta
parent
efc030ffe4
commit
5df79510e2
@@ -53,6 +53,12 @@ var createSourceOCIRepositoryCmd = &cobra.Command{
|
|||||||
--verify-provider=cosign \
|
--verify-provider=cosign \
|
||||||
--verify-subject="^https://github.com/stefanprodan/podinfo/.github/workflows/release.yml@refs/tags/6.6.2$" \
|
--verify-subject="^https://github.com/stefanprodan/podinfo/.github/workflows/release.yml@refs/tags/6.6.2$" \
|
||||||
--verify-issuer="^https://token.actions.githubusercontent.com$"
|
--verify-issuer="^https://token.actions.githubusercontent.com$"
|
||||||
|
|
||||||
|
# Create an OCIRepository for a Helm chart layer
|
||||||
|
flux create source oci valkey-cluster \
|
||||||
|
--url=oci://example.com/charts/valkey \
|
||||||
|
--tag=0.11.6 \
|
||||||
|
--layer-selector=application/vnd.cncf.helm.chart.content.v1.tar+gzip:copy
|
||||||
`,
|
`,
|
||||||
RunE: createSourceOCIRepositoryCmdRun,
|
RunE: createSourceOCIRepositoryCmdRun,
|
||||||
}
|
}
|
||||||
@@ -73,6 +79,7 @@ type sourceOCIRepositoryFlags struct {
|
|||||||
ignorePaths []string
|
ignorePaths []string
|
||||||
provider flags.SourceOCIProvider
|
provider flags.SourceOCIProvider
|
||||||
insecure bool
|
insecure bool
|
||||||
|
layerSelector string
|
||||||
}
|
}
|
||||||
|
|
||||||
var sourceOCIRepositoryArgs = newSourceOCIFlags()
|
var sourceOCIRepositoryArgs = newSourceOCIFlags()
|
||||||
@@ -99,6 +106,7 @@ func init() {
|
|||||||
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.verifyOIDCIssuer, "verify-issuer", "", "regular expression to use for the OIDC issuer during signature verification")
|
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.verifyOIDCIssuer, "verify-issuer", "", "regular expression to use for the OIDC issuer during signature verification")
|
||||||
createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)")
|
createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)")
|
||||||
createSourceOCIRepositoryCmd.Flags().BoolVar(&sourceOCIRepositoryArgs.insecure, "insecure", false, "for when connecting to a non-TLS registries over plain HTTP")
|
createSourceOCIRepositoryCmd.Flags().BoolVar(&sourceOCIRepositoryArgs.insecure, "insecure", false, "for when connecting to a non-TLS registries over plain HTTP")
|
||||||
|
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.layerSelector, "layer-selector", "", "the OCI artifact layer selector in the format '<media-type>:<operation>'")
|
||||||
|
|
||||||
createSourceCmd.AddCommand(createSourceOCIRepositoryCmd)
|
createSourceCmd.AddCommand(createSourceOCIRepositoryCmd)
|
||||||
}
|
}
|
||||||
@@ -114,6 +122,11 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("--tag, --tag-semver or --digest is required")
|
return fmt.Errorf("--tag, --tag-semver or --digest is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layerSelector, err := parseLayerSelector(sourceOCIRepositoryArgs.layerSelector)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
sourceLabels, err := parseLabels()
|
sourceLabels, err := parseLabels()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -152,6 +165,7 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
if tag := sourceOCIRepositoryArgs.tag; tag != "" {
|
if tag := sourceOCIRepositoryArgs.tag; tag != "" {
|
||||||
repository.Spec.Reference.Tag = tag
|
repository.Spec.Reference.Tag = tag
|
||||||
}
|
}
|
||||||
|
repository.Spec.LayerSelector = layerSelector
|
||||||
|
|
||||||
if createSourceArgs.fetchTimeout > 0 {
|
if createSourceArgs.fetchTimeout > 0 {
|
||||||
repository.Spec.Timeout = &metav1.Duration{Duration: createSourceArgs.fetchTimeout}
|
repository.Spec.Timeout = &metav1.Duration{Duration: createSourceArgs.fetchTimeout}
|
||||||
@@ -234,6 +248,28 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseLayerSelector(selector string) (*sourcev1.OCILayerSelector, error) {
|
||||||
|
if selector == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaType, operation, found := strings.Cut(selector, ":")
|
||||||
|
if !found || mediaType == "" || operation == "" {
|
||||||
|
return nil, fmt.Errorf("invalid --layer-selector %q: must be in the format '<media-type>:<operation>'", selector)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch operation {
|
||||||
|
case sourcev1.OCILayerExtract, sourcev1.OCILayerCopy:
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid --layer-selector %q: operation must be %q or %q", selector, sourcev1.OCILayerExtract, sourcev1.OCILayerCopy)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &sourcev1.OCILayerSelector{
|
||||||
|
MediaType: mediaType,
|
||||||
|
Operation: operation,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func upsertOCIRepository(ctx context.Context, kubeClient client.Client,
|
func upsertOCIRepository(ctx context.Context, kubeClient client.Client,
|
||||||
ociRepository *sourcev1.OCIRepository) (types.NamespacedName, error) {
|
ociRepository *sourcev1.OCIRepository) (types.NamespacedName, error) {
|
||||||
namespacedName := types.NamespacedName{
|
namespacedName := types.NamespacedName{
|
||||||
|
|||||||
@@ -81,6 +81,21 @@ func TestCreateSourceOCI(t *testing.T) {
|
|||||||
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --verify-provider=cosign --verify-secret-ref=cosign-pub --export",
|
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --verify-provider=cosign --verify-secret-ref=cosign-pub --export",
|
||||||
assertFunc: assertGoldenFile("./testdata/oci/export_with_verify_secret.golden"),
|
assertFunc: assertGoldenFile("./testdata/oci/export_with_verify_secret.golden"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "export manifest with layer selector",
|
||||||
|
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --layer-selector=application/vnd.cncf.helm.chart.content.v1.tar+gzip:copy --export",
|
||||||
|
assertFunc: assertGoldenFile("./testdata/oci/export_with_layer_selector.golden"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid layer selector operation",
|
||||||
|
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --layer-selector=application/vnd.cncf.helm.chart.content.v1.tar+gzip:move --export",
|
||||||
|
assertFunc: assertError("invalid --layer-selector \"application/vnd.cncf.helm.chart.content.v1.tar+gzip:move\": operation must be \"extract\" or \"copy\""),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid layer selector format",
|
||||||
|
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --layer-selector=application/vnd.cncf.helm.chart.content.v1.tar+gzip --export",
|
||||||
|
assertFunc: assertError("invalid --layer-selector \"application/vnd.cncf.helm.chart.content.v1.tar+gzip\": must be in the format '<media-type>:<operation>'"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
apiVersion: source.toolkit.fluxcd.io/v1
|
||||||
|
kind: OCIRepository
|
||||||
|
metadata:
|
||||||
|
name: podinfo
|
||||||
|
namespace: flux-system
|
||||||
|
spec:
|
||||||
|
interval: 10m0s
|
||||||
|
layerSelector:
|
||||||
|
mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
|
||||||
|
operation: copy
|
||||||
|
ref:
|
||||||
|
tag: 6.3.5
|
||||||
|
url: oci://ghcr.io/stefanprodan/manifests/podinfo
|
||||||
Reference in New Issue
Block a user