get.porter.sh/porter@v1.3.0/pkg/storage/migrations/manager_test.go (about)

     1  package migrations
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"get.porter.sh/porter/pkg/config"
     8  	"get.porter.sh/porter/pkg/secrets"
     9  	"get.porter.sh/porter/pkg/storage"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  func TestManager_LoadSchema(t *testing.T) {
    15  	t.Run("valid schema", func(t *testing.T) {
    16  		schema := storage.NewSchema()
    17  
    18  		c := config.NewTestConfig(t)
    19  		m := NewTestManager(c)
    20  		defer m.Close()
    21  
    22  		err := m.store.Update(context.Background(), CollectionConfig, storage.UpdateOptions{Document: schema, Upsert: true})
    23  		require.NoError(t, err, "Save schema failed")
    24  
    25  		err = m.loadSchema(context.Background())
    26  		require.NoError(t, err, "LoadSchema failed")
    27  		assert.NotEmpty(t, m.schema, "Schema should be populated with the file's data")
    28  	})
    29  
    30  	t.Run("missing schema, empty home", func(t *testing.T) {
    31  		c := config.NewTestConfig(t)
    32  		m := NewTestManager(c)
    33  		defer m.Close()
    34  
    35  		err := m.loadSchema(context.Background())
    36  		require.NoError(t, err, "LoadSchema failed")
    37  		assert.NotEmpty(t, m.schema, "Schema should be initialized automatically when PORTER_HOME is empty")
    38  	})
    39  
    40  	t.Run("missing schema, existing home data", func(t *testing.T) {
    41  		c := config.NewTestConfig(t)
    42  		m := NewTestManager(c)
    43  		defer m.Close()
    44  
    45  		i := storage.Installation{InstallationSpec: storage.InstallationSpec{
    46  			Name: "abc123",
    47  		}}
    48  		err := m.store.Insert(context.Background(), storage.CollectionInstallations, storage.InsertOptions{Documents: []interface{}{i}})
    49  		require.NoError(t, err)
    50  
    51  		err = m.loadSchema(context.Background())
    52  		require.NoError(t, err, "LoadSchema failed")
    53  		assert.Empty(t, m.schema, "Schema should be empty because none was loaded")
    54  	})
    55  }
    56  
    57  func TestManager_NoMigrationEmptyHome(t *testing.T) {
    58  	config := config.NewTestConfig(t)
    59  	_, home := config.TestContext.UseFilesystem()
    60  	config.SetHomeDir(home)
    61  	defer config.Close()
    62  
    63  	mgr := NewTestManager(config)
    64  	defer mgr.Close()
    65  	claimStore := storage.NewInstallationStore(mgr)
    66  
    67  	_, err := claimStore.ListInstallations(context.Background(), storage.ListOptions{})
    68  	require.NoError(t, err, "ListInstallations failed")
    69  
    70  	credStore := storage.NewCredentialStore(mgr, nil)
    71  	_, err = credStore.ListCredentialSets(context.Background(), storage.ListOptions{})
    72  	require.NoError(t, err, "List credentials failed")
    73  
    74  	paramStore := storage.NewParameterStore(mgr, nil)
    75  	_, err = paramStore.ListParameterSets(context.Background(), storage.ListOptions{})
    76  	require.NoError(t, err, "List credentials failed")
    77  }
    78  
    79  func TestInstallationStorage_HaltOnMigrationRequired(t *testing.T) {
    80  	t.Parallel()
    81  
    82  	tc := config.NewTestConfig(t)
    83  	mgr := NewTestManager(tc)
    84  	defer mgr.Close()
    85  	claimStore := storage.NewInstallationStore(mgr)
    86  
    87  	schema := storage.NewSchema()
    88  	schema.Installations = "needs-migration"
    89  	err := mgr.store.Update(context.Background(), CollectionConfig, storage.UpdateOptions{Document: schema, Upsert: true})
    90  	require.NoError(t, err, "Save schema failed")
    91  
    92  	checkMigrationError := func(t *testing.T, err error) {
    93  		require.Error(t, err, "Operation should halt because a migration is required")
    94  		assert.Contains(t, err.Error(), "The schema of Porter's data is in an older format than supported by this version of Porter", "The error should be a migration error")
    95  
    96  		wantVersionComp := `Porter  uses the following database schema:
    97  
    98  storage.Schema{ID:"schema", Installations:"1.0.2", Credentials:"1.0.1", Parameters:"1.1.0"}
    99  
   100  Your database schema is:
   101  
   102  storage.Schema{ID:"schema", Installations:"needs-migration", Credentials:"1.0.1", Parameters:"1.1.0"}`
   103  		assert.Contains(t, err.Error(), wantVersionComp, "the migration error should contain the current and expected db schema")
   104  	}
   105  
   106  	t.Run("list", func(t *testing.T) {
   107  		_, err = claimStore.ListInstallations(context.Background(), storage.ListOptions{})
   108  		checkMigrationError(t, err)
   109  	})
   110  
   111  	t.Run("read", func(t *testing.T) {
   112  		_, err = claimStore.GetInstallation(context.Background(), "", "mybun")
   113  		checkMigrationError(t, err)
   114  	})
   115  
   116  }
   117  
   118  func TestClaimStorage_NoMigrationRequiredForEmptyHome(t *testing.T) {
   119  	t.Parallel()
   120  
   121  	config := config.NewTestConfig(t)
   122  	_, home := config.TestContext.UseFilesystem()
   123  	config.SetHomeDir(home)
   124  	defer config.Close()
   125  
   126  	mgr := NewTestManager(config)
   127  	defer mgr.Close()
   128  	claimStore := storage.NewInstallationStore(mgr)
   129  
   130  	names, err := claimStore.ListInstallations(context.Background(), storage.ListOptions{})
   131  	require.NoError(t, err, "ListInstallations failed")
   132  	assert.Empty(t, names, "Expected an empty list of installations since porter home is new")
   133  }
   134  
   135  func TestCredentialStorage_HaltOnMigrationRequired(t *testing.T) {
   136  	tc := config.NewTestConfig(t)
   137  	mgr := NewTestManager(tc)
   138  	testSecrets := secrets.NewTestSecretsProvider()
   139  	defer mgr.Close()
   140  	credStore := storage.NewTestCredentialProviderFor(t, mgr, testSecrets)
   141  
   142  	schema := storage.NewSchema()
   143  	schema.Credentials = "needs-migration"
   144  	err := mgr.store.Update(context.Background(), CollectionConfig, storage.UpdateOptions{Document: schema, Upsert: true})
   145  	require.NoError(t, err, "Save schema failed")
   146  
   147  	checkMigrationError := func(t *testing.T, err error) {
   148  		require.Error(t, err, "Operation should halt because a migration is required")
   149  		assert.Contains(t, err.Error(), "The schema of Porter's data is in an older format than supported by this version of Porter", "The error should be a migration error")
   150  
   151  		wantVersionComp := `Porter  uses the following database schema:
   152  
   153  storage.Schema{ID:"schema", Installations:"1.0.2", Credentials:"1.0.1", Parameters:"1.1.0"}
   154  
   155  Your database schema is:
   156  
   157  storage.Schema{ID:"schema", Installations:"1.0.2", Credentials:"needs-migration", Parameters:"1.1.0"}`
   158  		assert.Contains(t, err.Error(), wantVersionComp, "the migration error should contain the current and expected db schema")
   159  	}
   160  
   161  	t.Run("list", func(t *testing.T) {
   162  		_, err = credStore.ListCredentialSets(context.Background(), storage.ListOptions{})
   163  		checkMigrationError(t, err)
   164  	})
   165  
   166  	t.Run("read", func(t *testing.T) {
   167  		_, err = credStore.GetCredentialSet(context.Background(), "", "mybun")
   168  		checkMigrationError(t, err)
   169  	})
   170  }
   171  
   172  func TestCredentialStorage_NoMigrationRequiredForEmptyHome(t *testing.T) {
   173  	config := config.NewTestConfig(t)
   174  	_, home := config.TestContext.UseFilesystem()
   175  	config.SetHomeDir(home)
   176  	defer config.Close()
   177  
   178  	mgr := NewTestManager(config)
   179  	defer mgr.Close()
   180  	testSecrets := secrets.NewTestSecretsProvider()
   181  	credStore := storage.NewTestCredentialProviderFor(t, mgr, testSecrets)
   182  
   183  	names, err := credStore.ListCredentialSets(context.Background(), storage.ListOptions{
   184  		Namespace: "",
   185  		Name:      "",
   186  		Labels:    nil,
   187  		Skip:      0,
   188  		Limit:     0,
   189  	})
   190  	require.NoError(t, err, "List failed")
   191  	assert.Empty(t, names, "Expected an empty list of credentials since porter home is new")
   192  }
   193  
   194  func TestParameterStorage_HaltOnMigrationRequired(t *testing.T) {
   195  	tc := config.NewTestConfig(t)
   196  	mgr := NewTestManager(tc)
   197  	defer mgr.Close()
   198  	testSecrets := secrets.NewTestSecretsProvider()
   199  	paramStore := storage.NewTestParameterProviderFor(t, mgr, testSecrets)
   200  
   201  	schema := storage.NewSchema()
   202  	schema.Parameters = "needs-migration"
   203  	err := mgr.store.Update(context.Background(), CollectionConfig, storage.UpdateOptions{Document: schema, Upsert: true})
   204  	require.NoError(t, err, "Save schema failed")
   205  
   206  	checkMigrationError := func(t *testing.T, err error) {
   207  		require.Error(t, err, "Operation should halt because a migration is required")
   208  		assert.Contains(t, err.Error(), "The schema of Porter's data is in an older format than supported by this version of Porter", "The error should be a migration error")
   209  
   210  		wantVersionComp := `Porter  uses the following database schema:
   211  
   212  storage.Schema{ID:"schema", Installations:"1.0.2", Credentials:"1.0.1", Parameters:"1.1.0"}
   213  
   214  Your database schema is:
   215  
   216  storage.Schema{ID:"schema", Installations:"1.0.2", Credentials:"1.0.1", Parameters:"needs-migration"}`
   217  		assert.Contains(t, err.Error(), wantVersionComp, "the migration error should contain the current and expected db schema")
   218  	}
   219  
   220  	t.Run("list", func(t *testing.T) {
   221  		_, err = paramStore.ListParameterSets(context.Background(), storage.ListOptions{})
   222  		checkMigrationError(t, err)
   223  	})
   224  
   225  	t.Run("read", func(t *testing.T) {
   226  		_, err = paramStore.GetParameterSet(context.Background(), "", "mybun")
   227  		checkMigrationError(t, err)
   228  	})
   229  }
   230  
   231  func TestParameterStorage_NoMigrationRequiredForEmptyHome(t *testing.T) {
   232  	config := config.NewTestConfig(t)
   233  	_, home := config.TestContext.UseFilesystem()
   234  	config.SetHomeDir(home)
   235  	defer config.Close()
   236  
   237  	mgr := NewTestManager(config)
   238  	defer mgr.Close()
   239  	testSecrets := secrets.NewTestSecretsProvider()
   240  	paramStore := storage.NewTestParameterProviderFor(t, mgr, testSecrets)
   241  
   242  	names, err := paramStore.ListParameterSets(context.Background(), storage.ListOptions{})
   243  	require.NoError(t, err, "List failed")
   244  	assert.Empty(t, names, "Expected an empty list of parameters since porter home is new")
   245  }