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 }