Add `oci://` prefix
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
parent
c9f5af7ddc
commit
ded0c2d78b
|
@ -25,12 +25,16 @@ import (
|
|||
const (
|
||||
// OCIRepositoryKind is the string representation of a OCIRepository.
|
||||
OCIRepositoryKind = "OCIRepository"
|
||||
|
||||
// OCIRepositoryPrefix is the prefix used for OCIRepository URLs.
|
||||
OCIRepositoryPrefix = "oci://"
|
||||
)
|
||||
|
||||
// OCIRepositorySpec defines the desired state of OCIRepository
|
||||
type OCIRepositorySpec struct {
|
||||
// URL is a reference to an OCI artifact repository hosted
|
||||
// on a remote container registry.
|
||||
// +kubebuilder:validation:Pattern="^oci://"
|
||||
// +required
|
||||
URL string `json:"url"`
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ spec:
|
|||
url:
|
||||
description: URL is a reference to an OCI artifact repository hosted
|
||||
on a remote container registry.
|
||||
pattern: ^oci://
|
||||
type: string
|
||||
verify:
|
||||
description: Verification specifies the configuration to verify the
|
||||
|
|
|
@ -4,6 +4,6 @@ metadata:
|
|||
name: ocirepository-sample
|
||||
spec:
|
||||
interval: 1m
|
||||
url: ghcr.io/stefanprodan/manifests/podinfo
|
||||
url: oci://ghcr.io/stefanprodan/manifests/podinfo
|
||||
ref:
|
||||
tag: 6.1.6
|
||||
|
|
|
@ -20,8 +20,10 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
|
@ -363,12 +365,31 @@ func (r *OCIRepositoryReconciler) reconcileSource(ctx context.Context, obj *sour
|
|||
return sreconcile.ResultSuccess, nil
|
||||
}
|
||||
|
||||
// parseRepositoryURL extracts the repository URL.
|
||||
func (r *OCIRepositoryReconciler) parseRepositoryURL(obj *sourcev1.OCIRepository) (string, error) {
|
||||
if !strings.HasPrefix(obj.Spec.URL, sourcev1.OCIRepositoryPrefix) {
|
||||
return "", fmt.Errorf("URL must be in format 'oci://<domain>/<org>/<repo>'")
|
||||
}
|
||||
|
||||
url := strings.TrimPrefix(obj.Spec.URL, sourcev1.OCIRepositoryPrefix)
|
||||
ref, err := name.ParseReference(url)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("'%s' invalid URL: %w", obj.Spec.URL, err)
|
||||
}
|
||||
|
||||
return ref.Context().Name(), nil
|
||||
}
|
||||
|
||||
// getArtifactURL determines which tag or digest should be used and returns the OCI artifact FQN.
|
||||
func (r *OCIRepositoryReconciler) getArtifactURL(ctx context.Context, obj *sourcev1.OCIRepository, keychain authn.Keychain) (string, error) {
|
||||
url := obj.Spec.URL
|
||||
url, err := r.parseRepositoryURL(obj)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if obj.Spec.Reference != nil {
|
||||
if obj.Spec.Reference.Digest != "" {
|
||||
return fmt.Sprintf("%s@%s", obj.Spec.URL, obj.Spec.Reference.Digest), nil
|
||||
return fmt.Sprintf("%s@%s", url, obj.Spec.Reference.Digest), nil
|
||||
}
|
||||
|
||||
if obj.Spec.Reference.SemVer != "" {
|
||||
|
@ -376,11 +397,11 @@ func (r *OCIRepositoryReconciler) getArtifactURL(ctx context.Context, obj *sourc
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s:%s", obj.Spec.URL, tag), nil
|
||||
return fmt.Sprintf("%s:%s", url, tag), nil
|
||||
}
|
||||
|
||||
if obj.Spec.Reference.Tag != "" {
|
||||
return fmt.Sprintf("%s:%s", obj.Spec.URL, obj.Spec.Reference.Tag), nil
|
||||
return fmt.Sprintf("%s:%s", url, obj.Spec.Reference.Tag), nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -239,6 +239,7 @@ func TestOCIRepository_SecretRef(t *testing.T) {
|
|||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
repositoryURL := fmt.Sprintf("%s/podinfo", regServer.registryHost)
|
||||
ociURL := fmt.Sprintf("oci://%s", repositoryURL)
|
||||
|
||||
// Push Test Image
|
||||
err = crane.Push(image, repositoryURL, crane.WithAuth(&authn.Basic{
|
||||
|
@ -260,14 +261,14 @@ func TestOCIRepository_SecretRef(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "private-registry-access-via-secretref",
|
||||
url: repositoryURL,
|
||||
url: ociURL,
|
||||
digest: podinfoImageDigest,
|
||||
includeSecretRef: true,
|
||||
includeServiceAccount: false,
|
||||
},
|
||||
{
|
||||
name: "private-registry-access-via-serviceaccount",
|
||||
url: repositoryURL,
|
||||
url: ociURL,
|
||||
digest: podinfoImageDigest,
|
||||
includeSecretRef: false,
|
||||
includeServiceAccount: true,
|
||||
|
@ -289,7 +290,7 @@ func TestOCIRepository_SecretRef(t *testing.T) {
|
|||
},
|
||||
Type: corev1.SecretTypeDockerConfigJson,
|
||||
StringData: map[string]string{
|
||||
".dockerconfigjson": fmt.Sprintf(`{"auths": {%q: {"username": %q, "password": %q}}}`, tt.url, testRegistryUsername, testRegistryPassword),
|
||||
".dockerconfigjson": fmt.Sprintf(`{"auths": {%q: {"username": %q, "password": %q}}}`, repositoryURL, testRegistryUsername, testRegistryPassword),
|
||||
},
|
||||
}
|
||||
g.Expect(testEnv.CreateAndWait(ctx, secret)).To(Succeed())
|
||||
|
@ -435,6 +436,7 @@ func TestOCIRepository_FailedAuth(t *testing.T) {
|
|||
g.Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
repositoryURL := fmt.Sprintf("%s/podinfo", regServer.registryHost)
|
||||
ociURL := fmt.Sprintf("oci://%s", repositoryURL)
|
||||
|
||||
// Push Test Image
|
||||
err = crane.Push(image, repositoryURL, crane.WithAuth(&authn.Basic{
|
||||
|
@ -458,7 +460,7 @@ func TestOCIRepository_FailedAuth(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "missing-auth",
|
||||
url: repositoryURL,
|
||||
url: ociURL,
|
||||
repoUsername: "",
|
||||
repoPassword: "",
|
||||
digest: podinfoImageDigest,
|
||||
|
@ -467,7 +469,7 @@ func TestOCIRepository_FailedAuth(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "invalid-auth-via-secret",
|
||||
url: repositoryURL,
|
||||
url: ociURL,
|
||||
repoUsername: "InvalidUser",
|
||||
repoPassword: "InvalidPassword",
|
||||
digest: podinfoImageDigest,
|
||||
|
@ -476,7 +478,7 @@ func TestOCIRepository_FailedAuth(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "invalid-auth-via-service-account",
|
||||
url: repositoryURL,
|
||||
url: ociURL,
|
||||
repoUsername: "InvalidUser",
|
||||
repoPassword: "InvalidPassword",
|
||||
digest: podinfoImageDigest,
|
||||
|
@ -500,7 +502,7 @@ func TestOCIRepository_FailedAuth(t *testing.T) {
|
|||
},
|
||||
Type: corev1.SecretTypeDockerConfigJson,
|
||||
StringData: map[string]string{
|
||||
".dockerconfigjson": fmt.Sprintf(`{"auths": {%q: {"username": %q, "password": %q}}}`, tt.url, tt.repoUsername, tt.repoPassword),
|
||||
".dockerconfigjson": fmt.Sprintf(`{"auths": {%q: {"username": %q, "password": %q}}}`, repositoryURL, tt.repoUsername, tt.repoPassword),
|
||||
},
|
||||
}
|
||||
g.Expect(testEnv.CreateAndWait(ctx, secret)).To(Succeed())
|
||||
|
@ -623,7 +625,7 @@ func createPodinfoImageFromTar(tarFileName, tag string, imageServer *httptest.Se
|
|||
}
|
||||
|
||||
return &podinfoImage{
|
||||
url: repositoryURL,
|
||||
url: "oci://" + repositoryURL,
|
||||
tag: tag,
|
||||
digest: podinfoImageDigest,
|
||||
}, nil
|
||||
|
|
Loading…
Reference in New Issue