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