github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/provider/common/state_test.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common_test 5 6 import ( 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 11 jc "github.com/juju/testing/checkers" 12 gc "gopkg.in/check.v1" 13 goyaml "gopkg.in/yaml.v2" 14 15 "github.com/juju/juju/core/instance" 16 "github.com/juju/juju/environs" 17 "github.com/juju/juju/environs/storage" 18 envtesting "github.com/juju/juju/environs/testing" 19 "github.com/juju/juju/provider/common" 20 coretesting "github.com/juju/juju/testing" 21 ) 22 23 type StateSuite struct { 24 coretesting.BaseSuite 25 } 26 27 var _ = gc.Suite(&StateSuite{}) 28 29 func (suite *StateSuite) newStorageWithDataDir(c *gc.C) (storage.Storage, string) { 30 closer, stor, dataDir := envtesting.CreateLocalTestStorage(c) 31 suite.AddCleanup(func(*gc.C) { closer.Close() }) 32 envtesting.UploadFakeTools(c, stor, "released", "released") 33 return stor, dataDir 34 } 35 36 func (suite *StateSuite) newStorage(c *gc.C) storage.Storage { 37 stor, _ := suite.newStorageWithDataDir(c) 38 return stor 39 } 40 41 func (suite *StateSuite) TestCreateStateFileWritesEmptyStateFile(c *gc.C) { 42 stor := suite.newStorage(c) 43 44 url, err := common.CreateStateFile(stor) 45 c.Assert(err, jc.ErrorIsNil) 46 47 reader, err := storage.Get(stor, common.StateFile) 48 c.Assert(err, jc.ErrorIsNil) 49 data, err := ioutil.ReadAll(reader) 50 c.Assert(err, jc.ErrorIsNil) 51 c.Check(string(data), gc.Equals, "") 52 c.Assert(url, gc.NotNil) 53 expectedURL, err := stor.URL(common.StateFile) 54 c.Assert(err, jc.ErrorIsNil) 55 c.Check(url, gc.Equals, expectedURL) 56 } 57 58 func (suite *StateSuite) TestDeleteStateFile(c *gc.C) { 59 closer, stor, dataDir := envtesting.CreateLocalTestStorage(c) 60 defer closer.Close() 61 62 err := common.DeleteStateFile(stor) 63 c.Assert(err, jc.ErrorIsNil) // doesn't exist, juju don't care 64 65 _, err = common.CreateStateFile(stor) 66 c.Assert(err, jc.ErrorIsNil) 67 _, err = os.Stat(filepath.Join(dataDir, common.StateFile)) 68 c.Assert(err, jc.ErrorIsNil) 69 70 err = common.DeleteStateFile(stor) 71 c.Assert(err, jc.ErrorIsNil) 72 _, err = os.Stat(filepath.Join(dataDir, common.StateFile)) 73 c.Assert(err, jc.Satisfies, os.IsNotExist) 74 } 75 76 func (suite *StateSuite) TestSaveStateWritesStateFile(c *gc.C) { 77 stor := suite.newStorage(c) 78 state := common.BootstrapState{ 79 StateInstances: []instance.Id{instance.Id("an-instance-id")}, 80 } 81 marshaledState, err := goyaml.Marshal(state) 82 c.Assert(err, jc.ErrorIsNil) 83 84 err = common.SaveState(stor, &state) 85 c.Assert(err, jc.ErrorIsNil) 86 87 loadedState, err := storage.Get(stor, common.StateFile) 88 c.Assert(err, jc.ErrorIsNil) 89 content, err := ioutil.ReadAll(loadedState) 90 c.Assert(err, jc.ErrorIsNil) 91 c.Check(content, gc.DeepEquals, marshaledState) 92 } 93 94 func (suite *StateSuite) setUpSavedState(c *gc.C, dataDir string) common.BootstrapState { 95 state := common.BootstrapState{ 96 StateInstances: []instance.Id{instance.Id("an-instance-id")}, 97 } 98 content, err := goyaml.Marshal(state) 99 c.Assert(err, jc.ErrorIsNil) 100 err = ioutil.WriteFile(filepath.Join(dataDir, common.StateFile), []byte(content), 0644) 101 c.Assert(err, jc.ErrorIsNil) 102 return state 103 } 104 105 func (suite *StateSuite) TestLoadStateReadsStateFile(c *gc.C) { 106 storage, dataDir := suite.newStorageWithDataDir(c) 107 state := suite.setUpSavedState(c, dataDir) 108 storedState, err := common.LoadState(storage) 109 c.Assert(err, jc.ErrorIsNil) 110 c.Check(*storedState, gc.DeepEquals, state) 111 } 112 113 func (suite *StateSuite) TestLoadStateMissingFile(c *gc.C) { 114 stor := suite.newStorage(c) 115 _, err := common.LoadState(stor) 116 c.Check(err, gc.Equals, environs.ErrNotBootstrapped) 117 } 118 119 func (suite *StateSuite) TestLoadStateIntegratesWithSaveState(c *gc.C) { 120 storage := suite.newStorage(c) 121 state := common.BootstrapState{ 122 StateInstances: []instance.Id{instance.Id("an-instance-id")}, 123 } 124 err := common.SaveState(storage, &state) 125 c.Assert(err, jc.ErrorIsNil) 126 storedState, err := common.LoadState(storage) 127 c.Assert(err, jc.ErrorIsNil) 128 129 c.Check(*storedState, gc.DeepEquals, state) 130 } 131 132 func (suite *StateSuite) TestAddStateInstance(c *gc.C) { 133 storage := suite.newStorage(c) 134 for _, str := range []string{"a", "b", "c"} { 135 id := instance.Id(str) 136 err := common.AddStateInstance(storage, instance.Id(id)) 137 c.Assert(err, jc.ErrorIsNil) 138 } 139 140 storedState, err := common.LoadState(storage) 141 c.Assert(err, jc.ErrorIsNil) 142 c.Check(storedState, gc.DeepEquals, &common.BootstrapState{ 143 StateInstances: []instance.Id{ 144 instance.Id("a"), 145 instance.Id("b"), 146 instance.Id("c"), 147 }, 148 }) 149 } 150 151 func (suite *StateSuite) TestRemoveStateInstancesPartial(c *gc.C) { 152 storage := suite.newStorage(c) 153 state := common.BootstrapState{ 154 StateInstances: []instance.Id{ 155 instance.Id("a"), 156 instance.Id("b"), 157 instance.Id("c"), 158 }, 159 } 160 err := common.SaveState(storage, &state) 161 c.Assert(err, jc.ErrorIsNil) 162 163 err = common.RemoveStateInstances( 164 storage, 165 state.StateInstances[0], 166 instance.Id("not-there"), 167 state.StateInstances[2], 168 ) 169 c.Assert(err, jc.ErrorIsNil) 170 171 storedState, err := common.LoadState(storage) 172 c.Assert(storedState, gc.DeepEquals, &common.BootstrapState{ 173 StateInstances: []instance.Id{ 174 state.StateInstances[1], 175 }, 176 }) 177 } 178 179 func (suite *StateSuite) TestRemoveStateInstancesNone(c *gc.C) { 180 storage := suite.newStorage(c) 181 state := common.BootstrapState{ 182 StateInstances: []instance.Id{instance.Id("an-instance-id")}, 183 } 184 err := common.SaveState(storage, &state) 185 c.Assert(err, jc.ErrorIsNil) 186 187 err = common.RemoveStateInstances( 188 storage, 189 instance.Id("not-there"), 190 ) 191 c.Assert(err, jc.ErrorIsNil) 192 193 storedState, err := common.LoadState(storage) 194 c.Assert(storedState, gc.DeepEquals, &state) 195 } 196 197 func (suite *StateSuite) TestRemoveStateInstancesNoProviderState(c *gc.C) { 198 storage := suite.newStorage(c) 199 err := common.RemoveStateInstances(storage, instance.Id("id")) 200 // No error if the id is missing, so no error if the entire 201 // provider-state file is missing. This is the case if 202 // bootstrap failed. 203 c.Assert(err, jc.ErrorIsNil) 204 }