@@ -34,20 +34,27 @@ import (
3434
3535 "ocm.software/open-component-model/bindings/go/blob"
3636 "ocm.software/open-component-model/bindings/go/blob/filesystem"
37+ filesystemaccess "ocm.software/open-component-model/bindings/go/blob/filesystem/spec/access"
3738 "ocm.software/open-component-model/bindings/go/blob/inmemory"
39+ filesystemv1alpha1 "ocm.software/open-component-model/bindings/go/configuration/filesystem/v1alpha1/spec"
40+ "ocm.software/open-component-model/bindings/go/credentials"
3841 "ocm.software/open-component-model/bindings/go/ctf"
3942 descriptor "ocm.software/open-component-model/bindings/go/descriptor/runtime"
4043 v2 "ocm.software/open-component-model/bindings/go/descriptor/v2"
4144 "ocm.software/open-component-model/bindings/go/oci"
45+ ociinmemory "ocm.software/open-component-model/bindings/go/oci/cache/inmemory"
4246 ocictf "ocm.software/open-component-model/bindings/go/oci/ctf"
4347 "ocm.software/open-component-model/bindings/go/oci/repository/provider"
48+ "ocm.software/open-component-model/bindings/go/oci/repository/resource"
4449 urlresolver "ocm.software/open-component-model/bindings/go/oci/resolver/url"
4550 ocmoci "ocm.software/open-component-model/bindings/go/oci/spec/access"
4651 v1 "ocm.software/open-component-model/bindings/go/oci/spec/access/v1"
4752 "ocm.software/open-component-model/bindings/go/oci/spec/layout"
4853 ctfrepospecv1 "ocm.software/open-component-model/bindings/go/oci/spec/repository/v1/ctf"
4954 ocirepospecv1 "ocm.software/open-component-model/bindings/go/oci/spec/repository/v1/oci"
55+ "ocm.software/open-component-model/bindings/go/oci/spec/transformation/v1alpha1"
5056 "ocm.software/open-component-model/bindings/go/oci/tar"
57+ "ocm.software/open-component-model/bindings/go/oci/transformer"
5158 "ocm.software/open-component-model/bindings/go/repository"
5259 ocmruntime "ocm.software/open-component-model/bindings/go/runtime"
5360)
@@ -422,6 +429,57 @@ func Test_Integration_CTF_Lister(t *testing.T) {
422429 require .Equal (t , expectedList , result )
423430}
424431
432+ // Test_Integration_Transformers needs a different setup than the other tests.
433+ // Reason being that transformer.GetOCIArtifact requires repository.ResourceRepository.
434+ // Since oci.Repository does not implement repository.ResourceRepository yet, we could not reuse the setup with
435+ // urlresolver.Resolver. We will be able to unify the testing setup once we refactored the oci Repositories
436+ // https://github.com/open-component-model/ocm-project/issues/774
437+ func Test_Integration_Transformers (t * testing.T ) {
438+ t .Parallel ()
439+ ctx := t .Context ()
440+
441+ t .Logf ("Starting transformers integration test" )
442+
443+ // Setup credentials and htpasswd
444+ password := generateRandomPassword (t , passwordLength )
445+ htpasswd := generateHtpasswd (t , testUsername , password )
446+
447+ // Start containerized registry
448+ t .Logf ("Launching test registry (%s)..." , distributionRegistryImage )
449+ registryContainer , err := registry .Run (ctx , distributionRegistryImage ,
450+ registry .WithHtpasswd (htpasswd ),
451+ testcontainers .WithEnv (map [string ]string {
452+ "REGISTRY_VALIDATION_DISABLED" : "true" ,
453+ "REGISTRY_LOG_LEVEL" : "debug" ,
454+ }),
455+ testcontainers .WithLogger (log .TestLogger (t )),
456+ )
457+ r := require .New (t )
458+ r .NoError (err )
459+ t .Cleanup (func () {
460+ r .NoError (testcontainers .TerminateContainer (registryContainer ))
461+ })
462+ t .Logf ("Test registry started" )
463+
464+ t .Run ("ociArtifact" , func (t * testing.T ) {
465+ r := require .New (t )
466+ registryAddress , err := registryContainer .HostAddress (ctx )
467+ r .NoError (err )
468+
469+ reference := func (ref string ) string {
470+ return fmt .Sprintf ("%s/%s" , registryAddress , ref )
471+ }
472+
473+ t .Run ("get oci artifact" , func (t * testing.T ) {
474+ resourceRepo := resource .NewResourceRepository (ociinmemory .New (), ociinmemory .New (), & filesystemv1alpha1.Config {})
475+
476+ t .Run ("get oci transformation" , func (t * testing.T ) {
477+ transformGetOCIArtifact (t , resourceRepo , testUsername , password , "ghcr.io/test:v1.0.0" , reference ("new-test:v1.0.0" ))
478+ })
479+ })
480+ })
481+ }
482+
425483func uploadDownloadLocalResourceOCILayout (t * testing.T , repo * oci.Repository , component string , version string ) {
426484 ctx := t .Context ()
427485 r := require .New (t )
@@ -946,3 +1004,98 @@ func getUsername(t *testing.T, gh string) (string, error) {
9461004
9471005 return structured ["login" ].(string ), nil
9481006}
1007+
1008+ func transformGetOCIArtifact (t * testing.T , repo repository.ResourceRepository , username , password , from , to string ) {
1009+ ctx := t .Context ()
1010+ r := require .New (t )
1011+
1012+ url , err := ocmruntime .ParseURLAndAllowNoScheme (to )
1013+ r .NoError (err )
1014+
1015+ toIdentity := ocmruntime.Identity {
1016+ "scheme" : "http" ,
1017+ "hostname" : url .Hostname (),
1018+ "port" : url .Port (),
1019+ "type" : "OCIRepository" ,
1020+ }
1021+
1022+ originalData := []byte ("foobar" )
1023+
1024+ data , access := createSingleLayerOCIImage (t , originalData , from )
1025+ r .NotNil (access )
1026+
1027+ access .Type = ocmruntime.Type {
1028+ Name : "ociArtifact" ,
1029+ Version : "v1" ,
1030+ }
1031+
1032+ blob := inmemory .New (bytes .NewReader (data ))
1033+
1034+ resource := descriptor.Resource {
1035+ ElementMeta : descriptor.ElementMeta {
1036+ ObjectMeta : descriptor.ObjectMeta {
1037+ Name : "test-resource" ,
1038+ Version : "v1.0.0" ,
1039+ },
1040+ },
1041+ Type : "some-arbitrary-type-packed-in-image" ,
1042+ Access : access ,
1043+ CreationTime : descriptor .CreationTime (time .Now ()),
1044+ }
1045+
1046+ targetAccess := resource .Access .DeepCopyTyped ()
1047+ targetAccess .(* v1.OCIImage ).ImageReference = fmt .Sprintf ("http://%s" , to )
1048+ resource .Access = targetAccess
1049+
1050+ credsMap := map [string ]map [string ]string {
1051+ toIdentity .String (): {
1052+ "username" : username ,
1053+ "password" : password ,
1054+ },
1055+ }
1056+ credsResolver := credentials .NewStaticCredentialsResolver (credsMap )
1057+ creds := credsMap [toIdentity .String ()]
1058+ r .NotNil (creds )
1059+
1060+ newRes , err := repo .UploadResource (ctx , & resource , blob , creds )
1061+ r .NoError (err )
1062+ resource = * newRes
1063+
1064+ combinedScheme := ocmruntime .NewScheme ()
1065+ v2 .MustAddToScheme (combinedScheme )
1066+ filesystemaccess .MustAddToScheme (combinedScheme )
1067+ combinedScheme .MustRegisterWithAlias (& v1alpha1.GetOCIArtifact {}, v1alpha1 .GetOCIArtifactV1alpha1 )
1068+
1069+ transform := transformer.GetOCIArtifact {
1070+ Scheme : combinedScheme ,
1071+ Repository : repo ,
1072+ CredentialProvider : credsResolver ,
1073+ }
1074+
1075+ v2Resource , err := descriptor .ConvertToV2Resource (ocmruntime .NewScheme (ocmruntime .WithAllowUnknown ()), newRes )
1076+ r .NoError (err )
1077+
1078+ spec := & v1alpha1.GetOCIArtifact {
1079+ Type : ocmruntime .NewVersionedType (v1alpha1 .GetOCIArtifactType , v1alpha1 .Version ),
1080+ ID : "test-get-oci-transform" ,
1081+ Spec : & v1alpha1.GetOCIArtifactSpec {
1082+ Resource : v2Resource ,
1083+ },
1084+ }
1085+
1086+ // Execute transformation
1087+ result , err := transform .Transform (ctx , spec )
1088+ require .NoError (t , err )
1089+ require .NotNil (t , result )
1090+
1091+ ociOutput , ok := result .(* v1alpha1.GetOCIArtifact )
1092+ require .True (t , ok )
1093+ require .NotNil (t , ociOutput )
1094+
1095+ require .NotNil (t , ociOutput .Output .File )
1096+ require .NotNil (t , ociOutput .Output .File .URI )
1097+
1098+ // must match pattern oci-artifact-%s.tar.gz
1099+ require .Regexp (t , `^oci-artifact-[a-f0-9]+\.tar\.gz$` , filepath .Base (ociOutput .Output .File .URI ))
1100+ require .Equal (t , ociOutput .Output .File .MediaType , "application/vnd.ocm.software.oci.layout.v1+tar+gzip" )
1101+ }
0 commit comments