get.porter.sh/porter@v1.3.0/tests/integration/dependenciesv1_test.go (about)

     1  //go:build integration
     2  
     3  package integration
     4  
     5  import (
     6  	"context"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  
    11  	"get.porter.sh/porter/pkg/cnab"
    12  	"get.porter.sh/porter/pkg/porter"
    13  	"get.porter.sh/porter/pkg/secrets"
    14  	"get.porter.sh/porter/pkg/storage"
    15  	"github.com/cnabio/cnab-go/secrets/host"
    16  	"github.com/stretchr/testify/assert"
    17  	"github.com/stretchr/testify/require"
    18  )
    19  
    20  func TestDependenciesLifecycle(t *testing.T) {
    21  	t.Parallel()
    22  	p := porter.NewTestPorter(t)
    23  	defer p.Close()
    24  	ctx := p.SetupIntegrationTest()
    25  
    26  	namespace := installWordpressBundle(ctx, p)
    27  	defer cleanupWordpressBundle(ctx, p, namespace)
    28  
    29  	upgradeWordpressBundle(ctx, p, namespace)
    30  
    31  	invokeWordpressBundle(ctx, p, namespace)
    32  
    33  	uninstallWordpressBundle(ctx, p, namespace)
    34  }
    35  
    36  func publishMySQLBundle(ctx context.Context, p *porter.TestPorter) {
    37  	bunDir, err := os.MkdirTemp("", "porter-mysql")
    38  	require.NoError(p.T(), err, "could not create temp directory to publish the mysql bundle")
    39  	defer os.RemoveAll(bunDir)
    40  
    41  	// Rebuild the bundle from a temp directory so that we don't modify the source directory
    42  	// and leave modified files around.
    43  	p.TestConfig.TestContext.AddTestDirectory(filepath.Join(p.RepoRoot, "build/testdata/bundles/mysql"), bunDir)
    44  	pwd := p.Getwd()
    45  	p.Chdir(bunDir)
    46  	defer p.Chdir(pwd)
    47  
    48  	publishOpts := porter.PublishOptions{}
    49  	publishOpts.Force = true
    50  	err = publishOpts.Validate(p.Config)
    51  	require.NoError(p.T(), err, "validation of publish opts for dependent bundle failed")
    52  
    53  	err = p.Publish(ctx, publishOpts)
    54  	require.NoError(p.T(), err, "publish of dependent bundle failed")
    55  }
    56  
    57  func installWordpressBundle(ctx context.Context, p *porter.TestPorter) (namespace string) {
    58  	// Publish the mysql bundle that we depend upon
    59  	publishMySQLBundle(ctx, p)
    60  
    61  	// Install the bundle that has dependencies
    62  	p.CopyDirectory(filepath.Join(p.RepoRoot, "build/testdata/bundles/wordpress"), ".", false)
    63  
    64  	namespace = p.RandomString(10)
    65  	installOpts := porter.NewInstallOptions()
    66  	installOpts.Namespace = namespace
    67  	installOpts.CredentialIdentifiers = []string{"ci"} // Use the ci credential set, porter should remember this for later
    68  	installOpts.Params = []string{
    69  		"wordpress-password=mypassword",
    70  		"namespace=" + namespace,
    71  		"mysql#namespace=" + namespace,
    72  	}
    73  
    74  	// Add a supplemental parameter set to vet dep param resolution
    75  	installOpts.ParameterSets = []string{"myparam"}
    76  	testParamSets := storage.NewParameterSet(namespace, "myparam", secrets.SourceMap{
    77  		Name: "mysql#probe-timeout",
    78  		Source: secrets.Source{
    79  			Strategy: host.SourceValue,
    80  			Hint:     "2",
    81  		},
    82  	})
    83  
    84  	p.TestParameters.InsertParameterSet(ctx, testParamSets)
    85  
    86  	err := installOpts.Validate(ctx, []string{}, p.Porter)
    87  	require.NoError(p.T(), err, "validation of install opts for root bundle failed")
    88  
    89  	err = p.InstallBundle(ctx, installOpts)
    90  	require.NoError(p.T(), err, "install of root bundle failed namespace %s", namespace)
    91  
    92  	// Verify that the dependency claim is present
    93  	i, err := p.Installations.GetInstallation(ctx, namespace, "wordpress-mysql")
    94  	require.NoError(p.T(), err, "could not fetch installation status for the dependency")
    95  	assert.Equal(p.T(), cnab.StatusSucceeded, i.Status.ResultStatus, "the dependency wasn't recorded as being installed successfully")
    96  	c, err := p.Installations.GetLastRun(ctx, namespace, i.Name)
    97  	require.NoError(p.T(), err, "GetLastRun failed")
    98  	resolvedParameters, err := p.Sanitizer.RestoreParameterSet(ctx, c.Parameters, cnab.ExtendedBundle{c.Bundle})
    99  	require.NoError(p.T(), err, "Resolve run failed")
   100  	assert.Equal(p.T(), "porter-ci-mysql", resolvedParameters["mysql-name"], "the dependency param value for 'mysql-name' is incorrect")
   101  	assert.Equal(p.T(), 2, resolvedParameters["probe-timeout"], "the dependency param value for 'probe-timeout' is incorrect")
   102  
   103  	// TODO(carolynvs): compare with last parameters set on the installation once we start tracking that
   104  
   105  	// Verify that the bundle claim is present
   106  	i, err = p.Installations.GetInstallation(ctx, namespace, "wordpress")
   107  	require.NoError(p.T(), err, "could not fetch claim for the root bundle")
   108  	assert.Equal(p.T(), cnab.StatusSucceeded, i.Status.ResultStatus, "the root bundle wasn't recorded as being installed successfully")
   109  
   110  	return namespace
   111  }
   112  
   113  func cleanupWordpressBundle(ctx context.Context, p *porter.TestPorter, namespace string) {
   114  	uninstallOptions := porter.NewUninstallOptions()
   115  	uninstallOptions.Namespace = namespace
   116  	uninstallOptions.CredentialIdentifiers = []string{"ci"}
   117  	uninstallOptions.Delete = true
   118  	err := uninstallOptions.Validate(ctx, []string{}, p.Porter)
   119  	require.NoError(p.T(), err, "validation of uninstall opts for root bundle failed")
   120  
   121  	err = p.UninstallBundle(ctx, uninstallOptions)
   122  	require.NoError(p.T(), err, "uninstall of root bundle failed")
   123  
   124  	// Verify that the dependency installation is deleted
   125  	i, err := p.Installations.GetInstallation(ctx, namespace, "wordpress-mysql")
   126  	require.ErrorIs(p.T(), err, storage.ErrNotFound{})
   127  	require.Equal(p.T(), storage.Installation{}, i)
   128  
   129  	// Verify that the root installation is deleted
   130  	i, err = p.Installations.GetInstallation(ctx, namespace, "wordpress")
   131  	require.ErrorIs(p.T(), err, storage.ErrNotFound{})
   132  	require.Equal(p.T(), storage.Installation{}, i)
   133  }
   134  
   135  func upgradeWordpressBundle(ctx context.Context, p *porter.TestPorter, namespace string) {
   136  	upgradeOpts := porter.NewUpgradeOptions()
   137  	upgradeOpts.Namespace = namespace
   138  	// do not specify credential sets, porter should reuse what was specified from install
   139  	upgradeOpts.Params = []string{
   140  		"wordpress-password=mypassword",
   141  		"namespace=" + namespace,
   142  		"mysql#namespace=" + namespace,
   143  	}
   144  	err := upgradeOpts.Validate(ctx, []string{}, p.Porter)
   145  	require.NoError(p.T(), err, "validation of upgrade opts for root bundle failed")
   146  
   147  	err = p.UpgradeBundle(ctx, upgradeOpts)
   148  	require.NoError(p.T(), err, "upgrade of root bundle failed")
   149  
   150  	// Verify that the dependency claim is upgraded
   151  	i, err := p.Installations.GetInstallation(ctx, namespace, "wordpress-mysql")
   152  	require.NoError(p.T(), err, "could not fetch claim for the dependency")
   153  	c, err := p.Installations.GetLastRun(ctx, i.Namespace, i.Name)
   154  	require.NoError(p.T(), err, "GetLastClaim failed")
   155  	assert.Equal(p.T(), cnab.ActionUpgrade, c.Action, "the dependency wasn't recorded as being upgraded")
   156  	assert.Equal(p.T(), cnab.StatusSucceeded, i.Status.ResultStatus, "the dependency wasn't recorded as being upgraded successfully")
   157  
   158  	// Verify that the bundle claim is upgraded
   159  	i, err = p.Installations.GetInstallation(ctx, namespace, "wordpress")
   160  	require.NoError(p.T(), err, "could not fetch claim for the root bundle")
   161  	c, err = p.Installations.GetLastRun(ctx, i.Namespace, i.Name)
   162  	require.NoError(p.T(), err, "GetLastClaim failed")
   163  	assert.Equal(p.T(), cnab.ActionUpgrade, c.Action, "the root bundle wasn't recorded as being upgraded")
   164  	assert.Equal(p.T(), cnab.StatusSucceeded, i.Status.ResultStatus, "the root bundle wasn't recorded as being upgraded successfully")
   165  
   166  	// Check that we are using the original credential set specified during install
   167  	require.Len(p.T(), i.CredentialSets, 1, "expected only one credential set associated to the installation")
   168  	assert.Equal(p.T(), "ci", i.CredentialSets[0], "expected to use the alternate credential set")
   169  }
   170  
   171  func invokeWordpressBundle(ctx context.Context, p *porter.TestPorter, namespace string) {
   172  	invokeOpts := porter.NewInvokeOptions()
   173  	invokeOpts.Namespace = namespace
   174  	invokeOpts.Action = "ping"
   175  	// Use a different set of creds to run this rando command
   176  	invokeOpts.CredentialIdentifiers = []string{"ci2"}
   177  	invokeOpts.Params = []string{
   178  		"wordpress-password=mypassword",
   179  		"namespace=" + namespace,
   180  	}
   181  	err := invokeOpts.Validate(ctx, []string{}, p.Porter)
   182  	require.NoError(p.T(), err, "validation of invoke opts for root bundle failed")
   183  
   184  	err = p.InvokeBundle(ctx, invokeOpts)
   185  	require.NoError(p.T(), err, "invoke of root bundle failed")
   186  
   187  	// Verify that the dependency claim is invoked
   188  	i, err := p.Installations.GetInstallation(ctx, namespace, "wordpress-mysql")
   189  	require.NoError(p.T(), err, "could not fetch claim for the dependency")
   190  	c, err := p.Installations.GetLastRun(ctx, i.Namespace, i.Name)
   191  	require.NoError(p.T(), err, "GetLastClaim failed")
   192  	assert.Equal(p.T(), "ping", c.Action, "the dependency wasn't recorded as being invoked")
   193  	assert.Equal(p.T(), cnab.StatusSucceeded, i.Status.ResultStatus, "the dependency wasn't recorded as being invoked successfully")
   194  
   195  	// Verify that the bundle claim is invoked
   196  	i, err = p.Installations.GetInstallation(ctx, namespace, "wordpress")
   197  	require.NoError(p.T(), err, "could not fetch claim for the root bundle")
   198  	c, err = p.Installations.GetLastRun(ctx, i.Namespace, i.Name)
   199  	require.NoError(p.T(), err, "GetLastClaim failed")
   200  	assert.Equal(p.T(), "ping", c.Action, "the root bundle wasn't recorded as being invoked")
   201  	assert.Equal(p.T(), cnab.StatusSucceeded, i.Status.ResultStatus, "the root bundle wasn't recorded as being invoked successfully")
   202  
   203  	// Check that we are now using the alternate credentials with the bundle
   204  	require.Len(p.T(), i.CredentialSets, 1, "expected only one credential set associated to the installation")
   205  	assert.Equal(p.T(), "ci2", i.CredentialSets[0], "expected to use the alternate credential set")
   206  }
   207  
   208  func uninstallWordpressBundle(ctx context.Context, p *porter.TestPorter, namespace string) {
   209  	uninstallOptions := porter.NewUninstallOptions()
   210  	uninstallOptions.Namespace = namespace
   211  	// Now go back to using the original set of credentials
   212  	uninstallOptions.CredentialIdentifiers = []string{"ci"}
   213  	uninstallOptions.Params = []string{
   214  		"namespace=" + namespace,
   215  		"mysql#namespace=" + namespace,
   216  	}
   217  	err := uninstallOptions.Validate(ctx, []string{}, p.Porter)
   218  	require.NoError(p.T(), err, "validation of uninstall opts for root bundle failed")
   219  
   220  	err = p.UninstallBundle(ctx, uninstallOptions)
   221  	require.NoError(p.T(), err, "uninstall of root bundle failed")
   222  
   223  	// Verify that the dependency claim is uninstalled
   224  	i, err := p.Installations.GetInstallation(ctx, namespace, "wordpress-mysql")
   225  	require.NoError(p.T(), err, "could not fetch installation for the dependency")
   226  	c, err := p.Installations.GetLastRun(ctx, i.Namespace, i.Name)
   227  	require.NoError(p.T(), err, "GetLastClaim failed")
   228  	assert.Equal(p.T(), cnab.ActionUninstall, c.Action, "the dependency wasn't recorded as being uninstalled")
   229  	assert.Equal(p.T(), cnab.StatusSucceeded, i.Status.ResultStatus, "the dependency wasn't recorded as being uninstalled successfully")
   230  
   231  	// Verify that the bundle claim is uninstalled
   232  	i, err = p.Installations.GetInstallation(ctx, namespace, "wordpress")
   233  	require.NoError(p.T(), err, "could not fetch installation for the root bundle")
   234  	c, err = p.Installations.GetLastRun(ctx, i.Namespace, i.Name)
   235  	require.NoError(p.T(), err, "GetLastClaim failed")
   236  	assert.Equal(p.T(), cnab.ActionUninstall, c.Action, "the root bundle wasn't recorded as being uninstalled")
   237  	assert.Equal(p.T(), cnab.StatusSucceeded, i.Status.ResultStatus, "the root bundle wasn't recorded as being uninstalled successfully")
   238  
   239  	// Check that we are now using the original credentials with the bundle
   240  	require.Len(p.T(), i.CredentialSets, 1, "expected only one credential set associated to the installation")
   241  	assert.Equal(p.T(), "ci", i.CredentialSets[0], "expected to use the alternate credential set")
   242  
   243  }