github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/pkg/index/index_factory_test.go (about)

     1  package index_test
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"testing"
     7  
     8  	"github.com/buildpacks/imgutil"
     9  	"github.com/google/go-containerregistry/pkg/authn"
    10  	"github.com/google/go-containerregistry/pkg/name"
    11  	v1 "github.com/google/go-containerregistry/pkg/v1"
    12  	"github.com/google/go-containerregistry/pkg/v1/random"
    13  	"github.com/google/go-containerregistry/pkg/v1/remote"
    14  	"github.com/heroku/color"
    15  	"github.com/sclevine/spec"
    16  	"github.com/sclevine/spec/report"
    17  
    18  	"github.com/buildpacks/pack/pkg/index"
    19  	h "github.com/buildpacks/pack/testhelpers"
    20  )
    21  
    22  var dockerRegistry *h.TestRegistryConfig
    23  
    24  func TestIndexFactory(t *testing.T) {
    25  	color.Disable(true)
    26  	defer color.Disable(false)
    27  
    28  	h.RequireDocker(t)
    29  
    30  	dockerRegistry = h.RunRegistry(t)
    31  	defer dockerRegistry.StopRegistry(t)
    32  
    33  	os.Setenv("DOCKER_CONFIG", dockerRegistry.DockerConfigDir)
    34  	spec.Run(t, "Fetcher", testIndexFactory, spec.Parallel(), spec.Report(report.Terminal{}))
    35  }
    36  
    37  func testIndexFactory(t *testing.T, when spec.G, it spec.S) {
    38  	var (
    39  		indexFactory  *index.IndexFactory
    40  		imageIndex    imgutil.ImageIndex
    41  		indexRepoName string
    42  		err           error
    43  		tmpDir        string
    44  	)
    45  
    46  	it.Before(func() {
    47  		tmpDir, err = os.MkdirTemp("", "index-factory-test")
    48  		h.AssertNil(t, err)
    49  		indexFactory = index.NewIndexFactory(authn.DefaultKeychain, tmpDir)
    50  	})
    51  
    52  	it.After(func() {
    53  		os.RemoveAll(tmpDir)
    54  	})
    55  
    56  	when("#CreateIndex", func() {
    57  		it.Before(func() {
    58  			indexRepoName = h.NewRandomIndexRepoName()
    59  		})
    60  
    61  		when("no options are provided", func() {
    62  			it("creates an image index", func() {
    63  				imageIndex, err = indexFactory.CreateIndex(indexRepoName)
    64  				h.AssertNil(t, err)
    65  				h.AssertNotNil(t, imageIndex)
    66  			})
    67  		})
    68  	})
    69  
    70  	when("#Exists", func() {
    71  		when("index exists on disk", func() {
    72  			it.Before(func() {
    73  				indexRepoName = h.NewRandomIndexRepoName()
    74  				setUpLocalIndex(t, indexFactory, indexRepoName)
    75  			})
    76  
    77  			it("returns true", func() {
    78  				h.AssertTrue(t, indexFactory.Exists(indexRepoName))
    79  			})
    80  		})
    81  
    82  		when("index does not exist on disk", func() {
    83  			it.Before(func() {
    84  				indexRepoName = h.NewRandomIndexRepoName()
    85  			})
    86  
    87  			it("returns false", func() {
    88  				h.AssertFalse(t, indexFactory.Exists(indexRepoName))
    89  			})
    90  		})
    91  	})
    92  
    93  	when("#LoadIndex", func() {
    94  		when("index exists on disk", func() {
    95  			it.Before(func() {
    96  				indexRepoName = h.NewRandomIndexRepoName()
    97  				setUpLocalIndex(t, indexFactory, indexRepoName)
    98  			})
    99  
   100  			it("loads the index from disk", func() {
   101  				imageIndex, err = indexFactory.LoadIndex(indexRepoName)
   102  				h.AssertNil(t, err)
   103  				h.AssertNotNil(t, imageIndex)
   104  			})
   105  		})
   106  
   107  		when("index does not exist on disk", func() {
   108  			it.Before(func() {
   109  				indexRepoName = h.NewRandomIndexRepoName()
   110  			})
   111  
   112  			it("errors with a message", func() {
   113  				_, err = indexFactory.LoadIndex(indexRepoName)
   114  				h.AssertError(t, err, fmt.Sprintf("Image: '%s' not found", indexRepoName))
   115  			})
   116  		})
   117  	})
   118  
   119  	when("#FetchIndex", func() {
   120  		when("index exists in a remote registry", func() {
   121  			var remoteIndexRepoName string
   122  
   123  			it.Before(func() {
   124  				indexRepoName = h.NewRandomIndexRepoName()
   125  				remoteIndexRepoName = newTestImageIndexName("fetch-remote")
   126  				setUpRandomRemoteIndex(t, remoteIndexRepoName, 1, 1)
   127  			})
   128  
   129  			it("creates an index with the underlying remote index", func() {
   130  				_, err = indexFactory.FetchIndex(indexRepoName, imgutil.FromBaseIndex(remoteIndexRepoName))
   131  				h.AssertNil(t, err)
   132  			})
   133  		})
   134  
   135  		when("index does not exist in a remote registry", func() {
   136  			it.Before(func() {
   137  				indexRepoName = h.NewRandomIndexRepoName()
   138  			})
   139  
   140  			it("errors with a message", func() {
   141  				_, err = indexFactory.FetchIndex(indexRepoName, imgutil.FromBaseIndex(indexRepoName))
   142  				h.AssertNotNil(t, err)
   143  			})
   144  		})
   145  	})
   146  
   147  	when("#FindIndex", func() {
   148  		when("index exists on disk", func() {
   149  			it.Before(func() {
   150  				indexRepoName = h.NewRandomIndexRepoName()
   151  				setUpLocalIndex(t, indexFactory, indexRepoName)
   152  			})
   153  
   154  			it("finds the index on disk", func() {
   155  				imageIndex, err = indexFactory.FindIndex(indexRepoName)
   156  				h.AssertNil(t, err)
   157  				h.AssertNotNil(t, imageIndex)
   158  			})
   159  		})
   160  
   161  		when("index exists in a remote registry", func() {
   162  			it.Before(func() {
   163  				indexRepoName = newTestImageIndexName("find-remote")
   164  				setUpRandomRemoteIndex(t, indexRepoName, 1, 1)
   165  			})
   166  
   167  			it("finds the index in the remote registry", func() {
   168  				imageIndex, err = indexFactory.FindIndex(indexRepoName)
   169  				h.AssertNil(t, err)
   170  				h.AssertNotNil(t, imageIndex)
   171  			})
   172  		})
   173  	})
   174  }
   175  
   176  func setUpLocalIndex(t *testing.T, indexFactory *index.IndexFactory, indexRepoName string) {
   177  	imageIndex, err := indexFactory.CreateIndex(indexRepoName)
   178  	h.AssertNil(t, err)
   179  	h.AssertNil(t, imageIndex.SaveDir())
   180  }
   181  
   182  func newTestImageIndexName(name string) string {
   183  	return dockerRegistry.RepoName(name + "-" + h.RandString(10))
   184  }
   185  
   186  // setUpRandomRemoteIndex creates a random image index with the provided (count) number of manifest
   187  // each manifest will have the provided number of layers
   188  func setUpRandomRemoteIndex(t *testing.T, repoName string, layers, count int64) v1.ImageIndex {
   189  	ref, err := name.ParseReference(repoName, name.WeakValidation)
   190  	h.AssertNil(t, err)
   191  
   192  	randomIndex, err := random.Index(1024, layers, count)
   193  	h.AssertNil(t, err)
   194  
   195  	err = remote.WriteIndex(ref, randomIndex, remote.WithAuthFromKeychain(authn.DefaultKeychain))
   196  	h.AssertNil(t, err)
   197  
   198  	return randomIndex
   199  }