...

Source file src/edge-infra.dev/pkg/f8n/warehouse/lift/unpack/unpack_test.go

Documentation: edge-infra.dev/pkg/f8n/warehouse/lift/unpack

     1  package unpack
     2  
     3  import (
     4  	"os"
     5  	"testing"
     6  
     7  	"github.com/google/go-containerregistry/pkg/name"
     8  	assertAPI "github.com/stretchr/testify/assert"
     9  
    10  	"edge-infra.dev/pkg/f8n/warehouse/cluster"
    11  	"edge-infra.dev/pkg/f8n/warehouse/lift"
    12  	"edge-infra.dev/pkg/f8n/warehouse/oci"
    13  	"edge-infra.dev/pkg/f8n/warehouse/oci/layer"
    14  	"edge-infra.dev/pkg/f8n/warehouse/pallet"
    15  	"edge-infra.dev/pkg/lib/uuid"
    16  	"edge-infra.dev/test/fixtures"
    17  )
    18  
    19  var (
    20  	path      *fixtures.Path
    21  	fluentbit oci.Artifact // package containing unrenderable dependency
    22  	shoot     oci.Artifact // v1.ImageIndex test fixture
    23  	certMgr   oci.Artifact // v1.Image test fixture
    24  
    25  	// walk function that verifies all layers are processed
    26  	layerCheck = func(t *testing.T) Fn {
    27  		return func(_ pallet.Pallet, ll []layer.Layer) error {
    28  			for _, l := range ll {
    29  				checkLayerProcessing(t, l)
    30  			}
    31  			return nil
    32  		}
    33  	}
    34  )
    35  
    36  func TestMain(m *testing.M) {
    37  	// one time set up of shared test fixtures
    38  	var err error
    39  	path, err = fixtures.Layout()
    40  	if err != nil {
    41  		panic(err)
    42  	}
    43  
    44  	shoot, err = path.Get(name.MustParseReference("shoot:latest"))
    45  	if err != nil {
    46  		panic(err)
    47  	}
    48  	certMgr, err = path.Get(name.MustParseReference("cert-manager:latest"))
    49  	if err != nil {
    50  		panic(err)
    51  	}
    52  	fluentbit, err = path.Get(name.MustParseReference("fluentbit-test:latest"))
    53  	if err != nil {
    54  		panic(err)
    55  	}
    56  
    57  	os.Exit(m.Run())
    58  }
    59  
    60  func TestUnpack(t *testing.T) {
    61  	var (
    62  		assert  = assertAPI.New(t)
    63  		visited = map[string]bool{}
    64  	)
    65  
    66  	// TODO: test that nodes excluded by ForProvider aren't visited
    67  
    68  	assert.NoError(Walk(shoot, func(p pallet.Pallet, _ []layer.Layer) error {
    69  		if visited[p.Name()] {
    70  			t.Error("node already visited, function called twice", p.Name())
    71  			return nil
    72  		}
    73  		t.Log("visiting", p.Name())
    74  		deps, err := p.Dependencies()
    75  		assert.NoError(err)
    76  
    77  		// NOTE: this test logic isn't fantastic. it assumes that the test pallet,
    78  		// shoot, doesn't have nested composite dependencies
    79  		for _, d := range deps {
    80  			t.Log("checking dep", d.Name())
    81  			// we will only have visited the dependency if it isn't a composite package
    82  			// (aka, doesnt have its own images)
    83  			isComposite, err := oci.IsComposite(d)
    84  			assert.NoError(err)
    85  			switch {
    86  			case !isComposite:
    87  				assert.Truef(visited[d.Name()],
    88  					"dependency %s was not visited first for package %s", d.Name(), p.Name())
    89  			// but we should have visited its dependencies
    90  			case isComposite:
    91  				deps, err := d.Dependencies()
    92  				assert.NoError(err)
    93  
    94  				for _, d2 := range deps {
    95  					isComposite, err := oci.IsComposite(d2)
    96  					assert.NoError(err)
    97  					if isComposite {
    98  						assert.Truef(visited[d2.Name()],
    99  							"dependency %s was not visited first for package %s", d2.Name(), d.Name())
   100  					}
   101  				}
   102  			}
   103  		}
   104  
   105  		visited[p.Name()] = true
   106  		return nil
   107  	}, ForProvider(cluster.Generic)))
   108  
   109  	t.Run("ForProvider required for some input types", func(t *testing.T) {
   110  		var (
   111  			assert  = assertAPI.New(t)
   112  			nopWalk = func(_ pallet.Pallet, _ []layer.Layer) error {
   113  				return nil
   114  			}
   115  		)
   116  
   117  		assert.Error(Walk(shoot, nopWalk), "v1.ImageIndex should require ForProvider")
   118  
   119  		p, err := pallet.New(shoot)
   120  		assert.NoError(err)
   121  		assert.Error(Walk(p, nopWalk), "Pallet should require ForProvider")
   122  
   123  		cm, err := path.Get(name.MustParseReference("cert-manager:latest"))
   124  		assert.NoError(err)
   125  		assert.NoError(Walk(cm, nopWalk), "v1.Image should not require ForProvider")
   126  
   127  		p, err = pallet.New(cm)
   128  		assert.NoError(err)
   129  		assert.NoError(Walk(p, nopWalk), "Pallet backed by v1.Image should not require ForProvider")
   130  	})
   131  
   132  	t.Run("Layers Processed for all Input Types", func(t *testing.T) {
   133  		var (
   134  			assert = assertAPI.New(t)
   135  			walk   = layerCheck(t)
   136  			opts   = []Option{
   137  				ForProvider(cluster.Generic),
   138  				RenderWith(map[string]string{lift.ClusterUUIDRenderingParameter: uuid.New().UUID}),
   139  			}
   140  		)
   141  
   142  		assert.NoError(Walk(shoot, walk, opts...),
   143  			"v1.ImageIndex layers weren't processsed")
   144  		assert.NoError(Walk(certMgr, walk, opts...),
   145  			"v1.Image layers weren't processed")
   146  
   147  		p, err := pallet.New(shoot)
   148  		assert.NoError(err)
   149  		assert.NoError(Walk(p, walk, opts...),
   150  			"Pallet from v1.ImageIndex layers weren't processed")
   151  
   152  		p, err = pallet.New(shoot)
   153  		assert.NoError(err)
   154  		assert.NoError(Walk(p, walk, opts...),
   155  			"Pallet from v1.Image layers weren't processed")
   156  	})
   157  
   158  	t.Run("Handle Unrenderable Dependency", func(t *testing.T) {
   159  		assertAPI.NoError(t, Walk(fluentbit, layerCheck(t),
   160  			ForProvider(cluster.Generic),
   161  			RenderWith(map[string]string{lift.ClusterUUIDRenderingParameter: uuid.New().UUID})),
   162  		)
   163  	})
   164  }
   165  

View as plain text