get.porter.sh/porter@v1.3.0/pkg/runtime/runtime_test.go (about)

     1  package runtime
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"path/filepath"
     7  	"testing"
     8  
     9  	"get.porter.sh/porter/pkg/cnab"
    10  	"get.porter.sh/porter/pkg/config"
    11  	"get.porter.sh/porter/pkg/manifest"
    12  	"get.porter.sh/porter/pkg/portercontext"
    13  	"github.com/cnabio/cnab-go/bundle"
    14  	"github.com/cnabio/cnab-go/bundle/definition"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  func TestPorterRuntime_Execute_readMixinOutputs(t *testing.T) {
    20  	r := NewTestPorterRuntime(t)
    21  
    22  	testFiles := []string{
    23  		"emptyoutput",
    24  		"jsonoutput",
    25  		"multiliner",
    26  		"oneliner",
    27  	}
    28  
    29  	for _, testFile := range testFiles {
    30  		r.TestContext.AddTestFile(
    31  			fmt.Sprintf("testdata/outputs/%s.txt", testFile),
    32  			filepath.Join(portercontext.MixinOutputsDir, testFile))
    33  	}
    34  
    35  	gotOutputs, err := r.readMixinOutputs()
    36  	require.NoError(t, err)
    37  
    38  	for _, testFile := range testFiles {
    39  		if exists, _ := r.config.FileSystem.Exists(testFile); exists {
    40  			require.Fail(t, fmt.Sprintf("file %s should not exist after reading outputs", testFile))
    41  		}
    42  	}
    43  
    44  	wantOutputs := map[string]string{
    45  		"emptyoutput": "",
    46  		"jsonoutput": `{
    47    "foo": true,
    48    "things": [
    49      123,
    50      "abc",
    51      false
    52    ]
    53  }`,
    54  		"multiliner": `FOO
    55  
    56  BAR
    57  BAZ`,
    58  		"oneliner": "ABC",
    59  	}
    60  
    61  	assert.Equal(t, wantOutputs, gotOutputs)
    62  }
    63  
    64  func TestPorterRuntime_ApplyStepOutputsToBundle_None(t *testing.T) {
    65  	r := NewTestPorterRuntime(t)
    66  	m := &manifest.Manifest{Name: "mybun"}
    67  	r.RuntimeManifest = r.NewRuntimeManifest(cnab.ActionInstall, m)
    68  
    69  	outputs := map[string]string{
    70  		"foo": "bar",
    71  		"123": "abc",
    72  	}
    73  
    74  	err := r.applyStepOutputsToBundle(outputs)
    75  	assert.NoError(t, err)
    76  }
    77  
    78  func TestPorterRuntime_ApplyStepOutputsToBundle_Some_Match(t *testing.T) {
    79  	r := NewTestPorterRuntime(t)
    80  	m := &manifest.Manifest{
    81  		Name: "mybun",
    82  		Outputs: manifest.OutputDefinitions{
    83  			"foo": {
    84  				Name: "foo",
    85  				Schema: definition.Schema{
    86  					Type: "string",
    87  				},
    88  				Sensitive: true,
    89  			},
    90  			"123": {
    91  				Name: "123",
    92  				Schema: definition.Schema{
    93  					Type: "string",
    94  				},
    95  				Sensitive: false,
    96  			},
    97  		},
    98  	}
    99  	r.RuntimeManifest = r.NewRuntimeManifest(cnab.ActionInstall, m)
   100  
   101  	outputs := map[string]string{
   102  		"foo": "bar",
   103  		"123": "abc",
   104  	}
   105  
   106  	err := r.applyStepOutputsToBundle(outputs)
   107  	assert.NoError(t, err)
   108  
   109  	want := map[string]string{
   110  		"foo": "bar",
   111  		"123": "abc",
   112  	}
   113  
   114  	for _, outputName := range []string{"foo", "123"} {
   115  		bytes, err := r.config.FileSystem.ReadFile(filepath.Join(config.BundleOutputsDir, outputName))
   116  		assert.NoError(t, err)
   117  
   118  		assert.Equal(t, want[outputName], string(bytes))
   119  	}
   120  }
   121  
   122  func TestPorterRuntime_ApplyStepOutputsToBundle_Some_NoMatch(t *testing.T) {
   123  	r := NewTestPorterRuntime(t)
   124  	m := &manifest.Manifest{
   125  		Name: "mybun",
   126  		Outputs: manifest.OutputDefinitions{
   127  			"bar": {
   128  				Name: "bar",
   129  			},
   130  			"456": {
   131  				Name: "456",
   132  			},
   133  		},
   134  	}
   135  	r.RuntimeManifest = r.NewRuntimeManifest(cnab.ActionInstall, m)
   136  
   137  	outputs := map[string]string{
   138  		"foo": "bar",
   139  		"123": "abc",
   140  	}
   141  
   142  	err := r.applyStepOutputsToBundle(outputs)
   143  	assert.NoError(t, err)
   144  
   145  	// No outputs declared in the manifest match those in outputs,
   146  	// so no output file is expected to be written
   147  	for _, output := range []string{"foo", "bar", "123", "456"} {
   148  		_, err := r.config.FileSystem.ReadFile(filepath.Join(config.BundleOutputsDir, output))
   149  		assert.Error(t, err)
   150  	}
   151  }
   152  
   153  func TestPorterRuntime_ApplyStepOutputsToBundle_ApplyTo_True(t *testing.T) {
   154  	r := NewTestPorterRuntime(t)
   155  	m := &manifest.Manifest{
   156  		Name: "mybun",
   157  		Outputs: manifest.OutputDefinitions{
   158  			"foo": {
   159  				Name: "foo",
   160  				ApplyTo: []string{
   161  					"upgrade",
   162  				},
   163  			},
   164  			"123": {
   165  				Name: "123",
   166  				ApplyTo: []string{
   167  					"install",
   168  				},
   169  				Schema: definition.Schema{
   170  					Type: "string",
   171  				},
   172  				Sensitive: false,
   173  			},
   174  		},
   175  	}
   176  	r.RuntimeManifest = r.NewRuntimeManifest(cnab.ActionInstall, m)
   177  
   178  	outputs := map[string]string{
   179  		"foo": "bar",
   180  		"123": "abc",
   181  	}
   182  
   183  	err := r.applyStepOutputsToBundle(outputs)
   184  	assert.NoError(t, err)
   185  
   186  	// foo output should not exist (applyTo doesn't match)
   187  	_, err = r.config.FileSystem.ReadFile(filepath.Join(config.BundleOutputsDir, "foo"))
   188  	assert.Error(t, err)
   189  
   190  	// 123 output should exist (applyTo matches)
   191  	bytes, err := r.config.FileSystem.ReadFile(filepath.Join(config.BundleOutputsDir, "123"))
   192  	assert.NoError(t, err)
   193  
   194  	want := "abc"
   195  	assert.Equal(t, want, string(bytes))
   196  }
   197  
   198  func TestRuntimeManifest_ApplyUnboundBundleOutputs_File(t *testing.T) {
   199  	const srcPath = "/home/nonroot/.kube/config"
   200  	const outputName = "kubeconfig"
   201  
   202  	ctx := context.Background()
   203  	testcases := []struct {
   204  		name       string
   205  		shouldBind bool
   206  		def        manifest.OutputDefinition
   207  	}{
   208  		{name: "file with applyto",
   209  			shouldBind: true,
   210  			def: manifest.OutputDefinition{
   211  				Name: outputName,
   212  				ApplyTo: []string{
   213  					"install",
   214  				},
   215  				Schema: definition.Schema{
   216  					Type: "file",
   217  				},
   218  				Path: srcPath,
   219  			},
   220  		},
   221  		{name: "file no applyto",
   222  			shouldBind: true,
   223  			def: manifest.OutputDefinition{
   224  				Name: outputName,
   225  				Schema: definition.Schema{
   226  					Type: "file",
   227  				},
   228  				Path: srcPath,
   229  			},
   230  		},
   231  		{name: "not file",
   232  			shouldBind: true,
   233  			def: manifest.OutputDefinition{
   234  				Name: outputName,
   235  				Schema: definition.Schema{
   236  					Type: "string",
   237  				},
   238  				Path: srcPath,
   239  			},
   240  		},
   241  		{name: "file no path",
   242  			shouldBind: false,
   243  			def: manifest.OutputDefinition{
   244  				Name: outputName,
   245  				Schema: definition.Schema{
   246  					Type: "string",
   247  				},
   248  				Path: "",
   249  			},
   250  		},
   251  	}
   252  
   253  	for _, tc := range testcases {
   254  		t.Run(tc.name, func(t *testing.T) {
   255  			m := &manifest.Manifest{
   256  				Name: "mybun",
   257  				Outputs: manifest.OutputDefinitions{
   258  					tc.def.Name: tc.def,
   259  				},
   260  			}
   261  			cfg := NewConfigFor(config.NewTestConfig(t).Config)
   262  			rm := NewRuntimeManifest(cfg, cnab.ActionInstall, m)
   263  			rm.bundle = cnab.NewBundle(bundle.Bundle{
   264  				Definitions: map[string]*definition.Schema{
   265  					tc.def.Name: &tc.def.Schema,
   266  				},
   267  				Outputs: map[string]bundle.Output{
   268  					tc.def.Name: {
   269  						Definition: tc.def.Name,
   270  						Path:       tc.def.Path,
   271  					},
   272  				},
   273  			})
   274  
   275  			_, err := rm.config.FileSystem.Create(srcPath)
   276  			require.NoError(t, err)
   277  
   278  			err = rm.applyUnboundBundleOutputs(ctx)
   279  			require.NoError(t, err)
   280  
   281  			exists, _ := rm.config.FileSystem.Exists("/cnab/app/outputs/" + outputName)
   282  			assert.Equal(t, exists, tc.shouldBind)
   283  		})
   284  	}
   285  }
   286  
   287  func TestPorterRuntime_LoadImageMappingFilesNoRelo(t *testing.T) {
   288  	r := NewTestPorterRuntime(t)
   289  	r.TestContext.AddTestFile("testdata/bundle-images.json", "/cnab/bundle.json")
   290  	bun, reloMap, err := r.getImageMappingFiles()
   291  	assert.NoError(t, err)
   292  	assert.Empty(t, reloMap)
   293  	assert.Equal(t, "mysql", bun.Name)
   294  }
   295  
   296  func TestLoadImageMappingFilesNoBundle(t *testing.T) {
   297  	r := NewTestPorterRuntime(t)
   298  	r.TestContext.AddTestFile("testdata/relocation-mapping.json", "/cnab/app/relocation-mapping.json")
   299  	_, _, err := r.getImageMappingFiles()
   300  	require.Error(t, err)
   301  	assert.Contains(t, err.Error(), "cannot read bundle")
   302  }
   303  
   304  func TestLoadImageMappingFilesBadBundle(t *testing.T) {
   305  	r := NewTestPorterRuntime(t)
   306  	r.TestContext.AddTestFileFromRoot("pkg/porter/testdata/porter.yaml", "/cnab/bundle.json")
   307  	r.TestContext.AddTestFile("testdata/relocation-mapping.json", "/cnab/app/relocation-mapping.json")
   308  	_, _, err := r.getImageMappingFiles()
   309  	require.Error(t, err)
   310  	assert.Contains(t, err.Error(), "cannot load bundle")
   311  }
   312  
   313  func TestLoadImageMappingFilesGoodFiles(t *testing.T) {
   314  	r := NewTestPorterRuntime(t)
   315  	r.TestContext.AddTestFile("testdata/bundle-images.json", "/cnab/bundle.json")
   316  	r.TestContext.AddTestFile("testdata/relocation-mapping.json", "/cnab/app/relocation-mapping.json")
   317  
   318  	bun, reloMap, err := r.getImageMappingFiles()
   319  	assert.NoError(t, err)
   320  	assert.NotEmpty(t, reloMap)
   321  	assert.Equal(t, "mysql", bun.Name)
   322  }