get.porter.sh/porter@v1.3.0/pkg/storage/migrations/migration_test.go (about) 1 package migrations 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 "testing" 8 "time" 9 10 "get.porter.sh/porter/pkg/config" 11 "get.porter.sh/porter/pkg/portercontext" 12 testmigrations "get.porter.sh/porter/pkg/storage/migrations/testhelpers" 13 14 "get.porter.sh/porter/pkg/cnab" 15 "get.porter.sh/porter/pkg/secrets" 16 "get.porter.sh/porter/pkg/storage" 17 "get.porter.sh/porter/pkg/test" 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 ) 21 22 func TestConvertInstallation(t *testing.T) { 23 inst := convertInstallation("mybuns") 24 assert.Empty(t, inst.ID, "the installation id should start off uninitialized so that later we can set it using the claim") 25 assert.Empty(t, inst.Namespace, "by default installations are migrated into the global namespace") 26 assert.Equal(t, "mybuns", inst.Name, "incorrect name") 27 assert.Equal(t, storage.DefaultInstallationSchemaVersion, inst.SchemaVersion, "incorrect schema version") 28 } 29 30 func TestConvertClaimToRun(t *testing.T) { 31 c := portercontext.NewTestContext(t) 32 33 inst := storage.NewInstallation("", "mybuns") 34 35 claimData, err := os.ReadFile(filepath.Join(c.FindRepoRoot(), "tests/testdata/porter_home/v0/claims/hello1/01G1VJGY43HT3KZN82DS6DDPWK.json")) 36 require.NoError(t, err, "could not read testdata") 37 38 run, err := convertClaimToRun(inst, claimData) 39 require.NoError(t, err, "error converting claim") 40 41 assert.Equal(t, "01G1VJGY43HT3KZN82DS6DDPWK", run.ID, "incorrect run id") 42 assert.Equal(t, storage.DefaultInstallationSchemaVersion, run.SchemaVersion, "incorrect schema version, should be the current schema supported by porter") 43 assert.Equal(t, "hello1", run.Installation, "incorrect installation name") 44 assert.Equal(t, "01G1VJGY43HT3KZN82DSJY4NNB", run.Revision, "incorrect revision") 45 assert.Equal(t, "2022-04-29T16:09:42.65907-05:00", run.Created.Format(time.RFC3339Nano), "incorrect created timestamp") 46 assert.Equal(t, "install", run.Action, "incorrect action") 47 assert.NotEmpty(t, run.Bundle, "bundle was not populated") 48 assert.Len(t, run.Parameters.Parameters, 1, "incorrect parameters") 49 50 param := run.Parameters.Parameters[0] 51 assert.Equal(t, param.Name, "porter-debug", "incorrect parameter name") 52 assert.Equal(t, param.Source.Strategy, "value", "incorrect parameter source key") 53 assert.Equal(t, param.Source.Hint, "false", "incorrect parameter source value") 54 } 55 56 func TestConvertResult(t *testing.T) { 57 c := portercontext.NewTestContext(t) 58 59 run := storage.NewRun("myns", "mybuns") 60 61 resultData, err := os.ReadFile(filepath.Join(c.FindRepoRoot(), "tests/testdata/porter_home/v0/results/01G1VJGY43HT3KZN82DS6DDPWK/01G1VJH2HP97B5B0N5S37KYMVG.json")) 62 require.NoError(t, err, "could not read testdata result") 63 64 result, err := convertResult(run, resultData) 65 require.NoError(t, err, "failed to convert result") 66 67 assert.Equal(t, storage.DefaultInstallationSchemaVersion, result.SchemaVersion, "incorrect schema version") 68 assert.Equal(t, run.Namespace, result.Namespace, "incorrect namespace") 69 assert.Equal(t, run.Installation, result.Installation, "incorrect installation name") 70 assert.Equal(t, "yay!", result.Message, "incorrect message") 71 assert.Equal(t, "boop!", result.Custom, "incorrect custom data") 72 assert.Equal(t, "01G1VJH2HP97B5B0N5S37KYMVG", result.ID, "incorrect id") 73 assert.Equal(t, run.ID, result.RunID, "incorrect run id") 74 assert.Equal(t, "2022-04-29T16:09:47.190534-05:00", result.Created.Format(time.RFC3339Nano), "incorrect created timestamp") 75 assert.Equal(t, "succeeded", result.Status, "incorrect status") 76 assert.Len(t, result.OutputMetadata, 1, "expected one output populated") 77 78 contentDigest, _ := result.OutputMetadata.GetContentDigest(cnab.OutputInvocationImageLogs) 79 assert.Equal(t, "sha256:28ccd0529aa1edefb0e771a28c31c0193f656718af985fed197235ba98fc5696", contentDigest, "incorrect output content digest") 80 81 generatedFlag, _ := result.OutputMetadata.GetGeneratedByBundle(cnab.OutputInvocationImageLogs) 82 assert.False(t, generatedFlag, "incorrect generated output flag") 83 } 84 85 func TestConvertOutput(t *testing.T) { 86 c := portercontext.NewTestContext(t) 87 88 outputData, err := os.ReadFile(filepath.Join(c.FindRepoRoot(), "tests/testdata/porter_home/v0/outputs/01G1VJH2HP97B5B0N5S37KYMVG/01G1VJH2HP97B5B0N5S37KYMVG-io.cnab.outputs.invocationImageLogs")) 89 require.NoError(t, err, "error reading testdata output file") 90 91 run := storage.NewRun("myns", "mybuns") 92 result := run.NewResult("succeeded") 93 94 output, err := convertOutput(result, "01G1VJH2HP97B5B0N5S37KYMVG-io.cnab.outputs.invocationImageLogs", outputData) 95 require.NoError(t, err, "error converting output") 96 97 require.Equal(t, storage.DefaultInstallationSchemaVersion, output.SchemaVersion, "incorrect schema version") 98 require.Equal(t, result.Namespace, output.Namespace, "incorrect namespace") 99 require.Equal(t, result.Installation, output.Installation, "incorrect installation") 100 require.Equal(t, "io.cnab.outputs.invocationImageLogs", output.Name, "incorrect name") 101 require.Equal(t, result.ID, output.ResultID, "incorrect result id") 102 require.Equal(t, result.RunID, output.RunID, "incorrect run id") 103 require.Equal(t, outputData, output.Value, "incorrect output value") 104 } 105 106 func TestMigration_Migrate(t *testing.T) { 107 c := testmigrations.CreateLegacyPorterHome(t) 108 defer c.Close() 109 home, err := c.GetHomeDir() 110 require.NoError(t, err, "could not get the home directory") 111 ctx, _, _ := c.SetupIntegrationTest() 112 113 destStore := storage.NewTestStore(c) 114 testSecrets := secrets.NewTestSecretsProvider() 115 testParams := storage.NewTestParameterProviderFor(t, destStore, testSecrets) 116 testSanitizer := storage.NewSanitizer(testParams, testSecrets) 117 118 opts := storage.MigrateOptions{ 119 OldHome: home, 120 OldStorageAccount: "src", 121 NewNamespace: "myns", 122 } 123 m := NewMigration(c.Config, opts, destStore, testSanitizer) 124 defer m.Close() 125 126 err = m.Connect(ctx) 127 require.NoError(t, err, "connect failed") 128 129 updatedSchema, err := m.Migrate(ctx) 130 require.NoError(t, err, "migrate installations failed") 131 assert.Equal(t, storage.NewSchema(), updatedSchema, "incorrect schema was applied after the migration") 132 133 validateMigratedInstallations(ctx, t, c, destStore, opts) 134 validateMigratedCredentialSets(ctx, t, destStore, opts) 135 validateMigratedParameterSets(ctx, t, destStore, opts) 136 } 137 138 func validateMigratedInstallations(ctx context.Context, t *testing.T, c *config.TestConfig, destStore storage.TestStore, opts storage.MigrateOptions) { 139 is := storage.NewInstallationStore(destStore) 140 installations, err := is.ListInstallations(ctx, storage.ListOptions{Namespace: opts.NewNamespace}) 141 require.NoError(t, err, "could not list installations in the destination database") 142 assert.Len(t, installations, 4, "expected 3 installation to be migrated") 143 144 // Validate that the installation as migrated correctly 145 inst, err := is.GetInstallation(ctx, opts.NewNamespace, "hello1") 146 require.NoError(t, err, "could not retrieve the hello1 test installation") 147 148 assert.Equal(t, storage.DefaultInstallationSchemaVersion, inst.SchemaVersion, "incorrect installation schema") 149 assert.Equal(t, "01G1VJGY43HT3KZN82DS6DDPWH", inst.ID, "the installation should set its installation id to the id of the earliest claim so that it's consistently generated") 150 assert.Equal(t, "hello1", inst.Name, "incorrect installation name") 151 assert.Equal(t, opts.NewNamespace, inst.Namespace, "installation namespace should be set to the destination namespace") 152 assert.Empty(t, inst.Bundle, "We didn't track the bundle reference in v0, so this can't be populated") 153 assert.Empty(t, inst.Custom, "We didn't allow setting custom metadata on installations in v0, so this can't be populated") 154 assert.Empty(t, inst.Labels, "We didn't allow setting labels on installations in v0, so this can't be populated") 155 assert.Empty(t, inst.CredentialSets, "We didn't track credential sets used when running a bundle in v0, so this can't be populated") 156 assert.Empty(t, inst.ParameterSets, "We didn't track parameter sets used when running a bundle in v0, so this can't be populated") 157 assert.Empty(t, inst.Parameters.Parameters, "We didn't track manually specified parameters when running a bundle in v0, so this can't be populated") 158 159 // Validate the installation status, which is calculated based on the runs and their results 160 assert.Equal(t, "2022-04-28T16:09:42.65907-05:00", inst.Status.Created.Format(time.RFC3339Nano), "Created timestamp should be set to the timestamp of the first run") 161 assert.Equal(t, "2022-04-29T16:13:20.48026-05:00", inst.Status.Modified.Format(time.RFC3339Nano), "Modified timestamp should be set to the timestamp of the last run") 162 require.NotNil(t, inst.Status.Installed, "the install timestamp should be set") 163 assert.Equal(t, "2022-04-29T16:09:47.190534-05:00", inst.Status.Installed.Format(time.RFC3339Nano), "the install timestamp should be set to the timestamp of the successful install result") 164 assert.NotNil(t, inst.Status.Uninstalled, "the uninstall timestamp should be set") 165 assert.Equal(t, "2022-04-29T16:13:21.802457-05:00", inst.Status.Uninstalled.Format(time.RFC3339Nano), "the uninstalled timestamp should be set to the timestamp of the successful uninstall result") 166 assert.Equal(t, "01G1VJQJV0RN5AW5BSZHNTVYTV", inst.Status.RunID, "incorrect last run id set on the installation status") 167 assert.Equal(t, "01G1VJQM4AVN7SCXC8WV3M0D7N", inst.Status.ResultID, "incorrect last result id set on the installation status") 168 assert.Equal(t, "succeeded", inst.Status.ResultStatus, "the installation status should be successful") 169 assert.Equal(t, "0.1.1", inst.Status.BundleVersion, "incorrect installation bundle version") 170 assert.Empty(t, inst.Status.BundleReference, "We didn't track bundle reference in v0, so this can't be populated") 171 assert.Empty(t, inst.Status.BundleDigest, "We didn't track bundle digest in v0, so this can't be populated") 172 173 runs, results, err := is.ListRuns(ctx, opts.NewNamespace, inst.Name) 174 require.NoError(t, err, "could not list runs in the destination database") 175 assert.Len(t, runs, 5, "expected 5 runs") // dry-run, failed install, successful install, upgrade, uninstall 176 177 lastRun := runs[4] 178 assert.Equal(t, storage.DefaultInstallationSchemaVersion, lastRun.SchemaVersion, "incorrect run schema version") 179 assert.Equal(t, "01G1VJQJV0RN5AW5BSZHNTVYTV", lastRun.ID, "incorrect run id") 180 assert.Equal(t, "01G1VJQJV0RN5AW5BSZNJ1G6R7", lastRun.Revision, "incorrect run revision") 181 assert.Equal(t, inst.Namespace, lastRun.Namespace, "incorrect run namespace") 182 assert.Equal(t, inst.Name, lastRun.Installation, "incorrect run installation name") 183 assert.Empty(t, lastRun.BundleReference, "We didn't track bundle reference in v0, so this can't be populated") 184 assert.Empty(t, lastRun.BundleDigest, "We didn't track bundle digest in v0, so this can't be populated") 185 assert.Equal(t, "uninstall", lastRun.Action, "incorrect run action") 186 assert.Empty(t, lastRun.Custom, "We didn't set custom datadata on claims in v0, so this can't be populated") 187 assert.Equal(t, "2022-04-29T16:13:20.48026-05:00", lastRun.Created.Format(time.RFC3339Nano), "incorrect run created timestamp") 188 assert.Empty(t, lastRun.ParameterSets, "We didn't track run parameter sets in v0, so this can't be populated") 189 assert.Empty(t, lastRun.ParameterOverrides, "We didn't track run parameter overrides in v0, so this can't be populated") 190 assert.Empty(t, lastRun.CredentialSets, "We didn't track run credential sets in v0, so this can't be populated") 191 assert.Len(t, lastRun.Parameters.Parameters, 1, "expected one parameter set on the run") 192 params := lastRun.Parameters.Parameters 193 assert.Equal(t, "porter-debug", params[0].Name, "expected the porter-debug parameter to be set on the run") 194 assert.Equal(t, "value", params[0].Source.Strategy, "expected the porter-debug parameter to be a hard-coded value") 195 assert.Equal(t, "true", params[0].Source.Hint, "expected the porter-debug parameter to be false") 196 197 runResults := results[lastRun.ID] 198 assert.Len(t, runResults, 2, "expected 2 results for the last run") 199 200 lastResult := runResults[1] 201 assert.Equal(t, "01G1VJQM4AVN7SCXC8WV3M0D7N", lastResult.ID, "incorrect result id") 202 assert.Equal(t, lastRun.ID, lastResult.RunID, "incorrect result id") 203 assert.Equal(t, inst.Name, lastResult.Installation, "incorrect result installation name") 204 assert.Equal(t, inst.Namespace, lastResult.Namespace, "incorrect result namespace") 205 assert.Equal(t, "succeeded", lastResult.Status, "incorrect result status") 206 assert.Equal(t, "yipee", lastResult.Message, "incorrect result message") 207 assert.Empty(t, lastResult.Custom, "We didn't track custom metadata on results in v0, so this can't be populated") 208 assert.Equal(t, "2022-04-29T16:13:21.802457-05:00", lastResult.Created.Format(time.RFC3339Nano), "invalid result created timestamp") 209 assert.Contains(t, lastResult.OutputMetadata, cnab.OutputInvocationImageLogs, "expected the logs to be captured as an output") 210 digest, _ := lastResult.OutputMetadata.GetContentDigest(cnab.OutputInvocationImageLogs) 211 assert.Equal(t, "sha256:a7fdc86f826691ae1c6bf6bbcba43abbb67cf45b45093652a98327521a62d69c", digest, "incorrect content digest for logs output") 212 generatedFlag, ok := lastResult.OutputMetadata.GetGeneratedByBundle(cnab.OutputInvocationImageLogs) 213 assert.True(t, ok, "expected a generated flag to be set on the logs output") 214 assert.False(t, generatedFlag, "incorrect content digest for logs output") 215 216 logsOutput, err := is.GetLastOutput(ctx, inst.Namespace, inst.Name, cnab.OutputInvocationImageLogs) 217 require.NoError(t, err, "error retrieving the last set of logs for the installation") 218 219 wantFile := filepath.Join(c.TestContext.FindRepoRoot(), "tests/testdata/porter_home/v0/outputs/01G1VJQM4AVN7SCXC8WV3M0D7N/01G1VJQM4AVN7SCXC8WV3M0D7N-io.cnab.outputs.invocationImageLogs") 220 test.CompareGoldenFile(t, wantFile, string(logsOutput.Value)) 221 } 222 223 func validateMigratedCredentialSets(ctx context.Context, t *testing.T, destStore storage.TestStore, opts storage.MigrateOptions) { 224 store := storage.NewCredentialStore(destStore, nil) 225 credentialSets, err := store.ListCredentialSets(ctx, storage.ListOptions{Namespace: opts.NewNamespace}) 226 require.NoError(t, err, "could not list credentialSets in the destination database") 227 assert.Len(t, credentialSets, 1, "expected 1 credential set to be migrated") 228 229 // Validate that the credential sets are migrated correctly 230 creds, err := store.GetCredentialSet(ctx, opts.NewNamespace, "credentials-tutorial") 231 require.NoError(t, err, "could not retrieve the migrated credentials-tutorial credential set") 232 233 assert.Equal(t, storage.DefaultCredentialSetSchemaVersion, creds.SchemaVersion, "incorrect schema version") 234 assert.Equal(t, "myns", creds.Namespace, "incorrect namespace") 235 assert.Equal(t, "credentials-tutorial", creds.Name, "incorrect name") 236 assert.Equal(t, "2022-06-06T16:06:52.099455-05:00", creds.Status.Created.Format(time.RFC3339Nano), "incorrect created timestamp") 237 assert.Equal(t, "2022-06-06T16:07:52.099455-05:00", creds.Status.Modified.Format(time.RFC3339Nano), "incorrect modified timestamp") 238 assert.Empty(t, creds.Labels, "incorrect labels") 239 require.Len(t, creds.Credentials, 1, "incorrect number of credentials migrated") 240 241 cred := creds.Credentials[0] 242 assert.Equal(t, "github-token", cred.Name, "incorrect credential name") 243 assert.Equal(t, "env", cred.Source.Strategy, "incorrect credential source key") 244 assert.Equal(t, "GITHUB_TOKEN", cred.Source.Hint, "incorrect credential source value") 245 } 246 247 func validateMigratedParameterSets(ctx context.Context, t *testing.T, destStore storage.TestStore, opts storage.MigrateOptions) { 248 store := storage.NewParameterStore(destStore, nil) 249 parameterSets, err := store.ListParameterSets(ctx, storage.ListOptions{Namespace: opts.NewNamespace}) 250 require.NoError(t, err, "could not list parameterSets in the destination database") 251 assert.Len(t, parameterSets, 1, "expected 1 parameter set to be migrated") 252 253 // Validate that the parameter sets are migrated correctly 254 ps, err := store.GetParameterSet(ctx, opts.NewNamespace, "hello-llama") 255 require.NoError(t, err, "could not retrieve the migrated hello-llama parameter set") 256 257 assert.Equal(t, storage.DefaultParameterSetSchemaVersion, ps.SchemaVersion, "incorrect schema version") 258 assert.Equal(t, "myns", ps.Namespace, "incorrect namespace") 259 assert.Equal(t, "hello-llama", ps.Name, "incorrect name") 260 assert.Equal(t, "2022-06-06T16:06:21.635528-05:00", ps.Status.Created.Format(time.RFC3339Nano), "incorrect created timestamp") 261 assert.Equal(t, "2022-06-06T17:06:21.635528-05:00", ps.Status.Modified.Format(time.RFC3339Nano), "incorrect modified timestamp") 262 assert.Empty(t, ps.Labels, "incorrect labels") 263 require.Len(t, ps.Parameters, 1, "incorrect number of parameters migrated") 264 265 param := ps.Parameters[0] 266 assert.Equal(t, "name", param.Name, "incorrect parameter name") 267 assert.Equal(t, "env", param.Source.Strategy, "incorrect parameter source key") 268 assert.Equal(t, "USER", param.Source.Hint, "incorrect parameter source value") 269 }