github.com/iqoqo/nomad@v0.11.3-0.20200911112621-d7021c74d101/client/state/upgrade_int_test.go (about) 1 package state_test 2 3 import ( 4 "compress/gzip" 5 "fmt" 6 "io" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 "testing" 12 13 "github.com/hashicorp/nomad/client/allocrunner" 14 "github.com/hashicorp/nomad/client/allocwatcher" 15 clientconfig "github.com/hashicorp/nomad/client/config" 16 "github.com/hashicorp/nomad/client/consul" 17 "github.com/hashicorp/nomad/client/devicemanager" 18 dmstate "github.com/hashicorp/nomad/client/devicemanager/state" 19 "github.com/hashicorp/nomad/client/pluginmanager/drivermanager" 20 . "github.com/hashicorp/nomad/client/state" 21 "github.com/hashicorp/nomad/client/vaultclient" 22 "github.com/hashicorp/nomad/helper/boltdd" 23 "github.com/hashicorp/nomad/helper/testlog" 24 "github.com/hashicorp/nomad/nomad/structs" 25 pstructs "github.com/hashicorp/nomad/plugins/shared/structs" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 ) 29 30 // TestBoltStateDB_Upgrade_Ok asserts upgading an old state db does not error 31 // during upgrade and restore. 32 func TestBoltStateDB_UpgradeOld_Ok(t *testing.T) { 33 t.Parallel() 34 35 files, err := filepath.Glob("testdata/*.db*") 36 require.NoError(t, err) 37 38 for _, fn := range files { 39 t.Run(fn, func(t *testing.T) { 40 dir, err := ioutil.TempDir("", "nomadtest") 41 require.NoError(t, err) 42 defer os.RemoveAll(dir) 43 44 var src io.ReadCloser 45 src, err = os.Open(fn) 46 require.NoError(t, err) 47 defer src.Close() 48 49 // testdata may be gzip'd; decode on copy 50 if strings.HasSuffix(fn, ".gz") { 51 src, err = gzip.NewReader(src) 52 require.NoError(t, err) 53 } 54 55 dst, err := os.Create(filepath.Join(dir, "state.db")) 56 require.NoError(t, err) 57 58 // Copy test files before testing them for safety 59 _, err = io.Copy(dst, src) 60 require.NoError(t, err) 61 62 require.NoError(t, src.Close()) 63 64 dbI, err := NewBoltStateDB(testlog.HCLogger(t), dir) 65 require.NoError(t, err) 66 defer dbI.Close() 67 68 db := dbI.(*BoltStateDB) 69 70 // Simply opening old files should *not* alter them 71 require.NoError(t, db.DB().View(func(tx *boltdd.Tx) error { 72 b := tx.Bucket([]byte("meta")) 73 if b != nil { 74 return fmt.Errorf("meta bucket found but should not exist yet!") 75 } 76 return nil 77 })) 78 79 needsUpgrade, err := NeedsUpgrade(db.DB().BoltDB()) 80 require.NoError(t, err) 81 require.True(t, needsUpgrade) 82 83 // Attept the upgrade 84 require.NoError(t, db.Upgrade()) 85 86 needsUpgrade, err = NeedsUpgrade(db.DB().BoltDB()) 87 require.NoError(t, err) 88 require.False(t, needsUpgrade) 89 90 // Ensure Allocations can be restored and 91 // NewAR/AR.Restore do not error. 92 allocs, errs, err := db.GetAllAllocations() 93 require.NoError(t, err) 94 assert.Len(t, errs, 0) 95 96 for _, alloc := range allocs { 97 checkUpgradedAlloc(t, dir, db, alloc) 98 } 99 100 // Should be nil for all upgrades 101 ps, err := db.GetDevicePluginState() 102 require.NoError(t, err) 103 require.Nil(t, ps) 104 105 ps = &dmstate.PluginState{ 106 ReattachConfigs: map[string]*pstructs.ReattachConfig{ 107 "test": {Pid: 1}, 108 }, 109 } 110 require.NoError(t, db.PutDevicePluginState(ps)) 111 112 require.NoError(t, db.Close()) 113 }) 114 } 115 } 116 117 // checkUpgradedAlloc creates and restores an AllocRunner from an upgraded 118 // database. 119 // 120 // It does not call AR.Run as its intended to be used against a wide test 121 // corpus in testdata that may be expensive to run and require unavailable 122 // dependencies. 123 func checkUpgradedAlloc(t *testing.T, path string, db StateDB, alloc *structs.Allocation) { 124 _, err := db.GetDeploymentStatus(alloc.ID) 125 assert.NoError(t, err) 126 127 tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup) 128 for _, task := range tg.Tasks { 129 _, _, err := db.GetTaskRunnerState(alloc.ID, task.Name) 130 require.NoError(t, err) 131 } 132 133 clientConf, cleanup := clientconfig.TestClientConfig(t) 134 135 // Does *not* cleanup overridden StateDir below. That's left alone for 136 // the caller to cleanup. 137 defer cleanup() 138 139 clientConf.StateDir = path 140 141 conf := &allocrunner.Config{ 142 Alloc: alloc, 143 Logger: clientConf.Logger, 144 ClientConfig: clientConf, 145 StateDB: db, 146 Consul: consul.NewMockConsulServiceClient(t, clientConf.Logger), 147 Vault: vaultclient.NewMockVaultClient(), 148 StateUpdater: &allocrunner.MockStateUpdater{}, 149 PrevAllocWatcher: allocwatcher.NoopPrevAlloc{}, 150 PrevAllocMigrator: allocwatcher.NoopPrevAlloc{}, 151 DeviceManager: devicemanager.NoopMockManager(), 152 DriverManager: drivermanager.TestDriverManager(t), 153 } 154 ar, err := allocrunner.NewAllocRunner(conf) 155 require.NoError(t, err) 156 157 // AllocRunner.Restore should not error 158 require.NoError(t, ar.Restore()) 159 }